From: Matthew Dillon Date: Thu, 16 Dec 2004 03:37:30 +0000 (+0000) Subject: Correct a bug where incoming connections do not properly initialize the X-Git-Tag: v2.0.1~9532 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/421de19e31318721c95ddb298c1c734933a2a615 Correct a bug where incoming connections do not properly initialize the inflight bandwidth calculator. Reorg the code a bit, removing random initialization elsewhere and putting it all in one place. Add an idle check and a pure-ack check. Reported-by: Dan Nelson --- diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 02555639da..e47300d370 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -82,7 +82,7 @@ * * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.73.2.31 2003/01/24 05:11:34 sam Exp $ - * $DragonFly: src/sys/netinet/tcp_subr.c,v 1.40 2004/11/14 00:49:08 hsu Exp $ + * $DragonFly: src/sys/netinet/tcp_subr.c,v 1.41 2004/12/16 03:37:30 dillon Exp $ */ #include "opt_compat.h" @@ -692,7 +692,6 @@ tcp_newtcpcb(struct inpcb *inp) tp->snd_bwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_rcvtime = ticks; - tp->t_bw_rtttime = ticks; /* * IPv4 TTL initialization is necessary for an IPv6 socket as well, * because the socket may be bound to an IPv6 wildcard address, @@ -1834,6 +1833,7 @@ tcp_xmit_bandwidth_limit(struct tcpcb *tp, tcp_seq ack_seq) u_long bw; u_long bwnd; int save_ticks; + int delta_ticks; /* * If inflight_enable is disabled in the middle of a tcp connection, @@ -1845,6 +1845,28 @@ tcp_xmit_bandwidth_limit(struct tcpcb *tp, tcp_seq ack_seq) return; } + /* + * Validate the delta time. If a connection is new or has been idle + * a long time we have to reset the bandwidth calculator. + */ + save_ticks = ticks; + delta_ticks = save_ticks - tp->t_bw_rtttime; + if (tp->t_bw_rtttime == 0 || delta_ticks < 0 || delta_ticks > hz * 10) { + tp->t_bw_rtttime = ticks; + tp->t_bw_rtseq = ack_seq; + if (tp->snd_bandwidth == 0) + tp->snd_bandwidth = tcp_inflight_min; + return; + } + if (delta_ticks == 0) + return; + + /* + * Sanity check, plus ignore pure window update acks. + */ + if ((int)(ack_seq - tp->t_bw_rtseq) <= 0) + return; + /* * Figure out the bandwidth. Due to the tick granularity this * is a very rough number and it MUST be averaged over a fairly @@ -1852,20 +1874,10 @@ tcp_xmit_bandwidth_limit(struct tcpcb *tp, tcp_seq ack_seq) * that is not using all available bandwidth, but for now our * slop will ramp us up if this case occurs and the bandwidth later * increases. - * - * Note: if ticks rollover 'bw' may wind up negative. We must - * effectively reset t_bw_rtttime for this case. */ - save_ticks = ticks; - if ((u_int)(save_ticks - tp->t_bw_rtttime) < 1) - return; - - bw = (int64_t)(ack_seq - tp->t_bw_rtseq) * hz / - (save_ticks - tp->t_bw_rtttime); + bw = (int64_t)(ack_seq - tp->t_bw_rtseq) * hz / delta_ticks; tp->t_bw_rtttime = save_ticks; tp->t_bw_rtseq = ack_seq; - if (tp->t_bw_rtttime == 0 || (int)bw < 0) - return; bw = ((int64_t)tp->snd_bandwidth * 15 + bw) >> 4; tp->snd_bandwidth = bw; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index e92ac2e770..5381cef64d 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -82,7 +82,7 @@ * * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.51.2.17 2002/10/11 11:46:44 ume Exp $ - * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.29 2004/12/08 23:59:01 hsu Exp $ + * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.30 2004/12/16 03:37:30 dillon Exp $ */ #include "opt_ipsec.h" @@ -873,7 +873,6 @@ tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin, tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); tp->iss = tcp_new_isn(tp); - tp->t_bw_rtseq = tp->iss; tcp_sendseqinit(tp); /* @@ -1036,7 +1035,6 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); tp->iss = tcp_new_isn(tp); - tp->t_bw_rtseq = tp->iss; tcp_sendseqinit(tp); /*