From e7e56def2ef154c3ef20baf91251d7acf0d765b1 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 27 Aug 2019 12:15:43 -0700 Subject: tcp: improve mss computation Type: fix Use different mss for v4 and v6 packets. Change-Id: Ifcd322c1fd74f749a42bae671dd6cfed8c32b150 Signed-off-by: Florin Coras (cherry picked from commit cedcf608fefc5bdeff13bb0914fa15266e971d7c) --- src/vnet/tcp/tcp.c | 44 +++++++++++++++++++++++++++++++++++++++++++- src/vnet/tcp/tcp.h | 1 - src/vnet/tcp/tcp_output.c | 46 +++++----------------------------------------- 3 files changed, 48 insertions(+), 43 deletions(-) (limited to 'src/vnet/tcp') diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index bfab1d6f0c5..cd7b9e80c7a 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -637,6 +637,47 @@ tcp_generate_random_iss (tcp_connection_t * tc) return ((tmp >> 32) ^ (tmp & 0xffffffff)); } +/** + * Initialize max segment size we're able to process. + * + * The value is constrained by the output interface's MTU and by the size + * of the IP and TCP headers (see RFC6691). It is also what we advertise + * to our peer. + */ +static void +tcp_init_rcv_mss (tcp_connection_t * tc) +{ + u8 ip_hdr_len; + + ip_hdr_len = tc->c_is_ip4 ? sizeof (ip4_header_t) : sizeof (ip6_header_t); + tc->mss = tcp_cfg.default_mtu - sizeof (tcp_header_t) - ip_hdr_len; +} + +static void +tcp_init_mss (tcp_connection_t * tc) +{ + u16 default_min_mss = 536; + + tcp_init_rcv_mss (tc); + + /* TODO consider PMTU discovery */ + tc->snd_mss = clib_min (tc->rcv_opts.mss, tc->mss); + + if (tc->snd_mss < 45) + { + /* Assume that at least the min default mss works */ + tc->snd_mss = default_min_mss; + tc->rcv_opts.mss = default_min_mss; + } + + /* We should have enough space for 40 bytes of options */ + ASSERT (tc->snd_mss > 45); + + /* If we use timestamp option, account for it */ + if (tcp_opts_tstamp (&tc->rcv_opts)) + tc->snd_mss -= TCP_OPTION_LEN_TIMESTAMP; +} + /** * Initialize connection send variables. */ @@ -651,6 +692,7 @@ tcp_init_snd_vars (tcp_connection_t * tc) */ tcp_set_time_now (tcp_get_worker (vlib_get_thread_index ())); + tcp_init_rcv_mss (tc); tc->iss = tcp_generate_random_iss (tc); tc->snd_una = tc->iss; tc->snd_nxt = tc->iss + 1; @@ -1541,7 +1583,7 @@ tcp_configuration_init (void) tcp_cfg.max_rx_fifo = 32 << 20; tcp_cfg.min_rx_fifo = 4 << 10; - tcp_cfg.default_mtu = 1460; + tcp_cfg.default_mtu = 1500; tcp_cfg.initial_cwnd_multiplier = 0; tcp_cfg.enable_tx_pacing = 1; tcp_cfg.cc_algo = TCP_CC_NEWRENO; diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index cad105b0c23..d55ff801c00 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -743,7 +743,6 @@ void tcp_send_reset (tcp_connection_t * tc); void tcp_send_syn (tcp_connection_t * tc); void tcp_send_synack (tcp_connection_t * tc); void tcp_send_fin (tcp_connection_t * tc); -void tcp_init_mss (tcp_connection_t * tc); void tcp_update_burst_snd_vars (tcp_connection_t * tc); void tcp_update_rto (tcp_connection_t * tc); void tcp_flush_frame_to_output (tcp_worker_ctx_t * wrk, u8 is_ip4); diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 862f4a2f307..239f6035d5f 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -75,19 +75,6 @@ tcp_window_compute_scale (u32 window) return wnd_scale; } -/** - * Update max segment size we're able to process. - * - * The value is constrained by our interface's MTU and IP options. It is - * also what we advertise to our peer. - */ -void -tcp_update_rcv_mss (tcp_connection_t * tc) -{ - /* TODO find our iface MTU */ - tc->mss = tcp_cfg.default_mtu - sizeof (tcp_header_t); -} - /** * TCP's initial window */ @@ -263,16 +250,16 @@ tcp_options_write (u8 * data, tcp_options_t * opts) } static int -tcp_make_syn_options (tcp_options_t * opts, u8 wnd_scale) +tcp_make_syn_options (tcp_connection_t * tc, tcp_options_t * opts) { u8 len = 0; opts->flags |= TCP_OPTS_FLAG_MSS; - opts->mss = tcp_cfg.default_mtu; /*XXX discover that */ + opts->mss = tc->mss; len += TCP_OPTION_LEN_MSS; opts->flags |= TCP_OPTS_FLAG_WSCALE; - opts->wscale = wnd_scale; + opts->wscale = tc->rcv_wscale; len += TCP_OPTION_LEN_WINDOW_SCALE; opts->flags |= TCP_OPTS_FLAG_TSTAMP; @@ -379,7 +366,7 @@ tcp_make_options (tcp_connection_t * tc, tcp_options_t * opts, case TCP_STATE_SYN_RCVD: return tcp_make_synack_options (tc, opts); case TCP_STATE_SYN_SENT: - return tcp_make_syn_options (opts, tc->rcv_wscale); + return tcp_make_syn_options (tc, opts); default: clib_warning ("State not handled! %d", state); return 0; @@ -422,29 +409,6 @@ tcp_update_burst_snd_vars (tcp_connection_t * tc) tcp_cc_event (tc, TCP_CC_EVT_START_TX); } -void -tcp_init_mss (tcp_connection_t * tc) -{ - u16 default_min_mss = 536; - tcp_update_rcv_mss (tc); - - /* TODO cache mss and consider PMTU discovery */ - tc->snd_mss = clib_min (tc->rcv_opts.mss, tc->mss); - - if (tc->snd_mss < 45) - { - /* Assume that at least the min default mss works */ - tc->snd_mss = default_min_mss; - tc->rcv_opts.mss = default_min_mss; - } - - /* We should have enough space for 40 bytes of options */ - ASSERT (tc->snd_mss > 45); - - /* If we use timestamp option, account for it */ - if (tcp_opts_tstamp (&tc->rcv_opts)) - tc->snd_mss -= TCP_OPTION_LEN_TIMESTAMP; -} #endif /* CLIB_MARCH_VARIANT */ static void * @@ -542,7 +506,7 @@ tcp_make_syn (tcp_connection_t * tc, vlib_buffer_t * b) /* Make and write options */ clib_memset (&snd_opts, 0, sizeof (snd_opts)); - tcp_opts_len = tcp_make_syn_options (&snd_opts, tc->rcv_wscale); + tcp_opts_len = tcp_make_syn_options (tc, &snd_opts); tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t); th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss, -- cgit 1.2.3-korg