summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2005-04-14 20:09:52 +0000
committerps <ps@FreeBSD.org>2005-04-14 20:09:52 +0000
commit2bf55008502e9691ab3ace062d854f1b10ba3667 (patch)
tree192aa6db528a920e2c180a45540eef55e2e4379f /sys/netinet/tcp_input.c
parent73d2098d76ba5faed40c4fbc11258fb04f02aa56 (diff)
downloadFreeBSD-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_input.c')
-rw-r--r--sys/netinet/tcp_input.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index d89bc2b..93e45e1 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.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) {
OpenPOWER on IntegriCloud