• Yuchung Cheng's avatar
    tcp: fix false undo corner cases · 6e08d5e3
    Yuchung Cheng authored
    The undo code assumes that, upon entering loss recovery, TCP
    1) always retransmit something
    2) the retransmission never fails locally (e.g., qdisc drop)
    
    so undo_marker is set in tcp_enter_recovery() and undo_retrans is
    incremented only when tcp_retransmit_skb() is successful.
    
    When the assumption is broken because TCP's cwnd is too small to
    retransmit or the retransmit fails locally. The next (DUP)ACK
    would incorrectly revert the cwnd and the congestion state in
    tcp_try_undo_dsack() or tcp_may_undo(). Subsequent (DUP)ACKs
    may enter the recovery state. The sender repeatedly enter and
    (incorrectly) exit recovery states if the retransmits continue to
    fail locally while receiving (DUP)ACKs.
    
    The fix is to initialize undo_retrans to -1 and start counting on
    the first retransmission. Always increment undo_retrans even if the
    retransmissions fail locally because they couldn't cause DSACKs to
    undo the cwnd reduction.
    Signed-off-by: default avatarYuchung Cheng <ycheng@google.com>
    Signed-off-by: default avatarNeal Cardwell <ncardwell@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    6e08d5e3
tcp_output.c 94.9 KB