Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Aug 2010 18:05:54 +0000 (UTC)
From:      Andre Oppermann <andre@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r211464 - head/sys/netinet
Message-ID:  <201008181805.o7II5s1R076527@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andre
Date: Wed Aug 18 18:05:54 2010
New Revision: 211464
URL: http://svn.freebsd.org/changeset/base/211464

Log:
  If a TCP connection has been idle for one retransmit timeout or more
  it must reset its congestion window back to the initial window.
  
  RFC3390 has increased the initial window from 1 segment to up to
  4 segments.
  
  The initial window increase of RFC3390 wasn't reflected into the
  restart window which remained at its original defaults of 4 segments
  for local and 1 segment for all other connections.  Both values are
  controllable through sysctl net.inet.tcp.local_slowstart_flightsize
  and net.inet.tcp.slowstart_flightsize.
  
  The increase helps TCP's slow start algorithm to open up the congestion
  window much faster.
  
  Reviewed by:	lstewart
  MFC after:	1 week

Modified:
  head/sys/netinet/tcp_output.c
  head/sys/netinet/tcp_var.h

Modified: head/sys/netinet/tcp_output.c
==============================================================================
--- head/sys/netinet/tcp_output.c	Wed Aug 18 17:40:10 2010	(r211463)
+++ head/sys/netinet/tcp_output.c	Wed Aug 18 18:05:54 2010	(r211464)
@@ -140,7 +140,7 @@ tcp_output(struct tcpcb *tp)
 {
 	struct socket *so = tp->t_inpcb->inp_socket;
 	long len, recwin, sendwin;
-	int off, flags, error;
+	int off, flags, error, rw;
 	struct mbuf *m;
 	struct ip *ip = NULL;
 	struct ipovly *ipov = NULL;
@@ -176,23 +176,34 @@ tcp_output(struct tcpcb *tp)
 	idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
 	if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur) {
 		/*
-		 * We have been idle for "a while" and no acks are
-		 * expected to clock out any data we send --
-		 * slow start to get ack "clock" running again.
+		 * If we've been idle for more than one retransmit
+		 * timeout the old congestion window is no longer
+		 * current and we have to reduce it to the restart
+		 * window before we can transmit again.
 		 *
-		 * Set the slow-start flight size depending on whether
-		 * this is a local network or not.
+		 * The restart window is the initial window or the last
+		 * CWND, whichever is smaller.
+		 * 
+		 * This is done to prevent us from flooding the path with
+		 * a full CWND at wirespeed, overloading router and switch
+		 * buffers along the way.
+		 *
+		 * See RFC5681 Section 4.1. "Restarting Idle Connections".
 		 */
-		int ss = V_ss_fltsz;
+		if (V_tcp_do_rfc3390)
+			rw = min(4 * tp->t_maxseg,
+				 max(2 * tp->t_maxseg, 4380));
 #ifdef INET6
-		if (isipv6) {
-			if (in6_localaddr(&tp->t_inpcb->in6p_faddr))
-				ss = V_ss_fltsz_local;
-		} else
-#endif /* INET6 */
-		if (in_localaddr(tp->t_inpcb->inp_faddr))
-			ss = V_ss_fltsz_local;
-		tp->snd_cwnd = tp->t_maxseg * ss;
+		else if ((isipv6 ? in6_localaddr(&tp->t_inpcb->in6p_faddr) :
+			  in_localaddr(tp->t_inpcb->inp_faddr)))
+#else
+		else if (in_localaddr(tp->t_inpcb->inp_faddr))
+#endif
+			rw = V_ss_fltsz_local * tp->t_maxseg;
+		else
+			rw = V_ss_fltsz * tp->t_maxseg;
+
+		tp->snd_cwnd = min(rw, tp->snd_cwnd);
 	}
 	tp->t_flags &= ~TF_LASTIDLE;
 	if (idle) {

Modified: head/sys/netinet/tcp_var.h
==============================================================================
--- head/sys/netinet/tcp_var.h	Wed Aug 18 17:40:10 2010	(r211463)
+++ head/sys/netinet/tcp_var.h	Wed Aug 18 18:05:54 2010	(r211464)
@@ -565,6 +565,7 @@ extern	int tcp_log_in_vain;
 VNET_DECLARE(int, tcp_mssdflt);	/* XXX */
 VNET_DECLARE(int, tcp_minmss);
 VNET_DECLARE(int, tcp_delack_enabled);
+VNET_DECLARE(int, tcp_do_rfc3390);
 VNET_DECLARE(int, tcp_do_newreno);
 VNET_DECLARE(int, path_mtu_discovery);
 VNET_DECLARE(int, ss_fltsz);
@@ -575,6 +576,7 @@ VNET_DECLARE(int, ss_fltsz_local);
 #define	V_tcp_mssdflt		VNET(tcp_mssdflt)
 #define	V_tcp_minmss		VNET(tcp_minmss)
 #define	V_tcp_delack_enabled	VNET(tcp_delack_enabled)
+#define	V_tcp_do_rfc3390	VNET(tcp_do_rfc3390)
 #define	V_tcp_do_newreno	VNET(tcp_do_newreno)
 #define	V_path_mtu_discovery	VNET(path_mtu_discovery)
 #define	V_ss_fltsz		VNET(ss_fltsz)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008181805.o7II5s1R076527>