Add MAC address support to LISP map-cache 74/1774/1
authorFilip Tehlar <ftehlar@cisco.com>
Fri, 24 Jun 2016 12:16:34 +0000 (14:16 +0200)
committerFilip Tehlar <ftehlar@cisco.com>
Mon, 27 Jun 2016 11:15:39 +0000 (13:15 +0200)
Change-Id: I80f05a222cb0f728ad2460efe33955e781b6849f
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
vnet/vnet/lisp-cp/control.c
vnet/vnet/lisp-cp/gid_dictionary.c
vnet/vnet/lisp-cp/gid_dictionary.h
vnet/vnet/lisp-cp/lisp_types.c
vnet/vnet/lisp-cp/lisp_types.h

index 1e3b98f..a820b9c 100644 (file)
@@ -211,6 +211,7 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
   u8 is_add = 1;
   gid_address_t eid;
   ip_prefix_t * prefp = &gid_address_ippref(&eid);
+  u8 * mac = gid_address_mac(&eid);
   gid_address_t * eids = 0;
   clib_error_t * error = 0;
   u8 * locator_set_name = 0;
@@ -235,6 +236,12 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
         gid_address_vni (&eid) = vni;
       else if (unformat (line_input, "eid %U", unformat_ip_prefix, prefp))
         {
+          gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
+          vec_add1(eids, eid);
+        }
+      else if (unformat (line_input, "eid %U", unformat_mac_address, mac))
+        {
+          gid_address_type (&eid) = GID_ADDR_MAC;
           vec_add1(eids, eid);
         }
       else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
@@ -256,7 +263,6 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
     }
   /* XXX treat batch configuration */
 
-  gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
   a->deid = eid;
   a->is_add = is_add;
   a->locator_set_index = locator_set_index;
@@ -661,6 +667,8 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   ip_address_t rloc, * rlocs = 0;
   ip_prefix_t * deid_ippref, * seid_ippref;
   gid_address_t seid, deid;
+  u8 * dmac = gid_address_mac (&deid);
+  u8 * smac = gid_address_mac (&seid);
   u8 deid_set = 0, seid_set = 0;
   u8 * s = 0;
   u32 vni, action = ~0;
@@ -675,9 +683,6 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   seid_ippref = &gid_address_ippref(&seid);
   deid_ippref = &gid_address_ippref(&deid);
 
-  gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
-  gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
-
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat (line_input, "del-all"))
@@ -689,6 +694,13 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
       else if (unformat (line_input, "deid %U",
                          unformat_ip_prefix, deid_ippref))
         {
+          gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
+          deid_set = 1;
+        }
+      else if (unformat (line_input, "deid %U",
+                         unformat_mac_address, dmac))
+        {
+          gid_address_type (&deid) = GID_ADDR_MAC;
           deid_set = 1;
         }
       else if (unformat (line_input, "vni %u", &vni))
@@ -699,6 +711,13 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
       else if (unformat (line_input, "seid %U",
                          unformat_ip_prefix, seid_ippref))
         {
+          gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
+          seid_set = 1;
+        }
+      else if (unformat (line_input, "seid %U",
+                         unformat_mac_address, smac))
+        {
+          gid_address_type (&seid) = GID_ADDR_MAC;
           seid_set = 1;
         }
       else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc))
@@ -734,18 +753,22 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
           goto done;
         }
 
