]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: drop initstepslew NTP implementation
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 7 Apr 2014 15:27:44 +0000 (17:27 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 9 Apr 2014 07:54:40 +0000 (09:54 +0200)
The initstepslew code has its own minimal NTP implementation. Drop the
code, add a new initstepslew mode to the reference updating code and
use regular NTP sources with iburst flag for initstepslew addresses
instead. When an update is made or a source is found unreachable, log a
message, remove the initstepslew sources and switch to normal mode.

This reduces code duplication and makes initstepslew use features
implemented only in the main code like source combining or SO_TIMESTAMP
support.

12 files changed:
Makefile.in
acquire.c [deleted file]
acquire.h [deleted file]
conf.c
conf.h
main.c
ntp_sources.c
ntp_sources.h
reference.c
reference.h
sources.c
test/simulation/103-initstepslew

index e11a1d13303b721062aa611306839ffbf5665ed1..64bef032d3888e074b66138ff5356d44db376e4b 100644 (file)
@@ -42,7 +42,7 @@ OBJS = util.o sched.o regress.o local.o \
        sys.o main.o ntp_io.o ntp_core.o ntp_sources.o \
        sources.o sourcestats.o reference.o \
        logging.o conf.o cmdmon.o keys.o \
-       nameserv.o acquire.o manual.o addrfilt.o \
+       nameserv.o manual.o addrfilt.o \
        cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
        broadcast.o refclock.o refclock_phc.o refclock_pps.o \
        refclock_shm.o refclock_sock.o tempcomp.o $(HASH_OBJ)
diff --git a/acquire.c b/acquire.c
deleted file mode 100644 (file)
index 599e702..0000000
--- a/acquire.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
-  chronyd/chronyc - Programs for keeping computer clocks accurate.
-
- **********************************************************************
- * Copyright (C) Richard P. Curnow  1997-2003
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- * 
- **********************************************************************
-
-  =======================================================================
-
-  Processing to perform the equivalent of what ntpdate does.  That is,
-  make a rapid-fire set of measurements to a designated set of
-  sources, and step or slew the local clock to bring it into line with
-  the result.
-
-  This is kept completely separate of the main chronyd processing, by
-  using a separate socket for sending/receiving the measurement
-  packets.  That way, ntp_core.c can be kept completely independent of
-  this functionality.
-  
-  A few of the finer points of how to construct valid RFC1305 packets
-  and validate responses for this case have been cribbed from the
-  ntpdate source.
-
-  */
-
-#include "config.h"
-
-#include "sysincl.h"
-
-#include "acquire.h"
-#include "memory.h"
-#include "sched.h"
-#include "local.h"
-#include "logging.h"
-#include "ntp.h"
-#include "util.h"
-#include "main.h"
-#include "conf.h"
-
-/* ================================================== */
-
-/* Interval between firing off the first sample to successive sources */
-#define INTER_SOURCE_START (0.2)
-
-#define MAX_SAMPLES 8
-
-#define MAX_DEAD_PROBES 4
-#define N_GOOD_SAMPLES 4
-
-#define RETRANSMISSION_TIMEOUT (1.0)
-
-#define NTP_VERSION 3
-#define NTP_MAX_COMPAT_VERSION 4
-#define NTP_MIN_COMPAT_VERSION 2
-
-typedef struct {
-  IPAddr ip_addr;               /* Address of the server */
-  int sanity;                   /* Flag indicating whether source
-                                   looks sane or not */
-  int n_dead_probes;            /* Number of probes sent to the server
-                                   since a good one */
-  int n_samples;                /* Number of samples accumulated */
-  int n_total_samples;          /* Total number of samples received
-                                   including useless ones */
-  double offsets[MAX_SAMPLES];  /* In seconds, positive means local
-                                   clock is fast of reference */
-  double root_distances[MAX_SAMPLES]; /* in seconds */
-  double inter_lo;              /* Low end of estimated range of offset */
-  double inter_hi;              /* High end of estimated range of offset */
-
-  NTP_int64 last_tx;            /* Transmit timestamp in last packet
-                                   transmitted to source. */
-
-  int timer_running;
-  SCH_TimeoutID timeout_id;
-} SourceRecord;
-
-static SourceRecord *sources;
-static int n_sources;
-static int n_started_sources;
-static int n_completed_sources;
-
-static double init_slew_threshold;
-
-union sockaddr_in46 {
-  struct sockaddr_in in4;
-#ifdef HAVE_IPV6
-  struct sockaddr_in6 in6;
-#endif
-  struct sockaddr u;
-};
-
-static int sock_fd4 = -1;
-#ifdef HAVE_IPV6
-static int sock_fd6 = -1;
-#endif
-
-/* ================================================== */
-
-static void (*saved_after_hook)(void *) = NULL;
-static void *saved_after_hook_anything = NULL;
-
-/* ================================================== */
-
-typedef struct {
-  double offset;
-  enum {LO, HIGH} type;
-  int index;
-} Endpoint;
-
-typedef struct {
-  double lo;
-  double hi;
-} Interval;
-
-/* ================================================== */
-
-static void read_from_socket(void *anything);
-static void transmit_timeout(void *x);
-static void wind_up_acquisition(void);
-static void start_source_timeout_handler(void *not_used);
-
-/* ================================================== */
-
-static SCH_TimeoutID source_start_timeout_id;
-
-/* ================================================== */
-
-void
-ACQ_Initialise(void)
-{
-}
-
-
-/* ================================================== */
-
-void
-ACQ_Finalise(void)
-{
-}
-
-/* ================================================== */
-
-static int
-prepare_socket(int family)
-{
-  unsigned short port_number = CNF_GetAcquisitionPort();
-  int sock_fd;
-  socklen_t addrlen;
-
-  sock_fd = socket(family, SOCK_DGRAM, 0);
-
-  if (sock_fd < 0) {
-    LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
-  }
-
-  /* Close on exec */
-  UTI_FdSetCloexec(sock_fd);
-
-  if (port_number == 0 || port_number == CNF_GetNTPPort()) {
-    /* Don't bother binding this socket - we're not fussed what port
-       number it gets */
-  } else {
-    union sockaddr_in46 my_addr;
-
-    memset(&my_addr, 0, sizeof (my_addr));
-
-    switch (family) {
-      case AF_INET:
-        my_addr.in4.sin_family = family;
-        my_addr.in4.sin_port = htons(port_number);
-        my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
-        addrlen = sizeof (my_addr.in4);
-        break;
-#ifdef HAVE_IPV6
-      case AF_INET6:
-        my_addr.in6.sin6_family = family;
-        my_addr.in6.sin6_port = htons(port_number);
-        my_addr.in6.sin6_addr = in6addr_any;
-        addrlen = sizeof (my_addr.in6);
-        break;
-#endif
-      default:
-        assert(0);
-    }
-
-    if (bind(sock_fd, &my_addr.u, addrlen) < 0) {
-      LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s", strerror(errno));
-      /* but keep running */
-    }
-  }
-
-  SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
-
-  return sock_fd;
-}
-/* ================================================== */
-
-static void
-initialise_io(int family)
-{
-  if (family == IPADDR_INET4 || family == IPADDR_UNSPEC)
-    sock_fd4 = prepare_socket(AF_INET);
-#ifdef HAVE_IPV6
-  if (family == IPADDR_INET6 || family == IPADDR_UNSPEC)
-    sock_fd6 = prepare_socket(AF_INET6);
-#endif
-}
-
-/* ================================================== */
-
-static void
-finalise_io(void)
-{
-  if (sock_fd4 >= 0) {
-    SCH_RemoveInputFileHandler(sock_fd4);
-    close(sock_fd4);
-  }
-  sock_fd4 = -1;
-#ifdef HAVE_IPV6
-  if (sock_fd6 >= 0) {
-    SCH_RemoveInputFileHandler(sock_fd6);
-    close(sock_fd6);
-  }
-  sock_fd6 = -1;
-#endif
-}
-
-/* ================================================== */
-
-static void
-probe_source(SourceRecord *src)
-{
-  NTP_Packet pkt;
-  int version = NTP_VERSION;
-  NTP_Mode my_mode = MODE_CLIENT;
-  struct timeval cooked;
-  union sockaddr_in46 his_addr;
-  int sock_fd;
-  socklen_t addrlen;
-  uint32_t ts_fuzz;
-
-#if 0
-  printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
-#endif
-
-  pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
-             ((version << 3) & 0x38) |
-             ((my_mode) & 0x7));
-
-  pkt.stratum = 0;
-  pkt.poll = 4;
-  pkt.precision = -6; /* as ntpdate */
-  pkt.root_delay = UTI_DoubleToInt32(1.0); /* 1 second */
-  pkt.root_dispersion = UTI_DoubleToInt32(1.0); /* likewise */
-  pkt.reference_id = 0;
-  pkt.reference_ts.hi = 0; /* Set to 0 */
-  pkt.reference_ts.lo = 0; /* Set to 0 */
-  pkt.originate_ts.hi = 0; /* Set to 0 */
-  pkt.originate_ts.lo = 0; /* Set to 0 */
-  pkt.receive_ts.hi = 0;   /* Set to 0 */
-  pkt.receive_ts.lo = 0;   /* Set to 0 */
-
-  /* And do transmission */
-
-  memset(&his_addr, 0, sizeof (his_addr));
-  switch (src->ip_addr.family) {
-    case IPADDR_INET4:
-      his_addr.in4.sin_addr.s_addr = htonl(src->ip_addr.addr.in4);
-      his_addr.in4.sin_port = htons(123); /* Fixed for now */
-      his_addr.in4.sin_family = AF_INET;
-      addrlen = sizeof (his_addr.in4);
-      sock_fd = sock_fd4;
-      break;
-#ifdef HAVE_IPV6
-    case IPADDR_INET6:
-      memcpy(&his_addr.in6.sin6_addr.s6_addr, &src->ip_addr.addr.in6,
-          sizeof (his_addr.in6.sin6_addr.s6_addr));
-      his_addr.in6.sin6_port = htons(123); /* Fixed for now */
-      his_addr.in6.sin6_family = AF_INET6;
-      addrlen = sizeof (his_addr.in6);
-      sock_fd = sock_fd6;
-      break;
-#endif
-    default:
-      assert(0);
-  }
-
-
-  ts_fuzz = UTI_GetNTPTsFuzz(LCL_GetSysPrecisionAsLog());
-  LCL_ReadCookedTime(&cooked, NULL);
-  UTI_TimevalToInt64(&cooked, &pkt.transmit_ts, ts_fuzz);
-
-  if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
-             0,
-             &his_addr.u, addrlen) < 0) {
-    LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
-        UTI_IPToString(&src->ip_addr),
-        strerror(errno));
-  }
-
-  src->last_tx = pkt.transmit_ts;
-
-  ++(src->n_dead_probes);
-  src->timer_running = 1;
-  src->timeout_id = SCH_AddTimeoutByDelay(RETRANSMISSION_TIMEOUT, transmit_timeout, (void *) src);
-}
-
-/* ================================================== */
-
-static void
-transmit_timeout(void *x)
-{
-  SourceRecord *src = (SourceRecord *) x;
-
-  src->timer_running = 0;
-
-#if 0
-  printf("Timeout expired for server %s\n", UTI_IPToString(&src->ip_addr));
-#endif
-
-  if (src->n_dead_probes < MAX_DEAD_PROBES) {
-    probe_source(src);
-  } else {
-    /* Source has croaked or is taking too long to respond */
-    ++n_completed_sources;
-    if (n_completed_sources == n_sources) {
-      wind_up_acquisition();
-    }
-  }
-}
-
-/* ================================================== */
-
-#define MAX_STRATUM 15
-
-static void
-process_receive(NTP_Packet *msg, SourceRecord *src, struct timeval *now)
-{
-
-  unsigned long lvm;
-  int leap, version, mode;
-  double root_delay, root_dispersion;
-  double total_root_delay, total_root_dispersion, total_root_distance;
-
-  struct timeval local_orig, local_average, remote_rx, remote_tx, remote_average;
-  double remote_interval, local_interval;
-  double delta, theta, epsilon;
-  int n;
-  
-  /* Most of the checks are from ntpdate */
-
-  /* Need to do something about authentication */
-
-  lvm = msg->lvm;
-  leap = (lvm >> 6) & 0x3;
-  version = (lvm >> 3) & 0x7;
-  mode = lvm & 0x7;
-
-  if ((leap == LEAP_Unsynchronised) ||
-      (version  < NTP_MIN_COMPAT_VERSION || version > NTP_MAX_COMPAT_VERSION) ||
-      (mode != MODE_SERVER && mode != MODE_PASSIVE)) {
-    return;
-  }
-
-  if (msg->stratum > MAX_STRATUM) {
-    return;
-  }
-
-  /* Check whether server is responding to our last request */
-  if ((msg->originate_ts.hi != src->last_tx.hi) ||
-      (msg->originate_ts.lo != src->last_tx.lo)) {
-    return;
-  }
-
-  /* Check that the server is sane */
-  if (((msg->originate_ts.hi == 0) && (msg->originate_ts.lo == 0)) ||
-      ((msg->receive_ts.hi == 0) && (msg->receive_ts.lo) == 0)) {
-    return;
-  }
-
-  root_delay = UTI_Int32ToDouble(msg->root_delay);
-  root_dispersion = UTI_Int32ToDouble(msg->root_dispersion);
-
-  UTI_Int64ToTimeval(&src->last_tx, &local_orig);
-  UTI_Int64ToTimeval(&msg->receive_ts, &remote_rx);
-  UTI_Int64ToTimeval(&msg->transmit_ts, &remote_tx);
-  UTI_AverageDiffTimevals(&remote_rx, &remote_tx, &remote_average, &remote_interval);
-  UTI_AverageDiffTimevals(&local_orig, now, &local_average, &local_interval);
-
-  delta = local_interval - remote_interval;
-
-  /* Defined as positive if we are fast.  Note this sign convention is
-     opposite to that used in ntp_core.c */
-
-  UTI_DiffTimevalsToDouble(&theta, &local_average, &remote_average);
-  
-  /* Could work out epsilon - leave till later */
-  epsilon = 0.0;
-
-  total_root_delay = fabs(delta) + root_delay;
-  total_root_dispersion = epsilon + root_dispersion;
-  total_root_distance = 0.5 * fabs(total_root_delay) + total_root_dispersion;
-
-  n = src->n_samples;
-#if 0
-  printf("Sample %d theta=%.6f delta=%.6f root_del=%.6f root_disp=%.6f root_dist=%.6f\n",
-         n, theta, delta, total_root_delay, total_root_dispersion, total_root_distance);
-#endif
-  src->offsets[n] = theta;
-  src->root_distances[n] = total_root_distance;
-  ++(src->n_samples);
-
-}
-
-/* ================================================== */
-
-static void
-read_from_socket(void *anything)
-{
-  int status;
-  ReceiveBuffer msg;
-  union sockaddr_in46 his_addr;
-  int sock_fd;
-  socklen_t his_addr_len;
-  int flags;
-  int message_length;
-  IPAddr remote_ip;
-  int i, ok;
-  struct timeval now;
-  SourceRecord *src;
-
-  flags = 0;
-  message_length = sizeof(msg);
-  his_addr_len = sizeof(his_addr);
-
-  /* Get timestamp */
-  SCH_GetLastEventTime(&now, NULL, NULL);
-
-  sock_fd = (long)anything;
-  status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
-                     &his_addr.u, &his_addr_len);
-
-  if (status < 0) {
-    LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
-    return;
-  }
-  
-  switch (his_addr.u.sa_family) {
-    case AF_INET:
-      remote_ip.family = IPADDR_INET4;
-      remote_ip.addr.in4 = ntohl(his_addr.in4.sin_addr.s_addr);
-      break;
-#ifdef HAVE_IPV6
-    case AF_INET6:
-      remote_ip.family = IPADDR_INET6;
-      memcpy(&remote_ip.addr.in6, his_addr.in6.sin6_addr.s6_addr,
-          sizeof (remote_ip.addr.in6));
-      break;
-#endif
-    default:
-      assert(0);
-  }
-
-#if 0
-  printf("Got message from %s\n", UTI_IPToString(&remote_ip));
-#endif
-  
-  /* Find matching host */
-  ok = 0;
-  for (i=0; i<n_sources; i++) {
-    if (UTI_CompareIPs(&remote_ip, &sources[i].ip_addr, NULL) == 0) {
-      ok = 1;
-      break;
-    }
-  }
-
-  if (ok) {
-
-    src = sources + i;
-    ++src->n_total_samples;
-
-    src->n_dead_probes = 0; /* reset this when we actually receive something */
-
-    /* If we got into this function, we know the retransmission timeout has not
-       expired for the source */
-    if (src->timer_running) {
-      SCH_RemoveTimeout(src->timeout_id);
-      src->timer_running = 0;
-    }
-
-    process_receive(&msg.ntp_pkt, src, &now);
-
-    /* Check if server done and requeue timeout */
-    if ((src->n_samples >= N_GOOD_SAMPLES) ||
-        (src->n_total_samples >= MAX_SAMPLES)) {
-      ++n_completed_sources;
-#if 0
-      printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
-#endif
-      if (n_completed_sources == n_sources) {
-        wind_up_acquisition();
-      }
-    } else {
-      
-      /* Send the next probe */
-      probe_source(src);
-
-    }
-  }
-
-}
-
-/* ================================================== */
-
-static void
-start_next_source(void)
-{
-  probe_source(sources + n_started_sources);
-#if 0
-  printf("Trying to start source %s\n", UTI_IPToString(&sources[n_started_sources].ip_addr));
-#endif
-  n_started_sources++;
-  
-  if (n_started_sources < n_sources) {
-    source_start_timeout_id = SCH_AddTimeoutByDelay(INTER_SOURCE_START, start_source_timeout_handler, NULL);
-  }
-}
-
-/* ================================================== */
-
-static int
-endpoint_compare(const void *a, const void *b)
-{
-  const Endpoint *aa = (const Endpoint *) a;
-  const Endpoint *bb = (const Endpoint *) b;
-
-  if (aa->offset < bb->offset) {
-    return -1;
-  } else if (aa->offset > bb->offset) {
-    return +1;
-  } else {
-    return 0;
-  }
-}
-
-/* ================================================== */
-
-static void
-process_measurements(void)
-{
-
-  SourceRecord *s;
-  Endpoint *eps;
-  int i, j;
-  int n_sane_sources;
-  double lo, hi;
-  double inter_lo, inter_hi;
-
-  int depth;
-  int best_depth;
-  int n_at_best_depth;
-  Interval *intervals;
-  double estimated_offset;
-  int index1, index2;
-
-  n_sane_sources = 0;
-
-  /* First, get a consistent interval for each source.  Those for
-     which this is not possible are considered to be insane. */
-
-  for (i=0; i<n_sources; i++) {
-    s = sources + i;
-    /* If we got no measurements, the source is insane */
-    if (s->n_samples == 0) {
-      s->sanity = 0;
-    } else {
-      s->sanity = 1; /* so far ... */
-      lo = s->offsets[0] - s->root_distances[0];
-      hi = s->offsets[0] + s->root_distances[0];
-      inter_lo = lo;
-      inter_hi = hi;
-      for (j=1; j<s->n_samples; j++) {
-        lo = s->offsets[j] - s->root_distances[j];
-        hi = s->offsets[j] + s->root_distances[j];
-        if ((inter_hi <= lo) || (inter_lo >= hi)) {
-          /* Oh dear, we won't get an interval for this source */
-          s->sanity = 0;
-          break;
-        } else {
-          inter_lo = (lo < inter_lo) ? inter_lo : lo;
-          inter_hi = (hi > inter_hi) ? inter_hi : hi;
-        }
-      }
-      if (s->sanity) {
-        s->inter_lo = inter_lo;
-        s->inter_hi = inter_hi;
-      }
-    }
-
-    if (s->sanity) {
-      ++n_sane_sources;
-    }
-
-  }
-
-  /* Now build the endpoint list, similar to the RFC1305 clock
-     selection algorithm. */
-  eps = MallocArray(Endpoint, 2*n_sane_sources);
-  intervals = MallocArray(Interval, n_sane_sources);
-
-  j = 0;
-  for (i=0; i<n_sources; i++) {
-    s = sources + i;
-    if (s->sanity) {
-      eps[j].offset = s->inter_lo;
-      eps[j].type = LO;
-      eps[j].index = i;
-      eps[j+1].offset = s->inter_hi;
-      eps[j+1].type = HIGH;
-      eps[j+1].index = i;
-      j += 2;
-    }
-  }
-
-  qsort(eps, 2*n_sane_sources, sizeof(Endpoint), endpoint_compare);
-
-  /* Now do depth searching algorithm */
-  n_at_best_depth = best_depth = depth = 0;
-  for (i=0; i<2*n_sane_sources; i++) {
-
-#if 0
-    fprintf(stderr, "Endpoint type %s source index %d [ip=%s] offset=%.6f\n",
-            (eps[i].type == LO) ? "LO" : "HIGH",
-            eps[i].index,
-            UTI_IPToString(&sources[eps[i].index].ip_addr),
-            eps[i].offset);
-#endif
-
-    switch (eps[i].type) {
-      case LO:
-        depth++;
-        if (depth > best_depth) {
-          best_depth = depth;
-          n_at_best_depth = 0;
-          intervals[0].lo = eps[i].offset;
-        } else if (depth == best_depth) {
-          intervals[n_at_best_depth].lo = eps[i].offset;
-        } else {
-          /* Nothing to do */
-        }
-
-        break;
-
-      case HIGH:
-        if (depth == best_depth) {
-          intervals[n_at_best_depth].hi = eps[i].offset;
-          n_at_best_depth++;
-        }
-
-        depth--;
-
-        break;
-
-    }
-  }
-
-  if (best_depth > 0) {
-    if ((n_at_best_depth % 2) == 1) {
-      index1 = (n_at_best_depth - 1) / 2;
-      estimated_offset = 0.5 * (intervals[index1].lo + intervals[index1].hi);
-    } else {
-      index2 = (n_at_best_depth / 2);
-      index1 = index2 - 1;
-      estimated_offset = 0.5 * (intervals[index1].lo + intervals[index2].hi);
-    }
-
-
-    /* Apply a step change to the system clock.  As per sign
-       convention in local.c and its children, a positive offset means
-       the system clock is fast of the reference, i.e. it needs to be
-       stepped backwards. */
-
-    if (fabs(estimated_offset) > init_slew_threshold) {
-      LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (step)",
-          fabs(estimated_offset),
-          (estimated_offset >= 0) ? "fast" : "slow");
-      LCL_ApplyStepOffset(estimated_offset);
-    } else {
-      LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (slew)",
-          fabs(estimated_offset),
-          (estimated_offset >= 0) ? "fast" : "slow");
-      LCL_AccumulateOffset(estimated_offset, 0.0);
-    }
-
-  } else {
-    LOG(LOGS_WARN, LOGF_Acquire, "No intersecting endpoints found");
-  }  
-
-  Free(intervals);
-  Free(eps);
-        
-}
-
-/* ================================================== */
-
-static void
-wind_up_acquisition(void)
-{
-
-  /* Now process measurements */
-  process_measurements();
-
-  Free(sources);
-
-  finalise_io();
-
-  if (saved_after_hook) {
-    (saved_after_hook)(saved_after_hook_anything);
-  }
-
-}
-
-/* ================================================== */
-
-static void
-start_source_timeout_handler(void *not_used)
-{
-
-  start_next_source();
-}
-
-/* ================================================== */
-
-void
-ACQ_StartAcquisition(int n, IPAddr *ip_addrs, double threshold, void (*after_hook)(void *), void *anything)
-{
-
-  int i, ip4, ip6;
-  int k, duplicate_ip;
-
-  saved_after_hook = after_hook;
-  saved_after_hook_anything = anything;
-
-  init_slew_threshold = threshold;
-
-  n_started_sources = 0;
-  n_completed_sources = 0;
-  n_sources = 0;
-  sources = MallocArray(SourceRecord, n);
-
-  for (i = ip4 = ip6 = 0; i < n; i++) {
-    /* check for duplicate IP addresses and ignore them */
-    duplicate_ip = 0;
-    for (k = 0; k < i; k++) {
-      duplicate_ip |= UTI_CompareIPs(&(sources[k].ip_addr),
-                                     &ip_addrs[i],
-                                     NULL) == 0;
-    }
-    if (!duplicate_ip) {
-      sources[n_sources].ip_addr = ip_addrs[i];
-      sources[n_sources].n_samples = 0;
-      sources[n_sources].n_total_samples = 0;
-      sources[n_sources].n_dead_probes = 0;
-      if (ip_addrs[i].family == IPADDR_INET4)
-        ip4++;
-      else if (ip_addrs[i].family == IPADDR_INET6)
-        ip6++;
-      n_sources++;
-    } else {
-      LOG(LOGS_WARN, LOGF_Acquire, "Ignoring duplicate source: %s",
-          UTI_IPToString(&ip_addrs[i]));
-    }
-  }
-
-  initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
-
-  /* Start sampling first source */
-  start_next_source();
-}
-
-/* ================================================== */
diff --git a/acquire.h b/acquire.h
deleted file mode 100644 (file)
index cd15cce..0000000
--- a/acquire.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-  chronyd/chronyc - Programs for keeping computer clocks accurate.
-
- **********************************************************************
- * Copyright (C) Richard P. Curnow  1997-2002
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- * 
- **********************************************************************
-
-  =======================================================================
-
-  Header file for acquisition module
-  */
-
-#ifndef GOT_ACQUIRE_H
-#define GOT_ACQUIRE_H
-
-#include "addressing.h"
-
-typedef struct ACQ_SourceRecord *ACQ_Source;
-
-extern void ACQ_Initialise(void);
-
-extern void ACQ_Finalise(void);
-
-extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, double init_slew_threshold,
-                                 void (*after_hook)(void *), void *anything);
-
-extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);
-
-extern void ACQ_MissedSample(ACQ_Source acq_source);
-
-#endif /* GOT_ACQUIRE_H */
diff --git a/conf.c b/conf.c
index 0b63ae93621d71b8295acf3bbc3af5961b10bd01..5af18d365b3dea366379c6f9c53ce0ace079e989 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -38,7 +38,6 @@
 #include "logging.h"
 #include "nameserv.h"
 #include "memory.h"
