diff options
author | ps <ps@FreeBSD.org> | 2005-04-14 20:09:52 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2005-04-14 20:09:52 +0000 |
commit | 2bf55008502e9691ab3ace062d854f1b10ba3667 (patch) | |
tree | 192aa6db528a920e2c180a45540eef55e2e4379f /sys/netinet/tcp_reass.c | |
parent | 73d2098d76ba5faed40c4fbc11258fb04f02aa56 (diff) | |
download | FreeBSD-src-2bf55008502e9691ab3ace062d854f1b10ba3667.zip FreeBSD-src-2bf55008502e9691ab3ace062d854f1b10ba3667.tar.gz |
Fix for a TCP SACK bug where more than (win/2) bytes could have been
in flight in SACK recovery.
Found by: Noritoshi Demizu
Submitted by: Mohan Srinivasan <mohans at yahoo-inc dot com>
Noritoshi Demizu <demizu at dd dot ij4u dot or dot jp>
Raja Mukerji <raja at moselle dot com>
Diffstat (limited to 'sys/netinet/tcp_reass.c')
-rw-r--r-- | sys/netinet/tcp_reass.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index d89bc2b..93e45e1 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -1840,7 +1840,27 @@ trimthenstep6: else if (++tp->t_dupacks > tcprexmtthresh || ((tcp_do_newreno || tp->sack_enable) && IN_FASTRECOVERY(tp))) { - tp->snd_cwnd += tp->t_maxseg; + + if (tp->sack_enable && IN_FASTRECOVERY(tp)) { + int data_in_pipe; + int sacked, lost_not_rexmitted; + + /* + * Compute the amount of data in flight first. + * We can inject new data into the pipe iff + * we have less than 1/2 the original window's + * worth of data in flight. + */ + sacked = tcp_sacked_bytes(tp, &lost_not_rexmitted); + data_in_pipe = (tp->snd_nxt - tp->snd_una) - + (sacked + lost_not_rexmitted); + if (data_in_pipe < tp->snd_ssthresh) { + tp->snd_cwnd += tp->t_maxseg; + if (tp->snd_cwnd > tp->snd_ssthresh) + tp->snd_cwnd = tp->snd_ssthresh; + } + } else + tp->snd_cwnd += tp->t_maxseg; (void) tcp_output(tp); goto drop; } else if (tp->t_dupacks == tcprexmtthresh) { |