Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Aug 2010 10:15:46 +0000 (UTC)
From:      Andre Oppermann <andre@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r211870 - stable/8/sys/netinet
Message-ID:  <201008271015.o7RAFknT072130@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andre
Date: Fri Aug 27 10:15:45 2010
New Revision: 211870
URL: http://svn.freebsd.org/changeset/base/211870

Log:
  MFC r211464:
  
    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:
  stable/8/sys/netinet/tcp_output.c
  stable/8/sys/netinet/tcp_var.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/netinet/tcp_output.c
==============================================================================
--- stable/8/sys/netinet/tcp_output.c	Fri Aug 27 09:59:51 2010	(r211869)
+++ stable/8/sys/netinet/tcp_output.c	Fri Aug 27 10:15:45 2010	(r211870)
@@ -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: stable/8/sys/netinet/tcp_var.h
==============================================================================
--- stable/8/sys/netinet/tcp_var.h	Fri Aug 27 09:59:51 2010	(r211869)
+++ stable/8/sys/netinet/tcp_var.h	Fri Aug 27 10:15:45 2010	(r211870)
@@ -556,6 +556,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);
@@ -566,6 +567,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?201008271015.o7RAFknT072130>