-#include "acquire.h"
 #include "cmdparse.h"
 #include "broadcast.h"
 #include "util.h"
@@ -110,7 +109,6 @@ static char *dumpdir = ".";
 static int enable_local=0;
 static int local_stratum;
 
-static int do_init_stepslew = 0;
 static int n_init_srcs;
 
 /* Threshold (in seconds) - if absolute value of initial error is less
@@ -787,9 +785,6 @@ parse_initstepslew(char *line)
       }
     }
   }
-  if (n_init_srcs > 0) {
-    do_init_stepslew = 1;
-  }
 }
 
 /* ================================================== */
@@ -1155,12 +1150,24 @@ parse_include(char *line)
 /* ================================================== */
 
 void
-CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything)
+CNF_AddInitSources(void)
 {
-  if (do_init_stepslew) {
-    ACQ_StartAcquisition(n_init_srcs, init_srcs_ip, init_slew_threshold, after_hook, anything);
-  } else {
-    (after_hook)(anything);
+  CPS_NTP_Source cps_source;
+  NTP_Remote_Address ntp_addr;
+  char dummy_hostname[2] = "H";
+  int i;
+
+  for (i = 0; i < n_init_srcs; i++) {
+    /* Get the default NTP params */
+    CPS_ParseNTPSourceAdd(dummy_hostname, &cps_source);
+
+    /* Add the address as an offline iburst server */
+    ntp_addr.ip_addr = init_srcs_ip[i];
+    ntp_addr.port = cps_source.port;
+    cps_source.params.iburst = 1;
+    cps_source.params.online = 0;
+
+    NSR_AddSource(&ntp_addr, NTP_SERVER, &cps_source.params);
   }
 }
 
@@ -1671,3 +1678,19 @@ CNF_GetHwclockFile(void)
 {
   return hwclock_file;
 }
+
+/* ================================================== */
+
+int
+CNF_GetInitSources(void)
+{
+  return n_init_srcs;
+}
+
+/* ================================================== */
+
+double
+CNF_GetInitStepThreshold(void)
+{
+  return init_slew_threshold;
+}
diff --git a/conf.h b/conf.h
index bdc3e7b1e0405291f5f72681328d0d97870bc1b2..70feee12b5e6e5a24c62581b240d7b98c987eb06 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -35,12 +35,11 @@ extern char *CNF_GetRtcDevice(void);
 
 extern void CNF_ReadFile(const char *filename);
 
+extern void CNF_AddInitSources(void);
 extern void CNF_AddSources(void);
 extern void CNF_AddBroadcasts(void);
 extern void CNF_AddRefclocks(void);
 
-extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything);
-
 extern unsigned short CNF_GetAcquisitionPort(void);
 extern unsigned short CNF_GetNTPPort(void);
 extern char *CNF_GetDriftFile(void);
