fib: refresh adj pointer after fib_walk_sync due to possible realloc
[vpp.git] / src / vnet / adj / adj_nbr.c
index c043bd5..758be3b 100644 (file)
@@ -344,7 +344,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
                                 u8 *rewrite)
 {
     ip_adjacency_t *walk_adj;
-    adj_index_t walk_ai;
+    adj_index_t walk_ai, ai;
     vlib_main_t * vm;
     u32 old_next;
     int do_walk;
@@ -352,7 +352,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
     vm = vlib_get_main();
     old_next = adj->lookup_next_index;
 
-    walk_ai = adj_get_index(adj);
+    ai = walk_ai = adj_get_index(adj);
     if (VNET_LINK_MPLS == adj->ia_link)
     {
         /*
@@ -396,7 +396,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
      * DPO, this adj will no longer be in use and its lock count will drop to 0.
      * We don't want it to be deleted as part of this endeavour.
      */
-    adj_lock(adj_get_index(adj));
+    adj_lock(ai);
     adj_lock(walk_ai);
 
     /*
@@ -449,6 +449,12 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
        };
 
        fib_walk_sync(FIB_NODE_TYPE_ADJ, walk_ai, &bw_ctx);
+       /*
+        * fib_walk_sync may allocate a new adjacency and potentially cuase a realloc
+        * for adj_pool. When that happens, adj pointer is no longer valid here.
+        * We refresh the adj pointer accordingly.
+        */
+       adj = adj_get (ai);
     }
 
     /*
@@ -507,10 +513,11 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
      */
     if (do_walk)
     {
+        walk_adj = adj_get(walk_ai);
         walk_adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
     }
 
-    adj_unlock(adj_get_index(adj));
+    adj_unlock(ai);
     adj_unlock(walk_ai);
 }