Distributed Systems · Time and Ordering
The NTP Four-Timestamp Exchange and Its Asymmetry Limit
How four timestamps yield an offset estimate, why the estimate is only as good as the path symmetry, and how the protocol decides which of several servers to believe.
A host that wants to know the time has one source of information: another host that claims to know it better. The only thing the two can exchange is messages, and the only measurable quantities are when those messages left and arrived according to two clocks that disagree. The protocol that extracts an offset from this thin evidence is NTP, and its arithmetic is small enough to state in four lines.
Four timestamps and two equations
A client sends a request to a server. Four timestamps are involved:
T1: the client’s clock when the request was transmitted.T2: the server’s clock when the request was received.T3: the server’s clock when the reply was transmitted.T4: the client’s clock when the reply was received.
The client knows T1 and T4 directly and reads T2 and T3 from the reply. Let θ be the offset of the server’s clock relative to the client’s, meaning the amount the client would have to advance its clock to agree, and let d be the true round-trip path delay, split into an outbound part d1 and an inbound part d2 with d = d1 + d2. Then:
T2 - T1 = d1 + θ
T4 - T3 = d2 - θ
Adding gives d = (T4 - T1) - (T3 - T2), the round-trip delay with the server’s processing time subtracted. Subtracting the second from the first gives θ = ((T2 - T1) + (T3 - T4)) / 2, the offset. Both quantities are computable from the four values alone, and both appear in the protocol’s data as the offset and the delay of the sample.
The derivation assumes d1 = d2. Nothing in the exchange can test that assumption. If the outbound path takes 30 ms and the inbound takes 10 ms, the computed offset is wrong by 10 ms, which is half the asymmetry. The error in θ is exactly (d1 - d2)/2, so a path with 2 ms of asymmetry produces a 1 ms offset error regardless of how carefully the timestamps were taken.
This is the fundamental limit. It is not a limitation of the algorithm, which is exact under its assumption; it is a limitation of the information available. The measured round trip bounds the asymmetry from above but cannot locate it within that bound, so the true offset lies somewhere in an interval of width equal to the round-trip delay, centred on the estimate.
The 48-byte packet and its fields
An NTP packet has a fixed 48-byte header. The first byte holds the leap indicator in two bits, the version number in three bits, and the mode in three bits. Mode 3 is client, mode 4 is server, mode 5 is broadcast. Then come stratum (one byte), poll (one byte, a signed exponent giving the interval as a power of two seconds), and precision (one byte, also a signed exponent giving the clock’s resolution as a power of two).
The next 32 bits are the root delay, a fixed-point value with 16 fractional bits; then the root dispersion, also 16 fractional bits; then a 32-bit reference identifier whose meaning depends on the stratum. Four 64-bit timestamps follow: reference, origin, receive, and transmit. The origin field echoes the client’s transmit timestamp so the client can match a reply to its request, and the transmit field carries T3. The receive field carries T2, and the reference timestamp records when the server’s clock was last set.
Each timestamp is a 64-bit fixed-point number: 32 bits of seconds since 1900-01-01 and 32 bits of fraction, giving a resolution of about 233 picoseconds and a range that wraps in 2036. The era wrap is a real operational concern, and it is why implementations track the era separately rather than relying on the raw 32-bit seconds field.
Root distance and the chain of trust
A server’s own clock is not perfect, and its error propagates to the client. NTP accounts for this with two fields. The root delay is the accumulated round-trip delay from the server to its own reference, and the root dispersion is the accumulated error from all the servers in the chain plus the drift of the server’s clock since its last correction. Together they form the root distance:
root_distance = root_delay / 2 + root_dispersion
A client adds its own measured delay and dispersion to that, and the total bounds how far its clock can be from the true reference. The bound is pessimistic by construction: it assumes every error in the chain adds in the same direction, which is unlikely but not impossible. A stratum-1 server has a small root distance; a server five strata away has one that may be tens of milliseconds.
The stratum field encodes the distance from the reference in hops, with 1 meaning directly attached to a reference clock, and 16 meaning unsynchronized. A server at stratum 16 must not be used as a source, and a client that receives such a reply discards it. The protocol also requires that a server never accept a client’s time as a source, so the stratum always increases along the chain; a loop would otherwise form.
Selecting among servers
A client typically queries several servers and must decide which to believe. RFC 5905 specifies a selection algorithm, not a simple average. Each server contributes a sample, and the samples are filtered over time: the clock filter keeps the last eight samples and chooses the one with the lowest delay, on the reasoning that the lowest-delay sample suffered the least queueing and therefore has the smallest asymmetry error.
The surviving samples then go through a intersection step. For each candidate, the client computes a correctness interval from the offset and the root distance, [offset - distance, offset + distance], and finds the largest set of candidates whose intervals share a common point. Candidates outside that set are falsetickers and are excluded. The remaining truechimers are combined by a weighted average in which the weights are inversely related to the root distance, so a closer server contributes more.
This is a majority-vote scheme with an important property: it can tolerate a minority of faulty or misconfigured servers. With three sources, one liar can be outvoted; with four, one liar plus one ambiguous source can still be resolved. The cost is that the client must query enough servers, and the interval arithmetic assumes the claimed root distances are honest, which a malicious server can violate.
A simpler profile of the same protocol, specified separately as SNTP, keeps the 48-byte packet format and the four-timestamp exchange but drops the clock filter, the intersection step, and the discipline loop. It is intended for hosts that need coarse time and cannot afford the state, and it accepts a correspondingly weaker guarantee: a single server, no falseticker detection, and an offset applied by whatever mechanism the host already has.
Discipline: step, slew, and the cost of both
Having computed an offset, the client must apply it to its own clock. Two mechanisms exist, and the choice is consequential.
Stepping sets the clock to the corrected value immediately. It is fast and it can move the clock backwards. Any program that computed a duration across the step sees a negative interval, and a program that ordered two events by reading the clock before and after the step may see the later event stamped earlier. Timers scheduled on the wall clock can fire early, late, or never, depending on how the kernel handles the adjustment. Steps are therefore reserved for large offsets, typically beyond the panic threshold, and are usually refused by default on servers that must not jump.
Slewing adjusts the rate instead. The kernel runs the clock slightly fast or slow until the offset is consumed, with a maximum slew rate of about 500 parts per million in the common implementations. A 1 ms offset at 500 ppm takes 2 seconds to absorb; a 1 s offset takes over half an hour. Slewing preserves monotonicity and keeps intervals meaningful, at the cost of a long convergence time during which the clock is deliberately wrong.
The two mechanisms are complementary, and a client typically slews small offsets and steps only when the offset exceeds a threshold that makes slewing impractical. The threshold is a policy choice, and it is the point where the administrator decides whether monotonicity or convergence speed matters more.
The measurement floor
Put together, the accuracy a client can reach is bounded by three terms: the asymmetry of the path, the resolution and stability of the server’s clock, and the drift of the client’s own oscillator between polls. On a local network with a symmetric path, sub-millisecond agreement is achievable. Across a wide-area path with routing asymmetry, milliseconds are typical, and the root distance reported by the server is the honest statement of how much to trust it.
The protocol’s discipline is that this number is always reported rather than hidden. A timestamp from an NTP-synchronized host is not a point; it is a point plus a bound, and the correct use of it is the interval comparison described in Wall-Clock Timestamps Do Not Order Distributed Events. Systems that need tighter bounds than NTP can provide either place the reference closer, use a hardware timestamping path, or abandon physical time as the ordering authority, which is the direction taken by Bounded Clock Uncertainty and the Commit-Wait Rule.
References
- RFC 5905: Network Time Protocol Version 4: Protocol and Algorithms Specification — IETF
- RFC 4330: Simple Network Time Protocol (SNTP) Version 4 — IETF
- Computer Network Time Synchronization: The Network Time Protocol — David L. Mills, CRC Press, 2006