aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2013-02-03 21:14:25 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-06 15:53:03 -0500
commit6731d2095bd4aef18027c72ef845ab1087c3ba63 (patch)
treee0937e662eb7fd4ed026590e8dfa6c3abd37b806 /net/ipv4
parentb6ec447df935669d670e82bd66d9d161418efdfa (diff)
tcp: fix for zero packets_in_flight was too broad
There are transients during normal FRTO procedure during which the packets_in_flight can go to zero between write_queue state updates and firing the resulting segments out. As FRTO processing occurs during that window the check must be more precise to not match "spuriously" :-). More specificly, e.g., when packets_in_flight is zero but FLAG_DATA_ACKED is true the problematic branch that set cwnd into zero would not be taken and new segments might be sent out later. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Tested-by: Eric Dumazet <edumazet@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp_input.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 680c4224ed96..ad70a962c20e 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3484,8 +3484,7 @@ static bool tcp_process_frto(struct sock *sk, int flag)
3484 ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) 3484 ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED)))
3485 tp->undo_marker = 0; 3485 tp->undo_marker = 0;
3486 3486
3487 if (!before(tp->snd_una, tp->frto_highmark) || 3487 if (!before(tp->snd_una, tp->frto_highmark)) {
3488 !tcp_packets_in_flight(tp)) {
3489 tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); 3488 tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag);
3490 return true; 3489 return true;
3491 } 3490 }
@@ -3505,6 +3504,11 @@ static bool tcp_process_frto(struct sock *sk, int flag)
3505 } 3504 }
3506 } else { 3505 } else {
3507 if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) { 3506 if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) {
3507 if (!tcp_packets_in_flight(tp)) {
3508 tcp_enter_frto_loss(sk, 2, flag);
3509 return true;
3510 }
3511
3508 /* Prevent sending of new data. */ 3512 /* Prevent sending of new data. */
3509 tp->snd_cwnd = min(tp->snd_cwnd, 3513 tp->snd_cwnd = min(tp->snd_cwnd,
3510 tcp_packets_in_flight(tp)); 3514 tcp_packets_in_flight(tp));