Line Disciplines and Streams Modules


Description

Most radio and modem clocks used for a primary (stratum-1) NTP server utilize serial ports operating at speeds of 9600 baud or greater. The intrinsic delay and jitter contributed by the serial port hardware and software driver can accumulate up to a millisecond in newer Unix systems and tens of milliseconds in older ones. In order to reduce the effects of delay and jitter, a set of special line disciplines, stream modules and operating system calls (ioctls) can be configured in some Unix kernels. These routines intercept special characters or signals provided by the radio or modem clock and save a timestamp for later processing.

The routines provide two important functions. Some insert a timestamp in the receive data stream upon occurance of a designated character or characters at the serial interface. This can be used to timestamp an on-time character produced by a radio clock, for example. Other routines support an application program interface for pulse-per-second (PPS) signals generated by some radio clocks and laboratory instruments. These routines are normally accessed through the PPSAPI application program interface described below.

The routines can be compiled in the kernel in older BSD-derived systems, or installed as System V streams modules and either compiled in the kernel or dynamically loaded when required. In either case, they require minor changes in some kernel files and in the NTP daemon ntpd. The streams modules can be pushed and popped from the streams stack using conventional System V streams program primitives. Note that some Unix kernels do not support line disciplines and some do not support System V streams. The routines described here are known to work correctly with the Unix kernels called out in the descriptions, but have not been tested for other kernels.

PPSAPI Application Program Interface

Pulse-per-second (PPS) signals are normally processed as described in the Pulse-per-second (PPS) Signal Interfacing page. The PPS Clock Discipline driver uses the PPSAPI application program interface to capture PPS signal transitions used to fine-tune the system clock. This interface, defined in RFC-2783, is the only PPS interface supported in NTP. While older PPS interfaces based on the ioctls described below continue to be supported, they are used only in the special header file /usr/include/sys/timepps.h, which implements the PPSAPI specific to each archeticture and operating system.

It is the intent of the evolving design to remove all PPS support from the various clock drivers and utilize only the PPS driver for PPS support. This allows the required sanity checks and signal grooming to be provided and maintained in one place and avoids cluttering up the drivers with duplicate functionality. Since the PPS signal samples are processed by the entire suite of NTP grooming, selection and clustering algorithms, noisy PPS signals and signals outside specific time and frequency tolerances are excluded.

The PPSAPI interface provides the following functions:

time_pps_create
Creates a PPS interface instance and returns a handle to it.
time_pps_destroy
Destroys a PPS interface and returns the resources used.
time_pps_setparams
Sets the parameters associated with a PPS interface instance, including offsets to be automatically added to captured timestamps.
time_pps_getparams
Returns the parameters associated with a PPS interface instance.
time_pps_getcap
Returns the capabilities of the current interface and kernel implementation.
time_pps_fetch
Returns the current timestamps associated with a PPS interface instance in either nanoseconds and nanoseconds (Unix timespec) or seconds and fraction (NTP) format.
time_pps_kcbind
If kernel PPS processing is supported, this binds the support to the associated PPS interface instance.

The entire PPS interface functionality is currently provided by inline code in the timepps.h header files implemented for SunOS, Solaris, FreeBSD, Linux and Tru64. While not all implementations support the full PPSAPI specification, they do support all the functions required for the PPS driver. The FreeBSD, Linux and Solaris implementations can be used with the stock kernels provided with those systems; however, the Tru64 and SunOS kernels require additional functions not provided in the stock kernels. Solaris users are cautioned that these ioctls function improperly in Solaris versions prior to 2.8 with patch Generic_108528-02.

tty_clk Line Discipline/Streams Module

This routine intercepts characters received from the serial port and passes unchanged all except a set of designated characters to the generic serial port discipline. For each of the exception characters, the character is inserted in the receiver buffer followed by a local timestamp in Unix timeval format. Both select() and SIGIO are supported by the routine. Support for this routine is automatically detected during the NTP build process and interface code compiled as necessary.

There are two versions of the tty_clk routine. The tty_clk.c line discipline is designed for older BSD systems and is compiled in the kernel. The tty_clk_STREAMS.c is designed for System V streams, in which case it can be either compiled in the kernel or dynamically loaded. Since these programs are small, unobtrusive, and do nothing unless specifically enabled by an application program, it probably doesn't matter which version is chosen. Instructions on how to configure and build a kernel supporting either of these routines is in the README file in the ./kernel directory.

The tty_clk routine defines a new ioctl CLK_SETSTR, which takes a pointer to a string of no more than 32 characters. Until the first CLK_SETSTR is performed, the routine will simply pass through characters. Once it is passed a string by CLK_SETSTR, any character in that string will be immediately followed by a timestamp in Unix timeval format. You can change the string whenever you want by doing another CLK_SETSTR. The character must be an exact, 8 bit match. The character '\000' cannot, be used, as it is the string terminator. Passing an empty string to CLK_SETSTR turns off timestamping. Passing NULL may produce surprising results.

TIOCDCDTIMESTAMP ioctl in FreeBSD

This ioctl is included in FreeBSD 2.2 and later. It causes a timestamp to be inserted in the serial port receive data stream when the data carrier detect (DCD) signal is asserted. This is useful for those radio clocks that indicate the on-time epoch by means of a modem control signal. It is not recommended that this be used for PPS timestamps, as this function is available using the PPS application program interface included in FreeBSD 3.4 and later.

The TIOCDCDTIMESTAMP ioctl() is detected and compiled automatically on FreeBSD systems if available. With FreeBSD 2.2 the measured delay between activation of the DCD signal and the time the timestamp is captured on a 66MHz 486DX2 is 19 ms and on a 100MHz Pentium is 6 ms.

ppsclockStreams Module

This routine is a streams module which causes a timestamp to be captured when the DCD signal is asserted. It is normally used in connection with a PPS signal generated by some radio clocks. However, it is normally used only by the PPSAPI interface and should be avoided in other contexts. Instructions on how to configure and build a kernel supporting either of these routines is in the README file in the ./kernel directory.

The ppsclock streams module implements the CIOGETEV ioctl, which takes a pointer to the structure

struct ppsclockev {
     struct timeval tv;
     u_int serial;
};

The ppsclock module is pushed on the streams stack of the serial port connected to the DCD line. At each positive-going edge of the PPS signal, the routine latches the current local timestamp and increments a counter. At each CIOGETEV ioctl call, the current values of the timestamp and counter are returned in the ppsclockev structure.

TIOCSPPS and TIOCGETPPSEV ioctls in Solaris

These ioctls are included in Solaris 2.4 and later. They implement the same function as the ppsclock streams module, but are implemented as integrated system calls independent of the streams facility. They are normally used in connection with a pulse-per-second (PPS) signal generated by some radio clocks. However, these ioctls are normally used only by the PPSAPI interface and should be avoided in other contexts. See the Sun documentation for the calling sequence and return values.

Users are cautioned that these ioctls function improperly in Solaris versions prior to 2.8 with patch Generic_108528-02.

tty_chu Line Discipline/Streams Module (depredated)

This routine is a special purpose line discipline for receiving a special timecode broadcast by Canadian time and frequency standard station CHU. It has been removed from the distribution since its function has been replaced by the Radio CHU Audio Demodulator/Decoder (type 7) clock driver.


David L. Mills <mills@udel.edu>