• Yuchung Cheng's avatar
    tcp: new delivery accounting · ddf1af6f
    Yuchung Cheng authored
    This patch changes the accounting of how many packets are
    newly acked or sacked when the sender receives an ACK.
    
    The current approach basically computes
    
       newly_acked_sacked = (prior_packets - prior_sacked) -
                            (tp->packets_out - tp->sacked_out)
    
       where prior_packets and prior_sacked out are snapshot
       at the beginning of the ACK processing.
    
    The new approach tracks the delivery information via a new
    TCP state variable "delivered" which monotically increases
    as new packets are delivered in order or out-of-order.
    
    The reason for this change is that the current approach is
    brittle that produces negative or inaccurate estimate.
    
       1) For non-SACK connections, an ACK that advances the SND.UNA
       could reset the DUPACK counters (tp->sacked_out) in
       tcp_process_loss() or tcp_fastretrans_alert(). This inflates
       the inflight suddenly and causes under-estimate or even
       negative estimate. Here is a real example:
    
                       before   after (processing ACK)
       packets_out     75       73
       sacked_out      23        0
       ca state        Loss     Open
    
       The old approach computes (75-23) - (73 - 0) = -21 delivered
       while the new approach computes 1 delivered since it
       considers the 2nd-24th packets are delivered OOO.
    
       2) MSS change would re-count packets_out and sacked_out so
       the estimate is in-accurate and can even become negative.
       E.g., the inflight is doubled when MSS is halved.
    
       3) Spurious retransmission signaled by DSACK is not accounted
    
    The new approach is simpler and more robust. For SACK connections,
    tp->delivered increments as packets are being acked or sacked in
    SACK and ACK processing.
    
    For non-sack connections, it's done in tcp_remove_reno_sacks() and
    tcp_add_reno_sack(). When an ACK advances the SND.UNA, tp->delivered
    is incremented by the number of packets ACKed (less the current
    number of DUPACKs received plus one packet hole).  Upon receiving
    a DUPACK, tp->delivered is incremented assuming one out-of-order
    packet is delivered.
    
    Upon receiving a DSACK, tp->delivered is incremtened assuming one
    retransmission is delivered in tcp_sacktag_write_queue().
    Signed-off-by: default avatarYuchung Cheng <ycheng@google.com>
    Signed-off-by: default avatarNeal Cardwell <ncardwell@google.com>
    Signed-off-by: default avatarEric Dumazet <ncardwell@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    ddf1af6f
tcp_input.c 181 KB