An Extension to the Selective Acknowledgement (SACK) Option for TCP
Extracted elements (20)
Because each duplicate segment is reported in only one ACK packet, D-SACK notification is lost if that ACK is dropped. This is an intentional simplicity trade-off; reliable notification would require more complex state at the receiver.
D-SACK does not change when a TCP receiver sends an ACK or how the cumulative ACK field is used; it only specifies the SACK option contents when an ACK is sent. This minimal scope limits the change required in existing TCP implementations.
D-SACK is intended only to enable sender-side detection of unnecessary retransmits; this document deliberately does not specify what action a sender should take upon detecting them. Subsequent documents will describe experimental proposals for sender responses.
D-SACK reuses the first SACK block position already designated by RFC 2018 for the triggering segment, requiring no changes to the option format or negotiation mechanism. A sender that does not understand D-SACK will silently ignore the first block without harm, making the extension fully backward compatible.
For partial duplicate sub-segments (arising when sender PMTU increases mid-session and a larger retransmit overlaps an already-received range), only the first duplicate sub-segment is reported to keep D-SACK simple and consistent with the single-block-first-position rule.
The sender must compare the D-SACK block to the cumulative ACK in the same packet rather than snd.una because ACK packets can be reordered in the network. Using snd.una could cause the sender to incorrectly classify a legitimate out-of-order SACK block as a duplicate report.
D-SACK requires no separate negotiation beyond existing SACK capability. If a TCP sender does not understand D-SACK, it simply discards D-SACK blocks and processes remaining SACK blocks normally, causing no interoperability problems with the extension.
PAWS (RFC 1323) still requires sending an ACK when a segment from a prior sequence-number cycle is received. D-SACK blocks can be included in such ACKs independently of the PAWS validity determination. Senders using D-SACK should be aware that a reported duplicate could stem from a prior sequence-number cycle rather than an actual retransmission.
A D-SACK block is only used to report a duplicate contiguous sequence received in the most recent packet. Each such duplicate is reported in at most one D-SACK block; the receiver sends two identical D-SACK blocks in subsequent packets only if it receives two separate duplicate segments.
An implementation MUST NOT compare the sequence space in the first SACK block to the TCP state variable snd.una when checking for duplicate data. The comparison must be against the cumulative ACK carried in the same packet, because ACK reordering makes snd.una an unreliable reference and can produce incorrect conclusions.
The first block of the SACK option should be a D-SACK block specifying the sequence numbers for the duplicate segment that triggered the acknowledgement. If the duplicate is part of a larger non-contiguous block above the cumulative ACK, the second SACK block should specify that larger block.
When a received packet contains multiple non-contiguous partial duplicate sub-segments, only the first duplicate sub-segment is reported in the D-SACK block. Subsequent duplicate sub-segments within the same packet are not reported.
A false (unnecessary) retransmit due to severe reordering is detectable via D-SACK: a D-SACK block whose sequence space is lower than the cumulative ACK and identical to a previously retransmitted segment indicates significant reordering triggered an unnecessary Fast Retransmit.
A retransmit timeout caused by an entire window of lost ACKs is detectable via D-SACK: if the first ACK received following a timeout carries a D-SACK block, it indicates the retransmitted data was a duplicate, meaning the original data was received and only the ACKs were lost.
An early retransmit timeout (RTO too short) is detectable via D-SACK: after the timeout the original delayed window arrives producing clean ACKs, then the retransmissions arrive producing ACKs with D-SACK blocks. The signature is a clean ACK for the retransmitted byte followed by an ACK carrying a D-SACK showing that byte was already received.
D-SACK (duplicate-SACK) is an extension to the SACK option where the first SACK block reports the sequence numbers of the duplicate segment that triggered the acknowledgement. This allows the TCP sender to infer when it has unnecessarily retransmitted a packet due to reordering, ACK loss, packet replication, or early retransmit timeout.
Network packet replication is detectable via D-SACK: a D-SACK block whose sequence space is lower than the cumulative ACK field in the same packet and does not match any previously retransmitted segment indicates the network replicated a data packet.
The TCP sender cannot necessarily trust the receiver to send accurate D-SACK information. Any sender mechanism that 'undoes' a congestion window reduction based on D-SACK reports must account for a misbehaving receiver falsely claiming duplicates to manipulate sender behavior.
This document neither strengthens nor weakens TCP's existing security properties. The D-SACK extension introduces no new attack surface beyond what SACK already exposes.
The SACK option (Kind=5, variable Length) contains up to four blocks, each with a 4-byte Left Edge (first sequence number) and 4-byte Right Edge (sequence number immediately following the last byte) of a received contiguous range. For D-SACK, the first block's left and right edges bound the duplicate contiguous sequence received in the most recent packet.