Add a 64-byte interface "tag" for vhost and tap interfaces 80/3980/7
authorDave Barach <dave@barachs.net>
Mon, 28 Nov 2016 16:41:35 +0000 (11:41 -0500)
committerDave Wallace <dwallacelf@gmail.com>
Thu, 1 Dec 2016 22:27:31 +0000 (22:27 +0000)
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>
vnet/vnet/interface.c
vnet/vnet/interface_cli.c
vnet/vnet/interface_funcs.h
vnet/vnet/vnet.h
vpp-api-test/vat/api_format.c
vpp/vpp-api/api.c
vpp/vpp-api/custom_dump.c
vpp/vpp-api/vpe.api

index e552733..6e3d7f2 100644 (file)
@@ -1202,6 +1202,7 @@ vnet_interface_init (vlib_main_t * vm)
 
     return error;
   }
 
     return error;
   }
+  vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword));
 }
 
 VLIB_INIT_FUNCTION (vnet_interface_init);
 }
 
 VLIB_INIT_FUNCTION (vnet_interface_init);
index 1c15eb1..7dbee86 100644 (file)
@@ -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;
   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)
     {
 
   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;
        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'",
       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 (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;
     }
       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);
 
   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* */
 
 };
 /* *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
  *
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 17c677f..a488599 100644 (file)
@@ -92,6 +92,44 @@ vnet_get_device_class (vnet_main_t * vnm, u32 dev_class_index)
                           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
  */
 /**
  * Call back walk type for walking SW indices on a HW interface
  */
index 36cdddd..5a8ae85 100644 (file)
@@ -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];
 
     _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
   /*
    * Last "api" error, preserved so we can issue reasonable diagnostics
    * at or near the top of the food chain
index 448ae75..958f75f 100644 (file)
@@ -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)                                           \
 _(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          \
 
 #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)                                     \
 _(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 */
 
 
 /* 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 random_mac = 1;
   u8 name_set = 0;
   u8 *tap_name;
+  u8 *tag = 0;
 
   memset (mac_address, 0, sizeof (mac_address));
 
 
   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;
        random_mac = 1;
       else if (unformat (i, "tapname %s", &tap_name))
        name_set = 1;
+      else if (unformat (i, "tag %s", &tag));
       else
        break;
     }
       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");
   if (vec_len (tap_name) > 63)
     {
       errmsg ("tap name too long\n");
+      return -99;
     }
   vec_add1 (tap_name, 0);
 
     }
   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));
   /* 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 (tap_name);
+  vec_free (tag);
 
   /* send it... */
   S;
 
   /* 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;
   u32 custom_dev_instance = ~0;
   u8 hwaddr[6];
   u8 use_custom_mac = 0;
+  u8 *tag = 0;
 
   /* Shut up coverity */
   memset (hwaddr, 0, sizeof (hwaddr));
 
   /* 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;
        use_custom_mac = 1;
       else if (unformat (i, "server"))
        is_server = 1;
+      else if (unformat (i, "tag %s", &tag))
+       ;
       else
        break;
     }
       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);
     }
   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;
 
   S;
   W;
@@ -16409,6 +16431,54 @@ api_feature_enable_disable (vat_main_t * vam)
   W;
 }
 
   W;
 }
 
+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)
 {
 static int
 q_or_quit (vat_main_t * vam)
 {
@@ -16807,7 +16877,7 @@ _(l2_flags,                                                             \
 _(bridge_flags,                                                         \
   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
 _(tap_connect,                                                          \
 _(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,                                                           \
 _(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> "                        \
 _(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                                    \
 
 /* List of command functions, CLI names map directly to functions */
 #define foreach_cli_function                                    \
index 2c0256c..b525372 100644 (file)
@@ -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)                   \
 _(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)                       \
 _(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)                                     \
 _(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)
 
 #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;
 {
   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;
   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,
 
   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;
 
   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;
   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);
   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)
 
   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;
                           u8 * interface_name, u32 context)
 {
   vl_api_sw_interface_details_t *mp;
+  vnet_main_t *vnm = vnet_get_main ();
   vnet_hw_interface_t *hi;
   vnet_hw_interface_t *hi;
+  u8 *tag;
 
   hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
 
 
   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);
 }
 
   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;
   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 ();
 
   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);
 
                             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,
   ({
   /* *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;
 
       if (!q)
        return;
 
+      vnet_clear_sw_interface_tag (vnm, sw_if_index);
       send_sw_interface_flags_deleted (vam, q, 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);
 }
 
   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)                                                \
 #define BOUNCE_HANDLER(nn)                                              \
 static void vl_api_##nn##_t_handler (                                   \
     vl_api_##nn##_t *mp)                                                \
index 28d3341..a36a8a4 100644 (file)
@@ -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 ");
   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);
 
   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));
     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;
 }
 
   FINISH;
 }
@@ -2926,6 +2929,21 @@ static void *vl_api_feature_enable_disable_t_print
   FINISH;
 }
 
   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)                                               \
 #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)                                           \
 _(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)
 {
   void
 vl_msg_api_custom_dump_configure (api_main_t * am)
 {
index 5ab2102..bcc3f4e 100644 (file)
@@ -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
   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 */
 };
 
 /* works */
@@ -226,6 +227,7 @@ define tap_connect
   u8 mac_address[6];
   u8 renumber;
   u32 custom_dev_instance;
   u8 mac_address[6];
   u8 renumber;
   u32 custom_dev_instance;
+  u8 tag[64];
 };
 
 /** \brief Reply for tap connect request
 };
 
 /** \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];
   u32 custom_dev_instance;
   u8 use_custom_mac;
   u8 mac_address[6];
+  u8 tag[64];
 };
 
 /** \brief vhost-user interface create response
 };
 
 /** \brief vhost-user interface create response
@@ -5518,3 +5521,28 @@ define feature_enable_disable_reply
     u32 context;
     i32 retval;
 };
     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;
+};