linux-cp: Add delegate to adjacencies 55/32255/2
authorMatthew Smith <mgsmith@netgate.com>
Thu, 6 May 2021 18:16:42 +0000 (13:16 -0500)
committerNeale Ranns <neale@graphiant.com>
Fri, 21 May 2021 11:51:38 +0000 (11:51 +0000)
Type: improvement

When an adjacency is created, add the linux-cp delegate on the new
adjacency so we can later deal with modifications & deletions in our
cache of adjacency data.

Add a pool of hash keys and associate the pool index for a particular
key with the adj_delegate_t. If the rewrite on an adjacency is changed,
this will allow us to delete the old hash table entry and it will not
become orphaned.

Signed-off-by: Matthew Smith <mgsmith@netgate.com>
Change-Id: I072b960c02cf377d66f7d18b8c0e9e05824a0ca3

src/plugins/linux-cp/lcp_adj.c

index 9a08591..cbeb91a 100644 (file)
@@ -20,6 +20,7 @@
 #include <vppinfra/bihash_template.c>
 
 static adj_delegate_type_t adj_type;
+static lcp_adj_key_t *adj_keys;
 
 /**
  * The table of adjacencies indexed by the rewrite string
@@ -50,23 +51,79 @@ lcp_adj_delegate_adj_deleted (adj_delegate_t *aed)
   lcp_adj_mk_key_adj (adj, &kv.k);
 
   BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 0);
+
+  if (aed->ad_index != INDEX_INVALID)
+    pool_put_index (adj_keys, aed->ad_index);
 }
 
+/* when an adj is modified:
+ *
+ * An existing hash entry may need to be deleted. This may occur when:
+ * * The newly modified adj does not have IP_LOOKUP_NEXT_REWRITE as next idx
+ * * The rewrite (== major component of hash key) changed
+ *
+ * A new hash entry may need to be added. This may occur when:
+ * * The newly modified adj has IP_LOOKUP_NEXT_REWRITE as next idx
+ * * The rewrite changed or there was no existing hash entry
+ */
 static void
 lcp_adj_delegate_adj_modified (adj_delegate_t *aed)
 {
   ip_adjacency_t *adj;
   lcp_adj_kv_t kv;
+  lcp_adj_key_t *adj_key = NULL;
+  u8 save_adj, key_changed;
+
+  key_changed = 0;
 
   adj = adj_get (aed->ad_adj_index);
+  save_adj = (IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index);
 
-  if (IP_LOOKUP_NEXT_REWRITE != adj->lookup_next_index)
-    return;
+  if (aed->ad_index != INDEX_INVALID)
+    adj_key = pool_elt_at_index (adj_keys, aed->ad_index);
 
-  lcp_adj_mk_key_adj (adj, &kv.k);
-  kv.v = aed->ad_adj_index;
+  /* return if there was no stored adj and we will not add one */
+  if (!adj_key && !save_adj)
+    return;
 
-  BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 1);
+  /* build kv if a new entry should be stored */
+  if (save_adj)
+    {
+      lcp_adj_mk_key_adj (adj, &kv.k);
+      kv.v = aed->ad_adj_index;
+      if (adj_key)
+       key_changed = (clib_memcmp (adj_key, &kv.k, sizeof (*adj_key)) != 0);
+    }
+
+  /* delete old entry if needed */
+  if (adj_key && ((save_adj && key_changed) || (!save_adj)))
+    {
+      lcp_adj_kv_t old_kv;
+
+      clib_memcpy_fast (&old_kv.k, adj_key, sizeof (*adj_key));
+      old_kv.v = 0;
+
+      BV (clib_bihash_add_del) (&lcp_adj_tbl, &old_kv.kv, 0);
+
+      if (!save_adj)
+       {
+         pool_put (adj_keys, adj_key);
+         aed->ad_index = INDEX_INVALID;
+       }
+    }
+
+  /* add new entry if needed */
+  if (save_adj)
+    {
+      BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 1);
+
+      if (!adj_key)
+       {
+         pool_get (adj_keys, adj_key);
+         aed->ad_index = adj_key - adj_keys;
+       }
+      clib_memcpy_fast (adj_key, &kv.k, sizeof (*adj_key));
+    }
 }
 
 static void
@@ -74,16 +131,23 @@ lcp_adj_delegate_adj_created (adj_index_t ai)
 {
   ip_adjacency_t *adj;
   lcp_adj_kv_t kv;
+  index_t lai = INDEX_INVALID;
+  lcp_adj_key_t *adj_key;
 
   adj = adj_get (ai);
 
-  if (IP_LOOKUP_NEXT_REWRITE != adj->lookup_next_index)
-    return;
+  if (IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index)
+    {
+      lcp_adj_mk_key_adj (adj, &kv.k);
+      pool_get (adj_keys, adj_key);
+      clib_memcpy_fast (adj_key, &kv.k, sizeof (*adj_key));
+      kv.v = ai;
 
-  lcp_adj_mk_key_adj (adj, &kv.k);
-  kv.v = ai;
+      BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 1);
+      lai = adj_key - adj_keys;
+    }
 
-  BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 1);
+  adj_delegate_add (adj, adj_type, lai);
 }
 
 u8 *