From 57b2e4acb1104ac34b1c2e29309e0f5f471b42d7 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 6 Jul 2021 08:25:36 -0700 Subject: [PATCH] tcp: use main thread pool for half-opens Type: improvement Signed-off-by: Florin Coras Change-Id: I4b3427b966f9ff1ba8895fed7db662d56650f3f5 --- src/vnet/tcp/tcp.c | 50 ++++++++++----------- src/vnet/tcp/tcp.h | 8 +--- src/vnet/tcp/tcp_cli.c | 110 ++------------------------------------------- src/vnet/tcp/tcp_inlines.h | 5 +-- src/vnet/tcp/tcp_input.c | 2 +- 5 files changed, 29 insertions(+), 146 deletions(-) diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index c70a44cae90..c54a994fede 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -181,6 +181,13 @@ tcp_session_get_listener (u32 listener_index) return &tc->connection; } +static tcp_connection_t * +tcp_half_open_connection_alloc (void) +{ + ASSERT (vlib_get_thread_index () == 0); + return tcp_connection_alloc (0); +} + /** * Cleanup half-open connection * @@ -188,10 +195,8 @@ tcp_session_get_listener (u32 listener_index) static void tcp_half_open_connection_free (tcp_connection_t * tc) { - tcp_main_t *tm = vnet_get_tcp_main (); - if (CLIB_DEBUG) - clib_memset (tc, 0xFA, sizeof (*tc)); - pool_put (tm->half_open_connections, tc); + ASSERT (vlib_get_thread_index () == 0); + return tcp_connection_free (tc); } /** @@ -219,18 +224,6 @@ tcp_half_open_connection_cleanup (tcp_connection_t * tc) return 0; } -static tcp_connection_t * -tcp_half_open_connection_new (void) -{ - tcp_main_t *tm = vnet_get_tcp_main (); - tcp_connection_t *tc = 0; - ASSERT (vlib_get_thread_index () == 0); - pool_get (tm->half_open_connections, tc); - clib_memset (tc, 0, sizeof (*tc)); - tc->c_c_index = tc - tm->half_open_connections; - return tc; -} - /** * Cleans up connection state. * @@ -304,13 +297,23 @@ tcp_connection_alloc (u8 thread_index) } tcp_connection_t * -tcp_connection_alloc_w_base (u8 thread_index, tcp_connection_t * base) +tcp_connection_alloc_w_base (u8 thread_index, tcp_connection_t **base) { tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index); tcp_connection_t *tc; - pool_get (wrk->connections, tc); - clib_memcpy_fast (tc, base, sizeof (*tc)); + /* Make sure connection is still valid if pool moves */ + if ((*base)->c_thread_index == thread_index) + { + u32 base_index = (*base)->c_c_index; + pool_get (wrk->connections, tc); + *base = tcp_connection_get (base_index, thread_index); + } + else + { + pool_get (wrk->connections, tc); + } + clib_memcpy_fast (tc, *base, sizeof (*tc)); tc->c_c_index = tc - wrk->connections; tc->c_thread_index = thread_index; return tc; @@ -816,7 +819,7 @@ tcp_session_open (transport_endpoint_cfg_t * rmt) /* * Create connection and send SYN */ - tc = tcp_half_open_connection_new (); + tc = tcp_half_open_connection_alloc (); ip_copy (&tc->c_rmt_ip, &rmt->ip, rmt->is_ip4); ip_copy (&tc->c_lcl_ip, &lcl_addr, rmt->is_ip4); tc->c_rmt_port = rmt->port; @@ -1515,13 +1518,6 @@ tcp_main_enable (vlib_main_t * vm) vlib_time_now (vm)); } - /* - * Use a preallocated half-open connection pool? - */ - if (tcp_cfg.preallocated_half_open_connections) - pool_init_fixed (tm->half_open_connections, - tcp_cfg.preallocated_half_open_connections); - tcp_initialize_iss_seed (tm); tm->bytes_per_buffer = vlib_buffer_get_default_data_size (vm); diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index 60b9095aea2..ca650b7fa29 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -193,9 +193,6 @@ typedef struct tcp_configuration_ /** Number of preallocated connections */ u32 preallocated_connections; - /** Number of preallocated half-open connections */ - u32 preallocated_half_open_connections; - /** Maxium allowed GSO packet size */ u32 max_gso_size; @@ -224,9 +221,6 @@ typedef struct _tcp_main /** Dispatch table by state and flags */ tcp_lookup_dispatch_t dispatch_table[TCP_N_STATES][64]; - /** Pool of half-open connections on which we've sent a SYN */ - tcp_connection_t *half_open_connections; - /** Seed used to generate random iss */ tcp_iss_seed_t iss_seed; @@ -294,7 +288,7 @@ tcp_get_worker (u32 thread_index) tcp_connection_t *tcp_connection_alloc (u8 thread_index); tcp_connection_t *tcp_connection_alloc_w_base (u8 thread_index, - tcp_connection_t * base); + tcp_connection_t **base); void tcp_connection_free (tcp_connection_t * tc); void tcp_connection_close (tcp_connection_t * tc); void tcp_connection_cleanup (tcp_connection_t * tc); diff --git a/src/vnet/tcp/tcp_cli.c b/src/vnet/tcp/tcp_cli.c index c11b154cebf..e602f114a74 100644 --- a/src/vnet/tcp/tcp_cli.c +++ b/src/vnet/tcp/tcp_cli.c @@ -899,110 +899,6 @@ VLIB_CLI_COMMAND (clear_tcp_stats_command, static) = }; /* *INDENT-ON* */ -static void -tcp_show_half_open (vlib_main_t * vm, u32 start, u32 end, u8 verbose) -{ - tcp_main_t *tm = &tcp_main; - u8 output_suppressed = 0; - u32 n_elts, count = 0; - tcp_connection_t *tc; - int max_index, i; - - n_elts = pool_elts (tm->half_open_connections); - max_index = clib_max (pool_len (tm->half_open_connections), 1) - 1; - if (verbose && end == ~0 && n_elts > 50) - { - vlib_cli_output (vm, "Too many connections, use range "); - return; - } - - if (!verbose) - { - vlib_cli_output (vm, "%u tcp half-open connections", n_elts); - return; - } - - for (i = start; i <= clib_min (end, max_index); i++) - { - if (pool_is_free_index (tm->half_open_connections, i)) - continue; - - tc = pool_elt_at_index (tm->half_open_connections, i); - - count += 1; - if (verbose) - { - if (count > 50 || (verbose > 1 && count > 10)) - { - output_suppressed = 1; - continue; - } - } - vlib_cli_output (vm, "%U", format_tcp_connection, tc, verbose); - } - if (!output_suppressed) - vlib_cli_output (vm, "%u tcp half-open connections", n_elts); - else - vlib_cli_output (vm, "%u tcp half-open connections matched. Output " - "suppressed. Use finer grained filter.", count); - -} - -static clib_error_t * -show_tcp_half_open_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u32 start, end = ~0, verbose = 0; - clib_error_t *error = 0; - - session_cli_return_if_not_enabled (); - - if (!unformat_user (input, unformat_line_input, line_input)) - { - tcp_show_half_open (vm, 0, ~0, 0); - return 0; - } - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "range %u %u", &start, &end)) - ; - else if (unformat (line_input, "verbose %d", &verbose)) - ; - else if (unformat (line_input, "verbose")) - verbose = 1; - else - { - error = clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - goto done; - } - } - - if (start > end) - { - error = clib_error_return (0, "invalid range start: %u end: %u", start, - end); - goto done; - } - - tcp_show_half_open (vm, start, end, verbose); - -done: - unformat_free (line_input); - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_tcp_half_open_command, static) = -{ - .path = "show tcp half-open", - .short_help = "show tcp half-open [verbose ] [range ]", - .function = show_tcp_half_open_fn, -}; -/* *INDENT-ON* */ - uword unformat_tcp_cc_algo (unformat_input_t * input, va_list * va) { @@ -1049,7 +945,7 @@ unformat_tcp_cc_algo_cfg (unformat_input_t * input, va_list * va) static clib_error_t * tcp_config_fn (vlib_main_t * vm, unformat_input_t * input) { - u32 cwnd_multiplier, tmp_time, mtu, max_gso_size; + u32 cwnd_multiplier, tmp_time, mtu, max_gso_size, tmp; uword memory_size; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) @@ -1057,8 +953,8 @@ tcp_config_fn (vlib_main_t * vm, unformat_input_t * input) if (unformat (input, "preallocated-connections %d", &tcp_cfg.preallocated_connections)) ; - else if (unformat (input, "preallocated-half-open-connections %d", - &tcp_cfg.preallocated_half_open_connections)) + /* Config deprecated. Will be removed in a later release */ + else if (unformat (input, "preallocated-half-open-connections %d", &tmp)) ; else if (unformat (input, "buffer-fail-fraction %f", &tcp_cfg.buffer_fail_fraction)) diff --git a/src/vnet/tcp/tcp_inlines.h b/src/vnet/tcp/tcp_inlines.h index 68eb4b147fa..dfdf801d0ab 100644 --- a/src/vnet/tcp/tcp_inlines.h +++ b/src/vnet/tcp/tcp_inlines.h @@ -66,10 +66,7 @@ tcp_listener_get (u32 tli) always_inline tcp_connection_t * tcp_half_open_connection_get (u32 conn_index) { - tcp_connection_t *tc = 0; - if (!pool_is_free_index (tcp_main.half_open_connections, conn_index)) - tc = pool_elt_at_index (tcp_main.half_open_connections, conn_index); - return tc; + return tcp_connection_get (conn_index, 0); } /** diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index 2ba96a5fe78..1e27b7dcb2e 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -1929,7 +1929,7 @@ tcp46_syn_sent_inline (vlib_main_t *vm, vlib_node_runtime_t *node, /* Valid SYN or SYN-ACK. Move connection from half-open pool to * current thread pool. */ - new_tc = tcp_connection_alloc_w_base (thread_index, tc); + new_tc = tcp_connection_alloc_w_base (thread_index, &tc); new_tc->rcv_nxt = vnet_buffer (b[0])->tcp.seq_end; new_tc->irs = seq; new_tc->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID; -- 2.16.6