From 8e39bb402afd5908f5b2747bcbb0cc5ffd06bacf Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Fri, 24 Jun 2016 14:16:34 +0200 Subject: [PATCH] Add MAC address support to LISP map-cache Change-Id: I80f05a222cb0f728ad2460efe33955e781b6849f Signed-off-by: Filip Tehlar --- vnet/vnet/lisp-cp/control.c | 53 ++++++++++++++++++++++--------- vnet/vnet/lisp-cp/gid_dictionary.c | 64 ++++++++++++++++++++++++++++++++++++-- vnet/vnet/lisp-cp/gid_dictionary.h | 10 ++++++ vnet/vnet/lisp-cp/lisp_types.c | 19 +++++++++++ vnet/vnet/lisp-cp/lisp_types.h | 2 ++ 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 @@ -15,6 +15,23 @@ #include +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); } 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 (); -- 2.16.6