aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2016-06-24 14:16:34 +0200
committerFilip Tehlar <ftehlar@cisco.com>2016-06-27 13:15:39 +0200
commit8e39bb402afd5908f5b2747bcbb0cc5ffd06bacf (patch)
tree043a8096267c793c790a5928ed6329fd40b14ed8
parent203c632d29fc5f5d820251e4e58ea724e1002a91 (diff)
Add MAC address support to LISP map-cache
Change-Id: I80f05a222cb0f728ad2460efe33955e781b6849f Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
-rw-r--r--vnet/vnet/lisp-cp/control.c53
-rw-r--r--vnet/vnet/lisp-cp/gid_dictionary.c64
-rw-r--r--vnet/vnet/lisp-cp/gid_dictionary.h10
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.c19
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.h2
5 files changed, 131 insertions, 17 deletions
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c
index 1e3b98ff5c6..a820b9cd28f 100644
--- a/vnet/vnet/lisp-cp/control.c
+++ b/vnet/vnet/lisp-cp/control.c
@@ -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)
diff --git a/vnet/vnet/lisp-cp/gid_dictionary.c b/vnet/vnet/lisp-cp/gid_dictionary.c
index 3805d5a8a5e..1beac54a5d8 100644
--- a/vnet/vnet/lisp-cp/gid_dictionary.c
+++ b/vnet/vnet/lisp-cp/gid_dictionary.c
@@ -16,6 +16,23 @@
#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)
{
int i, len;
@@ -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;
@@ -239,6 +257,29 @@ add_del_ip6_key (gid_dictionary_t *db, u32 vni, ip_prefix_t *pref, u32 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);
}
diff --git a/vnet/vnet/lisp-cp/gid_dictionary.h b/vnet/vnet/lisp-cp/gid_dictionary.h
index 5b1a59b0161..6a21cd82c18 100644
--- a/vnet/vnet/lisp-cp/gid_dictionary.h
+++ b/vnet/vnet/lisp-cp/gid_dictionary.h
@@ -31,6 +31,10 @@
#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
diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c
index 11e252aac54..1608e094f60 100644
--- a/vnet/vnet/lisp-cp/lisp_types.c
+++ b/vnet/vnet/lisp-cp/lisp_types.c
@@ -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;
diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h
index 709d415deca..83655d8db9a 100644
--- a/vnet/vnet/lisp-cp/lisp_types.h
+++ b/vnet/vnet/lisp-cp/lisp_types.h
@@ -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 ();