diff options
author | Dave Barach <dave@barachs.net> | 2020-06-05 07:06:21 -0400 |
---|---|---|
committer | Andrew Yourtchenko <ayourtch@gmail.com> | 2020-08-18 19:47:21 +0000 |
commit | 1c39c6556df7ce3ba4509425c2976c015c07fa05 (patch) | |
tree | ad2829435a9e2f509e4f49c05178f8f98cf1dc88 | |
parent | 1c73742cb3c90f11a7b9e9c01100c464a82951fd (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
(cherry picked from commit c2d2228e928b7c69dc88e9c3b7502966d0e32d8d)
-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 03c82062cc0..3871e2c1612 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, @@ -88,6 +108,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); } |