summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2007-08-30 06:21:05 +0200
committerAdrian Bunk <bunk@stusta.de>2007-09-24 23:02:47 +0200
commit3198d0f16dec0c87071cf26f3f11af9c8f0a009b (patch)
tree4fe6063703d512c44d18e8700d55c6cb5a7ffe0c
parent725ad2a8f1358bff885414f5e91d253c99921ddc (diff)
TCP: Fix TCP handling of SACK in bidirectional flows
It's possible that new SACK blocks that should trigger new LOST markings arrive with new data (which previously made is_dupack false). In addition, I think this fixes a case where we get a cumulative ACK with enough SACK blocks to trigger the fast recovery (is_dupack would be false there too). I'm not completely pleased with this solution because readability of the code is somewhat questionable as 'is_dupack' in SACK case is no longer about dupacks only but would mean something like 'lost_marker_work_todo' too... But because of Eifel stuff done in CA_Recovery, the FLAG_DATA_SACKED check cannot be placed to the if statement which seems attractive solution. Nevertheless, I didn't like adding another variable just for that either... :-) Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Adrian Bunk <bunk@kernel.org>
-rw-r--r--net/ipv4/tcp_input.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 412e3d214d7c..cdeca2d5c115 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1909,7 +1909,10 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
- int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP));
+ int is_dupack = (tp->snd_una == prior_snd_una &&
+ (!(flag&FLAG_NOT_DUP) ||
+ ((flag&FLAG_DATA_SACKED) &&
+ (tp->fackets_out > tp->reordering))));
/* Some technical things:
* 1. Reno does not count dupacks (sacked_out) automatically. */