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
MFC after:		1 week
This commit is contained in:
Michael Tuexen 2021-01-13 22:48:17 +01:00
parent 54c743e5b2
commit d2b3ceddcc
8 changed files with 58 additions and 18 deletions

View File

@ -34,7 +34,7 @@
.\" From: @(#)tcp.4 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
.Dd December 19, 2020
.Dd January 14, 2021
.Dt TCP 4
.Os
.Sh NAME
@ -369,8 +369,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
@ -728,12 +737,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"

View File

@ -1692,11 +1692,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",

View File

@ -11463,11 +11463,12 @@ bbr_do_segment_nounlock(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)) {
retval = 0;
goto done_with_input;
}

View File

@ -10879,11 +10879,12 @@ rack_do_segment_nounlock(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;

View File

@ -256,6 +256,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,

View File

@ -1231,18 +1231,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 */
}
/*

View File

@ -451,10 +451,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;
}

View File

@ -840,6 +840,7 @@ VNET_DECLARE(int, tcp_do_autosndbuf);
VNET_DECLARE(int, tcp_do_ecn);
VNET_DECLARE(int, tcp_do_newcwv);
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);
@ -883,6 +884,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)