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)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to