git: e82353f84c58 - stable/12 - tcp: add sysctl to tolerate TCP segments missing timestamps

Michael Tuexen tuexen at FreeBSD.org
Sun Jan 24 15:20:30 UTC 2021


The branch stable/12 has been updated by tuexen:

URL: https://cgit.FreeBSD.org/src/commit/?id=e82353f84c58da9a5c38bd471a09936c16a5b6ea

commit e82353f84c58da9a5c38bd471a09936c16a5b6ea
Author:     Michael Tuexen <tuexen at FreeBSD.org>
AuthorDate: 2021-01-13 21:48:17 +0000
Commit:     Michael Tuexen <tuexen at FreeBSD.org>
CommitDate: 2021-01-24 14:46:12 +0000

    tcp: add sysctl to tolerate TCP segments missing timestamps
    
    When timestamp support has been negotiated, TCP segements received
    without a timestamp should be discarded. However, there are broken
    TCP implementations (for example, stacks used by Omniswitch 63xx and
    64xx models), which send TCP segments without timestamps although
    they negotiated timestamp support.
    This patch adds a sysctl variable which tolerates such TCP segments
    and allows to interoperate with broken stacks.
    
    Reviewed by:            jtl@, rscheff@
    Differential Revision:  https://reviews.freebsd.org/D28142
    Sponsored by:           Netflix, Inc.
    PR:                     252449
    
    (cherry picked from commit d2b3ceddccac60b563f642898e3a314647666a10)
---
 share/man/man4/tcp.4          | 23 ++++++++++++++++++++---
 sys/netinet/tcp_input.c       |  5 +++--
 sys/netinet/tcp_stacks/rack.c |  5 +++--
 sys/netinet/tcp_subr.c        |  5 +++++
 sys/netinet/tcp_syncache.c    | 26 +++++++++++++++++++-------
 sys/netinet/tcp_timewait.c    |  5 +++--
 sys/netinet/tcp_var.h         |  2 ++
 7 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4
index c9458c7cbafa..e1e87afd7fd6 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 31, 2020
+.Dd January 14, 2021
 .Dt TCP 4
 .Os
 .Sh NAME
@@ -333,8 +333,17 @@ MIB.
 .Bl -tag -width ".Va TCPCTL_DO_RFC1323"
 .It Dv TCPCTL_DO_RFC1323
 .Pq Va rfc1323
-Implement the window scaling and timestamp options of RFC 1323
+Implement the window scaling and timestamp options of RFC 1323/RFC 7323
 (default is true).
+.It Va tolerate_missing_ts
+Tolerate the missing of timestamps (RFC 1323/RFC 7323) for
+.Tn TCP
+segments belonging to
+.Tn TCP
+connections for which support of
+.Tn TCP
+timestamps has been negotiated.
+(default is 0, i.e., the missing of timestamps is not tolerated).
 .It Dv TCPCTL_MSSDFLT
 .Pq Va mssdflt
 The default value used for the maximum segment size
@@ -673,12 +682,20 @@ when trying to use a TCP function block that is not available;
 .Xr tcp_functions 9
 .Rs
 .%A "V. Jacobson"
-.%A "R. Braden"
+.%A "B. Braden"
 .%A "D. Borman"
 .%T "TCP Extensions for High Performance"
 .%O "RFC 1323"
 .Re
 .Rs
+.%A "D. Borman"
+.%A "B. Braden"
+.%A "V. Jacobson"
+.%A "R. Scheffenegger"
+.%T "TCP Extensions for High Performance"
+.%O "RFC 7323"
+.Re
+.Rs
 .%A "A. Heffernan"
 .%T "Protection of BGP Sessions via the TCP MD5 Signature Option"
 .%O "RFC 2385"
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 31f18c669640..755d645d338c 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1708,11 +1708,12 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
 	/*
 	 * If timestamps were negotiated during SYN/ACK and a
 	 * segment without a timestamp is received, silently drop
-	 * the segment, unless it is a RST segment.
+	 * the segment, unless it is a RST segment or missing timestamps are
+	 * tolerated.
 	 * See section 3.2 of RFC 7323.
 	 */
 	if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
