• Ilpo Järvinen's avatar
    tcp: fix retrans_stamp advancing in error cases · 77722b17
    Ilpo Järvinen authored
    It can happen, that tcp_retransmit_skb fails due to some error.
    In such cases we might end up into a state where tp->retrans_out
    is zero but that's only because we removed the TCPCB_SACKED_RETRANS
    bit from a segment but couldn't retransmit it because of the error
    that happened. Therefore some assumptions that retrans_out checks
    are based do not necessarily hold, as there still can be an old
    retransmission but that is only visible in TCPCB_EVER_RETRANS bit.
    As retransmission happen in sequential order (except for some very
    rare corner cases), it's enough to check the head skb for that bit.
    
    Main reason for all this complexity is the fact that connection dying
    time now depends on the validity of the retrans_stamp, in particular,
    that successive retransmissions of a segment must not advance
    retrans_stamp under any conditions. It seems after quick thinking that
    this has relatively low impact as eventually TCP will go into CA_Loss
    and either use the existing check for !retrans_stamp case or send a
    retransmission successfully, setting a new base time for the dying
    timer (can happen only once). At worst, the dying time will be
    approximately the double of the intented time. In addition,
    tcp_packet_delayed() will return wrong result (has some cc aspects
    but due to rarity of these errors, it's hardly an issue).
    
    One of retrans_stamp clearing happens indirectly through first going
    into CA_Open state and then a later ACK lets the clearing to happen.
    Thus tcp_try_keep_open has to be modified too.
    
    Thanks to Damian Lukowski <damian@tvk.rwth-aachen.de> for hinting
    that this possibility exists (though the particular case discussed
    didn't after all have it happening but was just a debug patch
    artifact).
    Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    77722b17
tcp_input.c 168 KB