diff options
Diffstat (limited to 'src/vnet/fib/fib_walk.c')
-rw-r--r-- | src/vnet/fib/fib_walk.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/src/vnet/fib/fib_walk.c b/src/vnet/fib/fib_walk.c index c570476d130..701801370b1 100644 --- a/src/vnet/fib/fib_walk.c +++ b/src/vnet/fib/fib_walk.c @@ -322,10 +322,10 @@ typedef enum fib_walk_advance_rc_t_ static fib_walk_advance_rc_t fib_walk_advance (fib_node_index_t fwi) { - fib_node_back_walk_ctx_t *ctx, *old; fib_node_back_walk_rc_t wrc; fib_node_ptr_t sibling; fib_walk_t *fwalk; + uint n_ctxs, ii; int more_elts; /* @@ -339,12 +339,20 @@ fib_walk_advance (fib_node_index_t fwi) if (more_elts) { - old = fwalk->fw_ctx; - vec_foreach(ctx, fwalk->fw_ctx) - { - wrc = fib_node_back_walk_one(&sibling, ctx); + /* + * loop through the backwalk contexts. This can grow in length + * as walks on the same object meet each other. Order is preserved so the + * most recently started walk as at the back of the vector. + */ + ii = 0; + n_ctxs = vec_len(fwalk->fw_ctx); + + while (ii < n_ctxs) + { + wrc = fib_node_back_walk_one(&sibling, &fwalk->fw_ctx[ii]); + ii++; fwalk = fib_walk_get(fwi); fwalk->fw_n_visits++; @@ -356,14 +364,11 @@ fib_walk_advance (fib_node_index_t fwi) */ return (FIB_WALK_ADVANCE_MERGE); } - if (old != fwalk->fw_ctx) - { - /* - * nasty re-entrant addition of a walk has realloc'd the vector - * break out - */ - return (FIB_WALK_ADVANCE_MERGE); - } + + /* + * re-evaluate the number of backwalk contexts we need to process. + */ + n_ctxs = vec_len(fwalk->fw_ctx); } /* * move foward to the next node to visit |