Core Question
Core Question
Nothing on the network guarantees a packet won't loop forever between routers. What stops it, and who reports back when it doesn't make it?
Outcome
Outcome
By the end of this session, the learner should be able to:
- state exactly what a router does to TTL on every hop, in one sentence
- name the single comparison that decides Forwarded versus Expired
- explain what
expire()builds and what two things it carries - trace a starting TTL through repeated hops and predict the exact hop count where it expires
Read Order
Read Order
- Read
HopOutcome - Read
decrement_and_decide() - Read
expire() - Run
examples/icmp/session_03_walkthrough.py
Read It Like Code
Read It Like Code
decrement_and_decide(ttl: int) -> tuple[int, HopOutcome] expire(quoted: QuotedPacket, router_name: str) -> IcmpMessage
Fields That Matter
Fields That Matter
| Field | Why it matters |
|---|---|
ttl (input to decrement_and_decide) | The hop budget as it arrives at this router — already decremented by every router before this one. |
remaining | ttl - 1, computed once. Every decision in this file is downstream of this one subtraction. |
router_name (in expire()) | Identifies which router spent the last hop — it ends up embedded in the code string of the resulting message. |
quoted (in expire()) | The packet that got killed, carried into the TIME_EXCEEDED message exactly as Session 01 described: an error is a packet about a packet. |
Decision Flow
Decision Flow
remaining = ttl - 1 remaining == 0 -> EXPIRED (this router kills the packet, reports back with expire()) otherwise -> FORWARDED (this router passes the packet on)
Reading Lens
Reading Lens
The important move in this session is to stop thinking of TTL as "a number that goes down" and start asking:
- how many hops does this packet have left *before* this router touches it?
- is the
== 0branch the one that fires here, or theotherwisebranch? - when a packet expires, which router's name ends up in the report, and why would that matter to whoever's troubleshooting?
Toy Model Boundary
Toy Model Boundary
This file is 27 lines, deliberately as small as src/protocol_in_code/parser/checksum.py — the point of both is that the core mechanism is a single arithmetic operation, not a subsystem. Real routers also generate ICMP Time Exceeded under rate limiting, so a router that's spending a lot of hops on dying packets doesn't flood the source with reports — this toy model has no such limiting. IPv4 only: IPv6 renames the field Hop Limit, but the decrement-and-compare logic here carries over unchanged in spirit.
Code Landmarks
Code Landmarks
decrement_and_decide()
The whole file's logic in three lines: remaining = ttl - 1, then one if remaining == 0. There's no separate "less than zero" branch — a well-formed router only ever sees ttl >= 1 arrive, so remaining lands at 0 or higher, never negative.
expire()
Builds a TIME_EXCEEDED IcmpMessage whose code is an f-string naming router_name, and whose quoted is passed straight through. Read this next to Session 01's validate_message(): TIME_EXCEEDED is in ERROR_TYPES, so this message is only valid *because* it carries a quote — expire() isn't optional about that, it's structurally required.
Failure Questions
Failure Questions
Use the source file to answer these:
- What is
remainingwhendecrement_and_decideis called withttl=1, and which branch does that value hit? - Where exactly in the source does the
== 0comparison live, and what would change if it were<= 0instead? - Why does
expire()require aQuotedPacketargument at all — what does Session 01 tell you about what happens if you tried to build aTIME_EXCEEDEDmessage without one? - What two pieces of information does the
codestring inexpire()'s output carry, and where do they come from? - If a packet starts at
ttl=1and hits exactly one router, does it ever get forwarded? Trace the single call todecrement_and_decide()that answers this.
Walkthrough
Walkthrough
Run this:
PYTHONPATH=src python3 examples/icmp/session_03_walkthrough.py
The walkthrough decrements a healthy TTL and a dying one, builds a TIME_EXCEEDED message with expire(), and then loops a TTL of 4 down to expiry to confirm it takes exactly four hops.
Done When
Done When
The learner can say all of the following without looking at notes:
- "Every router does exactly one thing to TTL: subtract one, then check if that hit zero."
- "TIME_EXCEEDED is an error, so by Session 01's rule it must carry a quote —
expire()has no other option." - "A packet with TTL
nsurvives exactlyn - 1forwards before thenth router expires it."
References
References
- RFC 792 (Internet Control Message Protocol)
Continue