MAP: Add optional user-supplied 'tag' field in MAPs. 04/18304/3
authorJon Loeliger <jdl@netgate.com>
Tue, 12 Mar 2019 18:09:08 +0000 (13:09 -0500)
committerOle Trøan <otroan@employees.org>
Tue, 19 Mar 2019 20:44:34 +0000 (20:44 +0000)
Like other entities, allow an arbitrray user-supplied 'tag'
field to be place on created MAP domains.  It is also later
returned with the MAP details.  You might be thinking "User
assigned MAP name" here.

As the MAP domain structure was at the limit of a cacheline size,
introduce a parallel "extra data" vector with non-essential domain
information in it.

Change-Id: Icc12b64cc4cb3e040c9a475908b19f6abaf4c293
Signed-off-by: Jon Loeliger <jdl@netgate.com>
src/plugins/map/map.api
src/plugins/map/map.c
src/plugins/map/map.h
src/plugins/map/map_api.c

index f64fe4c..74133c9 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-option version = "3.0.0";
+option version = "3.1.0";
 
 import "vnet/ip/ip_types.api";
 
@@ -27,6 +27,7 @@ import "vnet/ip/ip_types.api";
     @param psid_offset - Port Set Identifider (PSID) offset
     @param psid_length - PSID length
     @param mtu - MTU
+    @param tag - A user field stored with the MAP
 */
 define map_add_domain
 {
@@ -39,6 +40,7 @@ define map_add_domain
   u8 psid_offset;
   u8 psid_length;
   u16 mtu;
+  string tag;
 };
 
 /** \brief Reply for MAP domain add
@@ -94,6 +96,19 @@ define map_domain_dump
   u32 context;
 };
 
+/** \brief Details about a single MAP domain
+    @param context - returned sender context, to match reply w/ request
+    @param domain_index - MAP domain index
+    @param ip6_prefix - Rule IPv6 prefix
+    @param ip4_prefix - Rule IPv4 prefix
+    @param ip6_src - MAP domain IPv6 BR address / Tunnel source
+    @param ea_bits_len - Embedded Address bits length
+    @param psid_offset - Port Set Identifider (PSID) offset
+    @param psid_length - PSID length
+    @param flags -
+    @param mtu - MTU
+    @param tag - The user field stored with the MAP at creation time
+*/
 define map_domain_details
 {
   u32 context;
@@ -106,6 +121,7 @@ define map_domain_details
   u8 psid_length;
   u8 flags;
   u16 mtu;
+  string tag;
 };
 
 define map_rule_dump
index d77b141..a535442 100644 (file)
@@ -59,6 +59,52 @@ map_main_t map_main;
  */
 
 
