tcp: undo on DSACK during recovery
authorYuchung Cheng <ycheng@google.com>
Wed, 29 May 2013 14:20:14 +0000 (14:20 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 May 2013 01:06:11 +0000 (18:06 -0700)
If the receiver supports DSACK, sender can detect false recoveries and
revert cwnd reductions triggered by either severe network reordering or
concurrent reordering and loss event.

Signed-off-by: Yuchung Cheng <ycheng@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_input.c

index c35b227519827cf583cf840eb85b9c402d1dce2f..907311c9a0121226209a93f381bdd0d6774e5c54 100644 (file)
@@ -2315,7 +2315,7 @@ static bool tcp_try_undo_recovery(struct sock *sk)
 }
 
 /* Try to undo cwnd reduction, because D-SACKs acked all retransmitted data */
-static void tcp_try_undo_dsack(struct sock *sk)
+static bool tcp_try_undo_dsack(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
@@ -2323,7 +2323,9 @@ static void tcp_try_undo_dsack(struct sock *sk)
                DBGUNDO(sk, "D-SACK");
                tcp_undo_cwnd_reduction(sk, false);
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO);
+               return true;
        }
+       return false;
 }
 
 /* We can clear retrans_stamp when there are no retransmissions in the
@@ -2751,6 +2753,10 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked,
                        do_lost = tcp_is_reno(tp) ||
                                  tcp_fackets_out(tp) > tp->reordering;
                }
+               if (tcp_try_undo_dsack(sk)) {
+                       tcp_try_keep_open(sk);
+                       return;
+               }
                break;
        case TCP_CA_Loss:
                tcp_process_loss(sk, flag, is_dupack);