Network Working Group                             Jeffrey Mogul, DECWRL,
Internet-Draft                                         David Mills, UDel
Expires: 22 March 1998                               Jan Brittenson, Sun
                                                       10 September 1997

                     Pulse-Per-Second API for UNIX

                       draft-mogul-pps-api-00.txt


STATUS OF THIS MEMO

        NOTE: THIS IS A PRELIMARY DESIGN DRAFT.  DO NOT IMPLEMENT
        BASED ON THIS DRAFT.  THE DESIGN WILL CHANGE.

        This document is an Internet-Draft. Internet-Drafts are
        working documents of the Internet Engineering Task Force
        (IETF), its areas, and its working groups. Note that other
        groups may also distribute working documents as
        Internet-Drafts.

        Internet-Drafts are draft documents valid for a maximum of
        six months and may be updated, replaced, or obsoleted by
        other documents at any time. It is inappropriate to use
        Internet-Drafts as reference material or to cite them other
        than as "work in progress."

        To learn the current status of any Internet-Draft, please
        check the "1id-abstracts.txt" listing contained in the
        Internet-Drafts Shadow Directories on ftp.is.co.za
        (Africa), nic.nordu.net (Europe), munnari.oz.au (Pacific
        Rim), ds.internic.net (US East Coast), or ftp.isi.edu (US
        West Coast).

        Distribution of this document is unlimited.  Please send
        comments to the authors.


ABSTRACT

        RFC1589 describes a UNIX kernel implementation model for
        high-precision time-keeping.  This is meant for use in
        conjunction with the Network Time Protocol (NTP, RFC1305),
        or similar time synchronization protocols.  One aspect of
        this model is an accurate interface to the high-accuracy,
        one pulse-per-second (PPS) output typically available from
        precise time sources (such as a GPS or GOES receiver).
        RFC1589 did not define an API for managing the PPS
        facility.  This document specifies such an API.






Mogul, Mills                                                    [Page 1]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


                           TABLE OF CONTENTS

1 Introduction                                                         2
2 Data types for representing timestamps                               3
     2.1 Precision                                                     4
     2.2 Time scale                                                    4
3 API                                                                  5
     3.1 New data structures                                           5
     3.2 Mode bit definitions                                          6
     3.3 New functions                                                 7
          3.3.1 New functions: access to PPS events                    7
          3.3.2 New functions: setting PPS mode bits                   8
          3.3.3 New functions: access to PPS timestamps                9
          3.3.4 New functions: disciplining the kernel timebase       10
     3.4 Example                                                      10
4 PPSDISC Line discipline                                             11
     4.1 Example                                                      11
5 Security Considerations                                             12
6 Acknowledgements                                                    12
7 References                                                          12
8 Authors' addresses                                                  13


1 Introduction

   RFC1589 [3] describes a model and programming interface for generic
   operating system software that manages the system clock and timer
   functions. The model provides improved accuracy and stability for
   most workstations and servers using the Network Time Protocol
   (NTP) [2] or similar time synchronization protocol.  The model
   supports the use of external timing sources, such as the precision
   pulse-per-second (PPS) signals typically available from precise time
   sources (such as a GPS or GOES receiver).

   However, RFC1589 did not define an application programming interface
   (API) for the PPS facility.  This document specifies such an
   interface, for use with UNIX (or UNIX-like) operating systems.  Such
   systems often conform to the ``Single UNIX Specification'' [4],
   sometimes known as POSIX.

   One convenient means to provide a PPS signal to a computer system is
   to connect that signal to a modem-control pin on a serial-line
   interface to the computer.  The Data Carrier Detect (DCD) pin is
   frequently used for this purpose.  Typically, the time-code output of
   the time source is transmitted to the computer over the same serial
   line.  The computer detects a signal transition on the DCD pin,
   usually by receiving an interrupt.

   Although existing practice has focussed on the use of serial lines
   and DCD transitions, PPS signals might also be delivered by other
   kinds of devices.  The API specified in this document does not