-      /* if seid not set, make sure the ip version is the same as that of the
-       * deid. This ensures the seid to be configured will be either 0/0 or
-       * ::/0 */
-      if (!seid_set)
-        ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref);
-
-      if (is_add &&
-          (ip_prefix_version (deid_ippref) != ip_prefix_version(seid_ippref)))
+      if (GID_ADDR_IP_PREFIX == gid_address_type (&deid))
         {
-          clib_warning ("source and destination EIDs are not"
-                        " in the same IP family!");
-          goto done;
+          /* if seid not set, make sure the ip version is the same as that
+           * of the deid. This ensures the seid to be configured will be
+           * either 0/0 or ::/0 */
+          if (!seid_set)
+            ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref);
+
+          if (is_add &&
+              (ip_prefix_version (deid_ippref)
+               != ip_prefix_version(seid_ippref)))
+            {
+              clib_warning ("source and destination EIDs are not"
+                            " in the same IP family!");
+              goto done;
+            }
         }
 
       if (is_add && (~0 == action)
index 3805d5a..1beac54 100644 (file)
 
 #include <vnet/lisp-cp/gid_dictionary.h>
 
+static u32
+mac_lookup (gid_dictionary_t * db, u32 vni, u8 * key)
+{
+  int rv;
+  BVT(clib_bihash_kv) kv, value;
+
+  kv.key[0] = ((u64 *)key)[0];
+  kv.key[1] = (u64)vni;
+  kv.key[2] = 0;
+
+  rv = BV(clib_bihash_search_inline_2)(&db->mac_lookup_table, &kv, &value);
+  if (rv == 0)
+    return value.value;
+
+  return GID_LOOKUP_MISS;
+}
+
 static u32
 ip4_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t *key)
 {
@@ -102,7 +119,8 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
     {
     case GID_ADDR_IP_PREFIX:
       return ip_lookup (db, gid_address_vni(key), &gid_address_ippref(key));
-      break;
+    case GID_ADDR_MAC:
+      return mac_lookup (db, gid_address_vni(key), gid_address_mac(key));
     default:
       clib_warning ("address type %d not supported!", gid_address_type(key));
       break;
@@ -238,6 +256,29 @@ add_del_ip6_key (gid_dictionary_t *db, u32 vni, ip_prefix_t *pref, u32 val,
   return old_val;
 }
 
+static u32
+add_del_mac (gid_dictionary_t * db, u32 vni, u8 * mac, u32 val, u8 is_add)
+{
+  BVT(clib_bihash_kv) kv, value;
+  u32 old_val = ~0;
+
+  kv.key[0] = ((u64 *)mac)[0];
+  kv.key[1] = (u64)vni;
+  kv.key[2] = 0;
+
+  if (BV(clib_bihash_search) (&db->mac_lookup_table, &kv, &value) == 0)
+    old_val = value.value;
+
+  if (!is_add)
+    BV(clib_bihash_add_del) (&db->mac_lookup_table, &kv, 0 /* is_add */);
+  else
+    {
+      kv.value = val;
+      BV(clib_bihash_add_del) (&db->mac_lookup_table, &kv, 1 /* is_add */);
+    }
+  return old_val;
+}
+
 static u32
 add_del_ip (gid_dictionary_t *db, u32 vni, ip_prefix_t *key, u32 value,
             u8 is_add)
@@ -267,7 +308,9 @@ gid_dictionary_add_del (gid_dictionary_t *db, gid_address_t *key, u32 value,
     case GID_ADDR_IP_PREFIX:
       return add_del_ip (db, gid_address_vni(key), &gid_address_ippref(key),
                          value, is_add);
-      break;
+    case GID_ADDR_MAC:
+      return add_del_mac (db, gid_address_vni(key), gid_address_mac(key),
+                          value, is_add);
     default:
       clib_warning ("address type %d not supported!", gid_address_type (key));
       break;
@@ -338,10 +381,27 @@ ip6_lookup_init (gid_dictionary_t * db)
                          db->ip6_lookup_table_nbuckets, db->ip6_lookup_table_size);
 }
 
+static void
+mac_lookup_init (gid_dictionary_t * db)
+{
+  if (db->mac_lookup_table_nbuckets == 0)
+    db->mac_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
+
+  db->mac_lookup_table_nbuckets = 1 << max_log2 (db->mac_lookup_table_nbuckets);
+
+  if (db->mac_lookup_table_size == 0)
+    db->mac_lookup_table_size = MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
+
+  BV(clib_bihash_init) (&db->mac_lookup_table, "mac lookup table",
+                        db->mac_lookup_table_nbuckets,
+                        db->mac_lookup_table_size);
+}
+
 void
 gid_dictionary_init (gid_dictionary_t * db)
 {
   ip4_lookup_init (db);
   ip6_lookup_init (db);
+  mac_lookup_init (db);
 }
 
index 5b1a59b..6a21cd8 100644 (file)
 #define IP6_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
 #define IP6_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20)
 
+/* Default size of the MAC hash table */
+#define MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
+#define MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20)
+
 typedef struct
 {
   BVT(clib_bihash) ip4_lookup_table;
@@ -57,6 +61,12 @@ typedef struct
   u32 ip6_lookup_table_nbuckets;
   uword ip6_lookup_table_size;
 
+  BVT(clib_bihash) mac_lookup_table;
+
+  /* mac lookup table config parameters */
+  u32 mac_lookup_table_nbuckets;
+  uword mac_lookup_table_size;
+
 } gid_dictionary_t;
 
 u32
index 11e252a..1608e09 100644 (file)
@@ -150,6 +150,22 @@ unformat_ip_prefix (unformat_input_t * input, va_list * args)
                    &ip_prefix_len(a));
 }
 
+uword
+unformat_mac_address (unformat_input_t * input, va_list * args)
+{
+  u8 * a = va_arg(*args, u8 *);
+  return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
+                   &a[4], &a[5]);
+}
+
+u8 *
+format_mac_address (u8 * s, va_list * args)
+{
+  u8 * a = va_arg (*args, u8 *);
+  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
+                 a[0], a[1], a[2], a[3], a[4], a[5]);
+}
+
 u8 *
 format_gid_address (u8 * s, va_list * args)
 {
@@ -164,6 +180,9 @@ format_gid_address (u8 * s, va_list * args)
       return format (s, "[%d] %U|%U", gid_address_vni(a),
                      format_ip_prefix, &gid_address_sd_source_pref(a),
                      format_ip_prefix, &gid_address_sd_dest_pref(a));
+    case GID_ADDR_MAC:
+      return format (s, "[%d] %U", gid_address_vni(a), format_mac_address,
+                     &gid_address_mac(a));
     default:
       clib_warning("Can't format gid type %d", type);
       return 0;
index 709d415..83655d8 100644 (file)
@@ -136,6 +136,8 @@ u8 * format_ip_address (u8 * s, va_list * args);
 uword unformat_ip_address (unformat_input_t * input, va_list * args);
 u8 * format_ip_prefix (u8 * s, va_list * args);
 uword unformat_ip_prefix (unformat_input_t * input, va_list * args);
+u8 * format_mac_address (u8 * s, va_list * args);
+uword unformat_mac_address (unformat_input_t * input, va_list * args);
 
 u16 ip4_address_size_to_put ();
 u16 ip6_address_size_to_put ();