summaryrefslogtreecommitdiffstats
path: root/src/vnet/adj
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2020-06-05 07:06:21 -0400
committerDave Barach <dave@barachs.net>2020-06-05 07:07:42 -0400
commitc2d2228e928b7c69dc88e9c3b7502966d0e32d8d (patch)
tree582909c4f2a7d6be84588ecdeb662ef6e8395b17 /src/vnet/adj
parenta5cf6e077ddafce9d4a92965e0f60e1a195a11a8 (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/vnet/adj')
-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 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);
}