Mogul, Mills                                                    [Page 2]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


   require the use of a serial line, although it may be somewhat biased
   in that direction.

   The typical use of this facility is for the operating system to
   record a high-resolution timestamp as soon as possible after it
   detects a PPS signal transition (usually indicated by an interrupt).
   This timestamp can then be made available, with less stringent delay
   constraints, to timekeeping software.  The software can compare the
   captured timestamp to the received time-code to accurately determine
   the absolute offset between the system clock and the precise time
   source.

   The operating system may also deliver the PPS event immediately to a
   procedure used to discipline its internal timebase, such as the
   hardpps() procedure described in RFC1589.

   The API specified in this document allows for one or more signal
   sources attached to a computer system to provide PPS inputs, at the
   option of user-level software.  User-level software may obtain
   DCD-transition timestamps for any of these PPS sources.  User-level
   software may optionally specify that at most one of these PPS sources
   be used to discipline the system's internal timebase.

   Although the primary purpose of this API is for capturing true
   pulse-per-second events, the API may also be used for accurately
   timestamping events of other periods, or even aperiodic events, when
   these can be expressed as signal transitions.

   This document does not define how the API must be implemented, and
   does not specify constraints on the accuracy, precision, or latency
   of the PPS feature.  However, the utility of this feature is
   inversely proportional to the delay (and variance of delay), and
   implementors are encouraged to take this seriously.

   In principle, the rate of events to be captured, or the frequency of
   the signals, can range from once per day (or less often) to several
   thousand per second.  However, since in most implementations the
   timestamping function will be implemented as a processor interrupt at
   a relatively high priority, it is prudent to limit the rate of such
   events.  This may be done either by mechanisms in the hardware that
   generates the signals, or by the operating system.


2 Data types for representing timestamps

   Computer systems use various representations of time.  Because this
   API is concerned with the provision of high-accuracy, high-resolution
   time information, the choice of representation is significant.  (Here
   we consider only binary representations, not human-format
   representations.)


Mogul, Mills                                                    [Page 3]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


   The two interesting questions are:

      1. what is the precision of the representation?

      2. what time scale is represented?

   These questions often lead to contentious arguments.  Since this API
   is intended for use with NTP and POSIX-compliant systems, however, we
   can limit the choices to representations compatible with existing NTP
   and POSIX practice, even if that practice is considered ``wrong'' in
   some quarters.

2.1 Precision
   In the NTP protocol, ``timestamps are represented as a 64-bit
   unsigned fixed-point number, in seconds relative to 0h on 1 January
   1900. The integer part is in the first 32 bits and the fraction part
   in the last 32 bits [...] The precision of this representation is
   about 200 picoseconds'' [2].

   However, most computer systems cannot measure time to this precision
   (this represents a clock rate of 5 GHz).  The POSIX gettimeofday()
   function returns a ``struct timeval'' value, with a precision of 1
   microsecond.  The POSIX clock_settime() function returns a ``struct
   timespec'' value, with a precision of 1 nanosecond.

   This API uses the ``struct timespec'' representation, since in a
   general-purpose computer system it is just barely feasible to measure
   time to a precision of a few microseconds.  It might become possible
   to improve this precision within the next few years.  We do not
   expect it to be feasible for a general-purpose system to measure time
   to a precision of less than one nanosecond in the foreseeable future.

2.2 Time scale
   Several different time scales have been proposed for use in computer
   systems.  UTC and TAI are the two obvious candidates.

   Some people would prefer the use of TAI, which is identical to UTC
   except that it does not correct for leap seconds.  Their preference
   for TAI stems from the difficulty of computing precise time
   differences when leap seconds are involved, especially when using
   times in the future (for which the exact number of leap seconds is,
   in general, unknowable).

   However, POSIX and NTP both use UTC, albeit with different base
   dates.  Given that support for TAI would, in general, require other
   changes to the POSIX specification, This API uses the POSIX base date
   of midnight January 1, 1970.





Mogul, Mills                                                    [Page 4]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


3 API

   A PPS facility can be used in two different ways:

      1. An application can obtain a timestamp, using the system's
         internal timebase, for the most recent PPS event.

      2. A kernel may directly utilize PPS events to discipline its
         internal timebase, thereby providing highly accurate time
         to all applications.

   This API supports both uses, individually or in combination.  The
   timestamping feature may be used on any number of PPS sources
   simultaneously; the timebase-disciplining feature may be used with at
   most one PPS source.

   Although the proper implementation of this API requires support from
   the kernel of a UNIX system, this document defines the API in terms
   of a set of library routines.  This gives the implementor some
   freedom to divide the effort between kernel code and library code
   (different divisions might be appropriate on microkernels and
   monolithic kernels, for example).