@@ -103,4 +102,7 @@ extern int CNF_GetMinSamples(void);
 extern double CNF_GetRtcAutotrim(void);
 extern char *CNF_GetHwclockFile(void);
 
+extern int CNF_GetInitSources(void);
+extern double CNF_GetInitStepThreshold(void);
+
 #endif /* GOT_CONF_H */
diff --git a/main.c b/main.c
index 207011f248f39c6c25b11296b8cf9f1f9dda683e..7eaf63ac4ae5fbcef69cd35378b2435982f820c5 100644 (file)
--- a/main.c
+++ b/main.c
@@ -44,7 +44,6 @@
 #include "conf.h"
 #include "cmdmon.h"
 #include "keys.h"
-#include "acquire.h"
 #include "manual.h"
 #include "rtc.h"
 #include "refclock.h"
@@ -64,6 +63,8 @@ static int initialised = 0;
 
 static int reload = 0;
 
+static REF_Mode ref_mode;
+
 /* ================================================== */
 
 static void
@@ -87,7 +88,6 @@ MAI_CleanupAndExit(void)
 
   TMC_Finalise();
   MNL_Finalise();
-  ACQ_Finalise();
   CLG_Finalise();
   NSR_Finalise();
   NCR_Finalise();
@@ -123,8 +123,15 @@ signal_cleanup(int x)
 /* ================================================== */
 
 static void
