Make the logic clear on when to use Eifel detection or fall back
authorJeffrey Hsu <hsu@dragonflybsd.org>
Thu, 14 Aug 2003 23:09:33 +0000 (23:09 +0000)
committerJeffrey Hsu <hsu@dragonflybsd.org>
Thu, 14 Aug 2003 23:09:33 +0000 (23:09 +0000)
onto the old RTT heuristic.

Move infrequently executed code out of the fast path to avoid
L1 instruction cache pollution.

Add statistics to disambiguate how a spurious retransmit was detected.

sys/netinet/tcp_input.c
sys/netinet/tcp_timer.c
sys/netinet/tcp_var.h

index 6ed1a05..f93f5bd 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2002-2003 Jeffrey Hsu
  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -32,7 +33,7 @@
  *
  *     @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/tcp_input.c,v 1.107.2.38 2003/05/21 04:46:41 cjc Exp $
- * $DragonFly: src/sys/netinet/tcp_input.c,v 1.8 2003/08/13 18:34:25 hsu Exp $
+ * $DragonFly: src/sys/netinet/tcp_input.c,v 1.9 2003/08/14 23:09:33 hsu Exp $
  */
 
 #include "opt_ipfw.h"          /* for ipfw_fwd         */
@@ -968,29 +969,24 @@ after_listen:
                                ++tcpstat.tcps_predack;
                                /*
                                 * "bad retransmit" recovery
+                                *
+                                * If Eifel detection applies, then
+                                * it is deterministic, so use it
+                                * unconditionally over the old heuristic.
+                                * Otherwise, fall back to the old heuristic.
                                 */
-                               useTS = tcp_do_eifel_detect &&
-                                       (to.to_flags & TOF_TS) &&
-                                       to.to_tsecr;
-                               if ((useTS &&
-                                    (tp->t_flags & TF_FIRSTACCACK) &&
-                                    (to.to_tsecr < tp->t_rexmtTS)) ||
-                                   (!useTS &&
-                                    (tp->t_rxtshift == 1 &&
-                                     ticks < tp->t_badrxtwin))) {
-                                       tp->snd_cwnd = tp->snd_cwnd_prev;
-                                       tp->snd_ssthresh =
-                                           tp->snd_ssthresh_prev;
-                                       tp->snd_recover = tp->snd_recover_prev;
-                                       if (tp->t_flags & TF_WASFRECOVERY)
-                                           ENTER_FASTRECOVERY(tp);
-                                       tp->snd_nxt = tp->snd_max;
-                                       tp->t_badrxtwin = 0;
-                                       tp->t_rxtshift = 0;
-                                       if (tp->t_flags & TF_FASTREXMT)
-                                               ++tcpstat.tcps_sndfastrexmitbad;
-                                       else
-                                               ++tcpstat.tcps_sndrtobad;
+                               if (tcp_do_eifel_detect &&
+                                   (to.to_flags & TOF_TS) && to.to_tsecr &&
+                                   (tp->t_flags & TF_FIRSTACCACK)) {
+                                       /* Eifel detection applicable. */
+                                       if (to.to_tsecr < tp->t_rexmtTS) {
+                                               tcp_revert_congestion_state(tp);
+                                               ++tcpstat.tcps_eifeldetected;
+                                       }
+                               } else if (tp->t_rxtshift == 1 &&
+                                          ticks < tp->t_badrxtwin) {
+                                       tcp_revert_congestion_state(tp);
+                                       ++tcpstat.tcps_rttdetected;
                                }
                                tp->t_flags &= ~(TF_FIRSTACCACK | TF_FASTREXMT);
                                /*
@@ -1836,24 +1832,17 @@ process_ACK:
                 * original cwnd and ssthresh, and proceed to transmit where
                 * we left off.
                 */
-               useTS = tcp_do_eifel_detect && (to.to_flags & TOF_TS) &&
-                   to.to_tsecr;
-               if ((useTS && (tp->t_flags & TF_FIRSTACCACK) && acked &&
-                    (to.to_tsecr < tp->t_rexmtTS)) ||
-                   (!useTS &&
-                    (tp->t_rxtshift == 1 && ticks < tp->t_badrxtwin))) {
-                       tp->snd_cwnd = tp->snd_cwnd_prev;
-                       tp->snd_ssthresh = tp->snd_ssthresh_prev;
-                       tp->snd_recover = tp->snd_recover_prev;
-                       if (tp->t_flags & TF_WASFRECOVERY)
-                               ENTER_FASTRECOVERY(tp);
-                       tp->snd_nxt = tp->snd_max;
-                       tp->t_badrxtwin = 0;    /* XXX probably not required */
-                       tp->t_rxtshift = 0;
-                       if (tp->t_flags & TF_FASTREXMT)
-                               ++tcpstat.tcps_sndfastrexmitbad;
-                       else
-                               ++tcpstat.tcps_sndrtobad;
+               if (tcp_do_eifel_detect && acked &&
+                   (to.to_flags & TOF_TS) && to.to_tsecr &&
+                   (tp->t_flags & TF_FIRSTACCACK)) {
+                       /* Eifel detection applicable. */
+                       if (to.to_tsecr < tp->t_rexmtTS) {
+                               tcp_revert_congestion_state(tp);
+                               ++tcpstat.tcps_eifeldetected;
+                       }
+               } else if (tp->t_rxtshift == 1 && ticks < tp->t_badrxtwin) {
+                       tcp_revert_congestion_state(tp);
+                       ++tcpstat.tcps_rttdetected;
                }
 
                /*
index 0292aff..c29f31c 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/tcp_timer.c,v 1.34.2.14 2003/02/03 02:33:41 hsu Exp $
- * $DragonFly: src/sys/netinet/tcp_timer.c,v 1.4 2003/08/13 18:34:25 hsu Exp $
+ * $DragonFly: src/sys/netinet/tcp_timer.c,v 1.5 2003/08/14 23:09:33 hsu Exp $
  */
 
 #include "opt_compat.h"
@@ -367,6 +367,23 @@ tcp_save_congestion_state(struct tcpcb *tp)
        }
 }
 