3.1 New data structures
   The API defines one new data structure:

      typedef struct ppsinfo {
              pps_seq_t   sequence;            /* event sequence # */
              struct timespec timestamp;       /* time of event */
              int     flags;                   /* flag bits */
      } ppsinfo_t;

   The ``pps_seq_t'' type is an unsigned integer data type of at least
   32 bits.  The precise declaration of this type is system-dependent.

   The sequence number increases once per captured timestamp.  Its
   initial value is undefined.  If incremented past the largest unsigned
   long value, the next value is zero.

      ---------
      Note that the sequence number is most useful in applications
      where events other than PPS transitions are to be captured,
      which might be involved in a precision stopwatch application,
      for example. In such cases, the sequence number may be used to
      detect overruns, where the application has missed one or more
      events.  It may also be used to detect an excessive event rate.
      ---------

   The timestamp field represents the value of the operating system's
   internal timebase when the timestamped occurred, or as close as
   possible to that time.

Mogul, Mills                                                    [Page 5]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


   The flag bits are:

      #define PPSFLAG_ASSERT          0x01
      #define PPSFLAG_CLEAR           0x02

   whose meanings are:

   PPSFLAG_ASSERT  The timestamp was captured when the PPS signal was
                   asserted (set to logical TRUE).

   PPSFLAG_CLEAR   The timestamp was captured when the PPS signal was
                   cleared (set to logical FALSE).

      ---------
      Which header file does this belong in?  <sys/timex.h>?
      <sys/time.h>?
      ---------

3.2 Mode bit definitions
   The API defines these mode bits:

      #define PPSMODE_NONE            0x00
      #define PPSMODE_ONASSERT        0x01
      #define PPSMODE_ONCLEAR         0x02
      #define PPSMODE_ONBOTH          (PPSMODE_ONASSERT|PPSMODE_ONCLEAR)
      #define PPSMODE_HARDPSS         0x04

   whose meanings are:

   PPSMODE_NONE    No timestamps will be captured.

   PPSMODE_ONASSERT
                   Causes a timestamp to be captured when the PPS signal
                   is asserted (set to logical TRUE).

   PPSMODE_ONCLEAR Causes a timestamp to be captured when the PPS signal
                   is cleared (set to logical FALSE).

   PPSMODE_ONBOTH  Causes a timestamp to be captured when the PPS signal
                   changes states, in either direction.

   PPSMODE_HARDPSS Causes the timestamp to be communicated to the
                   operating system module that disciplines the system's
                   internal timebase.

   The operating system will enforce two restrictions on the use of
   PPSMODE_HARDPPS:

      1. It may be applied to at most one signal source at any
         given time.


Mogul, Mills                                                    [Page 6]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


      2. It may only be set by a process with sufficient privileges
         to modify the system's internal timebase.  (On UNIX
         systems, such modification is normally done using
         settimeofday() and/or adjtime(), and is restricted to
         users with superuser privilege.)

   The operating system may implement all of these mode bits, or just a
   subset of them.  If an attempt is made to set an unsupported mode
   bit, the API will return an error.

      ---------
      Which header file does this belong in?  <sys/timex.h>?
      <sys/time.h>?
      ---------

3.3 New functions
   In the description of functions that follows, we use the following
   function parameters:

   filedes         A file descriptor (type: int), for a serial line or
                   other source of PPS events.

   ppsinfobuf      A record of type ``struct ppsinfo'', as defined in
                   section 3.1.

   mode            A set of mode bits (type: int), whose possible values
                   are defined in section 3.2.

3.3.1 New functions: access to PPS events
   The API includes several functions use to enable or disable the use
   of a file descriptor for other PPS-related functions.


SYNOPSIS

      int time_pps_enable(int filedes);
      int time_pps_disable(int filedes);


DESCRIPTION

   Before an application can use any of the other PPS-related functions,
   it must first call time_pps_enable() on an already-open file
   descriptor for an appropriate special file.  (The definition of what
   special files are appropriate for use with the PPS API is outside the
   scope of this specification, and may vary based on both operating
   system implementation, and local system configuration.  The usual
   case is a serial line, whose DCD pin is connected to a source of PPS
   events.)



Mogul, Mills                                                    [Page 7]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


   After having successfully enabled the use of PPS events on a file
   descriptor, an application may call time_pps_disable() on that file
   descriptor.  This stops the use of the PPS source for disciplining
   the system's timebase, if it had been configured to do so.

   The behavior of other functions in the PPS API is undefined, except
   when applied to a file descriptor after time_pps_enable() has been
   applied, and before time_pps_disable() has been applied.


