diff options
Diffstat (limited to 'src/vnet/session/session_lookup.c')
-rw-r--r-- | src/vnet/session/session_lookup.c | 158 |
1 files changed, 138 insertions, 20 deletions
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 5cd1712f195..9d028dbb28c 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -29,13 +29,14 @@ #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 */ static u32 *fib_index_to_table_index[2]; -/* *INDENT-OFF* */ /* 16 octets */ typedef CLIB_PACKED (struct { union @@ -72,7 +73,6 @@ typedef CLIB_PACKED (struct { u64 as_u64[6]; }; }) v6_connection_key_t; -/* *INDENT-ON* */ typedef clib_bihash_kv_16_8_t session_kv4_t; typedef clib_bihash_kv_48_8_t session_kv6_t; @@ -155,29 +155,70 @@ 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_always_inline u8 +session_table_is_alloced (u8 fib_proto, u32 fib_index) +{ + return (vec_len (fib_index_to_table_index[fib_proto]) > fib_index && + fib_index_to_table_index[fib_proto][fib_index] != ~0); +} + static session_table_t * session_table_get_or_alloc (u8 fib_proto, u32 fib_index) { session_table_t *st; u32 table_index; + ASSERT (fib_index != ~0); - if (vec_len (fib_index_to_table_index[fib_proto]) > fib_index && - fib_index_to_table_index[fib_proto][fib_index] != ~0) + + if (session_table_is_alloced (fib_proto, fib_index)) { table_index = fib_index_to_table_index[fib_proto][fib_index]; return session_table_get (table_index); } + + 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); + } + + /* Another worker just allocated this table */ + if (session_table_is_alloced (fib_proto, fib_index)) + { + table_index = fib_index_to_table_index[fib_proto][fib_index]; + st = session_table_get (table_index); + } else { st = session_table_alloc (); - table_index = session_table_index (st); + st->active_fib_proto = fib_proto; + session_table_init (st, fib_proto); vec_validate_init_empty (fib_index_to_table_index[fib_proto], fib_index, ~0); + table_index = session_table_index (st); fib_index_to_table_index[fib_proto][fib_index] = table_index; - st->active_fib_proto = fib_proto; - session_table_init (st, fib_proto); - return st; } + + if (needs_sync) + { + clib_spinlock_unlock (&slm->st_alloc_lock); + vlib_workers_continue (); + } + + return st; } static session_table_t * @@ -1046,9 +1087,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, /** * Lookup session with ip4 and transport layer information * - * Important note: this may look into another thread's pool table and - * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as - * if needed as soon as possible. + * Important note: this may look into another thread's pool table * * Lookup logic is similar to that of @ref session_lookup_connection_wt4 but * this returns a session as opposed to a transport connection and it does not @@ -1313,8 +1352,8 @@ session_lookup_connection (u32 fib_index, ip46_address_t * lcl, lcl_port, rmt_port, proto); } -int -vnet_session_rule_add_del (session_rule_add_del_args_t * args) +session_error_t +vnet_session_rule_add_del (session_rule_add_del_args_t *args) { app_namespace_t *app_ns = app_namespace_get (args->appns_index); session_rules_table_t *srt; @@ -1324,14 +1363,14 @@ vnet_session_rule_add_del (session_rule_add_del_args_t * args) int rv = 0; if (!app_ns) - return VNET_API_ERROR_APP_INVALID_NS; + return SESSION_E_INVALID_NS; if (args->scope > 3) - return VNET_API_ERROR_INVALID_VALUE; + return SESSION_E_INVALID; if (args->transport_proto != TRANSPORT_PROTO_TCP && args->transport_proto != TRANSPORT_PROTO_UDP) - return VNET_API_ERROR_INVALID_VALUE; + return SESSION_E_INVALID; if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0) { @@ -1571,7 +1610,6 @@ done: return error; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (session_rule_command, static) = { .path = "session rule", @@ -1579,7 +1617,6 @@ VLIB_CLI_COMMAND (session_rule_command, static) = "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>", .function = session_rule_command_fn, }; -/* *INDENT-ON* */ void session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto, @@ -1702,7 +1739,6 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_session_rules_command, static) = { .path = "show session rules", @@ -1710,11 +1746,93 @@ VLIB_CLI_COMMAND (show_session_rules_command, static) = "<lcl-port> <rmt-ip/plen> <rmt-port> scope <scope>]", .function = show_session_rules_command_fn, }; -/* *INDENT-ON* */ + +u8 * +format_session_lookup_tables (u8 *s, va_list *args) +{ + u32 fib_proto = va_arg (*args, u32); + u32 *fibs, num_fibs = 0, fib_index, indent; + session_table_t *st; + u64 total_mem = 0; + + fibs = fib_index_to_table_index[fib_proto]; + + for (fib_index = 0; fib_index < vec_len (fibs); fib_index++) + { + if (fibs[fib_index] == ~0) + continue; + + num_fibs += 1; + st = session_table_get (fibs[fib_index]); + total_mem += session_table_memory_size (st); + } + + indent = format_get_indent (s); + s = format (s, "active fibs:\t%u\n", num_fibs); + s = format (s, "%Umax fib-index:\t%u\n", format_white_space, indent, + vec_len (fibs) - 1); + s = format (s, "%Utable memory:\t%U\n", format_white_space, indent, + format_memory_size, total_mem); + s = format (s, "%Uvec memory:\t%U\n", format_white_space, indent, + format_memory_size, vec_mem_size (fibs)); + + return s; +} + +static clib_error_t * +show_session_lookup_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + session_table_t *st; + u32 fib_index = ~0; + + session_cli_return_if_not_enabled (); + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "table %u", &fib_index)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + if (fib_index != ~0) + { + st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); + if (st) + vlib_cli_output (vm, "%U", format_session_table, st); + else + vlib_cli_output (vm, "no ip4 table for fib-index %u", fib_index); + st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); + if (st) + vlib_cli_output (vm, "%U", format_session_table, st); + else + vlib_cli_output (vm, "no ip6 table for fib-index %u", fib_index); + goto done; + } + + vlib_cli_output (vm, "ip4 fib lookup tables:\n %U", + format_session_lookup_tables, FIB_PROTOCOL_IP4); + vlib_cli_output (vm, "ip6 fib lookup tables:\n %U", + format_session_lookup_tables, FIB_PROTOCOL_IP6); + +done: + return 0; +} + +VLIB_CLI_COMMAND (show_session_lookup_command, static) = { + .path = "show session lookup", + .short_help = "show session lookup [table <fib-index>]", + .function = show_session_lookup_command_fn, +}; 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 */ |