+void
+tcp_revert_congestion_state(struct tcpcb *tp)
+{
+       tp->snd_cwnd = tp->snd_cwnd_prev;
+       tp->snd_ssthresh = tp->snd_ssthresh_prev;
+       tp->snd_recover = tp->snd_recover_prev;
+       if (tp->t_flags & TF_WASFRECOVERY)
+           ENTER_FASTRECOVERY(tp);
+       if (tp->t_flags & TF_FASTREXMT)
+               ++tcpstat.tcps_sndfastrexmitbad;
+       else
+               ++tcpstat.tcps_sndrtobad;
+       tp->t_badrxtwin = 0;
+       tp->t_rxtshift = 0;
+       tp->snd_nxt = tp->snd_max;
+}
+
 void
 tcp_timer_rexmt(xtp)
        void *xtp;
index 5a4877e..196b04d 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)tcp_var.h   8.4 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/tcp_var.h,v 1.56.2.13 2003/02/03 02:34:07 hsu Exp $
- * $DragonFly: src/sys/netinet/tcp_var.h,v 1.6 2003/08/14 21:08:57 hsu Exp $
+ * $DragonFly: src/sys/netinet/tcp_var.h,v 1.7 2003/08/14 23:09:33 hsu Exp $
  */
 
 #ifndef _NETINET_TCP_VAR_H_
@@ -329,6 +329,8 @@ struct      tcpstat {
        u_long  tcps_sndrexmitbyte;     /* data bytes retransmitted */
        u_long  tcps_sndrtobad;         /* spurious RTO retransmissions */
        u_long  tcps_sndfastrexmitbad;  /* spurious Fast Retransmissions */
+       u_long  tcps_eifeldetected;     /* Eifel-detected spurious rexmits */
+       u_long  tcps_rttdetected;       /* RTT-detected spurious RTO rexmits */
        u_long  tcps_sndacks;           /* ack-only packets sent */
        u_long  tcps_sndprobe;          /* window probes sent */
        u_long  tcps_sndurg;            /* packets sent with URG only */
@@ -481,6 +483,7 @@ void         tcp_respond __P((struct tcpcb *, void *,
 struct rtentry *
         tcp_rtlookup __P((struct in_conninfo *));
 void    tcp_save_congestion_state(struct tcpcb *tp);
+void    tcp_revert_congestion_state(struct tcpcb *tp);
 void    tcp_setpersist __P((struct tcpcb *));
 void    tcp_slowtimo __P((void));
 struct tcptemp *