+/*
+ * Save usre-assigned MAP domain names ("tags") in a vector of
+ * extra domain information.
+ */
+static void
+map_save_extras (u32 map_domain_index, char *tag)
+{
+  map_main_t *mm = &map_main;
+  map_domain_extra_t *de;
+  u32 len;
+
+  if (map_domain_index == ~0)
+    return;
+
+  vec_validate (mm->domain_extras, map_domain_index);
+  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
+  clib_memset (de, 0, sizeof (*de));
+
+  if (!tag)
+    return;
+
+  len = strlen (tag) + 1;
+  de->tag = clib_mem_alloc (len);
+  clib_memcpy (de->tag, tag, len);
+}
+
+
+static void
+map_free_extras (u32 map_domain_index)
+{
+  map_main_t *mm = &map_main;
+  map_domain_extra_t *de;
+  char *tag;
+
+  if (map_domain_index == ~0)
+    return;
+
+  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
+  tag = de->tag;
+  if (!tag)
+    return;
+
+  clib_mem_free (tag);
+  de->tag = 0;
+}
+
 
 int
 map_create_domain (ip4_address_t * ip4_prefix,
@@ -69,7 +115,8 @@ map_create_domain (ip4_address_t * ip4_prefix,
                   u8 ip6_src_len,
                   u8 ea_bits_len,
                   u8 psid_offset,
-                  u8 psid_length, u32 * map_domain_index, u16 mtu, u8 flags)
+                  u8 psid_length,
+                  u32 * map_domain_index, u16 mtu, u8 flags, char *tag)
 {
   u8 suffix_len, suffix_shift;
   map_main_t *mm = &map_main;
@@ -122,6 +169,10 @@ map_create_domain (ip4_address_t * ip4_prefix,
   d->psid_mask = (1 << d->psid_length) - 1;
   d->ea_shift = 64 - ip6_prefix_len - suffix_len - d->psid_length;
 
+  /* Save a user-assigned MAP domain name if provided. */
+  if (tag)
+    map_save_extras (*map_domain_index, tag);
+
   /* MAP longest match lookup table (input feature / FIB) */
   mm->ip4_prefix_tbl->add (mm->ip4_prefix_tbl, &d->ip4_prefix,
                           d->ip4_prefix_len, *map_domain_index);
@@ -173,6 +224,9 @@ map_delete_domain (u32 map_domain_index)
   mm->ip6_src_prefix_tbl->delete (mm->ip6_src_prefix_tbl, &d->ip6_src,
                                  d->ip6_src_len);
 
+  /* Release user-assigned MAP domain name. */
+  map_free_extras (map_domain_index);
+
   /* Deleting rules */
   if (d->rules)
     clib_mem_free (d->rules);
@@ -476,6 +530,7 @@ map_add_domain_command_fn (vlib_main_t * vm,
   u32 ea_bits_len = 0, psid_offset = 0, psid_length = 0;
   u32 mtu = 0;
   u8 flags = 0;
+  u8 *tag = 0;
   ip6_src_len = 128;
   clib_error_t *error = NULL;
 
@@ -511,6 +566,8 @@ map_add_domain_command_fn (vlib_main_t * vm,
        num_m_args++;
       else if (unformat (line_input, "mtu %d", &mtu))
        num_m_args++;
+      else if (unformat (line_input, "tag %s", &tag))
+       ;
       else
        {
          error = clib_error_return (0, "unknown input `%U'",
@@ -528,7 +585,7 @@ map_add_domain_command_fn (vlib_main_t * vm,
   map_create_domain (&ip4_prefix, ip4_prefix_len,
                     &ip6_prefix, ip6_prefix_len, &ip6_src, ip6_src_len,
                     ea_bits_len, psid_offset, psid_length, &map_domain_index,
-                    mtu, flags);
+                    mtu, flags, (char *) tag);
 
 done:
   unformat_free (line_input);
@@ -870,16 +927,20 @@ format_map_domain (u8 * s, va_list * args)
   bool counters = va_arg (*args, int);
   map_main_t *mm = &map_main;
   ip6_address_t ip6_prefix;
+  u32 map_domain_index = d - mm->domains;
+  map_domain_extra_t *de;
 
   if (d->rules)
     clib_memset (&ip6_prefix, 0, sizeof (ip6_prefix));
   else
     ip6_prefix = d->ip6_prefix;
 
+  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
+
   s = format (s,
-             "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea-bits-len %d "
-             "psid-offset %d psid-len %d mtu %d %s",
-             d - mm->domains,
+             "[%d] tag {%s} ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d "
+             "ea-bits-len %d psid-offset %d psid-len %d mtu %d %s",
+             map_domain_index, de->tag,
              format_ip4_address, &d->ip4_prefix, d->ip4_prefix_len,
              format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
              format_ip6_address, &d->ip6_src, d->ip6_src_len,
@@ -891,10 +952,10 @@ format_map_domain (u8 * s, va_list * args)
       map_domain_counter_lock (mm);
       vlib_counter_t v;
       vlib_get_combined_counter (&mm->domain_counters[MAP_DOMAIN_COUNTER_TX],
-                                d - mm->domains, &v);
+                                map_domain_index, &v);
       s = format (s, "  TX: %lld/%lld", v.packets, v.bytes);
       vlib_get_combined_counter (&mm->domain_counters[MAP_DOMAIN_COUNTER_RX],
-                                d - mm->domains, &v);
+                                map_domain_index, &v);
       s = format (s, "  RX: %lld/%lld", v.packets, v.bytes);
       map_domain_counter_unlock (mm);
     }
@@ -2078,7 +2139,8 @@ VLIB_CLI_COMMAND(map_fragment_command, static) = {
  ?*/
 VLIB_CLI_COMMAND(map_add_domain_command, static) = {
   .path = "map add domain",
-  .short_help = "map add domain ip4-pfx <ip4-pfx> ip6-pfx <ip6-pfx> "
+  .short_help = "map add domain [tag <tag>] ip4-pfx <ip4-pfx> "
+      "ip6-pfx <ip6-pfx> "
       "ip6-src <ip6-pfx> ea-bits-len <n> psid-offset <n> psid-len <n> "
       "[map-t] [mtu <mtu>]",
   .function = map_add_domain_command_fn,
index 22ab719..a692b64 100644 (file)
@@ -36,7 +36,7 @@ int map_create_domain (ip4_address_t * ip4_prefix, u8 ip4_prefix_len,
                       ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
                       ip6_address_t * ip6_src, u8 ip6_src_len,
                       u8 ea_bits_len, u8 psid_offset, u8 psid_length,
-                      u32 * map_domain_index, u16 mtu, u8 flags);
+                      u32 * map_domain_index, u16 mtu, u8 flags, char *tag);
 int map_delete_domain (u32 map_domain_index);
 int map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t * tep,
                      bool is_add);
@@ -97,7 +97,8 @@ typedef enum
 
 /*
  * This structure _MUST_ be no larger than a single cache line (64 bytes).
- * If more space is needed make a union of ip6_prefix and *rules, those are mutually exclusive.
+ * If more space is needed make a union of ip6_prefix and *rules, as
+ * those are mutually exclusive.
  */
 typedef struct
 {
@@ -129,6 +130,16 @@ typedef struct
 STATIC_ASSERT ((sizeof (map_domain_t) <= CLIB_CACHE_LINE_BYTES),
               "MAP domain fits in one cacheline");
 
+/*
+ * Extra data about a domain that doesn't need to be time/space critical.
+ * This structure is in a vector parallel to the main map_domain_t,
+ * and indexed by the same map-domain-index values.
+ */
+typedef struct
+{
+  char *tag;                   /* Probably a user-assigned domain name. */
+} map_domain_extra_t;
+
 #define MAP_REASS_INDEX_NONE ((u16)0xffff)
 
 /*
@@ -251,6 +262,7 @@ extern map_main_pre_resolved_t pre_resolved[FIB_PROTOCOL_MAX];
 typedef struct {
   /* pool of MAP domains */
   map_domain_t *domains;
+  map_domain_extra_t *domain_extras;
 
   /* MAP Domain packet/byte counters indexed by map domain index */
   vlib_simple_counter_main_t *simple_domain_counters;
index b4f1467..92abecd 100644 (file)
@@ -53,6 +53,16 @@ vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
   int rv = 0;
   u32 index;
   u8 flags = 0;
+  char *tag = 0;
+  u32 len;
+
+  len = ntohl (mp->tag.length);
+  if (len > 0)
+    {
+      tag = clib_mem_alloc (len + 1);
+      clib_memcpy (tag, (char *) mp->tag.buf, len);
+      tag[len] = 0;
+    }
 
   rv =
     map_create_domain ((ip4_address_t *) & mp->ip4_prefix.prefix,
@@ -61,7 +71,10 @@ vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
                       mp->ip6_prefix.len,
                       (ip6_address_t *) & mp->ip6_src.prefix,
                       mp->ip6_src.len, mp->ea_bits_len, mp->psid_offset,
-                      mp->psid_length, &index, ntohs (mp->mtu), flags);
+                      mp->psid_length, &index, ntohs (mp->mtu), flags, tag);
+
+  if (tag)
+    clib_mem_free (tag);
 
   /* *INDENT-OFF* */
   REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
@@ -103,7 +116,9 @@ vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
   vl_api_map_domain_details_t *rmp;
   map_main_t *mm = &map_main;
   map_domain_t *d;
+  map_domain_extra_t *de;
   vl_api_registration_t *reg;
+  u32 map_domain_index;
 
   if (pool_elts (mm->domains) == 0)
     return;
@@ -115,11 +130,21 @@ vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
   /* *INDENT-OFF* */
   pool_foreach(d, mm->domains,
   ({
+    u32 len;
+
+    map_domain_index = d - mm->domains;
+    de = vec_elt_at_index(mm->domain_extras, map_domain_index);
+
+    len = 0;
+    if (de->tag)
+      len = strlen(de->tag);
+
     /* Make sure every field is initiated (or don't skip the clib_memset()) */
-    rmp = vl_msg_api_alloc (sizeof (*rmp));
+    rmp = vl_msg_api_alloc (sizeof (*rmp) + sizeof(rmp->tag.length) + len);
+
     rmp->_vl_msg_id = htons(VL_API_MAP_DOMAIN_DETAILS + mm->msg_id_base);
     rmp->context = mp->context;
-    rmp->domain_index = htonl(d - mm->domains);
+    rmp->domain_index = htonl(map_domain_index);
     clib_memcpy(&rmp->ip6_prefix.prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix.prefix));
     clib_memcpy(&rmp->ip4_prefix.prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix.prefix));
     clib_memcpy(&rmp->ip6_src.prefix, &d->ip6_src, sizeof(rmp->ip6_src.prefix));
@@ -132,6 +157,12 @@ vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
     rmp->flags = d->flags;
     rmp->mtu = htons(d->mtu);
 
+    if (de->tag)
+      {
+       rmp->tag.length = htonl (len);
+       clib_memcpy ((char *)rmp->tag.buf, de->tag, len);
+      }
+
     vl_api_send_msg (reg, (u8 *) rmp);
   }));
   /* *INDENT-ON* */