fib: Safe adj walk 44/27344/2
authorNeale Ranns <nranns@cisco.com>
Fri, 29 May 2020 14:19:41 +0000 (10:19 -0400)
committerFlorin Coras <florin.coras@gmail.com>
Fri, 29 May 2020 20:27:06 +0000 (20:27 +0000)
Type: fix

the hash walk does not give the same guarantees as the bihash so
walk in a safe manner.

Change-Id: Idfe48c3a84ab3a341d887f7d196bc81ba34ae8b0
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/vnet/adj/adj_nbr.c

index 55c76bd..78bf6df 100644 (file)
@@ -554,21 +554,28 @@ adj_nbr_walk (u32 sw_if_index,
              adj_walk_cb_t cb,
              void *ctx)
 {
+    adj_index_t ai, *ais, *aip;
     adj_nbr_key_t *key;
-    adj_index_t ai;
 
     if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
        return;
 
-    if (adj_nbr_tables[adj_nh_proto][sw_if_index] ||
-        hash_elts(adj_nbr_tables[adj_nh_proto][sw_if_index]))
+    ais = NULL;
+
+    /* elements may be removed from the table during the walk, so
+     * collect the set first then process them */
+    hash_foreach_mem (key, ai, adj_nbr_tables[adj_nh_proto][sw_if_index],
+    ({
+        vec_add1(ais, ai);
+    }));
+
+    vec_foreach(aip, ais)
     {
-        hash_foreach_mem (key, ai, adj_nbr_tables[adj_nh_proto][sw_if_index],
-        ({
-            ASSERT(key);
-            cb(ai, ctx);
-        }));
+        /* An adj may be deleted during the walk so check first */
+        if (!pool_is_free_index(adj_pool, *aip))
+            cb(*aip, ctx);
     }
+    vec_free(ais);
 }
 
 /**