diff options
author | Dave Barach <dave@barachs.net> | 2016-11-28 11:41:35 -0500 |
---|---|---|
committer | Dave Wallace <dwallacelf@gmail.com> | 2016-12-01 22:27:31 +0000 |
commit | 7be864ad0d8e3b139a277fb4a0234480f0cc3daa (patch) | |
tree | 75e69823c8cca3b780f27b54f2753f4ba7a987a5 | |
parent | e245d5ecef9a7b0969d160943b0a817c46e09f71 (diff) |
Add a 64-byte interface "tag" for vhost and tap interfaces
This patch should dispose of spurious objections around interface tag
requirements, currently in use as excuses not to support the vpp ML2
plugin.
Add "u8 tag[64];" to the sw_interface_details message sent by vpp to
control-plane clients. Add u8 tag[64] to the create_vhost_user_if and
tap_connect APIs.
Added debug CLI to set/show/clear the interface tag on any vnet sw
interface. Added the sw_interface_tag_add_del API to set/clear
tags on any vnet sw interface.
There can be no expectation of "tag atomicity" with respect to
physical hardware. Vpp discovers devices before establishing a
control-plane connection.
This patch upload verifies using the csit oper-161128 branch
Change-Id: If8520119e7a586c5ccf0fdda82484ac205622855
Signed-off-by: Dave Barach <dave@barachs.net>
-rw-r--r-- | vnet/vnet/interface.c | 1 | ||||
-rw-r--r-- | vnet/vnet/interface_cli.c | 67 | ||||
-rw-r--r-- | vnet/vnet/interface_funcs.h | 38 | ||||
-rw-r--r-- | vnet/vnet/vnet.h | 2 | ||||
-rw-r--r-- | vpp-api-test/vat/api_format.c | 80 | ||||
-rw-r--r-- | vpp/vpp-api/api.c | 74 | ||||
-rw-r--r-- | vpp/vpp-api/custom_dump.c | 23 | ||||
-rw-r--r-- | vpp/vpp-api/vpe.api | 28 |
8 files changed, 302 insertions, 11 deletions
diff --git a/vnet/vnet/interface.c b/vnet/vnet/interface.c index e552733e58b..6e3d7f291b7 100644 --- a/vnet/vnet/interface.c +++ b/vnet/vnet/interface.c @@ -1202,6 +1202,7 @@ vnet_interface_init (vlib_main_t * vm) return error; } + vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword)); } VLIB_INIT_FUNCTION (vnet_interface_init); diff --git a/vnet/vnet/interface_cli.c b/vnet/vnet/interface_cli.c index 1c15eb18028..7dbee867ded 100644 --- a/vnet/vnet/interface_cli.c +++ b/vnet/vnet/interface_cli.c @@ -228,6 +228,7 @@ show_sw_interfaces (vlib_main_t * vm, u32 sw_if_index = ~(u32) 0; u8 show_addresses = 0; u8 show_features = 0; + u8 show_tag = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -242,6 +243,8 @@ show_sw_interfaces (vlib_main_t * vm, show_addresses = 1; else if (unformat (input, "features") || unformat (input, "feat")) show_features = 1; + else if (unformat (input, "tag")) + show_tag = 1; else { error = clib_error_return (0, "unknown input `%U'", @@ -250,14 +253,26 @@ show_sw_interfaces (vlib_main_t * vm, } } - if (show_features) + if (show_features || show_tag) { if (sw_if_index == ~(u32) 0) return clib_error_return (0, "Interface not specified..."); + } + if (show_features) + { vnet_interface_features_show (vm, sw_if_index); return 0; } + if (show_tag) + { + u8 *tag; + tag = vnet_get_sw_interface_tag (vnm, sw_if_index); + vlib_cli_output (vm, "%U: %s", + format_vnet_sw_if_index_name, vnm, sw_if_index, + tag ? (char *) tag : "(none)"); + return 0; + } if (!show_addresses) vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, 0); @@ -1091,6 +1106,56 @@ VLIB_CLI_COMMAND (set_interface_mac_address_cmd, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +set_tag (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) +{ + vnet_main_t *vnm = vnet_get_main (); + u32 sw_if_index = ~0; + u8 *tag = 0; + + if (!unformat (input, "%U %s", unformat_vnet_sw_interface, + vnm, &sw_if_index, &tag)) + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + + vnet_set_sw_interface_tag (vnm, tag, sw_if_index); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_tag_command, static) = { + .path = "set interface tag", + .short_help = "set interface tag <intfc> <tag>", + .function = set_tag, +}; +/* *INDENT-ON* */ + +static clib_error_t * +clear_tag (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t *vnm = vnet_get_main (); + u32 sw_if_index = ~0; + + if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + + vnet_clear_sw_interface_tag (vnm, sw_if_index); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (clear_tag_command, static) = { + .path = "clear interface tag", + .short_help = "clear interface tag <intfc>", + .function = clear_tag, +}; +/* *INDENT-ON* */ + + /* * fd.io coding-style-patch-verification: ON * diff --git a/vnet/vnet/interface_funcs.h b/vnet/vnet/interface_funcs.h index 17c677f07b6..a488599cff0 100644 --- a/vnet/vnet/interface_funcs.h +++ b/vnet/vnet/interface_funcs.h @@ -92,6 +92,44 @@ vnet_get_device_class (vnet_main_t * vnm, u32 dev_class_index) dev_class_index); } +static inline u8 * +vnet_get_sw_interface_tag (vnet_main_t * vnm, u32 sw_if_index) +{ + uword *p; + p = hash_get (vnm->interface_tag_by_sw_if_index, sw_if_index); + if (p) + return ((u8 *) p[0]); + return 0; +} + +static inline void +vnet_set_sw_interface_tag (vnet_main_t * vnm, u8 * tag, u32 sw_if_index) +{ + uword *p; + p = hash_get (vnm->interface_tag_by_sw_if_index, sw_if_index); + if (p) + { + u8 *oldtag = (u8 *) p[0]; + hash_unset (vnm->interface_tag_by_sw_if_index, sw_if_index); + vec_free (oldtag); + } + + hash_set (vnm->interface_tag_by_sw_if_index, sw_if_index, tag); +} + +static inline void +vnet_clear_sw_interface_tag (vnet_main_t * vnm, u32 sw_if_index) +{ + uword *p; + p = hash_get (vnm->interface_tag_by_sw_if_index, sw_if_index); + if (p) + { + u8 *oldtag = (u8 *) p[0]; + hash_unset (vnm->interface_tag_by_sw_if_index, sw_if_index); + vec_free (oldtag); + } +} + /** * Call back walk type for walking SW indices on a HW interface */ diff --git a/vnet/vnet/vnet.h b/vnet/vnet/vnet.h index 36cdddd6ba4..5a8ae858678 100644 --- a/vnet/vnet/vnet.h +++ b/vnet/vnet/vnet.h @@ -68,6 +68,8 @@ typedef struct vnet_main_t _vnet_interface_function_list_elt_t * sw_interface_admin_up_down_functions[VNET_ITF_FUNC_N_PRIO]; + uword *interface_tag_by_sw_if_index; + /* * Last "api" error, preserved so we can issue reasonable diagnostics * at or near the top of the food chain diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c index 448ae75c3ae..958f75f5fa0 100644 --- a/vpp-api-test/vat/api_format.c +++ b/vpp-api-test/vat/api_format.c @@ -3547,7 +3547,8 @@ _(ip_source_and_port_range_check_interface_add_del_reply)\ _(delete_subif_reply) \ _(l2_interface_pbb_tag_rewrite_reply) \ _(punt_reply) \ -_(feature_enable_disable_reply) +_(feature_enable_disable_reply) \ +_(sw_interface_tag_add_del_reply) #define _(n) \ static void vl_api_##n##_t_handler \ @@ -3791,7 +3792,8 @@ _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \ _(PUNT_REPLY, punt_reply) \ _(IP_FIB_DETAILS, ip_fib_details) \ _(IP6_FIB_DETAILS, ip6_fib_details) \ -_(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply) +_(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply) \ +_(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply) /* M: construct, but don't yet send a message */ @@ -5629,6 +5631,7 @@ api_tap_connect (vat_main_t * vam) u8 random_mac = 1; u8 name_set = 0; u8 *tap_name; + u8 *tag = 0; memset (mac_address, 0, sizeof (mac_address)); @@ -5643,6 +5646,7 @@ api_tap_connect (vat_main_t * vam) random_mac = 1; else if (unformat (i, "tapname %s", &tap_name)) name_set = 1; + else if (unformat (i, "tag %s", &tag)); else break; } @@ -5655,16 +5659,28 @@ api_tap_connect (vat_main_t * vam) if (vec_len (tap_name) > 63) { errmsg ("tap name too long\n"); + return -99; } vec_add1 (tap_name, 0); + if (vec_len (tag) > 63) + { + errmsg ("tag too long\n"); + return -99; + } + vec_add1 (tag, 0); + /* Construct the API message */ M (TAP_CONNECT, tap_connect); mp->use_random_mac = random_mac; clib_memcpy (mp->mac_address, mac_address, 6); clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name)); + if (tag) + clib_memcpy (mp->tag, tag, vec_len (tag)); + vec_free (tap_name); + vec_free (tag); /* send it... */ S; @@ -10666,6 +10682,7 @@ api_create_vhost_user_if (vat_main_t * vam) u32 custom_dev_instance = ~0; u8 hwaddr[6]; u8 use_custom_mac = 0; + u8 *tag = 0; /* Shut up coverity */ memset (hwaddr, 0, sizeof (hwaddr)); @@ -10682,6 +10699,8 @@ api_create_vhost_user_if (vat_main_t * vam) use_custom_mac = 1; else if (unformat (i, "server")) is_server = 1; + else if (unformat (i, "tag %s", &tag)) + ; else break; } @@ -10711,6 +10730,9 @@ api_create_vhost_user_if (vat_main_t * vam) } mp->use_custom_mac = use_custom_mac; clib_memcpy (mp->mac_address, hwaddr, 6); + if (tag) + strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); + vec_free (tag); S; W; @@ -16410,6 +16432,54 @@ api_feature_enable_disable (vat_main_t * vam) } static int +api_sw_interface_tag_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_tag_add_del_t *mp; + f64 timeout; + u32 sw_if_index = ~0; + u8 *tag = 0; + u8 enable = 1; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "tag %s", &tag)) + ; + if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "del")) + enable = 0; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index\n"); + return -99; + } + + if (enable && (tag == 0)) + { + errmsg ("no tag specified\n"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del); + mp->sw_if_index = ntohl (sw_if_index); + mp->is_add = enable; + if (enable) + strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); + vec_free (tag); + + S; + W; +} + +static int q_or_quit (vat_main_t * vam) { longjmp (vam->jump_buf, 1); @@ -16807,7 +16877,7 @@ _(l2_flags, \ _(bridge_flags, \ "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \ _(tap_connect, \ - "tapname <name> mac <mac-addr> | random-mac") \ + "tapname <name> mac <mac-addr> | random-mac [tag <string>]") \ _(tap_modify, \ "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \ _(tap_delete, \ @@ -17085,7 +17155,9 @@ _(flow_classify_dump, "type [ip4|ip6]") \ _(ip_fib_dump, "") \ _(ip6_fib_dump, "") \ _(feature_enable_disable, "arc_name <arc_name> " \ - "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]") + "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]") \ +_(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>" \ +"[disable]") /* List of command functions, CLI names map directly to functions */ #define foreach_cli_function \ diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index 2c0256cc34e..b5253726915 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -255,8 +255,8 @@ _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable) \ _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable) \ _(GET_NODE_GRAPH, get_node_graph) \ _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats) \ -_(IOAM_ENABLE, ioam_enable) \ -_(IOAM_DISABLE, ioam_disable) \ +_(IOAM_ENABLE, ioam_enable) \ +_(IOAM_DISABLE, ioam_disable) \ _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set) \ _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator) \ _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid) \ @@ -332,7 +332,8 @@ _(IP_FIB_DUMP, ip_fib_dump) \ _(IP_FIB_DETAILS, ip_fib_details) \ _(IP6_FIB_DUMP, ip6_fib_dump) \ _(IP6_FIB_DETAILS, ip6_fib_details) \ -_(FEATURE_ENABLE_DISABLE, feature_enable_disable) +_(FEATURE_ENABLE_DISABLE, feature_enable_disable) \ +_(SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del) #define QUOTE_(x) #x #define QUOTE(x) QUOTE_(x) @@ -1997,8 +1998,10 @@ vl_api_tap_connect_t_handler (vl_api_tap_connect_t * mp, vlib_main_t * vm) { int rv; vl_api_tap_connect_reply_t *rmp; + vnet_main_t *vnm = vnet_get_main (); unix_shared_memory_queue_t *q; u32 sw_if_index = (u32) ~ 0; + u8 *tag; rv = vnet_tap_connect_renumber (vm, mp->tap_name, mp->use_random_mac ? 0 : mp->mac_address, @@ -2009,6 +2012,14 @@ vl_api_tap_connect_t_handler (vl_api_tap_connect_t * mp, vlib_main_t * vm) if (!q) return; + /* Add tag if supplied */ + if (rv == 0 && mp->tag[0]) + { + mp->tag[ARRAY_LEN (mp->tag) - 1] = 0; + tag = format (0, "%s%c", mp->tag, 0); + vnet_set_sw_interface_tag (vnm, tag, sw_if_index); + } + rmp = vl_msg_api_alloc (sizeof (*rmp)); rmp->_vl_msg_id = ntohs (VL_API_TAP_CONNECT_REPLY); rmp->context = mp->context; @@ -2054,6 +2065,11 @@ vl_api_tap_delete_t_handler (vl_api_tap_delete_t * mp, vlib_main_t * vm) u32 sw_if_index = ntohl (mp->sw_if_index); rv = vnet_tap_delete (vm, sw_if_index); + if (!rv) + { + vnet_main_t *vnm = vnet_get_main (); + vnet_clear_sw_interface_tag (vnm, sw_if_index); + } q = vl_api_client_index_to_input_queue (mp->client_index); if (!q) @@ -2684,7 +2700,9 @@ send_sw_interface_details (vpe_api_main_t * am, u8 * interface_name, u32 context) { vl_api_sw_interface_details_t *mp; + vnet_main_t *vnm = vnet_get_main (); vnet_hw_interface_t *hi; + u8 *tag; hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index); @@ -2752,6 +2770,10 @@ send_sw_interface_details (vpe_api_main_t * am, } } + tag = vnet_get_sw_interface_tag (vnm, swif->sw_if_index); + if (tag) + strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); + vl_msg_api_send_shmem (q, (u8 *) & mp); } @@ -4020,7 +4042,6 @@ vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp) int rv = 0; vl_api_create_vhost_user_if_reply_t *rmp; u32 sw_if_index = (u32) ~ 0; - vnet_main_t *vnm = vnet_get_main (); vlib_main_t *vm = vlib_get_main (); @@ -4029,6 +4050,19 @@ vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp) mp->renumber, ntohl (mp->custom_dev_instance), (mp->use_custom_mac) ? mp->mac_address : NULL); + /* Remember an interface tag for the new interface */ + if (rv == 0) + { + /* If a tag was supplied... */ + if (mp->tag[0]) + { + /* Make sure it's a proper C-string */ + mp->tag[ARRAY_LEN (mp->tag) - 1] = 0; + u8 *tag = format (0, "%s%c", mp->tag, 0); + vnet_set_sw_interface_tag (vnm, tag, sw_if_index); + } + } + /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY, ({ @@ -4074,6 +4108,7 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp) if (!q) return; + vnet_clear_sw_interface_tag (vnm, sw_if_index); send_sw_interface_flags_deleted (vam, q, sw_if_index); } } @@ -9113,6 +9148,37 @@ vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp) REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY); } +static void vl_api_sw_interface_tag_add_del_t_handler + (vl_api_sw_interface_tag_add_del_t * mp) +{ + vnet_main_t *vnm = vnet_get_main (); + vl_api_sw_interface_tag_add_del_reply_t *rmp; + int rv = 0; + u8 *tag; + u32 sw_if_index = ntohl (mp->sw_if_index); + + VALIDATE_SW_IF_INDEX (mp); + + if (mp->is_add) + { + if (mp->tag[0] == 0) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + mp->tag[ARRAY_LEN (mp->tag) - 1] = 0; + tag = format (0, "%s%c", mp->tag, 0); + vnet_set_sw_interface_tag (vnm, tag, sw_if_index); + } + else + vnet_clear_sw_interface_tag (vnm, sw_if_index); + + BAD_SW_IF_INDEX_LABEL; +out: + REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY); +} + #define BOUNCE_HANDLER(nn) \ static void vl_api_##nn##_t_handler ( \ vl_api_##nn##_t *mp) \ diff --git a/vpp/vpp-api/custom_dump.c b/vpp/vpp-api/custom_dump.c index 28d3341de8c..a36a8a43af0 100644 --- a/vpp/vpp-api/custom_dump.c +++ b/vpp/vpp-api/custom_dump.c @@ -431,7 +431,8 @@ static void *vl_api_tap_connect_t_print s = format (s, "tapname %s ", mp->tap_name); if (mp->use_random_mac) s = format (s, "random-mac "); - + if (mp->tag[0]) + s = format (s, "tag %s ", mp->tag); if (memcmp (mp->mac_address, null_mac, 6)) s = format (s, "mac %U ", format_ethernet_address, mp->mac_address); @@ -1568,6 +1569,8 @@ static void *vl_api_create_vhost_user_if_t_print s = format (s, "server "); if (mp->renumber) s = format (s, "renumber %d ", ntohl (mp->custom_dev_instance)); + if (mp->tag[0]) + s = format (s, "tag %s", mp->tag); FINISH; } @@ -2926,6 +2929,21 @@ static void *vl_api_feature_enable_disable_t_print FINISH; } +static void *vl_api_sw_interface_tag_add_del_t_print + (vl_api_sw_interface_tag_add_del_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: sw_interface_tag_add_del "); + s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index)); + if (mp->is_add) + s = format (s, "tag %s ", mp->tag); + else + s = format (s, "del "); + + FINISH; +} + #define foreach_custom_print_no_arg_function \ _(lisp_eid_table_vni_dump) \ _(lisp_map_resolver_dump) \ @@ -3098,7 +3116,8 @@ _(IOAM_ENABLE, ioam_enable) \ _(IOAM_DISABLE, ioam_disable) \ _(IP_FIB_DUMP, ip_fib_dump) \ _(IP6_FIB_DUMP, ip6_fib_dump) \ -_(FEATURE_ENABLE_DISABLE, feature_enable_disable) +_(FEATURE_ENABLE_DISABLE, feature_enable_disable) \ +_(SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del) void vl_msg_api_custom_dump_configure (api_main_t * am) { diff --git a/vpp/vpp-api/vpe.api b/vpp/vpp-api/vpe.api index 5ab21029fd3..bcc3f4ec1b3 100644 --- a/vpp/vpp-api/vpe.api +++ b/vpp/vpp-api/vpe.api @@ -117,6 +117,7 @@ define sw_interface_details u32 vtr_push_dot1q; // ethertype of first pushed tag is dot1q/dot1ad u32 vtr_tag1; // first pushed tag u32 vtr_tag2; // second pushed tag + u8 tag[64]; }; /* works */ @@ -226,6 +227,7 @@ define tap_connect u8 mac_address[6]; u8 renumber; u32 custom_dev_instance; + u8 tag[64]; }; /** \brief Reply for tap connect request @@ -2269,6 +2271,7 @@ define create_vhost_user_if u32 custom_dev_instance; u8 use_custom_mac; u8 mac_address[6]; + u8 tag[64]; }; /** \brief vhost-user interface create response @@ -5518,3 +5521,28 @@ define feature_enable_disable_reply u32 context; i32 retval; }; + +/** \brief Set / clear software interface tag + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - the interface + @param add_del - 1 = add, 0 = delete + @param tag - an ascii tag +*/ +define sw_interface_tag_add_del { + u32 client_index; + u32 context; + u8 is_add; + u32 sw_if_index; + u8 tag[64]; +}; + +/** \brief Reply to set / clear software interface tag + @param context - sender context which was passed in the request + @param retval - return code for the request +*/ +define sw_interface_tag_add_del_reply +{ + u32 context; + i32 retval; +}; |