diff options
-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; +}; |