From 2f51729bb31fcc2717782aa465835d93d73a567f Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Mon, 12 Aug 2019 14:17:47 -0700 Subject: tcp: extend protocol configuration Type: feature Ticket: VPP-1736 Expose more configuration parameters and refactor some of the existing ones. Change-Id: If44c31ff77ce3d7e8da67d39a4ff61346bdf5ccc Signed-off-by: Florin Coras (cherry picked from commit 9094b5c319d3f072d3c248fe7c876e4048c13ac2) --- src/vnet/tcp/tcp.c | 134 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 47 deletions(-) (limited to 'src/vnet/tcp/tcp.c') diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index 752257f4100..3b94420e639 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -73,7 +73,7 @@ tcp_add_del_adjacency (tcp_connection_t * tc, u8 is_add) static void tcp_cc_init (tcp_connection_t * tc) { - tc->cc_algo = tcp_cc_algo_get (tcp_main.cc_algo); + tc->cc_algo = tcp_cc_algo_get (tcp_cfg.cc_algo); tc->cc_algo->init (tc); } @@ -343,7 +343,7 @@ tcp_connection_reset (tcp_connection_t * tc) tcp_connection_timers_reset (tc); /* Set the cleanup timer, in case the session layer/app don't * cleanly close the connection */ - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time); session_transport_reset_notify (&tc->connection); tcp_connection_set_state (tc, TCP_STATE_CLOSED); session_transport_closed_notify (&tc->connection); @@ -354,7 +354,7 @@ tcp_connection_reset (tcp_connection_t * tc) case TCP_STATE_CLOSING: case TCP_STATE_LAST_ACK: tcp_connection_timers_reset (tc); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time); /* Make sure we mark the session as closed. In some states we may * be still trying to send data */ tcp_connection_set_state (tc, TCP_STATE_CLOSED); @@ -398,7 +398,7 @@ tcp_connection_close (tcp_connection_t * tc) tcp_connection_timers_reset (tc); tcp_send_fin (tc); tcp_connection_set_state (tc, TCP_STATE_FIN_WAIT_1); - tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_FINWAIT1_TIME); + tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time); break; case TCP_STATE_ESTABLISHED: /* If closing with unread data, reset the connection */ @@ -407,7 +407,7 @@ tcp_connection_close (tcp_connection_t * tc) tcp_send_reset (tc); tcp_connection_timers_reset (tc); tcp_connection_set_state (tc, TCP_STATE_CLOSED); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time); session_transport_closed_notify (&tc->connection); break; } @@ -419,7 +419,7 @@ tcp_connection_close (tcp_connection_t * tc) /* Set a timer in case the peer stops responding. Otherwise the * connection will be stuck here forever. */ ASSERT (tc->timers[TCP_TIMER_WAITCLOSE] == TCP_TIMER_HANDLE_INVALID); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_FINWAIT1_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time); break; case TCP_STATE_CLOSE_WAIT: if (!transport_max_tx_dequeue (&tc->connection)) @@ -427,20 +427,20 @@ tcp_connection_close (tcp_connection_t * tc) tcp_send_fin (tc); tcp_connection_timers_reset (tc); tcp_connection_set_state (tc, TCP_STATE_LAST_ACK); - tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME); + tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time); } else tc->flags |= TCP_CONN_FINPNDG; break; case TCP_STATE_FIN_WAIT_1: - tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME); + tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time); break; case TCP_STATE_CLOSED: tcp_connection_timers_reset (tc); /* Delete connection but instead of doing it now wait until next * dispatch cycle to give the session layer a chance to clear * unhandled events */ - tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME); + tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time); break; default: TCP_DBG ("state: %u", tc->state); @@ -664,7 +664,7 @@ tcp_connection_init_vars (tcp_connection_t * tc) /* tcp_connection_fib_attach (tc); */ if (transport_connection_is_tx_paced (&tc->connection) - || tcp_main.tx_pacing) + || tcp_cfg.enable_tx_pacing) tcp_enable_pacing (tc); if (tc->flags & TCP_CONN_RATE_SAMPLE) @@ -680,17 +680,17 @@ tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr, int index, port; if (is_ip4) { - index = tm->last_v4_address_rotor++; - if (tm->last_v4_address_rotor >= vec_len (tm->ip4_src_addresses)) - tm->last_v4_address_rotor = 0; - lcl_addr->ip4.as_u32 = tm->ip4_src_addresses[index].as_u32; + index = tm->last_v4_addr_rotor++; + if (tm->last_v4_addr_rotor >= vec_len (tcp_cfg.ip4_src_addrs)) + tm->last_v4_addr_rotor = 0; + lcl_addr->ip4.as_u32 = tcp_cfg.ip4_src_addrs[index].as_u32; } else { - index = tm->last_v6_address_rotor++; - if (tm->last_v6_address_rotor >= vec_len (tm->ip6_src_addresses)) - tm->last_v6_address_rotor = 0; - clib_memcpy_fast (&lcl_addr->ip6, &tm->ip6_src_addresses[index], + index = tm->last_v6_addr_rotor++; + if (tm->last_v6_addr_rotor >= vec_len (tcp_cfg.ip6_src_addrs)) + tm->last_v6_addr_rotor = 0; + clib_memcpy_fast (&lcl_addr->ip6, &tcp_cfg.ip6_src_addrs[index], sizeof (ip6_address_t)); } port = transport_alloc_local_port (TRANSPORT_PROTO_TCP, lcl_addr); @@ -715,8 +715,8 @@ tcp_session_open (transport_endpoint_cfg_t * rmt) /* * Allocate local endpoint */ - if ((rmt->is_ip4 && vec_len (tm->ip4_src_addresses)) - || (!rmt->is_ip4 && vec_len (tm->ip6_src_addresses))) + if ((rmt->is_ip4 && vec_len (tcp_cfg.ip4_src_addrs)) + || (!rmt->is_ip4 && vec_len (tcp_cfg.ip6_src_addrs))) rv = tcp_alloc_custom_local_endpoint (tm, &lcl_addr, &lcl_port, rmt->is_ip4); else @@ -1308,7 +1308,7 @@ tcp_timer_waitclose_handler (u32 conn_index) if (!(tc->flags & TCP_CONN_FINPNDG)) { tcp_connection_set_state (tc, TCP_STATE_CLOSED); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time); break; } @@ -1321,7 +1321,7 @@ tcp_timer_waitclose_handler (u32 conn_index) tcp_connection_set_state (tc, TCP_STATE_LAST_ACK); /* Make sure we don't wait in LAST ACK forever */ - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time); /* Don't delete the connection yet */ break; @@ -1334,21 +1334,21 @@ tcp_timer_waitclose_handler (u32 conn_index) * Notify session layer that transport is closed. */ tcp_connection_set_state (tc, TCP_STATE_CLOSED); tcp_send_reset (tc); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time); } else { /* We've sent the fin but no progress. Close the connection and * to make sure everything is flushed, setup a cleanup timer */ tcp_connection_set_state (tc, TCP_STATE_CLOSED); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time); } break; case TCP_STATE_LAST_ACK: case TCP_STATE_CLOSING: tcp_connection_timers_reset (tc); tcp_connection_set_state (tc, TCP_STATE_CLOSED); - tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME); + tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time); session_transport_closed_notify (&tc->connection); break; default: @@ -1395,7 +1395,7 @@ tcp_initialize_timer_wheels (tcp_main_t * tm) foreach_vlib_main (({ tw = &tm->wrk_ctx[ii].timer_wheel; tw_timer_wheel_init_16t_2w_512sl (tw, tcp_expired_timers_dispatch, - 100e-3 /* timer period 100ms */ , ~0); + TCP_TIMER_TICK, ~0); tw->last_run_time = vlib_time_now (this_vlib_main); })); /* *INDENT-ON* */ @@ -1443,7 +1443,7 @@ tcp_main_enable (vlib_main_t * vm) vec_validate (tm->connections, num_threads - 1); vec_validate (tm->wrk_ctx, num_threads - 1); n_workers = num_threads == 1 ? 1 : vtm->n_threads; - prealloc_conn_per_wrk = tm->preallocated_connections / n_workers; + prealloc_conn_per_wrk = tcp_cfg.preallocated_connections / n_workers; for (thread = 0; thread < num_threads; thread++) { @@ -1464,9 +1464,9 @@ tcp_main_enable (vlib_main_t * vm) /* * Use a preallocated half-open connection pool? */ - if (tm->preallocated_half_open_connections) + if (tcp_cfg.preallocated_half_open_connections) pool_init_fixed (tm->half_open_connections, - tm->preallocated_half_open_connections); + tcp_cfg.preallocated_half_open_connections); /* Initialize clocks per tick for TCP timestamp. Used to compute * monotonically increasing timestamps. */ @@ -1514,6 +1514,34 @@ tcp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add) tm->punt_unknown6 = is_add; } +/** + * Initialize default values for tcp parameters + */ +static void +tcp_configuration_init (void) +{ + /* Initial wnd for SYN. Fifos are not allocated at that point so use some + * predefined value. For SYN-ACK we still want the scale to be computed in + * the same way */ + tcp_cfg.max_rx_fifo = 32 << 20; + tcp_cfg.min_rx_fifo = 4 << 10; + + tcp_cfg.default_mtu = 1460; + tcp_cfg.initial_cwnd_multiplier = 0; + tcp_cfg.enable_tx_pacing = 1; + tcp_cfg.cc_algo = TCP_CC_NEWRENO; + + /* Time constants defined as timer tick (100ms) multiples */ + tcp_cfg.delack_time = 1; /* 0.1s */ + tcp_cfg.closewait_time = 20; /* 2s */ + tcp_cfg.timewait_time = 100; /* 10s */ + tcp_cfg.finwait1_time = 600; /* 60s */ + tcp_cfg.lastack_time = 300; /* 30s */ + tcp_cfg.finwait2_time = 300; /* 30s */ + tcp_cfg.closing_time = 300; /* 30s */ + tcp_cfg.cleanup_time = 1; /* 0.1s */ +} + static clib_error_t * tcp_init (vlib_main_t * vm) { @@ -1538,11 +1566,10 @@ tcp_init (vlib_main_t * vm) FIB_PROTOCOL_IP6, tcp6_output_node.index); tcp_api_reference (); + tcp_configuration_init (); + tm->cc_algo_by_name = hash_create_string (0, sizeof (uword)); - tm->tx_pacing = 1; - tm->cc_algo = TCP_CC_NEWRENO; - tm->default_mtu = 1460; - tm->initial_cwnd_multiplier = 0; + return 0; } @@ -1594,34 +1621,49 @@ 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) { - tcp_main_t *tm = vnet_get_tcp_main (); - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "preallocated-connections %d", - &tm->preallocated_connections)) + &tcp_cfg.preallocated_connections)) ; else if (unformat (input, "preallocated-half-open-connections %d", - &tm->preallocated_half_open_connections)) + &tcp_cfg.preallocated_half_open_connections)) ; else if (unformat (input, "buffer-fail-fraction %f", - &tm->buffer_fail_fraction)) + &tcp_cfg.buffer_fail_fraction)) ; else if (unformat (input, "max-rx-fifo %U", unformat_memory_size, - &tm->max_rx_fifo)) + &tcp_cfg.max_rx_fifo)) ; - else if (unformat (input, "mtu %d", &tm->default_mtu)) + else if (unformat (input, "min-rx-fifo %U", unformat_memory_size, + &tcp_cfg.min_rx_fifo)) + ; + else if (unformat (input, "mtu %d", &tcp_cfg.default_mtu)) ; else if (unformat (input, "initial-cwnd-multiplier %d", - &tm->initial_cwnd_multiplier)) + &tcp_cfg.initial_cwnd_multiplier)) ; else if (unformat (input, "no-tx-pacing")) - tm->tx_pacing = 0; + tcp_cfg.enable_tx_pacing = 0; else if (unformat (input, "cc-algo %U", unformat_tcp_cc_algo, - &tm->cc_algo)) + &tcp_cfg.cc_algo)) ; else if (unformat (input, "%U", unformat_tcp_cc_algo_cfg)) ; + else if (unformat (input, "closewait-time %d", &tcp_cfg.closewait_time)) + tcp_cfg.closewait_time /= TCP_TIMER_TICK; + else if (unformat (input, "timewait-time %d", &tcp_cfg.timewait_time)) + tcp_cfg.timewait_time /= TCP_TIMER_TICK; + else if (unformat (input, "finwait1-time %d", &tcp_cfg.finwait1_time)) + tcp_cfg.finwait1_time /= TCP_TIMER_TICK; + else if (unformat (input, "finwait2-time %d", &tcp_cfg.finwait2_time)) + tcp_cfg.finwait2_time /= TCP_TIMER_TICK; + else if (unformat (input, "lastack-time %d", &tcp_cfg.lastack_time)) + tcp_cfg.lastack_time /= TCP_TIMER_TICK; + else if (unformat (input, "closing-time %d", &tcp_cfg.closing_time)) + tcp_cfg.closing_time /= TCP_TIMER_TICK; + else if (unformat (input, "cleanup-time %d", &tcp_cfg.cleanup_time)) + tcp_cfg.cleanup_time /= TCP_TIMER_TICK; else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); @@ -1646,7 +1688,6 @@ tcp_configure_v4_source_address_range (vlib_main_t * vm, ip4_address_t * start, ip4_address_t * end, u32 table_id) { - tcp_main_t *tm = vnet_get_tcp_main (); vnet_main_t *vnm = vnet_get_main (); u32 start_host_byte_order, end_host_byte_order; fib_prefix_t prefix; @@ -1697,7 +1738,7 @@ tcp_configure_v4_source_address_range (vlib_main_t * vm, { dpo_id_t dpo = DPO_INVALID; - vec_add1 (tm->ip4_src_addresses, start[0]); + vec_add1 (tcp_cfg.ip4_src_addrs, start[0]); /* Add local adjacencies for the range */ @@ -1735,7 +1776,6 @@ tcp_configure_v6_source_address_range (vlib_main_t * vm, ip6_address_t * start, ip6_address_t * end, u32 table_id) { - tcp_main_t *tm = vnet_get_tcp_main (); fib_prefix_t prefix; u32 fib_index = 0; fib_node_index_t fei; @@ -1755,7 +1795,7 @@ tcp_configure_v6_source_address_range (vlib_main_t * vm, dpo_id_t dpo = DPO_INVALID; /* Remember this address */ - vec_add1 (tm->ip6_src_addresses, start[0]); + vec_add1 (tcp_cfg.ip6_src_addrs, start[0]); /* Lookup the prefix, to identify the interface involved */ prefix.fp_len = 128; -- cgit 1.2.3-korg