diff options
Diffstat (limited to 'src/vnet/adj/adj_nbr.c')
-rw-r--r-- | src/vnet/adj/adj_nbr.c | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c index 8524c6c83ae..b3a027b7af4 100644 --- a/src/vnet/adj/adj_nbr.c +++ b/src/vnet/adj/adj_nbr.c @@ -105,6 +105,46 @@ adj_nbr_remove (adj_index_t ai, } } +typedef struct adj_nbr_get_n_adjs_walk_ctx_t_ +{ + vnet_link_t linkt; + u32 count; +} adj_nbr_get_n_adjs_walk_ctx_t; + +static adj_walk_rc_t +adj_nbr_get_n_adjs_walk (adj_index_t ai, + void *data) +{ + adj_nbr_get_n_adjs_walk_ctx_t *ctx = data; + const ip_adjacency_t *adj; + + adj = adj_get(ai); + + if (ctx->linkt == adj->ia_link) + ctx->count++; + + return (ADJ_WALK_RC_CONTINUE); +} + +u32 +adj_nbr_get_n_adjs (vnet_link_t link_type, u32 sw_if_index) +{ + adj_nbr_get_n_adjs_walk_ctx_t ctx = { + .linkt = link_type, + }; + fib_protocol_t fproto; + + FOR_EACH_FIB_IP_PROTOCOL(fproto) + { + adj_nbr_walk (sw_if_index, + fproto, + adj_nbr_get_n_adjs_walk, + &ctx); + } + + return (ctx.count); +} + adj_index_t adj_nbr_find (fib_protocol_t nh_proto, vnet_link_t link_type, @@ -492,7 +532,7 @@ 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 + * fib_walk_sync may allocate a new adjacency and potentially cause a * realloc for adj_pool. When that happens, adj pointer is no longer * valid here. We refresh the adj pointer accordingly. */ @@ -560,7 +600,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj, walk_adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE; } - adj_delegate_adj_modified(adj); + adj_delegate_adj_modified(adj_get(ai)); adj_unlock(ai); adj_unlock(walk_ai); } @@ -753,9 +793,15 @@ adj_nbr_interface_state_change_one (adj_index_t ai, adj_lock (ai); adj = adj_get(ai); - adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE; fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx); + + /* + * fib_walk_sync may allocate a new adjacency and potentially cause 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); adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE; adj_unlock (ai); @@ -863,9 +909,15 @@ adj_nbr_interface_delete_one (adj_index_t ai, adj_lock(ai); adj = adj_get(ai); - adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE; fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx); + + /* + * fib_walk_sync may allocate a new adjacency and potentially cause 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); adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE; adj_unlock(ai); |