Which ACKs and SACK blocks does a TCP receiver that has acknowledged byte 1000 send when the first of the next three 1000-byte segments is lost?
answer
- the cumulative ACK cannot move
- each arrival above the gap is acknowledged
- SACK edges: first byte, byte after last
- the fill jumps the ACK forward
basics
~10 sEach later segment triggers an immediate duplicate ACK of 1001, carrying SACK blocks 2001-3001 and then 2001-4001. The receiver buffers bytes 2001-4000 undelivered; when 1001-2000 arrives, it acknowledges 4001 at once.
solid answer
~40 sSegment A (bytes 1001-2000) is lost, so `RCV.NXT` stays at 1001. When segment B (2001-3000) arrives above the gap, the receiver SHOULD send an **immediate duplicate ACK** of 1001 (RFC 5681), carrying a SACK block with left edge 2001 and right edge 3001, the byte after the block. Segment C (3001-4000) produces a second duplicate ACK of 1001, and its SACK block grows to 2001-4001 because the held bytes are now one contiguous range. Throughout, bytes 2001-4000 sit in the receive buffer and the application reads nothing past byte 1000. When the retransmitted A arrives it fills the gap; the receiver SHOULD acknowledge immediately, and the cumulative ACK jumps to 4001 with no SACK blocks left to report.
go deeper
Recall that the cumulative ACK cannot pass a missing byte, so every later arrival repeats the same ACK number.
Walk the trace with byte numbers, give each SACK block's edges correctly, and explain why the ACK jumps when the gap fills.
Read such a trace from a live connection: tell a duplicate ACK from a window update, and explain why few segments in flight produce too few duplicates.
Relate the stall this trace shows to transport design: one ordered stream per connection means one loss delays every byte queued behind it.
## The setup The receiver has already acknowledged everything up to byte 1000, so its **RCV.NXT** is 1001 and its last ACK carried acknowledgment number 1001. The sender now transmits three segments of 1,000 bytes each. Byte ranges below are inclusive; SACK edges follow RFC 2018's convention. | Segment | Bytes | Fate | |---|---|---| | A | 1001 to 2000 | lost in the network | | B | 2001 to 3000 | arrives | | C | 3001 to 4000 | arrives | Both sides negotiated **SACK** by exchanging the SACK-Permitted option in their SYNs; the option's layout belongs to the segment-header topic. ## Step by step at the receiver 1. **B arrives.** Its first byte, 2001, is inside the receive window but above `RCV.NXT`, so there is a gap. RFC 9293 says such data SHOULD be held for later processing, so B is buffered. RFC 5681 says the receiver SHOULD send an immediate duplicate ACK when a segment arrives above a gap, so it does not wait for any delayed-ACK timer. The ACK carries acknowledgment number **1001** and one SACK block: left edge **2001**, right edge **3001**. 2. **C arrives.** It is also above the gap and is buffered next to B. The receiver sends another immediate ACK of **1001**. Because B and C together form one contiguous range, the SACK option reports a single block **2001-4001**, not two blocks. RFC 2018 requires the first block to be the one containing the segment that triggered this ACK, and it is. 3. **A is retransmitted and arrives.** It starts at `RCV.NXT`, so it fills the gap. The whole range 1001-4000 is now contiguous and `RCV.NXT` jumps to 4001. RFC 5681 says a receiver SHOULD acknowledge immediately when a segment fills all or part of a gap, and this ACK carries **4001** with no SACK blocks, because nothing is held out of order any more. | Event | Buffered out of order | ACK number sent | SACK block(s) | |---|---|---|---| | B arrives | 2001-3000 | 1001 (1st duplicate) | 2001-3001 | | C arrives | 2001-4000 | 1001 (2nd duplicate) | 2001-4001 | | A arrives | none | 4001 | none | ## Reading the SACK edges correctly - The **left edge** is the first sequence number of the block. - The **right edge** is the sequence number **immediately following** the last byte of the block, so bytes 2001 to 3000 are reported as 2001-3001. - A block describes data that **was received**. The missing range is inferred from the gap between the cumulative ACK (1001) and the first block's left edge (2001). ## What the application sees Nothing new until A arrives. TCP delivers only the contiguous prefix, so 2,000 correct bytes wait in the buffer behind one missing segment. When A lands, all 3,000 bytes become readable at once. This is **head-of-line blocking** inside TCP: one hole stalls everything behind it on the same connection. ## What the sender learns - Without SACK, the sender would see two identical ACKs of 1001 and learn only that later segments are arriving and that 1001 is still missing. It could not tell which later bytes arrived. - With SACK, the blocks tell it that bytes 2001-4000 are held, so only 1001-2000 needs to be resent. - An ACK counts as a **duplicate** under RFC 5681 only if the sender has outstanding data, the ACK carries no data, SYN and FIN are off, the acknowledgment number equals the highest already received, and the advertised window is unchanged. A SACK-capable sender may also treat an ACK carrying new SACK information as a duplicate. - This trace produces **two** duplicates. The fast retransmit rule waits for three, so with only three segments in flight the sender's recovery comes from its other loss-recovery machinery; which one, and how the sending rate reacts, belong to the retransmission and congestion-control topics. ## Common slips - Writing the right edge as 3000, which is the last byte, instead of 3001. - Reporting two blocks, 2001-3001 and 3001-4001, for data that is contiguous. - Having the receiver advance its ACK to 3001 or 4001 while byte 1001 is still missing. - Assuming the receiver throws B and C away because they arrived out of order. RFC 9293 says such data SHOULD be held; discarding it would force the sender to resend all three segments.
- In the same trace, what changes if the middle segment (bytes 2001-3000) is the one lost instead?A arrives in order, so `RCV.NXT` becomes 2001 and its ACK may be delayed. C then arrives above the gap and forces an immediate ACK of 2001 with SACK block 3001-4001. If A's ACK was still being delayed, that ACK of 2001 is new to the sender, not a duplicate, so only the SACK block reveals the hole. When 2001-3000 arrives, the receiver acknowledges 4001 immediately.
- Why does a TCP receiver acknowledge out-of-order data immediately instead of delaying the ACK?RFC 5681 says out-of-order segments SHOULD be acknowledged immediately to accelerate loss recovery. The duplicate ACK is the sender's earliest evidence that something is missing, and each extra duplicate, with its SACK block, adds detail. Delaying it would slow recovery for no saving, since the receiver cannot advance its cumulative ACK anyway.
saying these in an interview costs you the question
- A SACK block's right edge is the last byte received in that block.
- The receiver advances its ACK past bytes it holds even though earlier bytes are missing.
- Out-of-order data is delivered to the application straight away and reordered by it.
- The receiver delays ACKs for out-of-order segments to wait for the gap to fill.
- Two adjacent received segments are reported as two separate SACK blocks.