aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/lisp-cp/gid_dictionary.c
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2017-05-17 17:21:10 +0200
committerFilip Tehlar <ftehlar@cisco.com>2017-05-30 07:18:54 +0200
commitd5a65db98d66c66b03b057ac568be05f2456f73c (patch)
tree8c8c5f14cf8402345e30f24c2491f144e96c8f9b /src/vnet/lisp-cp/gid_dictionary.c
parentcd76436097b9ddda76864af33c85aec9bab074a3 (diff)
LISP: L2 ARP handling
Change-Id: I1ec328cda73f7eaf7867cd8a2a17852ee0cd23f1 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'src/vnet/lisp-cp/gid_dictionary.c')
-rw-r--r--src/vnet/lisp-cp/gid_dictionary.c91
1 files changed, 86 insertions, 5 deletions
diff --git a/src/vnet/lisp-cp/gid_dictionary.c b/src/vnet/lisp-cp/gid_dictionary.c
index b01bb0e0..80d59faf 100644
--- a/src/vnet/lisp-cp/gid_dictionary.c
+++ b/src/vnet/lisp-cp/gid_dictionary.c
@@ -138,6 +138,15 @@ gid_dict_foreach_subprefix (gid_dictionary_t * db, gid_address_t * eid,
arg);
}
+void
+gid_dict_foreach_l2_arp_entry (gid_dictionary_t * db, void (*cb)
+ (BVT (clib_bihash_kv) * kvp, void *arg),
+ void *ht)
+{
+ gid_l2_arp_table_t *tab = &db->arp_table;
+ BV (clib_bihash_foreach_key_value_pair) (&tab->arp_lookup_table, cb, ht);
+}
+
static void
make_mac_sd_key (BVT (clib_bihash_kv) * kv, u32 vni, u8 src_mac[6],
u8 dst_mac[6])
@@ -328,7 +337,30 @@ ip_sd_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst,
return GID_LOOKUP_MISS;
}
-u32
+static void
+make_arp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip4_address_t * addr)
+{
+ kv->key[0] = (u64) bd;
+ kv->key[1] = (u64) addr->as_u32;
+ kv->key[2] = (u64) 0;
+}
+
+static u64
+arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key)
+{
+ int rv;
+ BVT (clib_bihash_kv) kv, value;
+
+ make_arp_key (&kv, bd, key);
+ rv = BV (clib_bihash_search_inline_2) (&db->arp_lookup_table, &kv, &value);
+
+ if (rv == 0)
+ return value.value;
+
+ return GID_LOOKUP_MISS_L2;
+}
+
+u64
gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
{
switch (gid_address_type (key))
@@ -358,6 +390,9 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
break;
}
break;
+ case GID_ADDR_ARP:
+ return arp_lookup (&db->arp_table, gid_address_arp_bd (key),
+ &gid_address_arp_ip4 (key));
default:
clib_warning ("address type %d not supported!", gid_address_type (key));
break;
@@ -825,21 +860,49 @@ add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value,
return ~0;
}
+static u32
+add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value,
+ u8 is_add)
+{
+ BVT (clib_bihash_kv) kv, result;
+ u32 old_val = ~0;
+
+ make_arp_key (&kv, bd, key);
+ if (BV (clib_bihash_search) (&db->arp_lookup_table, &kv, &result) == 0)
+ old_val = result.value;
+
+ if (is_add)
+ {
+ kv.value = value;
+ BV (clib_bihash_add_del) (&db->arp_lookup_table, &kv, 1 /* is_add */ );
+ db->count++;
+ }
+ else
+ {
+ BV (clib_bihash_add_del) (&db->arp_lookup_table, &kv, 0 /* is_add */ );
+ db->count--;
+ }
+ return old_val;
+}
+
u32
-gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value,
+gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value,
u8 is_add)
{
switch (gid_address_type (key))
{
case GID_ADDR_IP_PREFIX:
return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key),
- 0, value, is_add);
+ 0, (u32) value, is_add);
case GID_ADDR_MAC:
return add_del_mac (&db->sd_mac_table, gid_address_vni (key),
- gid_address_mac (key), 0, value, is_add);
+ gid_address_mac (key), 0, (u32) value, is_add);
case GID_ADDR_SRC_DST:
return add_del_sd (db, gid_address_vni (key), &gid_address_sd (key),
- value, is_add);
+ (u32) value, is_add);
+ case GID_ADDR_ARP:
+ return add_del_arp (&db->arp_table, gid_address_arp_bd (key),
+ &gid_address_arp_ip4 (key), value, is_add);
default:
clib_warning ("address type %d not supported!", gid_address_type (key));
break;
@@ -864,12 +927,30 @@ mac_lookup_init (gid_mac_table_t * db)
db->mac_lookup_table_size);
}
+static void
+arp_lookup_init (gid_l2_arp_table_t * db)
+{
+ if (db->arp_lookup_table_nbuckets == 0)
+ db->arp_lookup_table_nbuckets = ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
+
+ db->arp_lookup_table_nbuckets =
+ 1 << max_log2 (db->arp_lookup_table_nbuckets);
+
+ if (db->arp_lookup_table_size == 0)
+ db->arp_lookup_table_size = ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
+
+ BV (clib_bihash_init) (&db->arp_lookup_table, "arp lookup table",
+ db->arp_lookup_table_nbuckets,
+ db->arp_lookup_table_size);
+}
+
void
gid_dictionary_init (gid_dictionary_t * db)
{
ip4_lookup_init (&db->dst_ip4_table);
ip6_lookup_init (&db->dst_ip6_table);
mac_lookup_init (&db->sd_mac_table);
+ arp_lookup_init (&db->arp_table);
}
/*