aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/tcp.411
-rw-r--r--sys/netinet/tcp_timewait.c58
-rw-r--r--sys/netinet/tcp_var.h2
3 files changed, 49 insertions, 22 deletions
diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4
index 4c01daf4e14e..8bc1eb858a07 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 4f4ca445fa46..276733066c30 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -91,6 +91,11 @@
#include <security/mac/mac_framework.h>
+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 a1b0519ceac3..5b3733e8e91e 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)