rfc-6675

A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP

E. Blanton, M. Allman, L. Wang, I. Jarvinen, M. Kojo, Y. Nishida
date2012-08 streamIETF areawit wgtcpm statusPROPOSED STANDARD pages15 canonicalhttps://www.rfc-editor.org/rfc/rfc6675 doi10.17487/RFC6675
This document presents a conservative loss recovery algorithm for TCP that is based on the use of the selective acknowledgment (SACK) TCP option. The algorithm presented in this document conforms to the spirit of the current congestion control specification (RFC 5681), but allows TCP senders to recover more effectively when multiple segments are lost from a single flight of data. This document obsoletes RFC 3517 and describes changes from it. [STANDARDS-TRACK]

obsoletes

Extracted elements (24)

design-rationale §9

NextSeg() rule (3) was changed from MAY (in RFC 3517) to SHOULD, reflecting the authors' and working group's view that uncertain retransmissions to sustain the ACK clock should be performed by default unless an implementor has a compelling reason to omit them.

tcp

design-rationale §9

The duplicate acknowledgment definition was broadened to include any ACK carrying new SACK data covering the range HighACK to HighData. This allows SACK information (rather than just cumulative ACK stagnation) to trigger loss recovery entry, enabling more accurate distinction between loss and reordering.

tcp

design-rationale §2

The pipe algorithm (using a Pipe variable to estimate in-flight bytes) is used instead of RFC 5681's congestion window algorithm during recovery, allowing TCP to use fundamentally different congestion control that better handles multiple losses from a single flight.

tcp, congestion

design-rationale §9

The RescueRxt variable was added to allow one extra optimistic retransmission per loss recovery entry, limited to at most one segment of no more than 1 SMSS. This prevents ACK clock stalling when loss occurs at the end of the window and no new data is available.

tcp

interoperability-note §6

Implementers may optionally re-arm the RTO timer on each retransmission sent during recovery (rather than on each cumulative ACK advance per RFC 6298). This more conservative variant can prevent needless retransmissions when a loss event lasts longer than the RTO, but may not always be desirable.

tcp

interoperability-note §1

The SACK-based algorithm is a conservative replacement for fast recovery (RFC 5681) and can be safely used alongside standard TCP congestion control. Alternate SACK-based loss recovery methods may be used as long as they follow RFC 5681 guidelines.

tcp, congestion

normative-requirement §5.1 SHOULD

After an RTO, a SACK TCP sender SHOULD expunge SACK information (per RFC 2018) and MUST ignore prior SACK information when determining which data to retransmit. However, the sender SHOULD utilize all new SACK information made available during post-RTO loss recovery.

tcp

normative-requirement §5 MUST

An incoming cumulative ACK for a sequence number greater than RecoveryPoint signals end of loss recovery and the recovery phase MUST be terminated. Scoreboard information for sequence numbers greater than the new HighACK SHOULD NOT be cleared when leaving recovery.

tcp

normative-requirement §5 SHOULD

During loss recovery, if cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more segments as directed by NextSeg(). HighRxt MUST be updated to the highest retransmitted sequence number when retransmitting below HighData (unless NextSeg() rule 4 was used).

tcp, congestion

normative-requirement §5.1 MUST

If an RTO occurs during loss recovery, RecoveryPoint MUST be set to HighData, the new RecoveryPoint MUST be preserved, and the loss recovery algorithm MUST be terminated. A new recovery phase MUST NOT be initiated until HighACK >= the new RecoveryPoint.

tcp, congestion

normative-requirement §4 MUST

NextSeg() MUST return a lost segment (rule 1: smallest unSACKed S2 > HighRxt, below highest SACK coverage, where IsLost returns true) if one exists; otherwise MUST return new unsent data if available (rule 2); otherwise SHOULD return an unconfirmed-lost segment (rule 3); otherwise SHOULD return a single rescue retransmission of the highest outstanding unSACKed segment (rule 4).

