diff options
author | Dave Barach <dave@barachs.net> | 2020-06-05 07:06:21 -0400 |
---|---|---|
committer | Dave Barach <dave@barachs.net> | 2020-06-05 07:07:42 -0400 |
commit | c2d2228e928b7c69dc88e9c3b7502966d0e32d8d (patch) | |
tree | 582909c4f2a7d6be84588ecdeb662ef6e8395b17 /src | |
parent | a5cf6e077ddafce9d4a92965e0f60e1a195a11a8 (diff) |
fib: fix adj pool expand cases
adj_alloc (...) is not thread safe when the adj pool or combined
counter vectors expand.
Type: fix
Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: I55710de6ecc083b7434e11798659cca9250c9131
Diffstat (limited to 'src')
-rw-r--r-- | src/vnet/adj/adj.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index 2fb77fe78d3..db6d99a81d1 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -63,15 +63,35 @@ ip_adjacency_t * adj_alloc (fib_protocol_t proto) { ip_adjacency_t *adj; + u8 need_barrier_sync = 0; + vlib_main_t *vm; + vm = vlib_get_main(); + + ASSERT (vm->thread_index == 0); + + pool_get_aligned_will_expand (adj_pool, need_barrier_sync, + CLIB_CACHE_LINE_BYTES); + /* If the adj_pool will expand, stop the parade. */ + if (need_barrier_sync) + vlib_worker_thread_barrier_sync (vm); pool_get_aligned(adj_pool, adj, CLIB_CACHE_LINE_BYTES); adj_poison(adj); - /* Make sure certain fields are always initialized. */ /* Validate adjacency counters. */ + if (need_barrier_sync == 0) + { + /* If the adj counter pool will expand, stop the parade */ + need_barrier_sync = vlib_validate_combined_counter_will_expand + (&adjacency_counters, adj_get_index (adj)); + if (need_barrier_sync) + vlib_worker_thread_barrier_sync (vm); + } vlib_validate_combined_counter(&adjacency_counters, adj_get_index(adj)); + + /* Make sure certain fields are always initialized. */ vlib_zero_combined_counter(&adjacency_counters, adj_get_index(adj)); fib_node_init(&adj->ia_node, @@ -89,6 +109,9 @@ adj_alloc (fib_protocol_t proto) clib_memset(&adj->sub_type.midchain.next_dpo, 0, sizeof(adj->sub_type.midchain.next_dpo)); + if (need_barrier_sync) + vlib_worker_thread_barrier_release (vm); + return (adj); } |