-post_acquire_hook(void *anything)
+post_init_ntp_hook(void *anything)
 {
+  if (ref_mode == REF_ModeInitStepSlew) {
+    /* Remove the initstepslew sources and set normal mode */
+    NSR_RemoveAllSources();
+    ref_mode = REF_ModeNormal;
+    REF_SetMode(ref_mode);
+  }
+
   /* Close the pipe to the foreground process so it can exit */
   LOG_CloseParentFd();
 
@@ -145,10 +152,34 @@ post_acquire_hook(void *anything)
 
 /* ================================================== */
 
+static void
+reference_mode_end(int result)
+{
+  switch (ref_mode) {
+    case REF_ModeNormal:
+      break;
+    case REF_ModeInitStepSlew:
+      /* post_init_ntp_hook removes sources and a source call is
+         on the stack here, so it can't be called directly */
+      SCH_AddTimeoutByDelay(0.0, post_init_ntp_hook, NULL);
+      break;
+    default:
+      assert(0);
+  }
+}
+
+/* ================================================== */
+
 static void
 post_init_rtc_hook(void *anything)
 {
-  CNF_ProcessInitStepSlew(post_acquire_hook, NULL);
+  if (CNF_GetInitSources() > 0) {
+    CNF_AddInitSources();
+    assert(REF_GetMode() != REF_ModeNormal);
+    /* Wait for mode end notification */
+  } else {
+    (post_init_ntp_hook)(NULL);
+  }
 }
 
 /* ================================================== */
@@ -416,13 +447,19 @@ int main
   NCR_Initialise();
   NSR_Initialise();
   CLG_Initialise();
-  ACQ_Initialise();
   MNL_Initialise();
   TMC_Initialise();
 
   /* From now on, it is safe to do finalisation on exit */
   initialised = 1;
 
+  if (CNF_GetInitSources() > 0) {
+    ref_mode = REF_ModeInitStepSlew;
+  }
+
+  REF_SetModeEndHandler(reference_mode_end);
+  REF_SetMode(ref_mode);
+
   if (do_init_rtc) {
     RTC_TimeInit(post_init_rtc_hook, NULL);
   } else {
index 11085925fdd547383e0fa7f79d1e171ad1049c85..735ee0ab0844b2c2aa1269e1c5e361ee1a39f733 100644 (file)
@@ -339,6 +339,21 @@ NSR_RemoveSource(NTP_Remote_Address *remote_addr)
 
 /* ================================================== */
 
+void
+NSR_RemoveAllSources(void)
+{
+  int i;
+
+  for (i = 0; i < N_RECORDS; i++) {
+    if (!records[i].remote_addr)
+      continue;
+    NCR_DestroyInstance(records[i].data);
+    records[i].remote_addr = NULL;
+  }
+}
+
+/* ================================================== */
+
 /* This routine is called by ntp_io when a new packet arrives off the network,
    possibly with an authentication tail */
 void
index 596c040929b5ba69579f59ed3b37a223bb764031..43a1cc854325e0f7faea1e9efa8a947c63d33d15 100644 (file)
@@ -60,6 +60,9 @@ extern void NSR_ResolveSources(void);
 /* Procedure to remove a source */
 extern NSR_Status NSR_RemoveSource(NTP_Remote_Address *remote_addr);
 
+/* Procedure to remove all sources */
+extern void NSR_RemoveAllSources(void);
+
 /* This routine is called by ntp_io when a new packet arrives off the network */
 extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
 
index 3a3af1e2160c487ec25a5bd96619d06be4f0dd1d..3a721b96bcffa7c5545ecd49f26663c8cd4c4cbf 100644 (file)
@@ -67,6 +67,9 @@ static double correction_time_ratio;
 /* Flag indicating that we are initialised */
 static int initialised = 0;
 
+/* Current operating mode */
+static REF_Mode mode;
+
 /* Threshold and update limit for stepping clock */
 static int make_step_limit;
 static double make_step_threshold;
@@ -86,6 +89,9 @@ static int do_mail_change;
 static double mail_change_threshold;
 static char *mail_change_user;
 
+/* Handler for mode ending */
+static REF_ModeEndHandler mode_end_handler = NULL;
+
 /* Filename of the drift file. */
 static char *drift_file=NULL;
 static double drift_file_age;
@@ -155,6 +161,7 @@ REF_Initialise(void)
   double file_freq_ppm, file_skew_ppm;
   double our_frequency_ppm;
 
+  mode = REF_ModeIgnore;
   are_we_synchronised = 0;
   our_leap_status = LEAP_Unsynchronised;
   our_leap_sec = 0;
@@ -266,6 +273,29 @@ REF_Finalise(void)
 
 /* ================================================== */
 
+void REF_SetMode(REF_Mode new_mode)
+{
+  mode = new_mode;
+}
+
+/* ================================================== */
+
+REF_Mode
+REF_GetMode(void)
+{
+  return mode;
+}
+
+/* ================================================== */
+
+void
+REF_SetModeEndHandler(REF_ModeEndHandler handler)
+{
+  mode_end_handler = handler;
+}
+
+/* ================================================== */
+
 static double
 Sqr(double x)
 {
@@ -456,6 +486,18 @@ schedule_fb_drift(struct timeval *now)
 
 /* ================================================== */
 
+static void
+end_ref_mode(int result)
+{
+  mode = REF_ModeIgnore;
+
+  /* Dispatch the handler */
+  if (mode_end_handler)
+    (mode_end_handler)(result);
+}
+
+/* ================================================== */
+
 #define BUFLEN 255
 #define S_MAX_USER_LEN "128"
 
@@ -664,6 +706,43 @@ write_log(struct timeval *ref_time, char *ref, int stratum, NTP_Leap leap,
 
 /* ================================================== */
 
+static void
+special_mode_sync(int valid, double offset)
+{
+  int step;
+
+  switch (mode) {
+    case REF_ModeInitStepSlew:
+      if (!valid) {
+        LOG(LOGS_WARN, LOGF_Reference, "No suitable source for initstepslew");
+        end_ref_mode(0);
+        break;
+      }
+
+      step = fabs(offset) >= CNF_GetInitStepThreshold();
+
+      LOG(LOGS_INFO, LOGF_Reference,
+          "System's initial offset : %.6f seconds %s of true (%s)",
+          fabs(offset), offset >= 0 ? "fast" : "slow", step ? "step" : "slew");
+
+      if (step)
+        LCL_ApplyStepOffset(offset);
+      else
+        LCL_AccumulateOffset(offset, 0.0);
+
+      end_ref_mode(1);
+
+      break;
+    case REF_ModeIgnore:
+      /* Do nothing until the mode is changed */
+      break;
+    default:
+      assert(0);
+  }
+}
+
+/* ================================================== */
+
 void
 REF_SetReference(int stratum,
                  NTP_Leap leap,
@@ -695,6 +774,12 @@ REF_SetReference(int stratum,
 
   assert(initialised);
 
+  /* Special modes are implemented elsewhere */
+  if (mode != REF_ModeNormal) {
+    special_mode_sync(1, offset);
+    return;
+  }
+
   /* Guard against dividing by zero */
   if (skew < MIN_SKEW)
     skew = MIN_SKEW;
@@ -886,6 +971,12 @@ REF_SetUnsynchronised(void)
 
   assert(initialised);
 
+  /* Special modes are implemented elsewhere */
+  if (mode != REF_ModeNormal) {
+    special_mode_sync(0, 0.0);
+    return;
+  }
+
   /* This is cheaper than calling LCL_CookTime */
   SCH_GetLastEventTime(&now, NULL, &now_raw);
   UTI_DiffTimevalsToDouble(&uncorrected_offset, &now, &now_raw);
@@ -1086,5 +1177,3 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
   }
 
 }
-
-/* ================================================== */
index 9fe595fcc1354405cca93487428b5545c9bbc01d..babbd6ad486be9cdfe5d20efccdbae3c23805d7c 100644 (file)
@@ -40,6 +40,24 @@ extern void REF_Initialise(void);
 /* Fini function */
 extern void REF_Finalise(void);
 
+typedef enum {
+  REF_ModeNormal,
+  REF_ModeInitStepSlew,
+  REF_ModeIgnore,
+} REF_Mode;
+
+/* Set reference update mode */
+extern void REF_SetMode(REF_Mode mode);
+
+/* Get reference update mode */
+extern REF_Mode REF_GetMode(void);
+
+/* Function type for handlers to be called back when mode ends */
+typedef void (*REF_ModeEndHandler)(int result);
+
+/* Set the handler for being notified of mode ending */
+extern void REF_SetModeEndHandler(REF_ModeEndHandler handler);
+
 /* Function which takes a local cooked time and returns the estimated
    time of the reference.  It also returns the other parameters
    required for forming the outgoing NTP packet.
index e95fa8ae53599f595bd507aa5ab82bad7bf32ce9..77245ca7c39c5230f902f1c7145a00810d9c13b4 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -363,6 +363,12 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
     /* Try to select a better source */
     SRC_SelectSource(NULL);
   }
+
+  /* End special reference mode on last reachability update from iburst */
+  if (REF_GetMode() != REF_ModeNormal &&
+      inst->reachability_size >= REACH_BITS - 1) {
+    REF_SetUnsynchronised();
+  }
 }
 
 /* ================================================== */
index 0d0352b3f761eaaeb34bf19c3e3326425b76f9f6..163efc3df26518ec5541fbdb7bf5fa65a5f50f15 100755 (executable)
@@ -5,12 +5,13 @@ test_start "initstepslew directive"
 
 freq_offset=0.0
 wander=0.0
+time_rms_limit=1e-3
 limit=100
 
 client_conf="initstepslew 5 192.168.123.1"
 
-min_sync_time=15
-max_sync_time=30
+min_sync_time=20
+max_sync_time=35
 
 for time_offset in -2.0 -0.2 0.2 2.0; do
        run_test || test_fail
@@ -18,8 +19,8 @@ for time_offset in -2.0 -0.2 0.2 2.0; do
        check_sync || test_fail
 done
 
-min_sync_time=1
-max_sync_time=1
+min_sync_time=5
+max_sync_time=5
 
 for time_offset in -1e8 -1e2 1e2 1e8; do
        run_test || test_fail