RETURN VALUES

   On successful completion, the time_pps_enable() and
   time_pps_disable() functions return 0.  Otherwise, a value of -1 is
   returned and errno is set to indicate the error.


ERRORS

   If the time_pps_enable() or time_pps_disable() function fails, errno
   may be set to one of the following values:

   [EBADF]         The filedes parameter is not a valid file descriptor.

   [EINVAL]        The use of the PPS API is not supported for the file
                   descriptor.

   [EPERM]         The process's effective user ID does not have the
                   required privileges to use the PPS API.

3.3.2 New functions: setting PPS mode bits
   The API includes several functions use to control the mode of a
   PPS-enabled file descriptor.


SYNOPSIS

      int time_pps_setmode(int filedes, int mode);
      int time_pps_getmode(int filedes, int *mode);


DESCRIPTION

   An application may use time_pps_setmode() to set the mode value for a
   PPS line.  Mode bits are defined in section 3.2.  An application may
   use time_pps_getmode() to discover the current settings of the PPS
   mode bits.  An application that needs to change only a subset of the
   existing mode bits must first call time_pps_getmode() to obtain the
   current mode bit values, then set the new values using
   time_pps_setmode().


Mogul, Mills                                                    [Page 8]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


   The default value for the mode bits is PPSMODE_NONE.


RETURN VALUES

   On successful completion, the time_pps_setmode() and
   time_pps_getmode() functions return 0.  Otherwise, a value of -1 is
   returned and errno is set to indicate the error.


ERRORS

   If the time_pps_setmode() or time_pps_getmode() function fails, errno
   may be set to one of the following values:

   [EBADF]         The filedes parameter is not a valid file descriptor.

   [EFAULT]        A parameter points to an invalid address.

   [EINVAL]        The use of the PPS API is not supported for the file
                   descriptor.

   [EOPNOTSUPP]    The operating system does not support all of the
                   requested mode bits.

   [EPERM]         The process's effective user ID does not have the
                   required privileges to use the PPS API, or to set the
                   given mode.

3.3.3 New functions: access to PPS timestamps
   The API includes one function that gives applications access to PPS
   timestamps.


SYNOPSIS

      int time_pps_fetch(int filedes, struct ppsinfo *ppsinfobuf);


DESCRIPTION

   An application may use time_pps_fetch() to obtain the most recent
   timestamp captured for the signal source corresponding to the filedes
   parameter.

   The result is left in the ppsinfobuf parameter, whose fields are
   defined in section 3.1.





Mogul, Mills                                                    [Page 9]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


RETURN VALUES

   On successful completion, the time_pps_fetch() function returns 0.
   Otherwise, a value of -1 is returned and errno is set to indicate the
   error.


ERRORS

   If the time_pps_fetch() function fails, errno may be set to one of
   the following values:

   [EBADF]         The filedes parameter is not a valid file descriptor.

   [EFAULT]        A parameter points to an invalid address.

   [EINVAL]        The use of the PPS API is not supported for the file
                   descriptor.

3.3.4 New functions: disciplining the kernel timebase
   The API does not include an explicit function for configuring the use
   of a PPS signal to discipline the operating system timebase.  This is
   done using time_pps_setmode() and time_pps_getmode().

   Warning: If this feature is configured for a special file that does
   not have an accurate 1-pulse-per-second signal, use of this feature
   may result in seriously incorrect timekeeping for the entire system.
   For best results, the 1-PPS signal should have much better frequency
   stability than the system's internal clock source (usually a
   crystal-controlled oscillator), and should have jitter (variation in
   interarrival time) much less than the system's clock-tick interval.

   See RFC1589 [3] for more information about how the system's timebase
   is disciplined using a PPS signal.

3.4 Example
   A typical use of this API might be:

      int fd;
      int mode;
      ppsinfo infobuf;

      /* Open a file descriptor and enable PPS on rising edges */
      fd = open(PPSfilename, O_RDONLY, 0);
      time_pps_enable(fd);
      mode = PPSMODE_ONASSERT;
      time_pps_setmode(fd, mode);

      /* loop, printing the most recent timestamp every second or so */
      while (1) {


Mogul, Mills                                                   [Page 10]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


          sleep(1);
          time_pps_fetch(fd, &infobuf);
          printf("Timestamp: %d.%09d, sequence: %ld\n",
                      infobuf.timestamp.tv_sec,
                      infobuf.timestamp.tv_nsec,
                      infobuf.sequence);
      }

   Note that this example omits all of the error-checking that would be
   expected in a reliable program.


4 PPSDISC Line discipline

   One possible implementation of this API might be to define a new
   ``line discipline'' and then map the API onto a set of ioctl()
   commands.  Here we sketch such an implementation; note that this is
   not part of the specification of the API, and applications should not
   expect this low-level interface to be available.

   In this approach, the set of line disciplines is augmented with one
   new line discipline, PPSDISC.  This discipline will act exactly the
   same as the TTYDISC discipline, except for its handling of modem DCD
   interrupts.

   Once the TIOCSETD ioctl() has been used to select this line
   discipline, PPS-related operations on the serial line may be invoked
   using new ioctl() commands.  For example (values used only for
   illustration):

      #define PPSGETTIME    _IOR('t', 75, struct ppsinfo)
      #define PPSSETMODE    _IOW('t', 76, int)
      #define PPSGETMODE    _IOR('t', 77, int)

4.1 Example
   A typical use might be:

      int ldisc = PPSDISC;
      int ppsmode;
      struct ppsinfo ppsbuf;

      ioctl(fd, TIOCSETD, &ldisc);    /* set discipline */

      /*
       * Set this line to timestamp on a rising-edge interrupt,
       * and assign this line for the kernel hardpps() input
       */
      mode = PPSMODE_ONASSERT | PPSMODE_HARDPSS;
      ioctl(fd, PPSSETMODE, &mode);



Mogul, Mills                                                   [Page 11]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


      sleep(2);       /* allow time for the PPS pulse to happen */

      /* obtain most recent timestamp and sequence # for this line */
      ioctl(fd, PPSGETTIME, &ppsbuf);

   Again, this example imprudently omits any error-checking.


5 Security Considerations

   This API gives applications three capabilities:

      - Causing the system to capture timestamps on certain events.

      - Obtaining timestamps for certain events.

      - Affecting the system's internal timebase.

   The first capability should not affect security directly, but might
   cause a slight increase in interrupt latency and interrupt-handling
   overhead.

   The second capability might be useful in implementing certain kinds
   of covert communication channels.

   In most cases, neither of these first two issues is a significant
   security threat.  The system administrator may prevent applications
   from using this API by simply using the traditional UNIX file
   protection facility to limit access to the relevant special files, so
   the risk inherent in providing the API is minimal.

   The final capability is reserved to highly privileged users.  In UNIX
   systems, this means those with superuser privilege.  Such users can
   evade protections based on file permissions; however, such users can
   in general cause unbounded havoc, and can set the internal timebase
   (and its rate of change), so this API creates no new vulnerabilities.


6 Acknowledgements

   The API in this document draws some of its inspiration from the LBL
   ``ppsclock'' distribution [1], originally implemented in 1993 by
   Steve McCanne, Craig Leres, and Van Jacobson.  We also thank Craig
   Leres for helpful comments he contributed during the drafting of this
   document.


7 References




Mogul, Mills                                                   [Page 12]


Internet-Draft            Pulse-Per-Second API   10 September 1997 16:24


   1.  Steve McCanne, Craig Leres, and Van Jacobson.  PPSCLOCK.
   ftp://ftp.ee.lbl.gov/ppsclock.tar.Z.

   2.  David L. Mills.  Network Time Protocol (Version 3):
   Specification, Implementation and Analysis.  RFC 1305, IETF, March,
   1992.

   3.  David L. Mills.  A Kernel Model for Precision Timekeeping.  RFC
   1589, IETF, March, 1994.

   4.  The Open Group.  The Single UNIX Specification, Version 2 - 6 Vol
   Set for UNIX 98.  Document number T912, The Open Group, February,
   1997.


8 Authors' addresses

   Jeffrey C. Mogul
   Western Research Laboratory
   Digital Equipment Corporation
   250 University Avenue
   Palo Alto, California, 94305, U.S.A.
   Email: mogul@wrl.dec.com
   Phone: 1 650 617 3304 (email preferred)

   David L. Mills
   Electrical Engineering Department
   University of Delaware
   Newark, DE 19716
   Phone: (302) 831-8247
   EMail: mills@udel.edu

   Jan Brittenson
   Sun Microsystems
   Email:Jan.Brittenson@eng.Sun.COM

















Mogul, Mills                                                   [Page 13]