The packet procedure checks the message validity, computes
delay/offset samples and calls other procedures to filter the data and select the synchronization source. Test 1 requires the transmit
timestamp not match the last one received from the same peer; otherwise, the message might be an old duplicate. Test 2 requires the
originate timestamp match the last one sent to the same peer; otherwise, the message might be out of order, bogus or worse. In case of
broadcast mode (5) the apparent roundtrip delay will be zero and the full accuracy of the time-transfer operation may not be
achievable. However, the accuracy achieved may be adequate for most purposes. The poll-update procedure is called with argument
peer.hostpoll (peer.peerpoll may have changed).
begin packet procedure
peer.rec <-- sys.clock; /* capture receive timestamp */
if (pkt.mode != 5) begin
test1 <-- ( pkt.xmt != peer.org); /* test 1 */
test2 <-- (pkt.org = peer.xmt); /* test 2 */
pkt.org <-- peer.rec; /* fudge missing timestamps */
pkt.rec <-- pkt.xmt;
test1 <-- true; * fake tests */
test2 <-- true;
peer.org <-- pkt.xmt; /* update originate timestamp */
peer.peerpoll <-- pkt.poll; /* adjust poll interval */
Test 3 requires that both the originate and receive timestamps are nonzero. If either of the timestamps are zero, the association has
not synchronized or has lost reachability in one or both directions.
test3 <-- ( pkt.org != 0 and pkt.rec != 0); /* test 3 */
The roundtrip delay and clock offset relative to the peer are calculated as follows. Number the times of sending and receiving NTP
messages as shown in Figure 2<$&fig2> and let i be an even integer. Then Ti-3, Ti-2, Ti-1 and Ti are the contents of the
pkt.org, pkt.rec, pkt.xmt and peer.rec variables, respectively. The clock offset theta, roundtrip delay delta and dispersion epsilon
of the host relative to the peer is:
where, as before, phi = NTP.MAXSKEW over NTP.MAXAGE. The quantity epsilon represents the maximum error or dispersion due to
measurement error at the host and local-clock skew accumulation over the interval since the last message was transmitted to the peer.
subsequently, the dispersion will be updated by the clock-filter procedure.
The above method amounts to a continuously sampled, returnable-time system, which is used in some digital telephone networks [BEL86].
Among the advantages are that the order and timing of the messages are unimportant and that reliable delivery is not required.
Obviously, the accuracies achievable depend upon the statistical properties of the outbound and inbound data paths. Further analysis
and experimental results bearing on this issue can be found in [MIL90] and in Appendix H. Test 4 requires
that the calculated delay be within reasonable bounds:
test4 <-- (|delta| < NTP.MAXDISPERSE and epsilon < NTP.MAXDISPERSE); /* test 4 */
Test 5 is implemented only if the authentication mechanism described in Appendix C is implemented. It
requires either that authentication be explicitly disabled or that the authenticator be present and correct as determined by the
#ifdef (authentication implemented) /* test 5 */
<test5 <-- ( (peer.config = 1 and peer.authenable =0) or peer.authentic = 1);
Test 6 requires the peer clock be synchronized and the interval since the peer clock was last updated be positive and less than
NTP.MAXAGE. Test 7 insures that the host will not synchronize on a peer with greater stratum. Test 8 requires that the header contains
reasonable values for the pkt.rootdelay and pkt.rootdispersion fields.
test6 <-- ( roman pkt.leap != 112 and /* test 6 */
pkt.reftime <= pkt.xmt < pkt.reftime + NTP.MAXAGE)
test7 <-- pkt.stratum <= sys.stratum and /* test 7 */
pkt.stratum < NTP.MAXSTRATUM;
test8 <--( | pkt.rootdelay | < NTP.MAXDISPERSE and /* test 8 */
pkt.rootdispersion < NTP.MAXDISPERSE);
With respect to further processing, the packet includes valid (synchronized) data if tests one through four succeed (test1 & test2
& test3 & test4 = 1), regardless of the remaining tests. Only packets with valid data can be used to calculate offset, delay
and dispersion values. The packet includes a valid header if tests five through eight succeed (test5 & test6 & test7 &
test8 = 1), regardless of the remaining tests. Only packets with valid headers can be used to determine whether a peer can be selected
for synchronization. Note that test1 and test2 are not used in broadcast mode (forced to true), since the originate and receive
timestamps are undefined.
The clock-filter procedure is called to produce the delay (peer.delay), offset (peer.offset) and dispersion (peer.dispersion) for the
peer. Specification of the clock-filter algorithm is not an integral part of
the NTP specification, since there may be other algorithms that work well in practice. However, one found to work well in the Internet
environment is described in Section 4 and its use is recommended.
if (not valid header) exit;
peer.leap <-- pkt.leap; /* copy packet variables */
peer.stratum <-- pkt.stratum;
peer.precision <-- pkt.precision;
peer.rootdelay <-- pkt.rootdelay;
peer.rootdispersion <-- pkt.rootdispersion;
peer.refid <-- pkt.refid;
peer.reftime <-- pkt.reftime;
if (valid data) call clock-filter(theta ,delta ,epsilon); /* process sample */
end packet procedure;