The NewReno Modification to TCP's Fast Recovery Algorithm
obsoleted by
- rfc-6582 — The NewReno Modification to TCP's Fast Recovery Algorithm
obsoletes
- rfc-2582 — The NewReno Modification to TCP's Fast Recovery Algorithm
Extracted elements (26)
NewReno applies only to TCP connections unable to use SACK. When SACK is available it is the preferred mechanism; NewReno is a practical improvement for the large portion of connections where SACK is unavailable or unsupported by the peer.
Partial window deflation (deflating cwnd by the amount of new data acknowledged and adding back SMSS) was chosen over simply setting cwnd to ssthresh on each partial ACK, because it more accurately tracks the number of outstanding packets and recovers more smoothly when multiple packets are dropped.
The Careful variant requires that duplicate ACKs cover strictly more than 'recover' before invoking Fast Retransmit, rather than 'more than or equal to' (Less Careful). This avoids unnecessary Fast Retransmits in the second scenario (unnecessary retransmissions) at the cost of requiring a timeout in an ambiguous first scenario (dropped retransmission).
The Impatient variant (reset retransmit timer only after the first partial ACK) is recommended over the Slow-but-Steady variant (reset after every partial ACK) because it gives faster recovery for large congestion windows with many drops, even though the Slow-but-Steady variant can avoid unnecessary retransmissions in some scenarios.
The 'recover' variable (Careful variant) was chosen over the simpler default (RFC 2582 base) because, without it, multiple Fast Retransmits can occur unnecessarily after a retransmit timeout when the sender retransmits packets already received, triggering three spurious duplicate ACKs.
Data receivers that delay sending acknowledgements for out-of-order segments (waiting for the delayed ACK timer) severely limit NewReno's benefit by delaying the partial ACK at the sender. Receivers SHOULD send an immediate ACK for out-of-order segments, per RFC 2581.
If three or more duplicate ACKs are received when the sender is not in Fast Recovery and the ACKs do not cover more than 'recover', the sender MUST NOT execute the Fast Recovery inflation steps (Steps 3 and 4), or it risks a chain of spurious timeouts. Several NewReno implementations had this bug.
NewReno TCP performs worse than Reno TCP in the presence of packet reordering without loss: reordering that triggers three duplicate ACKs causes NewReno to unnecessarily retransmit an entire window of data, versus Reno's single unnecessary retransmission. SACK TCP handles both scenarios optimally.
The ACK heuristic (Step 1*) checks that cwnd > SMSS and that the difference between highest_ack and prev_highest_ack is at most 4*SMSS to infer a true loss. It can fail if several ACKs are lost, causing a jump in the cumulative ACK beyond the 4*SMSS threshold.
The timestamp heuristic (Step 1**) uses the timestamp echoed in the last non-duplicate ACK to distinguish a dropped retransmission from spurious duplicate ACKs, but can fail if the receiver echoes timestamps arbitrarily or if the timeout was spurious.
When not in Fast Recovery, the 'recover' variable should be advanced with snd_una to prevent sequence number wrap-around from falsely blocking entry into Fast Recovery when large amounts of data have been sent and acknowledged.
After a retransmit timeout, the highest sequence number transmitted MUST be recorded in the variable 'recover' and the sender MUST exit the Fast Recovery procedure if currently in it (Step 6).
An implementation SHOULD use a separate flag to record whether it is in Fast Recovery, rather than relying on the duplicate ACK counter, because the counter can be reset upon window updates and out-of-order ACKs.
During Fast Recovery, for each additional duplicate ACK received, cwnd is incremented by SMSS to reflect an additional segment that has left the network (Step 3).
For the first partial ACK that arrives during Fast Recovery, the retransmit timer MUST be reset (Step 5). Subsequent partial ACKs do not reset the timer under the Impatient variant.
Implementations SHOULD take measures to avoid a burst of data when leaving Fast Recovery, such as limiting packets sent per ACK ('maxburst_'), rate-based pacing, or setting ssthresh to the new cwnd and resetting cwnd to FlightSize.
On receipt of a full ACK (acknowledging all data up to and including 'recover'), cwnd is set to either min(ssthresh, FlightSize+SMSS) or ssthresh, deflating the window, and Fast Recovery is exited (Step 5).
On receipt of a partial ACK during Fast Recovery, the sender retransmits the first unacknowledged segment, deflates cwnd by the amount of new data acknowledged, adds back SMSS bytes if at least SMSS of new data was acknowledged, and does NOT exit Fast Recovery (Step 5).
The TCP sender MAY use timestamp- or ACK-advancement-based heuristics to decide to invoke Fast Retransmit even when three duplicate ACKs do not cover more than 'recover', to distinguish dropped retransmissions from unnecessary retransmissions.
Upon entering Fast Retransmit (Step 2), the lost segment is retransmitted and cwnd is set to ssthresh plus 3*SMSS, artificially inflating the congestion window by the number of segments that have left the network and been buffered by the receiver.
When entering Fast Retransmit (Step 1A), ssthresh MUST be set to no more than max(FlightSize/2, 2*SMSS), and the highest sequence number transmitted MUST be recorded in the variable 'recover'.
When three duplicate ACKs are received and the sender is not already in Fast Recovery, the sender MUST check whether the Cumulative Acknowledgement field covers more than the 'recover' variable before invoking Fast Retransmit. If not, the sender does not enter Fast Retransmit (Step 1B).
A 'partial acknowledgement' is an ACK received during Fast Recovery that acknowledges the retransmitted segment but not all data outstanding when Fast Recovery was entered. It signals additional packet drops in the window.
The 'recover' variable records the highest sequence number transmitted at the time Fast Retransmit was last entered or a retransmit timeout occurred. Its initial value is the initial send sequence number. It is used to suppress spurious Fast Retransmits after a timeout.
RFC 2581 discusses general security considerations for TCP congestion control. NewReno conforms with RFC 2581's congestion control requirements, so those considerations apply. There are no known additional security concerns specific to the NewReno algorithm.
NewReno Fast Recovery has two key states: normal (outside Fast Recovery) and Fast Recovery. Trigger to enter: third duplicate ACK when cwnd covers more than 'recover'. Triggers to exit: full ACK (Step 5) or retransmit timeout (Step 6). Partial ACKs cause retransmission but do not exit the state.