svn commit: r366565 - stable/12/sys/netinet

Richard Scheffenegger rscheff at FreeBSD.org
Fri Oct 9 09:37:44 UTC 2020


Author: rscheff
Date: Fri Oct  9 09:37:43 2020
New Revision: 366565
URL: https://svnweb.freebsd.org/changeset/base/366565

Log:
  MFC r366150: TCP: send full initial window when timestamps are in use
  
  The fastpath in tcp_output tries to send out
  full segments, and avoid sending partial segments by
  comparing against the static t_maxseg variable.
  That value does not consider tcp options like timestamps,
  while the initial window calculation is using
  the correct dynamic tcp_maxseg() function.
  
  Due to this interaction, the last, full size segment
  is considered too short and not sent out immediately.
  
  Reported by:	tuexen
  MFC after:	2 weeks
  Sponsored by:	NetApp, Inc.
  Differential Revision:	https://reviews.freebsd.org/D26478

Modified:
  stable/12/sys/netinet/tcp.h
  stable/12/sys/netinet/tcp_output.c
  stable/12/sys/netinet/tcp_subr.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/netinet/tcp.h
==============================================================================
--- stable/12/sys/netinet/tcp.h	Fri Oct  9 09:33:45 2020	(r366564)
+++ stable/12/sys/netinet/tcp.h	Fri Oct  9 09:37:43 2020	(r366565)
@@ -80,6 +80,8 @@ struct tcphdr {
 	u_short	th_urp;			/* urgent pointer */
 };
 
+#define	PADTCPOLEN(len)		((((len) / 4) + !!((len) % 4)) * 4)
+
 #define	TCPOPT_EOL		0
 #define	   TCPOLEN_EOL			1
 #define	TCPOPT_PAD		0		/* padding after EOL */

Modified: stable/12/sys/netinet/tcp_output.c
==============================================================================
--- stable/12/sys/netinet/tcp_output.c	Fri Oct  9 09:33:45 2020	(r366564)
+++ stable/12/sys/netinet/tcp_output.c	Fri Oct  9 09:37:43 2020	(r366565)
@@ -577,6 +577,20 @@ after_sack_rexmit:
 		if (len >= tp->t_maxseg)
 			goto send;
 		/*
+		 * As the TCP header options are now
+		 * considered when setting up the initial
+		 * window, we would not send the last segment
+		 * if we skip considering the option length here.
+		 * Note: this may not work when tcp headers change
+		 * very dynamically in the future.
+		 */
+		if ((((tp->t_flags & TF_SIGNATURE) ?
+			PADTCPOLEN(TCPOLEN_SIGNATURE) : 0) +
+		    ((tp->t_flags & TF_RCVD_TSTMP) ?
+			PADTCPOLEN(TCPOLEN_TIMESTAMP) : 0) +
+		    len) >= tp->t_maxseg)
+			goto send;
+		/*
 		 * NOTE! on localhost connections an 'ack' from the remote
 		 * end may occur synchronously with the output and cause
 		 * us to flush a buffer queued with moretocome.  XXX

Modified: stable/12/sys/netinet/tcp_subr.c
==============================================================================
--- stable/12/sys/netinet/tcp_subr.c	Fri Oct  9 09:33:45 2020	(r366564)
+++ stable/12/sys/netinet/tcp_subr.c	Fri Oct  9 09:37:43 2020	(r366565)
@@ -2941,7 +2941,6 @@ tcp_maxseg(const struct tcpcb *tp)
 	 * but this is harmless, since result of tcp_maxseg() is used
 	 * only in cwnd and ssthresh estimations.
 	 */
-#define	PAD(len)	((((len) / 4) + !!((len) % 4)) * 4)
 	if (TCPS_HAVEESTABLISHED(tp->t_state)) {
 		if (tp->t_flags & TF_RCVD_TSTMP)
 			optlen = TCPOLEN_TSTAMP_APPA;
@@ -2949,26 +2948,26 @@ tcp_maxseg(const struct tcpcb *tp)
 			optlen = 0;
 #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
 		if (tp->t_flags & TF_SIGNATURE)
-			optlen += PAD(TCPOLEN_SIGNATURE);
+			optlen += PADTCPOLEN(TCPOLEN_SIGNATURE);
 #endif
 		if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks > 0) {
 			optlen += TCPOLEN_SACKHDR;
 			optlen += tp->rcv_numsacks * TCPOLEN_SACK;
-			optlen = PAD(optlen);
+			optlen = PADTCPOLEN(optlen);
 		}
 	} else {
 		if (tp->t_flags & TF_REQ_TSTMP)
 			optlen = TCPOLEN_TSTAMP_APPA;
 		else
-			optlen = PAD(TCPOLEN_MAXSEG);
+			optlen = PADTCPOLEN(TCPOLEN_MAXSEG);
 		if (tp->t_flags & TF_REQ_SCALE)
-			optlen += PAD(TCPOLEN_WINDOW);
+			optlen += PADTCPOLEN(TCPOLEN_WINDOW);
 #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
 		if (tp->t_flags & TF_SIGNATURE)
-			optlen += PAD(TCPOLEN_SIGNATURE);
+			optlen += PADTCPOLEN(TCPOLEN_SIGNATURE);
 #endif
 		if (tp->t_flags & TF_SACK_PERMIT)
-			optlen += PAD(TCPOLEN_SACK_PERMITTED);
+			optlen += PADTCPOLEN(TCPOLEN_SACK_PERMITTED);
 	}
 #undef PAD
 	optlen = min(optlen, TCP_MAXOLEN);


More information about the svn-src-all mailing list