• Sébastien Barré's avatar
    tcp: avoid reducing cwnd when ACK+DSACK is received · 08abdffa
    Sébastien Barré authored
    With TLP, the peer may reply to a probe with an
    ACK+D-SACK, with ack value set to tlp_high_seq. In the current code,
    such ACK+DSACK will be missed and only at next, higher ack will the TLP
    episode be considered done. Since the DSACK is not present anymore,
    this will cost a cwnd reduction.
    
    This patch ensures that this scenario does not cause a cwnd reduction, since
    receiving an ACK+DSACK indicates that both the initial segment and the probe
    have been received by the peer.
    
    The following packetdrill test, from Neal Cardwell, validates this patch:
    
    // Establish a connection.
    0     socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
    +0     setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
    +0    bind(3, ..., ...) = 0
    +0    listen(3, 1) = 0
    
    +0    < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
    +0    > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 6>
    +.020 < . 1:1(0) ack 1 win 257
    +0    accept(3, ..., ...) = 4
    
    // Send 1 packet.
    +0    write(4, ..., 1000) = 1000
    +0    > P. 1:1001(1000) ack 1
    
    // Loss probe retransmission.
    // packets_out == 1 => schedule PTO in max(2*RTT, 1.5*RTT + 200ms)
    // In this case, this means: 1.5*RTT + 200ms = 230ms
    +.230 > P. 1:1001(1000) ack 1
    +0    %{ assert tcpi_snd_cwnd == 10 }%
    
    // Receiver ACKs at tlp_high_seq with a DSACK,
    // indicating they received the original packet and probe.
    +.020 < . 1:1(0) ack 1001 win 257 <sack 1:1001,nop,nop>
    +0    %{ assert tcpi_snd_cwnd == 10 }%
    
    // Send another packet.
    +0    write(4, ..., 1000) = 1000
    +0    > P. 1001:2001(1000) ack 1
    
    // Receiver ACKs above tlp_high_seq, which should end the TLP episode
    // if we haven't already. We should not reduce cwnd.
    +.020 < . 1:1(0) ack 2001 win 257
    +0    %{ assert tcpi_snd_cwnd == 10, tcpi_snd_cwnd }%
    
    Credits:
    -Gregory helped in finding that tcp_process_tlp_ack was where the cwnd
    got reduced in our MPTCP tests.
    -Neal wrote the packetdrill test above
    -Yuchung reworked the patch to make it more readable.
    
    Cc: Gregory Detal <gregory.detal@uclouvain.be>
    Cc: Nandita Dukkipati <nanditad@google.com>
    Tested-by: default avatarNeal Cardwell <ncardwell@google.com>
    Reviewed-by: default avatarYuchung Cheng <ycheng@google.com>
    Reviewed-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
    Signed-off-by: default avatarSébastien Barré <sebastien.barre@uclouvain.be>
    Acked-by: default avatarEric Dumazet <edumazet@google.com>
    Acked-by: default avatarNeal Cardwell <ncardwell@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    08abdffa
tcp_input.c 171 KB