tcp

normative-requirement §4 MUST NOT

SACKed data MUST NOT be removed from TCP's retransmission buffer until the data is cumulatively acknowledged, because SACK information is advisory and the receiver may renege.

tcp

normative-requirement §4 MUST

SetPipe() MUST set the 'pipe' variable to an estimate of octets currently in transit between sender and receiver, by traversing sequence space from HighACK to HighData. Pipe is incremented for each non-SACKed octet where IsLost returns false, and again for each octet at or below HighRxt (retransmitted octets are counted twice).

tcp, congestion

normative-requirement §5 MUST

Upon receipt of any ACK containing SACK information, the scoreboard MUST be updated via Update(). If the ACK is cumulative, DupAcks MUST be reset to zero.

tcp

normative-requirement §5 MUST

When entering fast retransmit and loss recovery: ssthresh = cwnd = FlightSize / 2, per RFC 5681. Segments sent via Limited Transmit MUST NOT be counted in FlightSize for this calculation.

tcp, congestion

protocol-element §2

A 'duplicate acknowledgment' is defined as a segment arriving with a SACK block identifying previously unacknowledged and un-SACKed octets between HighACK and HighData. Unlike RFC 5681, an ACK carrying new SACK data counts as a duplicate ACK even if it advances the cumulative acknowledgment point or carries new data.

tcp

protocol-element §2

DupThresh is set to 3 duplicate acknowledgments as the threshold for triggering retransmission, per RFC 5681. Implementers should consult updates to RFC 5681 for the current value or method of determining DupThresh.

tcp, congestion

protocol-element §4

IsLost(SeqNum) returns true when either DupThresh discontiguous SACKed sequences have arrived above SeqNum, or more than (DupThresh - 1) * SMSS bytes with sequence numbers greater than SeqNum have been SACKed. This improvement over RFC 3517 handles segments smaller than SMSS.

tcp

protocol-element §4

RescueRxt enables a single 'rescue' retransmission per loss recovery entry when all other NextSeg() rules fail but outstanding unSACKed data exists. This retransmits the highest outstanding unSACKed sequence number to sustain the ACK clock when loss occurs at the end of the window. HighRxt MUST NOT be updated for this retransmission.

tcp

protocol-element §2

The SACK-based algorithm maintains six sender variables: HighACK (highest cumulatively ACKed byte), HighData (highest transmitted sequence number), HighRxt (highest retransmitted sequence number during current recovery), RescueRxt (highest optimistically retransmitted sequence number), Pipe (estimated bytes outstanding in network), and DupAcks (duplicate acknowledgments since last cumulative ACK).

tcp, congestion

protocol-element §3

The scoreboard is a per-connection data structure used to store incoming SACK information. It tracks which octets have been cumulatively ACKed or SACKed, and must support Update(), IsLost(), SetPipe(), and NextSeg() operations. Implementations typically manage this as sequence number ranges rather than individual octets.

tcp

security-consideration §8

SACK-based loss recovery is more robust than standard TCP against attackers forging duplicate ACKs to force cwnd reduction, because SACK provides an additional check on ACK legitimacy. While not fool-proof, SACK offers meaningful protection against this attack vector.

tcp, security

security-consideration §8

SACK-based loss recovery mitigates a blind in-window attack variant (per RFC 5961 and CPNI309) where spoofed out-of-window data causes duplicate cumulative ACKs. Requiring SACK information to trigger loss recovery means attacker-induced duplicate ACKs without corresponding in-window SACK data will not trigger a recovery phase.

tcp, security

state-machine §5

Loss recovery is entered when DupAcks >= DupThresh (step 1) or IsLost(HighACK+1) returns true (step 2). Entry sets RecoveryPoint = HighData, reduces ssthresh and cwnd to FlightSize/2, retransmits first presumed-dropped segment, and runs SetPipe(). Recovery ends when a cumulative ACK exceeds RecoveryPoint.

tcp, congestion