1 = How to Write a Reference Clock Driver
2 include::include-html.ad[]
4 [cols="10%,90%",frame="none",grid="none",style="verse"]
5 |==============================
6 |image:pic/pogo4.gif[]|
7 {millshome}pictures.html[from 'Pogo', Walt Kelly]
9 You need a little magic.
11 |==============================
15 include::includes/misc.adoc[]
19 * link:#desc[Description]
20 * link:#file[Files Which Need to be Changed]
21 * link:#intf[Interface Routine Overview]
22 * link:#pps[Pulse-per-Second Interface]
26 == When Not to Write a Driver
28 If the device you are trying to support is an exotic GPS, you should
29 probably not write an +ntpd+ driver for it. Instead, check to see if
30 it is already supported by {GPSD}, a project with which NTPsec
31 cooperates closely. The GPSD people are specialists in managing GPSes
32 and better at it than we are, supporting a much broader range of
33 devices, and GPSD is designed to feed clock samples to +ntpd+ from any
34 of them. If you need to write a driver for a GPS, they'll take it and
37 If you have a non-GPS time source (like a time radio or GPSDO) that
38 you want to support, consider link:generic_howto.html[writing a mode
39 for it in the generic driver] rather than a full driver of its own;
40 this will be easier. The generic driver is so called because it
41 factors out a lot of I/O and housekeeping code common to all drivers,
42 allowing you support a new device type by writing only a parser for
46 == Structure of a Driver
48 NTP reference clock support maintains the fiction that the clock is
49 actually an ordinary server in the NTP tradition, but operating at a
50 synthetic stratum of zero. The entire suite of algorithms filter the
51 received data and select the best sources to correct the system clock.
52 No packets are exchanged with a reference clock; however, the transmit,
53 receive and packet procedures are replaced with code to simulate them.
55 The driver assumes three timescales: standard time maintained by a
56 distant laboratory such as USNO or NIST, reference time maintained by
57 the external radio and the system time maintained by NTP. The radio
58 synchronizes reference time via radio, satellite or modem. As the
59 transmission means may not always be reliable, most radios continue to
60 provide clock updates for some time after signal loss using an internal
61 reference oscillator. In such cases the radio may or may not reveal the
62 time since last synchronized or the estimated time error.
64 All three timescales run only in Coordinated Universal Time (UTC) and
65 are not adjusted for local timezone or standard/daylight time. The local
66 timezone, standard/daylight indicator and year, if provided, are
67 ignored. However, it is important to determine whether a leap second is
68 to be inserted in the UTC timescale in the near future so NTP can insert
69 it in the system timescale at the appropriate epoch.
71 The interface routines in the +ntp_refclock.c+ source file call the
72 following driver routines via a transfer vector:
75 The association has just been mobilized. The driver may allocate a
76 private structure and open the device(s) required.
78 The association is about to be demobilized. The driver should close
79 all device(s) and free private structures.
81 A timecode string is ready for retrieval using the +refclock_gtlin()+
82 or +refclock_gtraw()+ routines and provide clock updates.
84 Called at poll timeout, by default 64 s. Ordinarily, the driver will
85 send a poll sequence to the radio as required.
87 Called once per second. This can be used for housekeeping functions.
88 In the case with pulse-per-second (PPS) signals, this can be used to
89 process the signals and provide clock updates.
91 The receive routine retrieves a timecode string via serial or parallel
92 port, PPS signal or other means. It decodes the timecode in days, hours,
93 minutes, seconds and nanoseconds and checks for errors. It provides
94 these data along with the on-time timestamp to the +refclock_process+
95 routine, which saves the computed offset in a 60-sample circular buffer.
96 On occasion, either by timeout, sample count or call to the poll
97 routine, the driver calls +refclock_receive+ to process the circular
98 buffer samples and update the system clock.
100 The best way to understand how the clock drivers work is to study one of
101 the drivers already implemented, such as +refclock_spectracom.c+. The
102 main interface is the +refclockproc+ structure, which contains for most
103 drivers the decoded timecode, on-time timestamp, reference timestamp,
104 exception reports and statistics tallies, etc. The support routines are
105 passed a pointer to the +peer+ structure, which contains a pointer to
106 the +refclockproc+ structure, which in turn contains a pointer to the
107 unit structure, if used. For legacy purposes, a table
108 +typeunit[type][unit]+ contains the peer structure pointer for each
109 configured clock type and unit. This structure should not be used for
112 Radio and modem reference clocks by convention have addresses of the
113 form +127.127.t.u+, where _t_ is the clock type and _u_ in the range 0-3
114 is used to distinguish multiple instances of clocks of the same type.
115 These addresses used to be exposed as part of the refclock
116 configuration syntax, but are no longer. Nothing in ntpd now actually
117 requires this form of address for clocks, but it is still generated
118 so as not to hand surprises to legacy +ntpq+ instances that still make
121 Most clocks require a serial or parallel port or special bus peripheral.
122 The particular device is normally specified by adding a soft link
123 +/dev/deviceu+ to the particular hardware device.
125 By convention, reference clock drivers are named in the form
126 +refclock_xxxx.c+, where +xxxx+ is a unique string. Each driver is
127 assigned a unique long-form driver name, short-form driver name and
128 device name. The existing assignments are in the
129 link:refclock.html[Reference Clock Drivers] page and its dependencies.
131 == Conventions, Fudge Factors and Flags
133 Most drivers support manual or automatic calibration for systematic
134 offset bias using values encoded in the +refclock+ configuration command.
135 By convention, the +time1+ value defines the calibration offset in
136 seconds. For those drivers that support statistics collection using the
137 +filegen+ utility and the +clockstats+ file, the +flag4+ switch enables
140 If the calibration feature has been enabled, the +flag1+ switch is set
141 and the PPS signal is actively disciplining the system time, the +time1+
142 value is automatically adjusted to maintain a residual offset of zero.
143 Once the its value has stabilized, the value can be inserted in the
144 configuration file and the calibration feature disabled.
147 == Files Which Need to be Changed
149 When a new reference clock driver is installed, the following files need
150 to be edited. Note that changes are also necessary to properly integrate
151 the driver in the configuration and makefile scripts, but these are
152 decidedly beyond the scope of this page.
155 The reference clock type defines are used in many places. Each driver
156 is assigned a unique type number. Unused numbers are clearly marked in
157 the list. A unique +REFCLK_xxxx+ identification code should be
158 recorded in the list opposite its assigned type number.
159 +./libntp/clocktypes.c+::
160 The +./libntp/clktype+ array is used by certain display functions. A
161 unique short-form name of the driver should be entered together with
162 its assigned identification code.
163 +./ntpd/ntp_control.c+::
164 The +clocktypes+ array is used for certain control message displays
165 functions. It should be initialized with the reference clock class
166 assigned to the driver, as per the NTP specification RFC 1305. See the
167 +./include/ntp_control.h+ header file for the assigned classes.
168 +./ntpd/refclock_conf.c+::
169 This file contains a list of external structure definitions which are
170 conditionally defined. A new set of entries should be installed
171 similar to those already in the table. The +refclock_conf+ array is a
172 set of pointers to transfer vectors in the individual drivers. The
173 external name of the transfer vector should be initialized in
174 correspondence with the type number.
177 == Interface Routine Overview
179 +refclock_newpeer+ - initialize and start a reference clock.::
180 Allocates and initializes the interface structure which
181 supports a reference clock in the form of an ordinary NTP peer. A
182 driver-specific support routine completes the initialization, if used.
183 Default peer variables which identify the clock and establish its
184 reference ID and stratum are set here. It returns one if success and
185 zero if the clock address is invalid or already running, insufficient
186 resources are available or the driver declares a bum rap.
187 +refclock_unpeer+ - shut down a clock::
188 Shuts down a clock and returns its resources to the system.
189 +refclock_transmit+ - simulate the transmit procedure::
190 Implements the NTP transmit procedure for a reference
191 clock. This provides a mechanism to call the driver at the NTP poll
192 interval, as well as provides a reachability mechanism to detect a
193 broken radio or other madness.
194 +refclock_process+ - insert a sample in the circular buffer::
195 Saves the offset computed from the on-time timestamp and
196 the days, hours, minutes, seconds and nanoseconds in the circular
197 buffer. Note that no provision is included for the year, as provided
198 by some (but not all) radio clocks. Ordinarily, the year is implicit
199 in the Unix file system and hardware/software clock support, so this
200 is ordinarily not a problem.
201 +refclock_receive+ - simulate the receive and packet procedures::
202 Simulates the NTP receive and packet procedures for a
203 reference clock. This provides a mechanism in which the ordinary NTP
204 filter, selection and combining algorithms can be used to suppress
205 misbehaving radios and to mitigate between them when more than one is
206 available for backup.
207 +refclock_gtraw+, +refclock_gtlin+ - read the buffer and on-time timestamp::
208 These routines return the data received from the clock and the on-time
209 timestamp. The +refclock_gtraw+ routine returns a batch of one or more
210 characters returned by the Unix terminal routines in raw mode. The
211 +refclock_gtlin+ routine removes the parity bit and control characters
212 and returns all the characters up to and including the line
213 terminator. Either routine returns the number of characters delivered.
214 +refclock_open+ - open a serial port for reference clock::
215 Opens a serial port for I/O and sets default options. It
216 returns the file descriptor if success and zero if failure.
217 +refclock_ioctl+ - set serial port control functions::
218 Attempts to hide the internal, system-specific details of
219 serial ports. It can handle POSIX (+termios+), SYSV (+termio+) and BSD
220 (+sgtty+) interfaces with varying degrees of success. The routine
221 returns one if success and zero if failure.
223 Initializes the Pulse-per-Second interface (see below).
225 Called once per second to read the latest PPS offset
226 and save it in the circular buffer (see below).
229 == Pulse-per-Second Interface
231 When the Pulse-per-Second Application Interface (RFC 2783) is present, a
232 compact PPS interface is available to all drivers. See the
233 link:prefer.html[Mitigation Rules and the Prefer Peer] page for further
234 information. To use this interface, include the +timeppps.h+ and
235 +refclock_pps.h+ header files and define the +refclock_ppsctl+ structure
236 in the driver private storage. The +timepps.h+ file is specific to each
237 operating system and may not be available for some systems.
239 To use the interface, call +refclock_ppsapi+ from the startup routine
240 passing the device file descriptor and +refclock_ppsctl+ structure
241 pointer. Then, call +refclock_pps+ from the timer routine passing the
242 association pointer and +refclock_ppsctl+ structure pointer. See the
243 +refclock_pps.c+ file for examples and calling sequences. If the PPS
244 signal is valid, the offset sample will be save in the circular buffer
245 and a bit set in the association flags word indicating the sample is
246 valid and the driver an be selected as a PPS peer. If this bit is set
247 when the poll routine is called, the driver calls the
248 +refclock_receive+ routine to process the samples in the circular
249 buffer and update the system clock.
253 include::includes/footer.adoc[]