-		if ((thflags & TH_RST) != 0) {
+		if (((thflags & TH_RST) != 0) || V_tcp_tolerate_missing_ts) {
 			if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
 				log(LOG_DEBUG, "%s; %s: Timestamp missing, "
 				    "segment processed normally\n",
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index e46781bb01df..1d063a8a1f6f 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -6719,11 +6719,12 @@ rack_hpts_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
 	/*
 	 * If timestamps were negotiated during SYN/ACK and a
 	 * segment without a timestamp is received, silently drop
-	 * the segment, unless it is a RST segment.
+	 * the segment, unless it is a RST segment or missing timestamps are
+	 * tolerated.
 	 * See section 3.2 of RFC 7323.
 	 */
 	if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS) &&
-	    ((thflags & TH_RST) == 0)) {
+	    ((thflags & TH_RST) == 0) && (V_tcp_tolerate_missing_ts == 0)) {
 		way_out = 5;
 		retval = 0;
 		goto done_with_input;
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 17996b492a96..5394a63c1a12 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -195,6 +195,11 @@ SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_VNET | CTLFLAG_RW,
     &VNET_NAME(tcp_do_rfc1323), 0,
     "Enable rfc1323 (high performance TCP) extensions");
 
+VNET_DEFINE(int, tcp_tolerate_missing_ts) = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, tolerate_missing_ts, CTLFLAG_VNET | CTLFLAG_RW,
+    &VNET_NAME(tcp_tolerate_missing_ts), 0,
+    "Tolerate missing TCP timestamps");
+
 VNET_DEFINE(int, tcp_ts_offset_per_conn) = 1;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, ts_offset_per_conn, CTLFLAG_VNET | CTLFLAG_RW,
     &VNET_NAME(tcp_ts_offset_per_conn), 0,
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index fe55eadfbcff..d06b54cffc1c 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1161,18 +1161,30 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
 		/*
 		 * If timestamps were negotiated during SYN/ACK and a
 		 * segment without a timestamp is received, silently drop
-		 * the segment.
+		 * the segment, unless the missing timestamps are tolerated.
 		 * See section 3.2 of RFC 7323.
 		 */
 		if ((sc->sc_flags & SCF_TIMESTAMP) &&
 		    !(to->to_flags & TOF_TS)) {
-			SCH_UNLOCK(sch);
-			if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
-				log(LOG_DEBUG, "%s; %s: Timestamp missing, "
-				    "segment silently dropped\n", s, __func__);
-				free(s, M_TCPLOG);
+			if (V_tcp_tolerate_missing_ts) {
+				if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+					log(LOG_DEBUG,
+					    "%s; %s: Timestamp missing, "
+					    "segment processed normally\n",
+					    s, __func__);
+					free(s, M_TCPLOG);
+				}
+			} else {
+				SCH_UNLOCK(sch);
+				if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+					log(LOG_DEBUG,
+					    "%s; %s: Timestamp missing, "
+					    "segment silently dropped\n",
+					    s, __func__);
+					free(s, M_TCPLOG);
+				}
+				return (-1);  /* Do not send RST */
 			}
-			return (-1);  /* Do not send RST */
 		}
 
 		/*
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index a1f6226315b6..8ab87711595e 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -450,10 +450,11 @@ tcp_twcheck(struct inpcb *inp, struct tcpopt *to, struct tcphdr *th,
 	/*
 	 * If timestamps were negotiated during SYN/ACK and a
 	 * segment without a timestamp is received, silently drop
-	 * the segment.
+	 * the segment, unless the missing timestamps are tolerated.
 	 * See section 3.2 of RFC 7323.
 	 */
-	if (((to->to_flags & TOF_TS) == 0) && (tw->t_recent != 0)) {
+	if (((to->to_flags & TOF_TS) == 0) && (tw->t_recent != 0) &&
+	    (V_tcp_tolerate_missing_ts == 0)) {
 		goto drop;
 	}
 
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 4fffcb860806..965c2bf031e1 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -780,6 +780,7 @@ VNET_DECLARE(int, tcp_do_autorcvbuf);
 VNET_DECLARE(int, tcp_do_autosndbuf);
 VNET_DECLARE(int, tcp_do_ecn);
 VNET_DECLARE(int, tcp_do_rfc1323);
+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);
@@ -815,6 +816,7 @@ VNET_DECLARE(struct inpcbinfo, tcbinfo);
 #define	V_tcp_do_autosndbuf		VNET(tcp_do_autosndbuf)
 #define	V_tcp_do_ecn			VNET(tcp_do_ecn)
 #define	V_tcp_do_rfc1323		VNET(tcp_do_rfc1323)
+#define	V_tcp_tolerate_missing_ts	VNET(tcp_tolerate_missing_ts)
 #define V_tcp_ts_offset_per_conn	VNET(tcp_ts_offset_per_conn)
 #define	V_tcp_do_rfc3042		VNET(tcp_do_rfc3042)
 #define	V_tcp_do_rfc3390		VNET(tcp_do_rfc3390)


More information about the dev-commits-src-branches mailing list