From e2353a7f6c680ef50bc41892a4503168406b7787 Mon Sep 17 00:00:00 2001 From: Matthew Smith Date: Thu, 6 May 2021 13:16:42 -0500 Subject: linux-cp: Add delegate to adjacencies 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 Change-Id: I072b960c02cf377d66f7d18b8c0e9e05824a0ca3 --- src/plugins/linux-cp/lcp_adj.c | 84 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/src/plugins/linux-cp/lcp_adj.c b/src/plugins/linux-cp/lcp_adj.c index 9a08591a0c1..cbeb91a75a1 100644 --- a/src/plugins/linux-cp/lcp_adj.c +++ b/src/plugins/linux-cp/lcp_adj.c @@ -20,6 +20,7 @@ #include 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 * -- cgit 1.2.3-korg