summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2020-06-05 07:06:21 -0400
committerAndrew Yourtchenko <ayourtch@gmail.com>2020-08-18 19:47:21 +0000
commit1c39c6556df7ce3ba4509425c2976c015c07fa05 (patch)
treead2829435a9e2f509e4f49c05178f8f98cf1dc88
parent1c73742cb3c90f11a7b9e9c01100c464a82951fd (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.c25
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);
}