+* 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
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 */
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.
* 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)
#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 */
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
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 */
LFPTOD(&ci, t34);
p_offset = t34;
}
- p_del = peer->delay;
/*
* When calibration is complete and the clock is
*/
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.
)
{
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
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.
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
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;
* 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
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 */
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;
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
}
}
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;
}
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);
}
/*
* 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);
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;
* 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;
}
#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
*/
pps_info_t pps_info; /* last pps data */
pps_handle_t handle; /* pps handlebars */
};
-#endif /* HAVE_PPSAPI */
/*
* Function prototypes
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 */
/*
)
{
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;
"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 */
}
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
*/
/*
* 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(
#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);
-}
/*
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 */
#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
/*
* 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
* 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
#endif /* KERNEL_PLL LOCKCLOCK */
pp->lastref = pp->lastrec;
refclock_receive(peer);
- pp->fudgetime1 = 0;
}
#else
int refclock_local_bs;