diff options
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/session/session_lookup.c | 32 | ||||
-rw-r--r-- | src/vnet/session/session_lookup.h | 5 |
2 files changed, 37 insertions, 0 deletions
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 335905d6ead..354fab53bc3 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -29,6 +29,8 @@ #include <vnet/session/session.h> #include <vnet/session/application.h> +static session_lookup_main_t sl_main; + /** * Network namespace index (i.e., fib index) to session lookup table. We * should have one per network protocol type but for now we only support IP4/6 @@ -155,6 +157,12 @@ make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc) tc->rmt_port, tc->proto); } +static inline u8 +session_table_alloc_needs_sync (void) +{ + return !vlib_thread_is_main_w_barrier () && (vlib_num_workers () > 1); +} + static session_table_t * session_table_get_or_alloc (u8 fib_proto, u32 fib_index) { @@ -169,6 +177,19 @@ session_table_get_or_alloc (u8 fib_proto, u32 fib_index) } else { + u8 needs_sync = session_table_alloc_needs_sync (); + session_lookup_main_t *slm = &sl_main; + + /* Stop workers, otherwise consumers might be affected. This is + * acceptable because new tables should seldom be allocated */ + if (needs_sync) + { + vlib_workers_sync (); + + /* We might have a race, only one worker allowed at once */ + clib_spinlock_lock (&slm->st_alloc_lock); + } + st = session_table_alloc (); table_index = session_table_index (st); vec_validate_init_empty (fib_index_to_table_index[fib_proto], fib_index, @@ -176,6 +197,13 @@ session_table_get_or_alloc (u8 fib_proto, u32 fib_index) fib_index_to_table_index[fib_proto][fib_index] = table_index; st->active_fib_proto = fib_proto; session_table_init (st, fib_proto); + + if (needs_sync) + { + clib_spinlock_unlock (&slm->st_alloc_lock); + vlib_workers_continue (); + } + return st; } } @@ -1792,6 +1820,10 @@ VLIB_CLI_COMMAND (show_session_lookup_command, static) = { void session_lookup_init (void) { + session_lookup_main_t *slm = &sl_main; + + clib_spinlock_init (&slm->st_alloc_lock); + /* * Allocate default table and map it to fib_index 0 */ diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 86148d1830a..f9ffc15165a 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -29,6 +29,11 @@ typedef enum session_lookup_result_ SESSION_LOOKUP_RESULT_FILTERED } session_lookup_result_t; +typedef struct session_lookup_main_ +{ + clib_spinlock_t st_alloc_lock; +} session_lookup_main_t; + session_t *session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, u16 lcl_port, u16 rmt_port, u8 proto); |