What problem does TCP selective acknowledgment (SACK) solve that cumulative ACKs cannot, and why must a sender still keep data a SACK block reported?
answer
- several holes in one window
- one hole per round trip
- blocks describe what arrived
- advisory, the receiver may renege
basics
~20 sCumulative ACKs report only the contiguous prefix, so several losses in one window surface about one per round trip. SACK blocks describe data held beyond the gap but are advisory, so data is freed only once the cumulative ACK passes.
solid answer
~40 sA cumulative acknowledgment says "I have everything below X" and nothing about what arrived above X. With several segments lost from one window, the sender learns of roughly one hole per round trip, or guesses and resends data the receiver already has. **SACK** (RFC 2018) lets the receiver, when the peer's SYN carried SACK-Permitted, list up to four received blocks beyond the cumulative ACK, or three alongside the timestamp option, so the sender can resend only the holes. The blocks are **advisory**: the receiver is allowed to discard ("renege on") SACKed data, so RFC 2018 says the sender MUST NOT discard data until the `Acknowledgment Number` field covers it, and after a retransmission timeout it SHOULD forget its SACK information.
go deeper
Recall that a normal TCP ACK only says everything below a number arrived, and that SACK adds ranges received beyond a gap.
Explain negotiation through SACK-Permitted in the SYN, the edge convention, and why multiple losses in one window hurt without SACK.
Show why SACK is advisory: reneging, freeing only on the cumulative ACK, clearing SACK state after a timeout, and what D-SACK reveals.
Discuss the option-space budget: SACK blocks compete with timestamps and other options for 40 bytes, which caps what the receiver can report per ACK.
## What cumulative acknowledgment cannot say TCP's acknowledgment number (RFC 9293) is **cumulative**: it names the next byte expected and so confirms the contiguous prefix below it. It carries no information about data received **beyond** a gap. When one segment is lost that is enough, since duplicate ACKs tell the sender something is missing at the acknowledged point. When **several** segments are lost from the same window, the sender has two poor choices: - resend one missing segment, wait a round trip to see where the cumulative ACK stops next, and repeat, so recovering from n holes costs about n round trips; or - resend everything after the ACK point, wasting capacity on data the receiver already holds. ## What SACK adds **Selective Acknowledgment**, RFC 2018 (Standards Track), adds an option to ACK segments listing **blocks of contiguous data received and queued** above the cumulative acknowledgment. | | Cumulative ACK | SACK option | |---|---|---| | Where | fixed header field | TCP option, only when negotiated | | Says | all bytes below X have arrived | these ranges beyond X are held | | Binding? | yes, the sender may free the data | no, advisory; the receiver may renege | | Capacity | one number | 4 blocks, or 3 with timestamps | Negotiation happens once: a TCP that can process SACK sends the two-byte **SACK-Permitted** option in its SYN, and RFC 2018 forbids sending it on any other segment. A receiver MUST NOT send SACK options on a connection whose peer did not offer SACK-Permitted. ## How a receiver builds the option RFC 2018 gives the receiver's rules: 1. Each block is two 32-bit numbers: the **left edge** (first sequence number held) and the **right edge** (the sequence number immediately after the last byte held). 2. The **first block** MUST describe the contiguous range containing the segment that triggered this ACK, unless that segment advanced the acknowledgment number. The sender always gets the newest news first. 3. The receiver SHOULD include as many distinct blocks as fit, and SHOULD fill the rest by **repeating the most recently reported blocks**, so that each held block appears in at least three successive SACK options in normal operation. This covers the loss of individual ACKs. 4. SACK options SHOULD be included in every ACK that does not acknowledge the highest sequence number in the receiver's queue, which means every duplicate ACK in a loss episode. ## The size limit A SACK option with n blocks is **8n + 2** bytes, and TCP has **40 bytes** of option space, so at most **4 blocks** fit. The timestamp option (RFC 7323) takes 10 bytes plus 2 bytes of padding, which leaves room for **3 blocks**. A receiver with more holes than that cannot report them all in one ACK: the first block is always the newest, and older blocks may go unreported. ## Why SACK is advisory: reneging RFC 2018 lets a receiver later **discard** data it has already SACKed, for example when it runs short of buffer space, although doing so is discouraged. It follows that: - the sender MUST NOT discard data until the cumulative `Acknowledgment Number` has passed it, however many SACK blocks reported it; - after a **retransmission timeout** the sender SHOULD clear all its "SACKed" marks, because the timeout might mean the receiver reneged, and it MUST retransmit the segment at the left edge of the window regardless of those marks. SACK therefore steers **which** bytes to retransmit; only the cumulative ACK decides what is **finished**. ## Duplicate SACK RFC 2883 extends SACK with **D-SACK**: when the receiver gets bytes it already has, the first SACK block reports that duplicate range. The sender can then infer that one of its retransmissions was unnecessary, for example because a segment was only delayed or reordered. D-SACK needs no negotiation of its own beyond SACK-Permitted; a sender that does not understand it simply ignores that block. What the sender then does about a spurious retransmission belongs to the retransmission topic. ## Misconceptions to avoid - SACK does **not** replace the cumulative acknowledgment; it rides alongside it. - SACK blocks name data **received**, not data wanted. - SACK does not make the stream deliverable out of order: the application still waits for the missing bytes.
- Why can a TCP SACK option carry at most four blocks?TCP options are limited to 40 bytes, and a SACK option with n blocks takes 8n + 2 bytes: two 32-bit edges per block plus kind and length. That gives four blocks. RFC 2018 notes that the timestamp option, which takes 10 bytes plus 2 of padding, is usually present too, leaving room for three. The receiver always reports the newest block first and repeats recent blocks in later ACKs, so the loss of one ACK does not hide them.
- What is D-SACK and what does it let a TCP sender work out?D-SACK, from RFC 2883, uses the first SACK block to report a range the receiver received more than once. It requires no separate negotiation once SACK is permitted. Seeing it, the sender can infer that a retransmission was unnecessary, because the original copy also arrived. That exposes reordering, ACK loss or premature retransmission, which a plain SACK cannot distinguish.
- May a TCP endpoint send SACK blocks if the peer's SYN lacked the SACK-Permitted option?No. RFC 2018 says a data receiver that has not received SACK-Permitted on the SYN MUST NOT send SACK options on that connection, and SACK-Permitted itself MUST NOT appear on non-SYN segments. SACK is therefore decided for the whole connection during the handshake; a connection that did not negotiate it recovers with cumulative ACKs alone.
A reader tells the publisher "I have every page up to 40" and adds, in pencil, "I'm also holding pages 45 to 60". The publisher now knows to reprint only pages 41 to 44, but because the pencil note can be rubbed out, it keeps its copies of 45 to 60 until the reader says "everything up to 60".
saying these in an interview costs you the question
- Once a segment is SACKed the sender can free its buffer.
- SACK replaces the cumulative acknowledgment number.
- SACK blocks list the byte ranges the receiver wants retransmitted.
- Either side can start sending SACK blocks mid-connection without negotiation.
- A SACK option can report every hole, however many there are.
- SACK lets the application read data that arrived after a gap.