Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / ntp / html / howto.htm
1 <html><head><title>
2 How to Write a Reference Clock Driver
3 </title></head><body><h3>
4 How to Write a Reference Clock Driver
5 </h3>
6
7 <img align=left src=pic/pogo4.gif><a href=http://www.eecis.udel.edu/~mills/pictures.htm>from <i>Pogo</i>, Walt Kelly</a>
8
9 <p>You need a little magic.
10 <br clear=left><hr>
11
12 <h4>Description</h4>
13
14 <p>Reference clock support maintains the fiction that the clock is
15 actually an ordinary peer in the NTP tradition, but operating at a
16 synthetic stratum of zero. The entire suite of algorithms used to filter
17 the received data, select the best clocks or peers and combine them to
18 produce a local clock correction operate just like ordinary NTP peers.
19 In this way, defective clocks can be detected and removed from the peer
20 population. As no packets are exchanged with a reference clock; however,
21 the transmit, receive and packet procedures are replaced with separate
22 code to simulate them.
23
24 <p>Radio and modem reference clocks by convention have addresses in the
25 form <tt>127.127.<i>t</i>.<i>u</i></tt>, where <i>t</i> is the clock
26 type and <i>u</i> in the range 0-3 is used to distinguish multiple
27 instances of clocks of the same type. Most clocks require a serial port
28 or special bus peripheral. The particular device is normally specified
29 by adding a soft link <tt>/dev/device<i>d</i>d</tt> to the particular
30 hardware device involved, where <tt><i>d</i></tt> corresponds to the
31 unit number.
32
33 <p>The best way to understand how the clock drivers work is to study the
34 <tt>ntp_refclock.c</tt> module and one of the drivers already
35 implemented, such as <tt>refclock_wwvb.c</tt>. Routines
36 <tt>refclock_transmit()</tt> and <tt>refclock_receive()</tt> maintain
37 the peer variables in a state analogous to a network peer and pass
38 received data on through the clock filters. Routines
39 <tt>refclock_peer()</tt> and <tt>refclock_unpeer()</tt> are called to
40 initialize and terminate reference clock associations, should this ever
41 be necessary. A set of utility routines is included to open serial
42 devices, process sample data, edit input lines to extract embedded
43 timestamps and to perform various debugging functions.
44
45 <p>The main interface used by these routines is the
46 <tt>refclockproc</tt> structure, which contains for most drivers the
47 decimal equivalents of the year, day, month, hour, second and
48 millisecond/microsecond decoded from the ASCII timecode. Additional
49 information includes the receive timestamp, exception report, statistics
50 tallies, etc. The support routines are passed a pointer to the
51 <tt>peer</tt> structure, which is used for all peer-specific processing
52 and contains a pointer to the <tt>refclockproc</tt> structure, which in
53 turn contains a pointer to the unit structure, if used. For legacy
54 purposes, a table <tt>typeunit[type][unit]</tt> contains the peer
55 structure pointer for each configured clock type and unit.
56
57 <p>The reference clock interface supports auxiliary functions to support
58 in-stream timestamping, pulse-per-second (PPS) interfacing and precision
59 time kernel support. In most cases the drivers do not need to be aware
60 of them, since they are detected at autoconfigure time and loaded
61 automatically when the device is opened. These include the
62 <tt>tty_clk</tt> and <tt>ppsclock</tt> STREAMS modules and
63 <tt>ppsapi</tt> PPS interface described in the <a href="ldisc.htm">Line
64 Disciplines and Streams Modules</a> page. The <tt>tty_clk</tt> module
65 reduces latency errors due to the operating system and serial port code
66 in slower systems. The <tt>ppsclock</tt> module is an interface for the
67 PPS signal provided by some radios. The <tt>ppsapi</tt> PPS interface
68 replaces the <tt>ppsclock</tt> STREAMS module and is expected to become
69 the IETF standard cross-platform interface for PPS signals. In either
70 case, the PPS signal can be connected via a level converter/pulse
71 generator described in the <a href = "gadget.htm"> Gadget Box PPS Level
72 Converter and CHU Modem</a> page.
73
74 <p>By convention, reference clock drivers are named in the form
75 <tt>refclock_<i>xxxx</i>.c</tt>, where <i>xxxx</i> is a unique
76 string. Each driver is assigned a unique type number, long-form driver
77 name, short-form driver name, and device name. The existing assignments
78 are in the <a href="refclock.htm"> Reference Clock Drivers</a> page
79 and its dependencies. All drivers supported by the particular hardware
80 and operating system are automatically detected in the autoconfigure
81 phase and conditionally compiled. They are configured when the daemon is
82 started according to the configuration file, as described in the <a
83 href="config.htm"> Configuration Options </a> page.
84
85 <p>The standard clock driver interface includes a set of common support
86 routines some of which do such things as start and stop the device, open
87 the serial port, and establish special functions such as PPS signal
88 support. Other routines read and write data to the device and process
89 time values. Most drivers need only a little customizing code to, for
90 instance, transform idiosyncratic timecode formats to standard form,
91 poll the device as necessary, and handle exception conditions. A
92 standard interface is available for remote debugging and monitoring
93 programs, such as <tt>ntpq</tt> and <tt>ntpdc</tt>, as well as
94 the <tt>filegen</tt> facility, which can be used to record device
95 status on a continuous basis.
96
97 <p>The general organization of a typical clock driver includes a
98 receive-interrupt routine to read a timecode from the I/O buffer and
99 convert to internal format, generally in days, hours, minutes, seconds
100 and fraction. Some timecode formats include provisions for leap-second
101 warning and determine the clock hardware and software health. The
102 interrupt routine then calls <tt>refclock_process()</tt> with these data
103 and the timestamp captured at the on-time character of the timecode.
104 This routine saves each sample as received in a circular buffer, which
105 can store from a few up to 60 samples, in cases where the timecodes
106 arrive one per second.
107
108 <p>The <tt>refclock_transmit()</tt> routine in the interface is called
109 by the system at intervals defined by the poll interval in the peer
110 structure, generally 64 s. This routine in turn calls the transmit poll
111 routine in the driver. In the intended design, the driver calls the
112 <tt>refclock_receive()</tt> to process the offset samples that have
113 accumulated since the last poll and produce the final offset and
114 variance. The samples are processed by recursively discarding median
115 outlyers until about 60 percent of samples remain, then averaging the
116 surviving samples. When a reference clock must be explicitly polled to
117 produce a timecode, the driver can reset the poll interval so that the
118 poll routine is called a specified number of times at 1-s intervals.
119
120 <p>The interface code and this documentation have been developed over
121 some time and required not a little hard work converting old drivers,
122 etc. Should you find success writing a driver for a new radio or modem
123 service, please consider contributing it to the common good. Send the
124 driver file itself and patches for the other files to Dave Mills
125 (mills@udel.edu).
126
127 <h4>Conventions, Fudge Factors and Flags</h4>
128
129 <p>Most drivers support manual or automatic calibration for systematic
130 offset bias using values encoded in the <tt>fudge</tt> configuration
131 command. By convention, the <tt>time1</tt> value defines the calibration
132 offset in seconds. For those drivers that support statistics collection
133 using the <tt>filegen</tt> utility and the <tt>clockstats</tt> file, the
134 <tt>flag4</tt> switch enables the utility. When a PPS signal is
135 available, a special automatic calibration facility is provided. If the
136 <tt>flag1</tt> switch is set and the PPS signal is actively disciplining
137 the system time, the calibration value is automatically adjusted to
138 maintain a residual offset of zero. Should the PPS signal or the prefer
139 peer fail, the adjustment is frozen and the remaining drivers continue
140 to discipline the system clock with a minimum of residual error.
141
142 <h4>Files Which Need to be Changed</h4>
143
144 <p>A new reference clock implementation needs to supply, in addition to
145 the driver itself, several changes to existing files.
146
147 <dl>
148
149 <dt><tt>./include/ntp.h</tt>
150 <dd>The reference clock type defines are used in many places. Each
151 driver is assigned a unique type number. Unused numbers are clearly
152 marked in the list. A unique <tt>REFCLK_<i>xxxx</i></tt>
153 identification code should be recorded in the list opposite its assigned
154 type number.
155
156 <p><dt><tt>./libntp/clocktypes.c</tt>
157 <dd>The <tt>./libntp/clktype</tt> array is used by certain display
158 functions. A unique short-form name of the driver should be entered
159 together with its assigned identification code.
160
161 <p><dt><tt>./ntpd/ntp_control.c</tt>
162 <dd>The <tt>clocktypes</tt> array is used for certain control
163 message displays functions. It should be initialized with the reference
164 clock class assigned to the driver, as per the NTP specification
165 RFC-1305. See the <tt>./include/ntp_control.h</tt> header file for
166 the assigned classes.
167
168 <p><dt><tt>./ntpd/refclock_conf.c</tt>
169 <dd>This file contains a list of external structure definitions which
170 are conditionally defined. A new set of entries should be installed
171 similar to those already in the table. The <tt>refclock_conf</tt>
172 array is a set of pointers to transfer vectors in the individual
173 drivers. The external name of the transfer vector should be initialized
174 in correspondence with the type number.
175
176 <p><dt><tt>./acconfig.h</tt>
177 <dd>This is a configuration file used by the autoconfigure scheme. Add
178 two lines in the form:
179
180 <p><pre>
181   /* Define if we have a FOO clock */
182   #undef FOO
183 </pre>
184
185 <p>where FOO is the define used to cause the driver to be included in
186 the distribution.
187
188 <p><dt><tt>./configure.in</tt>
189 <dd>This is a configuration file used by the autoconfigure scheme. Add
190 lines similar to the following:
191
192 <p><pre>
193   AC_MSG_CHECKING(FOO clock_description)
194   AC_ARG_ENABLE(FOO, [  --enable-FOO        clock_description],
195       [ntp_ok=$enableval], [ntp_ok=$ntp_eac])
196   if test "$ntp_ok" = "yes"; then
197       ntp_refclock=yes
198       AC_DEFINE(FOO)
199   fi
200   AC_MSG_RESULT($ntp_ok)
201 </pre>
202
203 <p>(Note that <tt>$ntp_eac</tt> is the value from <tt>--
204 {dis,en}able-all-clocks</tt> for non-PARSE clocks and
205 <tt>$ntp_eacp</tt> is the value from <tt>--{dis,en}able-parse-
206 clocks</tt> for PARSE clocks. See the documentation on the autoconf
207 and automake tools from the GNU distributions.)
208
209 <p><dt><tt>./ntpd/Makefile.am</tt>
210 <dd><p>This is the makefile prototype used by the autoconfigure scheme.
211 Add the driver file name to the entries already in the
212 <tt>ntpd_SOURCES</tt> list.
213
214 <p>Patches to <tt>automake-1.0</tt> are required for the
215 autoconfigure scripts to work properly. The file <tt>automake-
216 1.0.patches</tt> can be used for this purpose.
217
218 <p><dt><tt>./ntpd/Makefile.am</tt>
219 <dd>Do the following sequence of commands:
220
221 <p><pre>
222   automake
223   autoconf
224   autoheader
225   configure
226 </pre>
227
228 <p>or simply run <tt>make</tt>, which will do this command sequence
229 automatically.
230
231 </dl>
232
233 <p><h4>Interface Routine Overview</h4>
234
235 <dl>
236
237 <dt><tt>refclock_newpeer</tt> - initialize and start a reference
238 clock
239 <dd>This routine allocates and initializes the interface structure which
240 supports a reference clock in the form of an ordinary NTP peer. A
241 driver-specific support routine completes the initialization, if used.
242 Default peer variables which identify the clock and establish its
243 reference ID and stratum are set here. It returns one if success and
244 zero if the clock address is invalid or already running, insufficient
245 resources are available or the driver declares a bum rap.
246 <p><dt><tt>refclock_unpeer</tt> - shut down a clock
247 <dd>This routine is used to shut down a clock and return its resources
248 to the system.
249
250 <p><dt><tt>refclock_transmit</tt> - simulate the transmit procedure
251 <dd>This routine implements the NTP transmit procedure for a reference
252 clock. This provides a mechanism to call the driver at the NTP poll
253 interval, as well as provides a reachability mechanism to detect a
254 broken radio or other madness.
255
256 <p><dt><tt>refclock_sample</tt> - process a pile of samples from the
257 clock
258 <dd>This routine converts the timecode in the form days, hours, minutes,
259 seconds, milliseconds/microseconds to internal timestamp format. It then
260 calculates the difference from the receive timestamp and assembles the
261 samples in a shift register. It implements a recursive median filter to
262 suppress spikes in the data, as well as determine a rough dispersion
263 estimate. A configuration constant time adjustment
264 <tt>fudgetime1</tt> can be added to the final offset to compensate
265 for various systematic errors. The routine returns one if success and
266 zero if failure due to invalid timecode data or very noisy offsets.
267
268 <p>Note that no provision is included for the year, as provided by some
269 (but not all) radio clocks. Ordinarily, the year is implicit in the Unix
270 file system and hardware/software clock support, so this is ordinarily
271 not a problem. Nevertheless, the absence of the year should be
272 considered more a bug than a feature and may be supported in future.
273
274 <p><dt><tt>refclock_receive</tt> - simulate the receive and packet
275 procedures
276 <dd>This routine simulates the NTP receive and packet procedures for a
277 reference clock. This provides a mechanism in which the ordinary NTP
278 filter, selection and combining algorithms can be used to suppress
279 misbehaving radios and to mitigate between them when more than one is
280 available for backup.
281
282 <p><dt><tt>refclock_gtlin</tt> - groom next input line and extract
283 timestamp
284 <dd>This routine processes the timecode received from the clock and
285 removes the parity bit and control characters. If a timestamp is present
286 in the timecode, as produced by the <tt>tty_clk</tt> line
287 discipline/streams module, it returns that as the timestamp; otherwise,
288 it returns the buffer timestamp. The routine return code is the number
289 of characters in the line.
290
291 <p><dt><tt>refclock_open</tt> - open serial port for reference clock
292 <dd>This routine opens a serial port for I/O and sets default options.
293 It returns the file descriptor if success and zero if failure.
294
295 <p><dt><tt>refclock_ioctl</tt> - set serial port control functions
296 <dd>This routine attempts to hide the internal, system-specific details
297 of serial ports. It can handle POSIX (<tt>termios</tt>), SYSV
298 (<tt>termio</tt>) and BSD (<tt>sgtty</tt>) interfaces with
299 varying degrees of success. The routine sets up the <tt>tty_clk,
300 chu_clk</tt> and <tt>ppsclock</tt> streams module/line discipline,
301 if compiled in the daemon and requested in the call. The routine returns
302 one if success and zero if failure.
303
304 <p><dt><tt>refclock_control</tt> - set and/or return clock values
305 <dd>This routine is used mainly for debugging. It returns designated
306 values from the interface structure that can be displayed using ntpdc
307 and the clockstat command. It can also be used to initialize
308 configuration variables, such as <tt>fudgetimes, fudgevalues,</tt>
309 reference ID and stratum.
310
311 <p><dt><tt>refclock_buginfo</tt> - return debugging info
312 <dd>This routine is used mainly for debugging. It returns designated
313 values from the interface structure that can be displayed using
314 <tt>ntpdc</tt> and the <tt>clkbug</tt> command.
315
316 </dl>
317
318 <hr><a href=index.htm><img align=left src=pic/home.gif></a><address><a
319 href=mailto:mills@udel.edu> David L. Mills &lt;mills@udel.edu&gt;</a>
320 </address></a></body></html>