diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index 4c01daf4e14..8bc1eb858a0 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 7, 2026 +.Dd May 17, 2026 .Dt TCP 4 .Os .Sh NAME @@ -940,6 +940,10 @@ maximum segment size. This helps throughput in general, but particularly affects short transfers and high-bandwidth large propagation-delay connections. +.It Va rfc6191 +Enable RFC 6191 connection recycling, which allows faster connection +recycling in certain circumstances when the new connection has TCP +timestamps enabled. .It Va sack.enable Enable support for RFC 2018, TCP Selective Acknowledgment option, which allows the receiver to inform the sender about all successfully @@ -1145,6 +1149,11 @@ when trying to use a TCP function block that is not available; .%T "Improving TCP's Robustness to Blind In-Window Attacks" .%O "RFC 5961" .Re +.Rs +.%A "F. Gont" +.%T "Reducing the TIME-WAIT State Using TCP Timestamps" +.%O "RFC 6191" +.Re .Sh HISTORY The .Tn TCP diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 4f4ca445fa4..276733066c3 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -91,6 +91,11 @@ #include +VNET_DEFINE(int, tcp_do_rfc6191) = 1; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_VNET | CTLFLAG_RW, + &VNET_NAME(tcp_do_rfc6191), 0, + "Enable RFC 6191 (Reduced TIME-WAIT State)"); + static u_int tcp_eff_msl(struct tcpcb *tp) { @@ -223,29 +228,40 @@ tcp_twcheck(struct inpcb *inp, struct tcpopt *to, struct tcphdr *th, } /* - * If a new connection request is received - * while in TIME_WAIT, drop the old connection - * and start over if allowed by RFC 6191. + * If a new connection request is received while in TIME_WAIT, + * drop the old connection and start over if appropriate. + * + * The original rule is to start over if and only if the sequence + * number of the new connection is greater than the last sequence + * number seen on the old connection. + * + * Additionally, RFC 6191 allows restarting if the new connection + * has TCP timestamps enabled and either the old one didn't, or it + * did but the timestamp on the incoming SYN is greater than the + * last timestamp seen on the old connection. + * * Allow UDP port number changes in this case. */ - if (((thflags & (TH_SYN | TH_ACK)) == TH_SYN) && - ((((tp->t_flags & TF_RCVD_TSTMP) != 0) && - ((to->to_flags & TOF_TS) != 0) && - TSTMP_LT(tp->ts_recent, to->to_tsval)) || - (((tp->t_flags & TF_RCVD_TSTMP) == 0) && - ((to->to_flags & TOF_TS) != 0) && - (V_tcp_tolerate_missing_ts == 0)) || - SEQ_GT(th->th_seq, tp->rcv_nxt))) { - /* - * In case we can't upgrade our lock just pretend we have - * lost this packet. - */ - if (INP_TRY_UPGRADE(inp) == 0) - goto drop; - if ((tp = tcp_close(tp)) != NULL) - INP_WUNLOCK(inp); - TCPSTAT_INC(tcps_tw_recycles); - return (true); + if ((thflags & (TH_SYN | TH_ACK)) == TH_SYN) { + bool rfc6191 = false; + + if ((to->to_flags & TOF_TS) != 0 && V_tcp_do_rfc6191) { + rfc6191 = (tp->t_flags & TF_RCVD_TSTMP) != 0 ? + TSTMP_LT(tp->ts_recent, to->to_tsval) : + V_tcp_tolerate_missing_ts == 0; + } + if (rfc6191 || SEQ_GT(th->th_seq, tp->rcv_nxt)) { + /* + * In case we can't upgrade our lock just pretend + * we have lost this packet. + */ + if (INP_TRY_UPGRADE(inp) == 0) + goto drop; + if ((tp = tcp_close(tp)) != NULL) + INP_WUNLOCK(inp); + TCPSTAT_INC(tcps_tw_recycles); + return (true); + } } /* diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index a1b0519ceac..5b3733e8e91 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1308,6 +1308,7 @@ VNET_DECLARE(int, tcp_tolerate_missing_ts); VNET_DECLARE(int, tcp_do_rfc3042); VNET_DECLARE(int, tcp_do_rfc3390); VNET_DECLARE(int, tcp_do_rfc3465); +VNET_DECLARE(int, tcp_do_rfc6191); VNET_DECLARE(int, tcp_do_sack); VNET_DECLARE(int, tcp_do_tso); VNET_DECLARE(int, tcp_ecn_maxretries); @@ -1358,6 +1359,7 @@ VNET_DECLARE(struct inpcbinfo, tcbinfo); #define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042) #define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390) #define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465) +#define V_tcp_do_rfc6191 VNET(tcp_do_rfc6191) #define V_tcp_do_sack VNET(tcp_do_sack) #define V_tcp_do_tso VNET(tcp_do_tso) #define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries)