]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Mitigation and PPS cleanup from Dave Mills
authorHarlan Stenn <stenn@ntp.org>
Thu, 9 Apr 2009 08:44:58 +0000 (04:44 -0400)
committerHarlan Stenn <stenn@ntp.org>
Thu, 9 Apr 2009 08:44:58 +0000 (04:44 -0400)
bk: 49ddb58auevn_N0PfnmIgoVl-tUVzw

ChangeLog
include/ntpd.h
ntpd/ntp_loopfilter.c
ntpd/ntp_proto.c
ntpd/ntp_timer.c
ntpd/refclock_atom.c
ntpd/refclock_conf.c
ntpd/refclock_local.c

index 91466ac2cb272ca5d41bcf13fa9c14b4f556243e..948635e946e23d6e4b1ccdc0a9a891bd18cc965f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,10 @@
+* Mitigation and PPS cleanup from Dave Mills.
 (4.2.5p161) 2009/03/31 Released by Harlan Stenn <stenn@ntp.org>
 * Documentation updates from Dave Mills.
 (4.2.5p160) 2009/03/30 Released by Harlan Stenn <stenn@ntp.org>
-* Include (4.2.4p7)
+* [Bug 1141] refclock_report missing braces cause spurious "peer event:
+  clock clk_unspec" log entries
+* Include (4.2.4p7-RC1)
 (4.2.5p159) 2009/03/28 Released by Harlan Stenn <stenn@ntp.org>
 * "bias" changes from Dave Mills.
 (4.2.5p158) 2009/01/30 Released by Harlan Stenn <stenn@ntp.org>
 ---
 (4.2.4p7-RC1) 2009/03/30 Released by Harlan Stenn <stenn@ntp.org>
 
-* [Bug 1141] refclock_report missing braces cause spurious "peer event:
-  clock clk_unspec" log entries
 * [Bug 873] Windows serial refclock proper TTY line discipline emulation
 * [Bug 1117] Deferred interface binding under Windows works only 
   correctly if FORCE_DNSRETRY is defined
index 345c7661c81a2c3339159da575a732bb59655c76..b61bcad0902984a8d66f6f53a59396e8583420ce 100644 (file)
@@ -352,6 +352,7 @@ extern u_long       last_time;              /* time of last clock update (s) */
 extern double  last_offset;            /* last clock offset (s) */
 extern u_char  allan_xpt;              /* Allan intercept (log2 s) */
 extern double  clock_jitter;           /* clock jitter (s) */
+extern double  sys_offset;             /* system offset (s) */
 extern double  sys_jitter;             /* system jitter (s) */
 
 /* ntp_monitor.c */
@@ -390,8 +391,6 @@ extern double       sys_rootdisp;           /* dispersion to primary source */
 extern u_int32 sys_refid;              /* reference id */
 extern l_fp    sys_reftime;            /* last update time */
 extern struct peer *sys_peer;          /* current peer */
-extern struct peer *sys_pps;           /* current PPS peer */
-extern struct peer *sys_prefer;                /* cherished peer */
 
 /*
  * Nonspecified system state variables.
index dd5162da059ffcb1c8f9fad56be35d46a82ffe63..afca118c1072ecb2dc6fb3792355afc7f3a48d59 100644 (file)
@@ -280,12 +280,8 @@ local_clock(
         * is most effective if the delays are highly assymetric and
         * clockhopping is avoided and the clock frequency wander is
         * relatively small.
-        *
-        * Note either there is no prefer peer or this update is from
-        * the prefer peer.
         */
-       if (sys_huffpuff != NULL && (sys_prefer == NULL || sys_prefer ==
-           peer)) {
+       if (sys_huffpuff != NULL) {
                if (peer->delay < sys_huffpuff[sys_huffptr])
                        sys_huffpuff[sys_huffptr] = peer->delay;
                if (peer->delay < sys_mindly)
@@ -675,7 +671,7 @@ local_clock(
 #ifdef DEBUG
        if (debug)
                printf(
-                   "local_clock: offset %.9f jit %.6f freq %.3f stab %.3f poll %d\n",
+                   "local_clock: offset %.9f jit %.9f freq %.3f stab %.3f poll %d\n",
                    clock_offset, clock_jitter, drift_comp * 1e6,
                    clock_stability * 1e6, sys_poll);
 #endif /* DEBUG */
index 17173a623c1eb832219646aa86b4a9f4a46fff0b..7fae541445ad5efc62406814181322809ca745d7 100644 (file)
@@ -59,8 +59,6 @@ double        sys_rootdisp;           /* dispersion to primary source */
 u_int32 sys_refid;             /* reference id (network byte order) */
 l_fp   sys_reftime;            /* last update time */
 struct peer *sys_peer;         /* current peer */
-struct peer *sys_pps;          /* PPS peer */
-struct peer *sys_prefer;       /* prefer peer */
 
 /*
  * Rate controls. Leaky buckets are used to throttle the packet
@@ -79,7 +77,7 @@ int   sys_bclient;            /* broadcast client enable */
 double sys_bdelay;             /* broadcast client default delay */
 int    sys_authenticate;       /* requre authentication for config */
 l_fp   sys_authdelay;          /* authentication delay */
-static double sys_offset;      /* current local clock offset */
+double sys_offset;     /* current local clock offset */
 double sys_mindisp = MINDISPERSE; /* min disp increment (s) */
 double sys_maxdist = MAXDISTANCE; /* selection threshold */
 double sys_jitter;             /* system jitter */
@@ -1459,7 +1457,6 @@ process_packet(
                        LFPTOD(&ci, t34);
                        p_offset = t34;
                }
-               p_del = peer->delay;
 
                /*
                 * When calibration is complete and the clock is
@@ -1470,14 +1467,11 @@ process_packet(
                 */
                if (peer->cast_flags & MDF_BCLNT) {
                        peer->cast_flags &= ~MDF_BCLNT;
-                       peer->bias = peer->offset - p_offset;
-#ifdef DEBUG
-                       if (debug)
-                               printf(
-                                   "packet: bias %f uoffset %f boffset %f\n",
-                                   peer->bias, peer->offset, p_offset);
-#endif
+                       peer->delay = (peer->offset - p_offset) * 2;
                }
+               p_del = peer->delay;
+               p_offset += p_del / 2;
+
 
        /*
         * Basic mode, otherwise known as the old fashioned way.
@@ -1603,19 +1597,22 @@ clock_update(
        )
 {
        double  dtemp;
-       u_long  epoch;
        l_fp    now;
 #ifdef HAVE_LIBSCF_H
        char    *fmri;
 #endif /* HAVE_LIBSCF_H */
 
        /*
-        * There must be a system peer at this point. If we just changed
-        * the system peer, but have a newer sample from the old one,
-        * wait until newer data are available. Note that the root
-        * dispersion is updated even if the offset has already been
-        * processed.
+        * Update the remaining system state variables. 
         */
+       sys_peer = peer;
+       sys_epoch = peer->epoch;
+       sys_stratum = min(peer->stratum + 1, STRATUM_UNSPEC);
+       if (peer->stratum == STRATUM_REFCLOCK ||
+           peer->stratum == STRATUM_UNSPEC)
+               sys_refid = peer->refid;
+       else
+               sys_refid = addr2refid(&peer->srcadr);
        dtemp = sys_jitter + fabs(sys_offset) + peer->disp + clock_phi *
            (current_time - peer->update);
 #ifdef REFCLOCK
@@ -1627,18 +1624,16 @@ clock_update(
                dtemp = sys_mindisp;
 #endif /* REFCLOCK */
        sys_rootdisp = dtemp + peer->rootdisp;
-       if (peer->epoch <= sys_epoch)
-               return;
-       epoch = peer->epoch - sys_epoch;
+       sys_rootdelay = peer->delay + peer->rootdelay;
+       sys_reftime = peer->dst;
+
 #ifdef DEBUG
        if (debug)
                printf(
                    "clock_update: at %lu sample %lu associd %d\n",
                    current_time, peer->epoch, peer->associd);
 #endif
-       sys_epoch = peer->epoch;
-       switch (local_clock(peer, epoch, sys_offset)) {
+       switch (local_clock(peer, peer->epoch, sys_offset)) {
 
        /*
         * Clock exceeds panic threshold. Life as we know it ends.
@@ -1699,9 +1694,6 @@ clock_update(
                                crypto_update();
 #endif /* OPENSSL */
                }
-               sys_stratum = min(peer->stratum + 1, STRATUM_UNSPEC);
-               sys_rootdelay = peer->delay + peer->rootdelay;
-               sys_reftime = peer->dst;
 
                /*
                 * If the leapseconds values are from file or network
@@ -2174,10 +2166,16 @@ clock_select(void)
        double  high, low;
        double  seljitter;
        double  synch[NTP_MAXASSOC], error[NTP_MAXASSOC];
+       double  orphdist = 1e10;;
        struct peer *osys_peer = NULL;
+       struct peer *sys_prefer = NULL; /* prefer peer */
+       struct peer *typesystem = NULL;
+       struct peer *typeorphan = NULL;
+#ifdef REFCLOCK
        struct peer *typeacts = NULL;
        struct peer *typelocal = NULL;
-       struct peer *typesystem = NULL;
+       struct peer *typepps = NULL;
+#endif /* REFCLOCK */
 
        static int list_alloc = 0;
        static struct endpoint *endpoint = NULL;
@@ -2192,9 +2190,6 @@ clock_select(void)
         * enough to handle all associations.
         */
        osys_peer = sys_peer;
-       sys_peer = NULL;
-       sys_pps = NULL;
-       sys_prefer = NULL;
        osurv = sys_survivors;
        sys_survivors = 0;
 #ifdef LOCKCLOCK
@@ -2246,26 +2241,42 @@ clock_select(void)
                        if (peer_unfit(peer))
                                continue;
 
-#ifdef REFCLOCK
                        /*
-                        * Don't allow the local clock or modem drivers
-                        * in the kitchen at this point. Do that later,
-                        * but only if nobody else is around. These guys
-                        * are all configured, so we never throw them
-                        * away.
+                        * If this is an orphan, choose the one with
+                        * the least distance.
                         */
-                       if (peer->refclktype == REFCLK_LOCALCLOCK
-#if defined(VMS) && defined(VMS_LOCALUNIT)
-                       /* wjm: VMS_LOCALUNIT taken seriously */
-                           && REFCLOCKUNIT(&peer->srcadr) !=
-                           VMS_LOCALUNIT
-#endif /* VMS && VMS_LOCALUNIT */
-                               ) {
-                               typelocal = peer;
+                       if (peer->stratum == sys_orphan) {
+                               double  ftemp;
+
+                               ftemp = addr2refid(&peer->srcadr);
+                               if (ftemp < orphdist) {
+                                       typeorphan = peer;
+                                       orphdist = ftemp;
+                               }
                                continue;
                        }
-                       if (peer->refclktype == REFCLK_ACTS) {
-                               typeacts = peer;
+#ifdef REFCLOCK
+                       /*
+                        * The following are special cases. We deal
+                        * with them later.
+                        */
+                       switch (peer->refclktype) { 
+                       case REFCLK_LOCALCLOCK:
+                               if (typelocal == NULL &&
+                                   !(peer->flags & FLAG_PREFER))
+                                       typelocal = peer;
+                               continue;
+                       
+                       case REFCLK_ATOM_PPS:
+                               if (typepps == NULL &&
+                                   !(peer->flags & FLAG_PREFER))
+                                       typepps = peer;
+                               continue;
+
+                       case REFCLK_ACTS:
+                               if (typeacts == NULL &&
+                                   !(peer->flags & FLAG_PREFER))
+                                       typeacts = peer;
                                continue;
                        }
 #endif /* REFCLOCK */
@@ -2411,13 +2422,12 @@ clock_select(void)
                        continue;
 
                /*
-                * The order metric is formed from the stratum times
-                * max distance (1.) plus the root distance. It strongly
-                * favors the lowest stratum, but a higher stratum peer
-                * can capture the clock if the low stratum dominant
-                * hasn't been heard for awhile.
+                * The metric is the scaled root distance plus the peer
+                * stratum. For compliance with the specification, both
+                * values are multiplied by the select threshold.
                 */
-               d = root_distance(peer) + peer->stratum * sys_maxdist;
+               d = (root_distance(peer) / sys_maxdist +
+                    peer->stratum) * sys_maxdist;
                if (j >= NTP_MAXASSOC) {
                        if (d >= synch[j - 1])
                                continue;
@@ -2440,39 +2450,40 @@ clock_select(void)
        nlist = j;
 
        /*
-        * If no survivors remain at this point, check if the local
-        * clock or modem drivers have been found. If so, nominate one
-        * of them as the only survivor. Otherwise, give up and leave
-        * the island to the rats.
+        * If no survivors remain at this point, check if the modem 
+        * driver, orphan server or local driver have been found. If
+        * so, nominate the first one found as the only survivor.
+        * Otherwise, give up and leave the island to the rats.
         */
        if (nlist == 0) {
                error[0] = 0;
                synch[0] = 0;
+               if (typeorphan != NULL) {
+                       peer_list[0] = typeorphan;
+                       nlist = 1;
+               }
+#ifdef REFCLOCK
                if (typeacts != NULL) {
                        peer_list[0] = typeacts;
                        nlist = 1;
                } else if (typelocal != NULL) {
                        peer_list[0] = typelocal;
                        nlist = 1;
-               } else {
-                       if (osys_peer != NULL)
-                               report_event(EVNT_NOPEER, NULL, NULL);
                }
+#endif /* REFCLOCK */
        }
 
        /*
-        * We can only trust the survivors if the number of candidates
-        * sys_minsane is at least the number required to detect and
-        * cast out one falsticker. For the Byzantine agreement
-        * algorithm used here, that number is 4; however, the default
-        * sys_minsane is 1 to speed initial synchronization. Careful
-        * operators will tinker a higher value and use at least that
-        * number of synchronization sources.
+        * Mark the candidates at this point as truechimers.
         */
-       for (i = 0; i < nlist; i++)
+       for (i = 0; i < nlist; i++) {
                peer_list[i]->status = CTL_PST_SEL_SELCAND;
-       if (nlist < sys_minsane)
-               return;
+#ifdef DEBUG
+               if (debug > 1)
+                       printf("select: survivor %s %f\n",
+                           stoa(&peer_list[i]->srcadr), synch[i]);
+#endif
+       }
 
        /*
         * Now, vote outlyers off the island by select jitter weighted
@@ -2505,8 +2516,11 @@ clock_select(void)
                        }
                }
                f = max(f, LOGTOD(sys_precision));
-               if (nlist <= sys_minclock || f <= d ||
-                   peer_list[k]->flags & (FLAG_TRUE | FLAG_PREFER)) {
+               if (nlist <= sys_minsane || nlist <= sys_minclock) {
+                       break;
+
+               } else if (f <= d || peer_list[k]->flags &
+                   (FLAG_TRUE | FLAG_PREFER)) {
                        seljitter = f;
                        break;
                }
@@ -2554,104 +2568,103 @@ clock_select(void)
                        j = i;
                if (peer->flags & FLAG_PREFER)
                        sys_prefer = peer;
-#ifdef REFCLOCK
-               if (peer->refclktype == REFCLK_ATOM_PPS)
-                       sys_pps = peer;
-#endif /* REFCLOCK */
        }
 
        /*
         * Anticlockhop provisions. Ordinarily, use the first survivor
-        * on the list. However, if the previous system peer is on the
-        * list but not first, use it if the synchronization distance is
-        * not greater than the accumulation over the last sys_maxhop
-        * poll intervals.
-        */
-       if (synch[j] < synch[0] + sys_mindisp + ULOGTOD(sys_poll) *
-           sys_maxhop * clock_phi)
-               typesystem = peer_list[j];
-       else
-               typesystem = peer_list[0];
+        * on the survivor list, if there is one, and if there are
+        * least sys_minsane survivors. Othersie, there are no
+        * survivors. However, if the previous system peer is on the
+        * list but not first, use it if the synchronization distance
+        * is not greater than the accumulation over the last
+        * sys_maxhop * poll intervals. Do this only if there are at
+        * least one kitten in the litter.
+        */
+       if (nlist > 0 && nlist >= sys_minsane) {
+               if (synch[j] < synch[0] + sys_mindisp +
+                   ULOGTOD(sys_poll) * sys_maxhop * clock_phi)
+                       typesystem = peer_list[j];
+               else
+                       typesystem = peer_list[0];
+       }
 
        /*
-        * Mitigation rules of the game. There are several types of
-        * peers that can be selected here: (1) orphan, (2) prefer peer
-        * (flag FLAG_PREFER) (3) pps peers (type REFCLK_ATOM_PPS), (4)
-        * the existing system peer, if any, and (5) the head of the
-        * survivor list.
+        * Mitigation rules of the game. We have the pick of the
+        * litter in typesystem if any survivors are left. If
+        * there is a prefer peer, use its offset and jitter.
+        * Otherwise, use the combined offset and jitter of all kitters.
         */
-       if (typesystem->stratum == sys_orphan) {
-               sys_peer = typesystem;
-               sys_peer->status = CTL_PST_SEL_SYSPEER;
-               sys_offset = sys_peer->offset;
-               sys_refid = addr2refid(&sys_peer->srcadr);
-               sys_jitter = LOGTOD(sys_precision);
+       if (typesystem != NULL) {
+               if (sys_prefer == NULL) {
+                       typesystem->status = CTL_PST_SEL_SYSPEER;
+                       clock_combine(peer_list, sys_survivors);
+                       sys_jitter = SQRT(SQUARE(typesystem->jitter) +
+                           SQUARE(sys_jitter) + SQUARE(seljitter));
+               } else {
+                       typesystem = sys_prefer;
+                       typesystem->status = CTL_PST_SEL_SYSPEER;
+                       sys_offset = typesystem->offset;
+                       sys_jitter = typesystem->jitter;
+               }
 #ifdef DEBUG
-               if (debug > 2)
-                       printf("select: orphan offset %.6f\n",
-                           sys_offset);
+               if (debug)
+                       printf("select: combine offset %.9f jitter %.9f\n",
+                           sys_offset, sys_jitter);
 #endif
-       } else if (sys_prefer) {
+       }
+#ifdef REFCLOCK
+       /*
+        * If a PPS driver is lit and the combined offset is less than
+        * 0.4 s, select the driver as the PPS peer and use its offset
+        * and jitter.
+        */
+       if (typepps != NULL && fabs(sys_offset < 0.4)) {
+               struct refclockproc *pp;
 
                /*
-                * If a pps peer is present, choose it; otherwise,
-                * choose the prefer peer.
+                * If flag1 is dim, PPS is enabled only if the prefer
+                * peer has survived the intersection algorithm and
+                * numbers the seconds. Otherwise, some other means
+                * must be provided to number the seconds.
                 */
-               if (sys_pps) {
-                       sys_peer = sys_pps;
-                       sys_peer->status = CTL_PST_SEL_PPS;
-                       sys_offset = sys_peer->offset;
-#ifdef DEBUG
-                       if (debug > 2)
-                               printf("select: pps offset %.6f\n",
-                                   sys_offset);
-#endif
-               } else {
-                       sys_peer = sys_prefer;
-                       sys_peer->status = CTL_PST_SEL_SYSPEER;
-                       sys_offset = sys_peer->offset;
-#ifdef DEBUG
-                       if (debug > 2)
-                               printf("select: prefer offset %.6f\n",
-                                   sys_offset);
-#endif
-               }
-               if (sys_peer->stratum == STRATUM_REFCLOCK ||
-                   sys_peer->stratum == STRATUM_UNSPEC)
-                       sys_refid = sys_peer->refid;
-               else
-                       sys_refid = addr2refid(&sys_peer->srcadr);
-               sys_jitter = sys_peer->jitter;
-       } else {
+               pp = typepps->procptr;
+               if (!(pp->sloppyclockflag & CLK_FLAG1) && sys_prefer ==
+                   NULL)
+                       return;
 
-               /*
-                * Otherwise, choose the anticlockhopper.
-                */ 
-               sys_peer = typesystem;
-               sys_peer->status = CTL_PST_SEL_SYSPEER;
-               clock_combine(peer_list, sys_survivors);
-               if (sys_peer->stratum == STRATUM_REFCLOCK ||
-                   sys_peer->stratum == STRATUM_UNSPEC)
-                       sys_refid = sys_peer->refid;
-               else
-                       sys_refid = addr2refid(&sys_peer->srcadr);
-               sys_jitter = SQRT(SQUARE(sys_peer->jitter) +
-                   SQUARE(sys_jitter) + SQUARE(seljitter));
+               typesystem = typepps;
+               typesystem->status = CTL_PST_SEL_PPS;
+               sys_offset = typesystem->offset;
+               sys_jitter = typesystem->jitter;
 #ifdef DEBUG
-               if (debug > 2)
-                       printf("select: combine offset %.6f\n",
-                           sys_offset);
+               if (debug)
+                       printf("select: pps offset %.9f jitter %.9f\n",
+                           sys_offset, sys_jitter);
 #endif
        }
+#endif /* REFCLOCK */
 
        /*
-        * We have found the alpha male.
+        * If there are no survivors at this point, there is no
+        * system peer. If so and this is an old update, keep the
+        * current statistics, but do not update the clock.
         */
-       sys_peer->flags |= FLAG_SYSPEER;
-       if (osys_peer != sys_peer) {
-               report_event(PEVNT_NEWPEER, sys_peer, NULL);
+       if (typesystem == NULL) {
+               if (osys_peer != NULL)
+                       report_event(EVNT_NOPEER, NULL, NULL);
+               sys_peer = NULL;                        
+               return;
        }
-       clock_update(sys_peer);
+       if (typesystem->epoch <= sys_epoch)
+               return;
+
+       /*
+        * We have found the alpha male. Wind the clock.
+        */
+       if (osys_peer != typesystem)
+               report_event(PEVNT_NEWPEER, typesystem, NULL);
+       typesystem->flags |= FLAG_SYSPEER;
+       clock_update(typesystem);
 }
 
 
@@ -2691,13 +2704,10 @@ root_distance(
        /*
         * Careful squeak here. The value returned must be greater than
         * the minimum root dispersion in order to avoid clockhop with
-        * highly precise reference clocks. In orphan mode use the peer
-        * address to fool the mitigation algorithm.
+        * highly precise reference clocks. Note that the root distance
+        * cannot exceed the sys_maxdist, as this is the cutoff by the
+        * selection algorithm.
         */
-       if (peer->stratum == sys_orphan)
-               return (addr2refid(&peer->srcadr) / FRAC * sys_maxdist /
-                   1.);
-
        return ((peer->delay + peer->rootdelay) / 2 + peer->disp +
            peer->rootdisp + clock_phi * (current_time - peer->update) +
            peer->jitter);
@@ -3448,7 +3458,6 @@ init_proto(void)
        sys_rootdisp = 0;
        L_CLR(&sys_reftime);
        sys_jitter = 0;
-       sys_peer = NULL;
        sys_precision = (s_char)default_get_precision();
        get_systime(&dummy);
        sys_survivors = 0;
index be3bfb0510325033cb1db7ba8e9d4af281177973..94a428f28fa19ce9da426fbff7c7e4dc76df640b 100644 (file)
@@ -332,13 +332,19 @@ timer(void)
         * reference ID the loopback address.
         */
        if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) {
-               if (sys_leap == LEAP_NOTINSYNC)
+               if (sys_leap == LEAP_NOTINSYNC) {
                        sys_leap = LEAP_NOWARNING;
+#ifdef OPENSSL
+                       if (crypto_flags)       
+                               crypto_update();
+#endif /* OPENSSL */
+               }
                sys_stratum = sys_orphan;
                if (sys_stratum > 1)
                        sys_refid = htonl(LOOPBACKADR);
                else
                        memcpy(&sys_refid, "LOOP", 4);
+               sys_offset = 0;
                sys_rootdelay = 0;
                sys_rootdisp = sys_mindisp;
        }
index 980cc07fe5c6033f834bbb0d26543220361aae2b..c3b278ca8731c5d9bf52808729a64f01d56eebe7 100644 (file)
 #include "ntp_refclock.h"
 #include "ntp_stdlib.h"
 
-#if defined(REFCLOCK) && defined(CLOCK_ATOM)
+/*
+ * This driver requires the PPSAPI interface (RFC 2783)
+ */
+#if defined(REFCLOCK) && defined(CLOCK_ATOM) && defined(HAVE_PPSAPI)
 
-#ifdef HAVE_PPSAPI
 # include "ppsapi_timepps.h"
-#endif /* HAVE_PPSAPI */
 
 /*
  * This driver furnishes an interface for pulse-per-second (PPS) signals
  * the API with multiple PPS drivers and multiple handles per driver. If
  * the PPSAPI is normally implemented in the /usr/include/sys/timepps.h
  * header file and kernel support specific to each operating system.
- * However, this driver can operate without this interface if means are
- * proviced to call the pps_sample() routine from another driver. Please
- * note; if the PPSAPI interface is present, it must be used.
- *
- * In many configurations a single port is used for the radio timecode
- * and PPS signal. In order to provide for this configuration and others
- * involving dedicated multiple serial/parallel ports, the driver first
- * attempts to open the device /dev/pps%d, where %d is the unit number.
- * If this fails, the driver attempts to open the device specified by
- * the pps configuration command. If a port is to be shared, the pps
- * command must be placed before the radio device(s) and the radio
- * device(s) must be placed before the PPS driver(s) in the
- * configuration file.
  *
  * This driver normally uses the PLL/FLL clock discipline implemented in
  * the ntpd code. Ordinarily, this is the most accurate means, as the
  *
  * Fudge Factors
  *
- * If flag2 is dim (default), the on-time epoch is the assert edge of
- * the PPS signal; if lit, the on-time epoch is the clear edge. If flag2
- * is lit, the assert edge is used; if flag3 is dim (default), the
- * kernel PPS support is disabled; if lit it is enabled. The time1
- * parameter can be used to compensate for miscellaneous device driver
- * and OS delays.
+ * If flag1 is dim (default) the PPS is active only if a prefer peer is
+ * preset; if lit the PPS is active as long as the system clock offset is
+ * synchronized and within 0.4 s. If flag2 is dim (default), the on-time
+ * epoch is the assert edge of the PPS signal; if lit, the on-time epoch
+ * is the clear edge. If flag3 is dim (default), the kernel PPS support
+ * is disabled; if lit it is enabled. The time1 parameter can be used to
+ * compensate for miscellaneous device driver and OS delays.
  */
 /*
  * Interface definitions
  */
-#ifdef HAVE_PPSAPI
 #define DEVICE         "/dev/pps%d" /* device name and unit */
-#endif /* HAVE_PPSAPI */
-
 #define        PRECISION       (-20)   /* precision assumed (about 1 us) */
 #define        REFID           "PPS\0" /* reference ID */
 #define        DESCRIPTION     "PPS Clock Discipline" /* WRU */
 #define NANOSECOND     1000000000 /* one second (ns) */
 #define RANGEGATE      500000  /* range gate (ns) */
 
-static struct peer *pps_peer;  /* atom driver for PPS sources */
-
-#ifdef HAVE_PPSAPI
 /*
  * PPS unit control structure
  */
@@ -100,7 +83,6 @@ struct ppsunit {
        pps_info_t pps_info;    /* last pps data */
        pps_handle_t handle;    /* pps handlebars */
 };
-#endif /* HAVE_PPSAPI */
 
 /*
  * Function prototypes
@@ -108,37 +90,21 @@ struct ppsunit {
 static int     atom_start      (int, struct peer *);
 static void    atom_poll       (int, struct peer *);
 static void    atom_shutdown   (int, struct peer *);
-#ifdef HAVE_PPSAPI
-static void    atom_control    (int, struct refclockstat *, struct
-                                   refclockstat *, struct peer *);
 static void    atom_timer      (int, struct peer *);
 static int     atom_ppsapi     (struct peer *, int);
-#endif /* HAVE_PPSAPI */
 
 /*
  * Transfer vector
  */
-#ifdef HAVE_PPSAPI
 struct refclock refclock_atom = {
        atom_start,             /* start up driver */
        atom_shutdown,          /* shut down driver */
        atom_poll,              /* transmit poll message */
-       atom_control,           /* fudge control */
+       noentry,                /* control (not used) */
        noentry,                /* initialize driver (not used) */
        noentry,                /* buginfo (not used) */
        atom_timer,             /* called once per second */
 };
-#else /* HAVE_PPSAPI */
-struct refclock refclock_atom = {
-       atom_start,             /* start up driver */
-       atom_shutdown,          /* shut down driver */
-       atom_poll,              /* transmit poll message */
-       noentry,                /* fudge control (not used) */
-       noentry,                /* initialize driver (not used) */
-       noentry,                /* buginfo (not used) */
-       NOFLAGS                 /* not used */
-};
-#endif /* HAVE_PPPSAPI */
 
 
 /*
@@ -151,22 +117,18 @@ atom_start(
        )
 {
        struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
        register struct ppsunit *up;
        char    device[80];
        int     mode;
-#endif /* HAVE_PPSAPI */
 
        /*
         * Allocate and initialize unit structure
         */
-       pps_peer = peer;
        pp = peer->procptr;
        peer->precision = PRECISION;
        pp->clockdesc = DESCRIPTION;
        pp->stratum = STRATUM_UNSPEC;
        memcpy((char *)&pp->refid, REFID, 4);
-#ifdef HAVE_PPSAPI
        up = emalloc(sizeof(struct ppsunit));
        memset(up, 0, sizeof(struct ppsunit));
        pp->unitptr = (caddr_t)up;
@@ -191,18 +153,11 @@ atom_start(
                    "refclock_atom: time_pps_create failed: %m");
                return (0);
        }
-
-       /*
-        * If the mode is nonzero, use that for the time_pps_setparams()
-        * mode; otherwise, PPS_CAPTUREASSERT.
-        */
-       mode = peer->ttl;
-       if (mode == 0)
+       if (pp->sloppyclockflag & CLK_FLAG2)
+               mode = PPS_CAPTURECLEAR;
+       else
                mode = PPS_CAPTUREASSERT;
        return (atom_ppsapi(peer, mode));
-#else /* HAVE_PPSAPI */
-       return (1);
-#endif /* HAVE_PPSAPI */
 }
 
 
@@ -220,45 +175,14 @@ atom_shutdown(
 
        pp = peer->procptr;
        up = (struct ppsunit *)pp->unitptr;
-#ifdef HAVE_PPSAPI
        if (up->fddev > 0)
                close(up->fddev);
        if (up->handle != 0)
                time_pps_destroy(up->handle);
-#endif /* HAVE_PPSAPI */
-       if (pps_peer == peer)
-               pps_peer = NULL;
        free(up);
 }
 
 
-#ifdef HAVE_PPSAPI
-/*
- * atom_control - fudge control
- */
-static void
-atom_control(
-       int unit,               /* unit (not used */
-       struct refclockstat *in, /* input parameters (not uded) */
-       struct refclockstat *out, /* output parameters (not used) */
-       struct peer *peer       /* peer structure pointer */
-       )
-{
-       struct refclockproc *pp;
-       int     mode;
-
-       pp = peer->procptr;
-       if (peer->ttl != 0)     /* all legal modes must be nonzero */
-               return;
-
-       if (pp->sloppyclockflag & CLK_FLAG2)
-               mode = PPS_CAPTURECLEAR;
-       else
-               mode = PPS_CAPTUREASSERT;
-       atom_ppsapi(peer, mode);
-}
-
-
 /*
  * Initialize PPSAPI
  */
@@ -315,10 +239,9 @@ atom_ppsapi(
 /*
  * atom_timer - called once per second
  *
- * This routine is called once per second when the PPSAPI interface is
- * present. It snatches the PPS timestamp from the kernel and saves the
- * sign-extended fraction in a circular buffer for processing at the
- * next poll event.
+ * This routine is called once per second. It snatches the PPS
+ * timestamp from the kernel and saves the sign-extended fraction in
+ * a circular buffer for processing at the next poll event.
  */
 static void
 atom_timer(
@@ -416,49 +339,6 @@ atom_timer(
 #endif
        return;
 }
-#endif /* HAVE_PPSAPI */
-
-
-/*
- * pps_sample - receive PPS data from some other clock driver
- *
- * This routine is called once per second when the external clock driver
- * processes PPS information. It processes the PPS timestamp and saves
- * the sign-extended fraction in a circular buffer for processing at the
- * next poll event. This works only for a single PPS device.
- *
- * The routine should be used by another configured driver ONLY when
- * this driver is configured as well and the PPSAPI is NOT in use.
- */
-int
-pps_sample(
-          l_fp *offset         /* PPS offset */
-          )
-{
-       register struct peer *peer;
-       struct refclockproc *pp;
-       l_fp lftmp;
-       double doffset;
-
-       peer = pps_peer;
-       if (peer == NULL)
-               return (1);
-
-       pp = peer->procptr;
-
-       /*
-        * Convert the timeval to l_fp and save for billboards. Sign-
-        * extend the fraction and stash in the buffer. No harm is done
-        * if previous data are overwritten. If the discipline comes bum
-        * or the data grow stale, just forget it.
-        */ 
-       pp->lastrec = *offset;
-       L_CLR(&lftmp);
-       L_ADDF(&lftmp, pp->lastrec.l_f);
-       LFPTOD(&lftmp, doffset);
-       SAMPLE(-doffset + pp->fudgetime1);
-       return (0);
-}
 
 
 /*
@@ -473,46 +353,20 @@ atom_poll(
        struct refclockproc *pp;
        pp = peer->procptr;
        pp->polls++;
-
-       /*
-        * Valid time is returned only if the prefer peer has survived
-        * the intersection algorithm and within 0.4 s of local time
-        * and not too long ago. This ensures the PPS time is within
-        * 0.5 s of the local time and the seconds numbering is
-        * unambiguous. Note that the leap bits, stratum and refid are
-        * set from the prefer peer, unless overriden by a fudge
-        * command.
-        */
-       pps_enable = 0;
+       if (pp->sloppyclockflag & CLK_FLAG3)
+               pps_enable = 1;
+       else
+               pps_enable = 0;
        if (pp->codeproc == pp->coderecv) {
                refclock_report(peer, CEVNT_TIMEOUT);
                return;
-
-       } else if (sys_prefer == NULL) {
-               pp->codeproc = pp->coderecv;
+       }
+       if (sys_leap == LEAP_NOTINSYNC)
                return;
 
-       } else if (fabs(sys_prefer->offset) >= 0.4) {
-               pp->codeproc = pp->coderecv;
-               return;
-       }
-       if (pp->sloppyclockflag & CLK_FLAG3)
-               pps_enable = 1;
-       pp->leap = sys_prefer->leap;
-       if (pp->stratum >= STRATUM_UNSPEC)
-               peer->stratum = sys_prefer->stratum;
-       else
-               peer->stratum = pp->stratum;
        pp->lastref = pp->lastrec;
        refclock_receive(peer);
 }
 #else
 int refclock_atom_bs;
-int
-pps_sample(
-          l_fp *offset         /* PPS offset */
-          )
-{
-       return (1);
-}
 #endif /* REFCLOCK */
index dc29d1e798fecf804c435b44e5b1fa88f9298427..c046d012dd9b4a4c6137132b0feafdb2ca5b7e63 100644 (file)
@@ -138,7 +138,7 @@ extern      struct refclock refclock_nmea;
 #define        refclock_nmea   refclock_none
 #endif
 
-#ifdef CLOCK_ATOM
+#if defined (CLOCK_ATOM) && defined(HAVE_PPSAPI)
 extern struct refclock refclock_atom;
 #else
 #define refclock_atom  refclock_none
index ffc052c0a9f7d0f683d564949141e0a93ae63980..1776b8af99a853a25097ee1451c5471d6da19a99 100644 (file)
 /*
  * This is a hack to allow a machine to use its own system clock as a
  * reference clock, i.e., to free-run using no outside clock discipline
- * source. This is useful if you want to use NTP in an isolated
- * environment with no radio clock or NIST modem available. Pick a
- * machine that you figure has a good clock oscillator and configure it
- * with this driver. Set the clock using the best means available, like
+ * source. Note that the clock selection algorithm will not select this
+ * driver unless all other sources of synchronization have been lost.
+ * This is useful if you want to use NTP in an isolated environment
+ * with no radio clock or NIST modem available. Pick a machine that you
+ * figure has a good clock oscillator and configure it with this
+ * driver. Set the clock using the best means available, like
  * eyeball-and-wristwatch. Then, point all the other machines at this
  * one or use broadcast (not multicast) mode to distribute time.
  *
  * Another application for this driver is if you want to use a
  * particular server's clock as the clock of last resort when all other
  * normal synchronization sources have gone away. This is especially
- * useful if that server has an ovenized oscillator.
+ * useful if that server has an ovenized oscillator. However, the
+ * preferred was to do this is using orphan mode. See the documentation.
  *
  * A third application for this driver is when an external discipline
  * source is available, such as the NIST "lockclock" program, which
  * oscillator. In extreme cases, this can cause clients to exceed the
  * 128-ms slew window and drop off the NTP subnet.
  *
- * THis driver includes provisions to telegraph synchronization state
- * and related variables by means of kernel variables with specially
- * modified kernels. This is done using the ntp_adjtime() syscall.
- * In the cases where another protocol or device synchronizes the local
- * host, the data given to the kernel can be slurped up by this driver
- * and distributed to clients by ordinary NTP messaging.
- *
- * In the default mode the behavior of the clock selection algorithm is
- * modified when this driver is in use. The algorithm is designed so
- * that this driver will never be selected unless no other discipline
- * source is available.
- *
  * Fudge Factors
  *
- * The stratum for this driver set at 5 by default, but it can be
- * changed by the fudge command and/or the ntpdc utility. The reference
- * ID is 127.0.0.1 by default, but can be changed using the same
- * mechanism.
+ * If fudge flag1 is lit, the leap second bit is set in the peer
+ * status word. It should be set early in the day of a leap second
+ * event and set dark on the day after the event.
  *
- * This driver provides a mechanism to trim the local clock in both time
- * and frequency, as well as a way to manipulate the leap bits. The
- * fudge time1 parameter adjusts the time, in seconds, and the fudge
- * time2 parameter adjusts the frequency, in ppm. The fudge time1
- * parameter is additive; that is, it adds an increment to the current
- * time. The fudge time2 parameter directly sets the frequency.
+ * Note the fudge time1 and time2 have been deprecated. The fudge time1
+ * was intended to apply a bias offset. This can be done using the Unix
+ * date command. The fudge time2 was intended to apply a bias frequency.
+ * This can be done using the frequency file and/or the freq
+ * configuration command.
  */
 /*
  * Local interface definitions
@@ -203,12 +192,8 @@ local_poll(
         * time1 (s) and a continuous frequency adjustment using fudge
         * time 2 (ppm).
         */
-       get_systime(&pp->lastrec);
-       pp->fudgetime1 += pp->fudgetime2 * 1e-6 * (current_time -
-           poll_time);
        poll_time = current_time;
-       refclock_process_offset(pp, pp->lastrec, pp->lastrec,
-           pp->fudgetime1);
+       refclock_process_offset(pp, pp->lastrec, pp->lastrec, 0);
 
        /*
         * If another process is disciplining the system clock, we set
@@ -248,7 +233,6 @@ local_poll(
 #endif /* KERNEL_PLL LOCKCLOCK */
        pp->lastref = pp->lastrec;
        refclock_receive(peer);
-       pp->fudgetime1 = 0;
 }
 #else
 int refclock_local_bs;