Core Question
Core Question
How does a sender infer a lost segment from ACKs alone, without waiting for a retransmission timer to expire?
Outcome
Outcome
By the end of this session, the learner should be able to:
- explain what a "duplicate ACK" is in terms of the value carried, not just that it repeats
- state exactly which repeat count flips the signal to fast retransmit
- explain why a fourth repeat of the same ack is not a second fast-retransmit trigger
- explain what resets the duplicate counter, and why that's the same event as "new data acked"
Read Order
Read Order
- Read
DUP_ACK_THRESHOLD - Read
AckSignal - Read
AckTracker - Read
on_ack() - Run
examples/tcp/session_06_walkthrough.py
Read It Like Code
Read It Like Code
AckTracker(
last_ack,
dup_count,
)Fields That Matter
Fields That Matter
| Field | Why it matters |
|---|---|
last_ack | The most recently seen ack value. Every incoming ack is compared against this, not against "the highest ack ever seen" or any window state. |
dup_count | How many times *in a row* the current last_ack has repeated. Any new ack value resets this to zero. |
Decision Flow
Decision Flow
ack != tracker.last_ack -> NEW_DATA_ACKED (last_ack updates, dup_count resets to 0)
ack == tracker.last_ack:
dup_count += 1
dup_count == DUP_ACK_THRESHOLD (3) -> FAST_RETRANSMIT
otherwise -> DUPLICATEReading Lens
Reading Lens
The important move in this session is to stop thinking "three duplicate ACKs means loss" as a vague rule of thumb, and start asking:
- is this comparison
==or>=? (It changes what happens on the fourth, fifth, sixth repeat.) - what exact value does
dup_counthold at the momentFAST_RETRANSMITis returned? - does a repeat of the ack *before* the current
last_ackcount toward anything, or is it just compared tolast_ack? - what is the very next
AckSignalafterFAST_RETRANSMIT, if the same ack repeats again?
Toy Model Boundary
Toy Model Boundary
Real TCP receivers with Selective Acknowledgment (SACK, RFC 2018) tell the sender exactly which blocks of data have arrived, so a sender doesn't have to guess from a single repeated cumulative ack which segment is missing — it can often identify and retransmit just the missing piece immediately. This toy has no SACK: on_ack() only ever sees a single integer ack value and counts exact repeats. It cannot tell three duplicate acks apart from "receiver is acking three different segments that all still expect the same next byte" versus "three separate small losses" — it just counts.
There's also no notion of an ACK carrying window or timestamp information here, and no interaction with the RTO timer from Session 05 — AckTracker is a pure counter over a stream of ack values, nothing more.
Code Landmarks
Code Landmarks
DUP_ACK_THRESHOLD = 3
A single module-level constant. Every "why three?" question in TCP folklore collapses to this one number being read once, in one comparison.
AckSignal
Three outcomes, no more. There is no "still waiting" or "unknown" — every call to on_ack() returns exactly one of these three.
on_ack()
The reading target, and it's short enough to read as one unit. The != branch is the reset path — it runs before dup_count is ever touched for this ack. The literal == DUP_ACK_THRESHOLD comparison (not >=) is what makes fast retransmit a one-time edge, not a level: the third repeat trips it, and the fourth repeat, still equal to last_ack, increments dup_count to 4 and falls through to DUPLICATE because 4 != 3.
Failure Questions
Failure Questions
Use the source file to answer these:
- At exactly the third duplicate of the same ack, what does
on_ack()return, and what istracker.dup_countimmediately after that call? - If the same ack repeats a fourth time after triggering
FAST_RETRANSMIT, what doeson_ack()return this time? Which line explains why it isn'tFAST_RETRANSMITagain? - An ack repeats twice (
dup_countreaches 2), then a genuinely new ack value arrives. What doeson_ack()return, and what arelast_ackanddup_countafterward? AckTracker()defaultslast_ackto0. If the very first real ack a sender ever sees also happens to be0, what doeson_ack()return, and why does the field's default value matter here?- If
DUP_ACK_THRESHOLDwere changed to1, what wouldon_ack()return on the very first duplicate, and which line's comparison would make that true?
Walkthrough
Walkthrough
Run this:
PYTHONPATH=src python3 examples/tcp/session_06_walkthrough.py
The walkthrough sends one ack, repeats it three times to watch DUPLICATE, DUPLICATE, FAST_RETRANSMIT, repeats it a fourth time to show the signal falls back to DUPLICATE, then sends new data to show the counter resets and a fresh duplicate run starts from 1.
Done When
Done When
The learner can say all of the following without looking at notes:
- "Three duplicates of the *same* ack value trip fast retransmit — the third one exactly, via
==, not>=." - "A fourth repeat is not a second fast-retransmit signal; it's just another duplicate."
- "Any ack value different from
last_ackresetsdup_countto zero — that's the same branch that reportsNEW_DATA_ACKED."
References
References
- RFC 5681 Section 3.2 (fast retransmit / fast recovery)
Continue