From bfdb979ed8c69cbc1e8bb84110840c7b4d2de161 Mon Sep 17 00:00:00 2001 From: Jeffrey Hsu Date: Thu, 14 Aug 2003 23:09:33 +0000 Subject: [PATCH] Make the logic clear on when to use Eifel detection or fall back 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 | 71 +++++++++++++++++------------------------ sys/netinet/tcp_timer.c | 19 ++++++++++- sys/netinet/tcp_var.h | 5 ++- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 6ed1a0501a..f93f5bdec7 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -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; } /* diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 0292aff1a9..c29f31c5c1 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -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; diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 5a4877ec86..196b04d866 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -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 * -- 2.41.0