From 3dd905a039735b6f361eca86c08aa9f25c2bbc4a Mon Sep 17 00:00:00 2001 From: tuexen Date: Tue, 31 Mar 2020 15:54:54 +0000 Subject: [PATCH] Allow the TCP backhole detection to be disabled at all, enabled only for IPv4, enabled only for IPv6, and enabled for IPv4 and IPv6. The current blackhole detection might classify a temporary outage as an MTU issue and reduces permanently the MSS. Since the consequences of such a reduction due to a misclassification are much more drastically for IPv4 than for IPv6, allow the administrator to enable it for IPv6 only. Reviewed by: bcr@ (man page), Richard Scheffenegger Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D24219 --- share/man/man4/tcp.4 | 24 +++++++++++++++++------- sys/netinet/tcp_stacks/bbr.c | 12 +++++++++--- sys/netinet/tcp_stacks/rack.c | 13 +++++++++---- sys/netinet/tcp_timer.c | 14 +++++++++----- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index b6110068171..0e35820c77d 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -34,7 +34,7 @@ .\" From: @(#)tcp.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd March 29, 2020 +.Dd March 31, 2020 .Dt TCP 4 .Os .Sh NAME @@ -628,21 +628,31 @@ specific connection. This is needed to help with connection establishment when a broken firewall is in the network path. .It Va pmtud_blackhole_detection -Turn on automatic path MTU blackhole detection. -In case of retransmits OS will -lower the MSS to check if it's MTU problem. -If current MSS is greater than -configured value to try +Enable automatic path MTU blackhole detection. +In case of retransmits of MSS sized segments, +the OS will lower the MSS to check if it's an MTU problem. +If the current MSS is greater than the configured value to try .Po Va net.inet.tcp.pmtud_blackhole_mss and .Va net.inet.tcp.v6pmtud_blackhole_mss .Pc , it will be set to this value, otherwise, -MSS will be set to default values +the MSS will be set to the default values .Po Va net.inet.tcp.mssdflt and .Va net.inet.tcp.v6mssdflt .Pc . +Settings: +.Bl -tag -compact +.It 0 +Disable path MTU blackhole detection. +.It 1 +Enable path MTU blackhole detection for IPv4 and IPv6. +.It 2 +Enable path MTU blackhole detection only for IPv4. +.It 3 +Enable path MTU blackhole detection only for IPv6. +.El .It Va pmtud_blackhole_mss MSS to try for IPv4 if PMTU blackhole detection is turned on. .It Va v6pmtud_blackhole_mss diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c index f465a6ce6da..2624ba8ea24 100644 --- a/sys/netinet/tcp_stacks/bbr.c +++ b/sys/netinet/tcp_stacks/bbr.c @@ -5041,6 +5041,7 @@ bbr_timeout_rxt(struct tcpcb *tp, struct tcp_bbr *bbr, uint32_t cts) { int32_t rexmt; int32_t retval = 0; + bool isipv6; bbr->r_ctl.rc_hpts_flags &= ~PACE_TMR_RXT; if (bbr->rc_all_timers_stopped) { @@ -5127,11 +5128,16 @@ bbr_timeout_rxt(struct tcpcb *tp, struct tcp_bbr *bbr, uint32_t cts) * of packets and process straight to FIN. In that case we won't * catch ESTABLISHED state. */ - if (V_tcp_pmtud_blackhole_detect && (((tp->t_state == TCPS_ESTABLISHED)) - || (tp->t_state == TCPS_FIN_WAIT_1))) { #ifdef INET6 - int32_t isipv6; + isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? true : false; +#else + isipv6 = false; #endif + if (((V_tcp_pmtud_blackhole_detect == 1) || + (V_tcp_pmtud_blackhole_detect == 2 && !isipv6) || + (V_tcp_pmtud_blackhole_detect == 3 && isipv6)) && + ((tp->t_state == TCPS_ESTABLISHED) || + (tp->t_state == TCPS_FIN_WAIT_1))) { /* * Idea here is that at each stage of mtu probe (usually, diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c index 6c95635c18f..6e660283a69 100644 --- a/sys/netinet/tcp_stacks/rack.c +++ b/sys/netinet/tcp_stacks/rack.c @@ -3123,6 +3123,7 @@ rack_timeout_rxt(struct tcpcb *tp, struct tcp_rack *rack, uint32_t cts) int32_t rexmt; struct inpcb *inp; int32_t retval = 0; + bool isipv6; inp = tp->t_inpcb; if (tp->t_timers->tt_flags & TT_STOPPED) { @@ -3209,11 +3210,16 @@ rack_timeout_rxt(struct tcpcb *tp, struct tcp_rack *rack, uint32_t cts) * of packets and process straight to FIN. In that case we won't * catch ESTABLISHED state. */ - if (V_tcp_pmtud_blackhole_detect && (((tp->t_state == TCPS_ESTABLISHED)) - || (tp->t_state == TCPS_FIN_WAIT_1))) { #ifdef INET6 - int32_t isipv6; + isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? true : false; +#else + isipv6 = false; #endif + if (((V_tcp_pmtud_blackhole_detect == 1) || + (V_tcp_pmtud_blackhole_detect == 2 && !isipv6) || + (V_tcp_pmtud_blackhole_detect == 3 && isipv6)) && + ((tp->t_state == TCPS_ESTABLISHED) || + (tp->t_state == TCPS_FIN_WAIT_1))) { /* * Idea here is that at each stage of mtu probe (usually, @@ -3243,7 +3249,6 @@ rack_timeout_rxt(struct tcpcb *tp, struct tcp_rack *rack, uint32_t cts) * default in an attempt to retransmit. */ #ifdef INET6 - isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? 1 : 0; if (isipv6 && tp->t_maxseg > V_tcp_v6pmtud_blackhole_mss) { /* Use the sysctl tuneable blackhole MSS. */ diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 6a98eb75d5e..bd5f51c5bb9 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -614,6 +614,7 @@ tcp_timer_rexmt(void * xtp) int rexmt; struct inpcb *inp; struct epoch_tracker et; + bool isipv6; #ifdef TCPDEBUG int ostate; @@ -712,12 +713,16 @@ tcp_timer_rexmt(void * xtp) * packets and process straight to FIN. In that case we won't catch * ESTABLISHED state. */ - if (V_tcp_pmtud_blackhole_detect && (((tp->t_state == TCPS_ESTABLISHED)) - || (tp->t_state == TCPS_FIN_WAIT_1))) { #ifdef INET6 - int isipv6; + isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? true : false; +#else + isipv6 = false; #endif - + if (((V_tcp_pmtud_blackhole_detect == 1) || + (V_tcp_pmtud_blackhole_detect == 2 && !isipv6) || + (V_tcp_pmtud_blackhole_detect == 3 && isipv6)) && + ((tp->t_state == TCPS_ESTABLISHED) || + (tp->t_state == TCPS_FIN_WAIT_1))) { /* * Idea here is that at each stage of mtu probe (usually, 1448 * -> 1188 -> 524) should be given 2 chances to recover before @@ -746,7 +751,6 @@ tcp_timer_rexmt(void * xtp) * in an attempt to retransmit. */ #ifdef INET6 - isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? 1 : 0; if (isipv6 && tp->t_maxseg > V_tcp_v6pmtud_blackhole_mss) { /* Use the sysctl tuneable blackhole MSS. */ -- 2.45.0