Networking · Transport Protocols
Timestamps, RTTM, and Protection Against Wrapped Sequences
How an echoed timestamp lets a sender time a retransmitted segment, why PAWS rejects segments by timestamp rather than sequence number, and what the option costs per segment.
The base TCP header carries one sequence number per direction and one acknowledgement. That is enough to reassemble a byte stream, but it is not enough to answer two questions that a high-performance connection needs answered: which transmission of a retransmitted segment produced this acknowledgement, and whether a segment that appears to be in the window is actually current or a survivor from a much older connection that happens to occupy the same sequence numbers.
The timestamp option answers both. It adds ten bytes to the header when present, twelve with padding, and it is negotiated in the handshake, so a connection either has it on every segment or not at all.
The option layout
The option carries two 32-bit values: TSval, the sender’s current timestamp, and TSecr, the
timestamp most recently received from the peer, echoed back.
Kind=8 Length=10 TSval (4 bytes) TSecr (4 bytes) [2 bytes padding to 4-byte boundary]
Every segment carries the sender’s TSval and echoes, in TSecr, the last TSval it received from the
peer. The values are not wall clock times. They are counters in an arbitrary unit, conventionally
incremented once per millisecond, starting from a random offset chosen at connection setup. The unit is
not negotiated and not transmitted; each side simply increments its own counter and the peer only ever
compares values it received from that side.
The random initial offset matters. If both sides started at zero, a timestamp value would be meaningful across connections, and an attacker could predict it. Starting from a random point makes the value unpredictable without requiring any cryptographic operation per segment.
Recovering RTT samples across retransmissions
Without timestamps, Karn’s algorithm forbids taking a round-trip sample from a segment that has been
retransmitted, because the acknowledgement does not say which transmission it refers to. With
timestamps it does. The sender stores the TSval it used for each transmission. When an
acknowledgement arrives carrying TSecr, the sender looks up that value, finds the transmission it
belongs to, and computes the interval from that transmission’s time to now.
The lookup is exact because the value identifies the transmission rather than the byte range. A
segment retransmitted at time t2 carries a different TSval than its original transmission at t1,
so the acknowledgement’s echo distinguishes them unambiguously. The sample is correct even in the case
that defeats Karn’s algorithm.
RFC 7323 calls the resulting measurement RTTM, for round-trip time measurement, and it removes the ambiguity that made Karn’s rule necessary. It does not license taking a sample from every acknowledgement, though. The rule the specification gives is that a received timestamp echo may be used to update the average only when the segment carrying it advances the left edge of the send window. Without that restriction a one-way data flow would inflate the estimate by the length of every pause: if the sender has nothing to send for a while, the next segment it does send echoes a timestamp from before the pause, and the implied round trip includes the idle period.
The benefit is largest exactly where the base mechanism is weakest. A connection losing segments steadily has few usable samples under Karn’s algorithm, so its round-trip estimate freezes and its timeout is driven entirely by the exponential backoff. With timestamps, every acknowledged transmission yields a sample, including the retransmitted ones, and the estimate keeps tracking the path. The interaction between this and the timeout computation is described in Retransmission Timeout Estimation and Karn’s Algorithm.
PAWS: rejecting by timestamp
Protection Against Wrapped Sequences addresses a different problem, and it is the reason the option is not merely a measurement convenience.
The sequence space is 2³² bytes. A connection transferring at 1 Gbit/s consumes that space in about 34 seconds. A connection that lives longer than that wraps, and after the wrap, sequence numbers that were used early in the connection become valid again. A delayed segment from the early part of the connection, arriving after the wrap, carries a sequence number that falls inside the current window. The sequence number cannot distinguish it from new data.
PAWS uses the timestamp to make the distinction. The rule is simple: a segment is acceptable only if
its TSval is not older than the most recent TSval accepted on that connection, using the same
modular comparison technique applied to the timestamp space. A segment that has been in the network
for 34 seconds carries a timestamp from 34 seconds ago, which is far behind the current value, and it
is discarded.
The comparison is (TSval_new − TSval_recent) mod 2³² < 2³¹, the same serial-number test the
protocol applies to sequence numbers. The specification constrains the clock from both sides: it must
tick at least once per 2³¹ bytes sent, so that a fast sender cannot wrap it unnoticed, and its
recycling time must exceed the maximum segment lifetime, which caps the rate at one tick per 59
nanoseconds at the worst-case lifetime of 255 seconds. A clock ticking once per millisecond sits
comfortably inside both bounds and wraps its sign bit in about 24.8 days.
PAWS also interacts with the receive window in a way that has practical consequences. A receiver that
has accepted a segment with timestamp T will reject any later segment with a smaller timestamp, even
if that segment is otherwise valid. On a path that reorders, this is exactly the intended behaviour. On
a path where the sender’s timestamp counter has been reset after a reboot, or after the connection
has been idle long enough for the peer to lose state, the rejection is spurious, and the connection
stalls until the peer’s timestamp advances past the recorded value. The stall is bounded by the
difference between the recorded value and the current one, which can be large.
RFC 7323 closes that case with a requirement rather than a hint. A connection idle long enough for the peer’s clock to wrap its sign bit leaves the recorded value too old to be a useful comparison, and PAWS would then reject everything the peer sends until the clock wrapped again. Implementations must invalidate the recorded value after a connection has been idle for more than 24 days, after which the next segment is accepted whatever its timestamp, and the recorded value is replaced. The 24-day figure is the worst case over the permitted clock rates, so it is the safe threshold to use without knowing the peer’s rate.
What the option costs
Ten bytes of option plus two bytes of padding is twelve bytes per segment. On a full-sized 1,460-byte segment that is under 1% overhead. On a small segment such as a 40-byte acknowledgement, it raises the segment size from 40 to 52 bytes, a 30% increase in bytes and a similar increase in processing cost.
The overhead is why the option is negotiated rather than always on. A connection that will never transfer enough data to wrap its sequence space gains nothing from PAWS, and a connection whose segments are all small gains nothing from RTTM because it has no retransmission ambiguity to resolve. The negotiation lets both sides decline.
The option also competes for header space. The 40-byte option area must hold the timestamp (12 bytes) and a SACK option (2 bytes plus 8 per block), and 12 + 2 + 4×8 exceeds it. A segment carrying a full four-block SACK cannot also carry a timestamp without dropping a block. Implementations resolve the conflict by reducing the SACK block count when a timestamp is present, which is why a connection using both options typically reports three blocks rather than four. The consequence is that loss recovery in a connection with timestamps has a slightly coarser map of received ranges, as described in SACK Blocks and the Retransmission Queue.
When timestamps distort the estimate
The timestamp value is read from a counter, not from the wire, so it measures the interval from when the sender’s stack stamped the segment to when the acknowledgement was stamped. It does not measure the interval from transmission to receipt, and it does not include the time the segment spent queued in the sender’s own device before the counter was read.
On the receiving side, the same applies. The receiver echoes the timestamp it last saw, but when acknowledgements are delayed the specification asks for the timestamp of the earliest unacknowledged segment rather than the one that completed the pair, so the measured interval includes the wait before the acknowledgement was sent.
The measurement is therefore of the protocol’s own handling time plus the network’s, and the two are not separable. A sender that computes a round trip from timestamps is measuring something slightly different from a sender that computes it from send-and-acknowledge times, and the difference is the receiver’s batching delay. Since both mechanisms produce samples that include that delay, the estimate is consistent; what changes is the segment the delay is charged to, which with timestamps is the earliest one still unacknowledged rather than whichever segment completed the batch.
There is a further subtlety with the resolution. A counter incrementing once per millisecond quantises every sample to 1 ms. On a path with a 0.2 ms round trip, every sample reads as 0 or 1 ms, and the resulting variance is an artefact of the quantisation rather than a property of the path. Implementations that need finer resolution use a higher increment rate, which shortens the time to wrap and therefore shortens the connection lifetime that PAWS can protect. The trade-off is between measurement precision and the wrap interval, and it is resolved by choosing a rate that keeps the wrap interval above the maximum connection lifetime the implementation is willing to support.
Where the two functions meet
RTTM and PAWS are independent uses of the same field, and they fail independently. A connection can have accurate RTT samples and still be vulnerable to wrapped-sequence acceptance if the peer’s timestamps are coarse; it can have effective PAWS and poor RTT samples if the timestamp is echoed but the sender does not store per-transmission values.
The combination is worth having because it converts two heuristics into determinations. Without timestamps, a retransmission is ambiguous and a duplicate is undetectable; with them, both are decided by a value that travels with the segment and cannot be forged by an old copy of it. The cost is twelve bytes and a small amount of per-connection state, and the option is refused at handshake by any peer that does not want to pay it.