This section consists of a formal definition of the Network Time
Protocol, including its data formats, entities, state variables,
events and event-processing procedures. The specification model is
based on the implementation model illustrated in Figure 2.1, but it
is not intended that this model is the only one upon which a
specification can be based. In particular, the specification is
intended to illustrate and clarify the intrinsic operations of NTP
and serve as a foundation for a more rigorous, comprehensive and
verifiable specification.
All mathematical operations expressed or implied herein are in
two's-complement arithmetic. Data are specified as integer or
fixed-point quantities. Since various implementations would be
expected to scale externally derived quantities for internal use,
neither the precision nor decimal-point placement for fixed-point
quantities is specified. Unless specified otherwise, all quantities
are unsigned and may occupy the full field width, if designated, with
an implied zero preceding the most significant (leftmost) bit.
Hardware and software packages designed to work with signed
quantities will thus yield surprising results when the most
significant (sign) bit is set. It is suggested that externally
derived, unsigned fixed-point quantities such as timestamps be
shifted right one bit for internal use, since the precision
represented by the full field width is seldom justified.
Since NTP timestamps are cherished data and, in fact, represent the
main product of the protocol, a special timestamp format has been
established. NTP timestamps are represented as a 64-bit unsigned
fixed-point number, in seconds relative to 0000 UT on 1 January 1900.
The integer part is in the first 32 bits and the fraction part in the
last 32 bits, as shown in the following diagram.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Integer Part |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Fraction Part |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
This format allows convenient multiple-precision arithmetic and
conversion to Time Protocol representation (seconds), but does
complicate the conversion to ICMP Timestamp message representation
(milliseconds). The precision of this representation is about 0.2
nanosecond, which should be adequate for even the most exotic
requirements.
Timestamps are determined by copying the current value of the logical
clock to a timestamp variable when some significant event, such as
the arrival of a message, occurs. In order to maintain the highest
accuracy, it is important that this be done as close to the hardware
or software driver associated with the event as possible. In
particular, departure timestamps should be redetermined for each
link-level retransmission. In some cases a particular timestamp may
not be available, such as when the host is rebooted or the protocol
first starts up. In these cases the 64-bit field is set to zero,
indicating the value is invalid or undefined.
Note that since some time in 1968 the most significant bit (bit 0 of
the Integer Part) has been set and that the 64-bit field will
overflow some time in 2036. Should NTP be in use in 2036, some
external means will be necessary to qualify time relative to 1900 and
time relative to 2036 (and other multiples of 136 years).
Timestamped data requiring such qualification will be so precious
that appropriate means should be readily available. There will exist
an 0.2-nanosecond interval, henceforth ignored, every 136 years when
the 64-bit field will be zero and thus considered invalid.
3.2. State Variables and Parameters
Following is a tabular summary of the various state variables and
parameters used by the protocol. They are separated into classes of
system variables, which relate to the operating system environment
and logical clock mechanism; peer variables, which are specific to
each peer operating in symmetric mode or client mode; packet
variables, which represent the contents of the NTP message; and
parameters, which are fixed in all implementations of the current
version. For each class the description of the variable is followed
by its name and the procedure or value which controls it. Note that
variables are in lower case, while parameters are in upper case.
System Variables Name Control
-------------------------------------------------------
Logical Clock sys.clock update
Clock Source sys.peer selection
algorithm
Leap Indicator sys.leap update
Stratum sys.stratum update
Precision sys.precision system
Synchronizing Distance sys.distance update
Estimated Drift Rate sys.drift system
Reference Clock Identifier sys.refid update
Reference Timestamp sys.reftime update
Table 3.1. System Variables
Peer Variables Name Control
-------------------------------------------------------
Peer Address peer.srcadr system
Peer Port peer.srcport system
Local Address peer.dstadr system
Local Port peer.dstport system
Peer State peer.state receive,
transmit
Reachability Register peer.reach receive,
transmit
Peer Timer peer.timer system
Timer Threshold peer.threshold system
Leap Indicator peer.leap receive
Stratum peer.stratum receive
Peer Poll Interval peer.ppoll receive
Host Poll Interval peer.hpoll receive,
transmit
Precision peer.precision receive
Synchronizing Distance peer.distance receive
Estimated Drift Rate peer.drift receive
Reference Clock Identifier peer.refid receive
Reference Timestamp peer.reftime receive
Originate Timestamp peer.org receive
Receive Timestamp peer.rec receive
Filter Register peer.filter filter
algorithm
Delay Estimate peer.delay filter
algorithm
Offset Estimate peer.offset filter
algorithm
Dispersion Estimate peer.dispersion filter
Table 3.2. Peer Variables
Packet Variables Name Control
-------------------------------------------------------
Peer Address pkt.srcadr transmit
Peer Port pkt.srcport transmit
Local Address pkt.dstadr transmit
Local Port pkt.dstport transmit
Leap Indicator pkt.leap transmit
Version Number pkt.version transmit
Stratum pkt.stratum transmit
Poll pkt.poll transmit
Precision pkt.precision transmit
Synchronizing Distance pkt.distance transmit
Estimated Drift Rate pkt.drift transmit
Reference Clock Identifier pkt.refid transmit
Reference Timestamp pkt.reftime transmit
Originate Timestamp pkt.org transmit
Receive Timestamp pkt.rec transmit
Transmit Timestamp pkt.xmt transmit
Table 3.3. Packet Variables
Parameters Name Value
-------------------------------------------------------
NTP Version NTP.VERSION 1
NTP Port NTP.PORT 123
Minimum Polling Interval NTP.MINPOLL 6 (64 sec)
Maximum Polling Interval NTP.MAXPOLL 10 (1024
sec)
Maximum Dispersion NTP.MAXDISP 65535 ms
Reachability Register Size PEER.WINDOW 8
Shift Register Size PEER.SHIFT 4/8
Dispersion Threshold PEER.THRESHOLD 500 ms
Filter Weight PEER.FILTER .5
Select Weight PEER.SELECT .75
Table 3.4. Parameters
Following is a description of the various variables used in the
protocol. Additional details on formats and use are presented in
later sections and appendices.
3.2.1. Common Variables
The following variables are common to the system, peer and packet
classes.
Peer Address (peer.srcadr, pkt.srcadr) Peer Port (peer.srcport,
pkt.srcport)
These are the 32-bit Internet address and 16-bit port number of
the remote host.
Local Address (peer.dstadr, pkt.dstadr) Local Port (peer.dstport,
pkt.dstport)
These are the 32-bit Internet address and 16-bit port number of
the local host. They are included among the state variables to
support multi-homing.
Leap Indicator (sys.leap, peer.leap, pkt.leap)
This is a two-bit code warning of an impending leap second to be
inserted in the NTP time scale. The bits are set before 23:59 on
the day of insertion and reset after 00:01 on the following day.
This causes the number of seconds (rollover interval) in the day
of insertion to be increased or decreased by one. In the case of
primary servers the bits are set by operator intervention, while
in the case of secondary servers the bits are set by the protocol.
The two bits are coded as follows:
00 no warning (day has 86400 seconds)
01 +1 second (day has 86401 seconds)
seconds)
10 -1 second (day has 86399 seconds)
seconds)
11 alarm condition (clock not synchronized)
In all except the alarm condition (11) NTP itself does nothing
with these bits, except pass them on to the time-conversion
routines that are not part of NTP. The alarm condition occurs
when, for whatever reason, the logical clock is not synchronized,
such as when first coming up or after an extended period when no
outside reference source is available.
Stratum (sys.stratum, peer.stratum, pkt.stratum)
This is an integer indicating the stratum of the logical clock. A
value of zero is interpreted as unspecified, one as a primary
clock (synchronized by outside means) and remaining values as the
stratum level (synchronized by NTP). For comparison purposes a
value of zero is considered greater than any other value.
Peer Poll Interval (peer.ppoll, pkt.poll)
This is a signed integer used only in symmetric mode and
indicating the minimum interval between messages sent to the peer,
in seconds as a power of two. For instance, a value of six
indicates a minimum interval of 64 seconds. The value of this
variable must not be less than NTP.MINPOLL and must not be greater
than NTP.MAXPOLL.
Precision (sys.precision, peer.precision, pkt.precision)
This is a signed integer indicating the precision of the logical
clock, in seconds to the nearest power of two. For instance, a
60-Hz line-frequency clock would be assigned the value -6, while a
1000-Hz crystal-derived clock would be assigned the value -10.
Synchronizing Distance (sys.distance, peer.distance, pkt.distance)
This is a fixed-point number indicating the estimated roundtrip
delay to the primary clock, in seconds.
Estimated Drift Rate (sys.drift, peer.drift, pkt.drift)
This is a fixed-point number indicating the estimated drift rate
of the local clock, in dimensionless units.
Reference Clock Identifier (sys.refid, peer.refid, pkt.refid)
This is a code identifying the particular reference clock or
server. The interpretation of the value depends on the stratum.
For stratum values of zero (unspecified) or one (primary clock),
the value is an ASCII string identifying the reason or clock,
respectively. For stratum values greater than one (synchronized
by NTP), the value is the 32-bit Internet address of the reference
server.
Reference Timestamp (sys.reftime, peer.reftime, pkt.reftime)
This is the local time, in timestamp format, when the logical
clock was last updated. If the logical clock has never been
synchronized, the value is zero.
3.2.2. System Variables
The following variables are used by the operating system in order to
synchronize the logical clock.
Logical Clock (sys.clock)
This is the current local time, in timestamp format. Local time
is derived from the hardware clock of the particular machine and
increments at intervals depending on the design used. An
appropriate design, including slewing and drift-compensation
mechanisms, is described in Section 5.
Clock Source (sys.peer)
This is a selector identifying the current clock source. Usually
this will be a pointer to a structure containing the peer
variables.
3.2.3. Peer Variables
Following is a list of state variables used by the peer management
and measurement functions. There is one set of these variables for
every peer operating in client mode or symmetric mode.
Peer State (peer.state)
This is a bit-encoded quantity used for various control functions.
Host Poll Interval (peer.hpoll)
This is a signed integer used only in symmetric mode and
indicating the minimum interval between messages expected from the
peer, in seconds as a power of two. For instance, a value of six
indicates a minimum interval of 64 seconds. The value of this
variable must not be less than NTP.MINPOLL and must not be greater
than NTP.MAXPOLL.
Reachability Register (peer.reach)
This is a code used to determine the reachability status of the
peer. It is used as a shift register, with bits entering from the
least significant (rightmost) end. The size of this register is
specified as PEER.SHIFT bits.
Peer Timer (peer.timer)
This is an integer counter used to control the interval between
transmitted NTP messages.
Timer Threshold (peer.threshold)
This is the timer value which, when reached, causes the timeout
procedure to be executed.
Originate Timestamp (peer.org, pkt.org)
This is the local time, in timestamp format, at the peer when its
latest NTP message was sent. If the peer becomes unreachable the
value is set to zero.
Receive Timestamp (peer.rec, pkt.rec)
This is the local time, in timestamp format, when the latest NTP
message from the peer arrived. If the peer becomes unreachable
the value is set to zero.
3.2.4. Packet Variables
Following is a list of variables used in NTP messages in addition to
the common variables above.
Version Number (pkt.version)
This is an integer indicating the version number of the sender.
NTP messages will always be sent with the current version number
NTP.VERSION and will always be accepted if the version number
matches NTP.VERSION. Exceptions may be advised on a case-by-case
basis at times when the version number is changed.
Transmit Timestamp (pkt.xmt)
This is the local time, in timestamp format, at which the NTP
message departed the sender.
3.2.5. Clock Filter Variables
When the filter and selection algorithms suggested in Section 4 are
used, the following state variables are defined. There is one set of
these variables for every peer operating in client mode or symmetric
mode.
Filter Register (peer.filter)
This is a shift register of PEER.WINDOW bits, where each stage is
a tuple consisting of the measured delay concatenated with the
measured offset associated with a single observation.
Delay/offset observations enter from the least significant
(rightmost) right and are shifted towards the most significant
(leftmost) end and eventually discarded as new observations
arrive. The register is cleared to zeros when (a) the peer
becomes unreachable or (b) the logical clock has just been reset
so as to cause a significant discontinuity in local time.
Delay Estimate (peer.delay)
This is a signed, fixed-point number indicating the latest delay
estimate output from the filter, in seconds. While the number is
signed, only those values greater than zero represent valid delay
estimates.
Offset Estimate (peer.offset)
This is a signed, fixed-point number indicating the latest offset
estimate output from the filter, in seconds.
Dispersion Estimate (peer.dispersion)
This is a fixed-point number indicating the latest dispersion
estimate output from the filter, in scrambled units.
3.2.6. Parameters
Following is a list of parameters assumed for all implementations
operating in the Internet system. It is necessary to agree on the
values for these parameters in order to avoid unnecessary network
overheads and stable peer associations.
Version Number (NTP.VERSION)
This is the NTP version number, currently one (1).
NTP Port (NTP.PORT)
This is the port number (123) assigned by the Internet Number Czar
to NTP.
Minimum Polling Interval (NTP.MINPOLL)
This is the minimum polling interval allowed by any peer of the
Internet system, currently set to 6 (64 seconds).
Maximum Polling Interval (NTP.MAXPOLL)
This is the maximum polling interval allowed by any peer of the
Internet system, currently set to 10 (1024 seconds).
Maximum Dispersion (NTP.MAXDISP)
This is the maximum dispersion assumed by the filter algorithms,
currently set to 65535 milliseconds.
Reachability Register Size (PEER.WINDOW)
This is the size of the Reachability Register (peer.reach),
currently set to eight (8) bits.
Shift Register Size (PEER.SHIFT)
When the filter and selection algorithms suggested in Section 4
are used, this is the size of the Clock Filter (peer.filter) shift
register, in bits. For crystal-stabilized oscillators a value of
eight (8) is suggested, while for mains-frequency oscillators a
value of four (4) is suggested. Additional considerations are
given in Section 5.
Dispersion Threshold (PEER.THRESHOLD)
When the filter and selection algorithms suggested in Section 4
are used, this is the threshold used to discard noisy data. While
a value of 500 milliseconds is suggested, the value may be changed
to suit local conditions on particular peer paths.
Filter Weight (PEER.FILTER)
When the filter algorithm suggested in Section 4 is used, this is
the filter weight used to discard noisy data. While a value of
0.5 is suggested, the value may be changed to suit local
conditions on particular peer paths.
Select Weight (PEER.SELECT)
When the selection algorithm suggested in Section 4 is used, this
is the select weight used to discard outlyers. data. While a
value of 0.75 is suggested, the value may be changed to suit local
conditions on particular peer paths.
3.3. Modes of Operation
An NTP host can operate in three modes: client, server and
symmetric. The mode of operation is determined by whether the source
port (peer.srcport) or destination port (peer.dstport) peer variables
contain the assigned NTP service port number NTP.PORT (123) as shown
in the following table.
peer.srcport peer.dstport Mode
-------------------------------------------
not NTP.PORT not NTP.PORT not possible
not NTP.PORT NTP.PORT server
NTP.PORT not NTP.PORT client
NTP.PORT NTP.PORT symmetric
A host operating in client mode occasionally sends an NTP message to
a host operating in server mode. The server responds by simply
interchanging addresses and ports, filling in the required
information and returning the message to the client. Servers then
need retain no state information between client requests. Clients
are free to manage the intervals between sending NTP messages to suit
local conditions.
In symmetric mode the client/server distinction disappears. Each
host maintains a table with as many entries as active peers. Each
entry includes a code uniquely identifying the peer (e.g., Internet
address and port), together with status information and a copy of the
timestamps last received. A host operating in symmetric mode
periodically sends NTP messages to each peer including the latest
copy of the timestamps. The intervals between sending NTP messages
are managed jointly by the host and each peer using the polling
variables peer.ppoll and peer.hpoll.
When a pair of peers operating in symmetric mode exchange NTP
messages and each determines that the other is reachable, an
association is formed. One or both peers must be in active state;
that is, sending messages to the other regardless of reachability
status. A peer not in active state is in passive state. If a peer
operating in passive state discovers that the other peer is no longer
reachable, it ceases sending messages and reclaims the storage and
timer resources used by the association. A peer operating in client
mode is always in active state, while a peer operating in server mode
is always in passive state.
3.4. Event Processing
The significant events of interest in NTP occur upon expiration of
the peer timer, one of which is dedicated to each peer operating in
symmetric or client modes, and upon arrival of an NTP message from
the various peers. An event can also occur as the result of an
operator command or detected system fault, such as a primary clock
failure. This section describes the procedures invoked when these
events occur.
3.4.1. Timeout Procedure
The timeout procedure is called in client and symmetric modes when
the peer timer (peer.timer) reaches the value of the timer threshold
(peer.threshold) variable. First, the reachability register
(peer.reach) is shifted one position to the left and a zero replaces
the vacated bit. Then an NTP message is constructed and sent to the
peer. If operating in active state or in passive state and
peer.reach is nonzero (reachable), the peer.timer is reinitialized
(resumes counting from zero) and the value of peer.threshold is set
to:
peer.threshold <- max( min( peer.ppoll, peer.hpoll,
NTP.MAXPOLL), NTP.MINPOLL) .
If operating in active state and peer.reach is zero (unreachable),
the peer variables are updated as follows:
peer.hpoll <- NTP.MINPOLL
peer.disp <- NTP.MAXDISP
peer.filter <- 0 (cleared)
peer.org <- 0
peer.rec <- 0
Then the clock selection algorithm is called, which may result in a
new clock source (sys.peer). In other cases the protocol ceases
operation and the storage and timer resources are reclaimed for
subsequent use.
An NTP message is constructed as follows (see Appendices A and B for
formats). First, the IP and UDP packet variables are copied from the
peer variables (note the interchange of source and destination
addresses and ports):
pkt.srcadr <- peer.dstadr pkt.srcport <- peer.dstport
pkt.dstadr <- peer.srcadr pkt.dstport <- peer.srcport
Next, the NTP packet variables are copied (rescaled as necessary)
from the system and peer variables:
pkt.leap <- sys.leap pkt.distance <- sys.distance
pkt.version <- NTP.VERSION pkt.drift <- sys.drift
pkt.stratum <- sys.stratum pkt.refid <- sys.refid
pkt.poll <- peer.hpoll pkt.reftime <- sys.reftime
pkt.precision <- sys.precision
Finally, the NTP packet timestamp variables are copied, depending on
whether the peer is operating in symmetric mode and reachable, in
symmetric mode and not reachable (but active) or in client mode:
Symmetric Reachable Symmetric Active Client
- ------------------- ------------------- -------------------
pkt.org <- peer.org pkt.org <- 0 pkt.org <- sys.clock
pkt.rec <- peer.rec pkt.rec <- 0 pkt.rec <- sys.clock
pkt.xmt <- sys.clock pkt.xmt <- sys.clock pkt.xmt <- sys.clock
Note that the order of copying should be designed so that the time to
perform the copy operations themselves does not degrade the
measurement accuracy, which implies that the sys.clock values should
be copied last. The reason for the choice of zeros to fill the
pkt.org and pkt.rec packet variables in the symmetric unreachable
case is to avoid the use of old data after a possibly extensive
period of unreachability. The reason for the choice of sys.clock to
fill these variables in the client case is that, if for some reason
the NTP message is returned by the recipient unaltered, as when
testing with an Internet-echo server, this convention still allows at
least the roundtrip time to be accurately determined without special
handling.
3.4.2. Receive Procedure
The receive procedure is executed upon arrival of an NTP message. If
the version number of the message (pkt.version) does not match the
current version number (NTP.VERSION), the message is discarded;
however, exceptions may be advised on a case-by-case basis at times
when the version number is changed.
If the clock of the sender is unsynchronized (pkt.leap = 11), or the
receiver is in server mode or the receiver is in symmetric mode and
the stratum of the sender is greater than the stratum of the receiver
(pkt.stratum > sys.stratum), the message is simply returned to the
sender along with the timestamps. In this case the addresses and
ports are interchanged in the IP and UDP headers:
pkt.srcadr <-> pkt.dstadr pkt.srcport <-> pkt.dstport
The following packet variables are updated from the system variables:
pkt.leap <- sys.leap pkt.distance <- sys.distance
pkt.version <- NTP.VERSION pkt.drift <- sys.drift
pkt.stratum <- sys.stratum pkt.refid <- sys.refid
pkt.precision <- sys.precision pkt.reftime <- sys.reftime
Note that the pkt.poll packet variable is unchanged. The timestamps
are updated in the order shown:
pkt.org <- pkt.xmt
pkt.rec <- sys.clock
pkt.xmt <- sys.clock
Finally, the message is forwarded to the sender and the server
receive procedure terminated at this point.
If the above is not the case, the source and destination Internet
addresses and ports in the IP and UDP headers are matched to the
correct peer. If there is a match, processing continues at the next
step below. If there is no match and symmetric mode is not indicated
(either pkt.srcport or pkt.dstport not equal to NTP.PORT), the
message must be a reply to a previously sent message from a client
which is no longer in operation. In this case the message is dropped
and the receive procedure terminated at this point.
If there is no match and symmetric mode is indicated, (both
pkt.srcport and pkt.dstport equal to NTP.PORT), an implementation-
specific instantiation procedure is called to create and initialize a
new set of peer variables and start the peer timer. The following
peer variables are set from the IP and UDP headers:
peer.srcadr <- pkt.srcadr peer.srcport <- pkt.srcport
peer.dstadr <- pkt.dstadr peer.dstport <- pkt.dstport
The following peer variables are initialized:
peer.state <- symmetric (passive)
peer.timer <- 0 (enabled)
peer.hpoll <- NTP.MINPOLL
peer.disp <- NTP.MAXDISP
The remaining peer variables are undefined and set to zero.
Assuming that instantiation is complete and that match occurs, the
least significant bit of the reachability register (peer.reach) is
set, indicating the peer is now reachable. The following peer
variables are copied (rescaled as necessary) from the NTP packet
variables and system variables:
peer.leap <- pkt.leap peer.distance <- pkt.distance
peer.stratum <- pkt.stratum peer.drift <- pkt.drift
peer.ppoll <- pkt.poll peer.refid <- pkt.refid
peer.precision <- pkt.precision peer.reftime <- pkt.reftime
peer.org <- pkt.xmt peer.rec <- sys.clock
peer.threshold <- max( min( peer.ppoll, peer.hpoll,
NTP.MAXPOLL), NTP.MINPOLL)
If either or both the pkt.org or pkt.rec packet variables are zero,
the sender did not have reliable values for them, so the receive
procedure is terminated at this point. If both of these variables
are nonzero, 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 3.1 and let i be an even
integer. Then t(i-3), t(i-2) and t(i-1) and t(i) are the contents of
the pkt.org, pkt.rec, pkt.xmt and peer.rec variables respectively.
| |
t(1) |------------------->| t(2)
| |
t(4) |<-------------------| t(3)
| |
t(5) |------------------->| t(6)
| |
t(8) |<-------------------| t(7)
| |
...
Figure 3.1. Calculating Delay and Offset
The roundtrip delay d and clock offset c of the receiving peer
relative to the sending peer is:
d = (t(i) - t(i-3)) - (t(i-1) - t(i-2))
c = [(t(i-2) - t(i-3)) + (t(i-1) - t(i))]/2 .
This method amounts to a continuously sampled, returnable-time
system, which is used in some digital telephone networks. Among the
advantages are that the order and timing of the messages is
unimportant and that reliable delivery is not required. Obviously,
the accuracies achievable depend upon the statistical properties of
the outbound and inbound net paths. Further analysis and
experimental results bearing on this issue can be found in
Appendix D.
The c and d values are then input to the clock filter algorithm to
produce the delay estimate (peer.delay) and offset estimate
(peer.offset) for the peer involved. If d becomes nonpositive due to
low delays, long polling intervals and high drift rates, it should be
considered invalid; however, even under these conditions it may
still be useful to update the local clock and reduce the drift rate
to the point that d becomes positive again. Specification of the
clock filter algorithm is not an integral part of the NTP
specification; however, one found to work well in the Internet
environment is described in Section 4.
When a primary clock is connected to the host, it is convenient to
incorporate its information into the data base as if the clock were
represented by an ordinary peer. The clocks are usually polled once
or twice a minute and the returned timecheck used to produce a new
update for the logical clock. The update procedure is then called
with the following assumed peer variables:
peer.offset <- timecheck - sys.clock
peer.delay <- as determined
peer.dispersion <- 0
peer.leap <- selected by operator, ordinarily 00
peer.stratum <- 0
peer.distance <- 0
peer.refid <- ASCII identifier
peer.reftime <- timecheck
In this case the peer.delay and peer.refid can be constants
reflecting the type and accuracy of the clock. By convention, the
value for peer.delay is ten times the expected mean error of the
clock, for instance, 10 milliseconds for a WWVB clock and 1000
milliseconds for a less accurate WWV clock, but with a floor of 100
milliseconds. Other peer variables such as the peer timer and
reachability register can be used to control the polling interval and
to confirm the clock is operating correctly. In this way the clock
filter and selection algorithms operate in the usual way and can be
used to mitigate the clock itself, should it appear to be operating
correctly, yet deliver bogus time.
3.4.3. Update Procedure
The update procedure is called when a new delay/offset estimate is
available. First, the clock selection algorithm determines the best
peer on the basis of estimated accuracy and reliability, which may
result in a new clock source (sys.peer). If sys.peer points to the
peer data structure with the just-updated estimates, the state
variables of that peer are used to update the system state variables
as follows:
sys.leap <- peer.leap
sys.stratum <- peer.stratum + 1
sys.distance <- peer.distance + peer.delay
sys.refid <- peer.srcadr
sys.reftime <- peer.rec
Finally, the logical clock procedure is called with peer.offset as
argument to update the logical clock (sys.clock) and recompute the
estimated drift rate (sys.drift). It may happen that the logical
clock may be reset, rather than slewed to its final value. In this
case the peer variables of all reachable peers are are updated as
follows:
peer.hpoll <- NTP.MINPOLL
peer.disp <- NTP.MAXDISP
peer.filter <- 0 (cleared)
peer.org <- 0
peer.rec <- 0
and the clock selection algorithm is called again, which results in a
null clock source (sys.peer = 0). A new selection will occur when
the filters fill up again and the dispersion settles down.
Specification of the clock selection algorithm and logical clock
procedure is not an integral part of the NTP specification. A clock
selection algorithm found to work well in the Internet environment is
described in Section 4, while a logical clock procedure is described
in Section 5. The clock selection algorithm described in Section 4
usually picks the server at the highest stratum and minimum delay
among all those available, unless that server appears to be a
falseticker. The result is that the algorithms all work to build a
minimum-weight spanning tree relative to the primary servers and thus
a hierarchical master-slave system similar to those used by some
digital telephone networks.
Upon reboot the NTP host initializes all system variables as follows:
sys.clock <- best available estimate
sys.leap <- 11 (unsynchronized)
sys.stratum <- 0 (undefined)
sys.precision <- as required
sys.distance <- 0 (undefined)
sys.drift <- as determined
sys.refid <- 0 (undefined)
sys.reftime <- 0 (undefined)
The logical clock sys.clock is presumably undefined at reboot;
however, in some designs such as the Fuzzball an estimate is
available from the reboot environment. The sys.precision variable is
determined by the intrinsic architecture of the local hardware clock.
The sys.drift variable is determined as a side effect of subsequent
logical clock updates, from whatever source.
Next, an implementation-specific instantiation procedure is called
repeatedly to establish the set of client peers or symmetric (active)
peers which will actively probe other servers during regular
operation. The mode and addresses of these peers is determined using
information read during the reboot procedure or as the result of
operator commands.