diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2000-09-05 21:57:42 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2000-09-05 21:57:42 +0000 |
commit | bd283c54e9b0fb364bc2573d357bf401b661b747 (patch) | |
tree | 74d5cff36092378594e3baf96ad1da74f036a829 | |
parent | 20def5508e57c7205c4776a54a03e0df6aa4f3cd (diff) |
various fixes to SACK and FACK from adesai@cisco.com, tomh@tomh.org and
osuga@mml.yrp.nttdocomo.co.jp
-rw-r--r-- | sys/netinet/tcp_input.c | 28 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 24 |
2 files changed, 41 insertions, 11 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index e84f649e326..33a38b7dee4 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.68 2000/07/27 04:05:26 itojun Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.69 2000/09/05 21:57:41 provos Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -1563,9 +1563,7 @@ trimthenstep6: * False fast retx after * timeout. Do not cut window. */ - tp->snd_cwnd += tp->t_maxseg; tp->t_dupacks = 0; - (void) tcp_output(tp); goto drop; } #endif @@ -1581,13 +1579,13 @@ trimthenstep6: tp->t_rtt = 0; tcpstat.tcps_sndrexmitfast++; #if defined(TCP_SACK) && defined(TCP_FACK) + tp->t_dupacks = tcprexmtthresh; (void) tcp_output(tp); /* * During FR, snd_cwnd is held * constant for FACK. */ tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = tcprexmtthresh; #else /* * tcp_output() will send @@ -1663,7 +1661,7 @@ trimthenstep6: th->th_ack) < tp->snd_ssthresh) tp->snd_cwnd = tcp_seq_subtract(tp->snd_max, - th->th_ack) + tp->t_maxseg; + th->th_ack); tp->t_dupacks = 0; #if defined(TCP_SACK) && defined(TCP_FACK) if (SEQ_GT(th->th_ack, tp->snd_fack)) @@ -1680,7 +1678,7 @@ trimthenstep6: tp->snd_ssthresh) tp->snd_cwnd = tcp_seq_subtract(tp->snd_max, - th->th_ack) + tp->t_maxseg; + th->th_ack); tp->t_dupacks = 0; } } @@ -1739,7 +1737,7 @@ trimthenstep6: if (cw > tp->snd_ssthresh) incr = incr * incr / cw; #if defined (TCP_SACK) - if (SEQ_GEQ(th->th_ack, tp->snd_last)) + if (tp->t_dupacks < tcprexmtthresh) #endif tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); } @@ -1759,8 +1757,14 @@ trimthenstep6: if (SEQ_LT(tp->snd_nxt, tp->snd_una)) tp->snd_nxt = tp->snd_una; #if defined (TCP_SACK) && defined (TCP_FACK) - if (SEQ_GT(tp->snd_una, tp->snd_fack)) + if (SEQ_GT(tp->snd_una, tp->snd_fack)) { tp->snd_fack = tp->snd_una; + /* Update snd_awnd for partial ACK + * without any SACK blocks. + */ + tp->snd_awnd = tcp_seq_subtract(tp->snd_nxt, + tp->snd_fack) + tp->retran_data; + } #endif switch (tp->t_state) { @@ -2546,6 +2550,8 @@ tcp_del_sackholes(tp, th) tp->snd_numholes--; } else if (SEQ_LT(cur->start, lastack)) { cur->start = lastack; + if (SEQ_LT(cur->rxmit, cur->start)) + cur->rxmit = cur->start; break; } else break; @@ -2588,7 +2594,11 @@ tcp_sack_partialack(tp, th) * fact that tp->snd_una has not been updated yet. In FACK * hold snd_cwnd constant during fast recovery. */ - tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); + if (tp->snd_cwnd > (th->th_ack - tp->snd_una)) { + tp->snd_cwnd -= th->th_ack - tp->snd_una; + tp->snd_cwnd += tp->t_maxseg; + } else + tp->snd_cwnd = tp->t_maxseg; #endif return 1; } diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 07164c6ff8a..a746eea1b41 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_output.c,v 1.30 2000/02/21 21:42:13 provos Exp $ */ +/* $OpenBSD: tcp_output.c,v 1.31 2000/09/05 21:57:41 provos Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* @@ -127,7 +127,17 @@ register struct tcpcb *tp; return 0; p = tp->snd_holes; while (p) { +#ifndef TCP_FACK if (p->dups >= tcprexmtthresh && SEQ_LT(p->rxmit, p->end)) { +#else + /* In FACK, if p->dups is less than tcprexmtthresh, but + * snd_fack advances more than tcprextmtthresh * tp->t_maxseg, + * tcp_input() will try fast retransmit. This forces output. + */ + if ((p->dups >= tcprexmtthresh || + tp->t_dupacks == tcprexmtthresh) && + SEQ_LT(p->rxmit, p->end)) { +#endif /* TCP_FACK */ if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */ p = p->next; continue; @@ -235,6 +245,15 @@ again: tcp_sack_adjust(tp); #endif off = tp->snd_nxt - tp->snd_una; +#if defined(TCP_SACK) && defined(TCP_FACK) + /* Normally, sendable data is limited by off < tp->snd_cwnd. + * But in FACK, sendable data is limited by snd_awnd < snd_cwnd, + * regardless of offset. + */ + if (!tp->sack_disable && (tp->t_dupacks > tcprexmtthresh)) + win = tp->snd_wnd; + else +#endif win = ulmin(tp->snd_wnd, tp->snd_cwnd); flags = tcp_outflags[tp->t_state]; @@ -248,7 +267,8 @@ again: * now, and we previously incremented snd_cwnd in tcp_input(). */ if (!tp->sack_disable && !sendalot) { - if ((p = tcp_sack_output(tp))) { + if (tp->t_dupacks >= tcprexmtthresh && + (p = tcp_sack_output(tp))) { off = p->rxmit - tp->snd_una; sack_rxmit = 1; #if 0 |