]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add support for reference clocks
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 5 May 2009 07:14:13 +0000 (09:14 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 5 May 2009 21:05:59 +0000 (23:05 +0200)
14 files changed:
Makefile.in
client.c
cmdmon.c
conf.c
conf.h
logging.h
main.c
ntp_core.c
refclock.c [new file with mode: 0644]
refclock.h [new file with mode: 0644]
sources.c
sources.h
util.c
util.h

index 6550543533ae640487115326bfa65674880afbc5..8058648f0d30d7369963c175c93dfa4c7a976f02 100644 (file)
@@ -41,7 +41,7 @@ OBJS = util.o sched.o regress.o local.o \
        logging.o conf.o cmdmon.o md5.o keys.o \
        nameserv.o acquire.o manual.o addrfilt.o \
        cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
-       broadcast.o
+       broadcast.o refclock.o
 
 EXTRA_OBJS=@EXTRA_OBJECTS@
 
index 54b640f5566ad66e0618d75cdd308bd5105f7ada..b4f65f0f2062f96f02b964934232a86ab85952c5 100644 (file)
--- a/client.c
+++ b/client.c
@@ -92,6 +92,19 @@ time_to_log_form(time_t t)
 
 /* ================================================== */
 
+static char *
+UTI_RefidToString(unsigned long ref_id)
+{
+  unsigned int a, b, c, d;
+  static char result[64];
+  a = (ref_id>>24) & 0xff;
+  b = (ref_id>>16) & 0xff;
+  c = (ref_id>> 8) & 0xff;
+  d = (ref_id>> 0) & 0xff;
+  snprintf(result, sizeof(result), "%c%c%c%c", a, b, c, d);
+  return result;
+}
+
 static char *
 UTI_IPToDottedQuad(unsigned long ip)
 {
@@ -1462,7 +1475,9 @@ process_cmd_sources(char *line)
           resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
 
           hostname_buf[25] = 0;
-          if (no_dns) {
+          if (mode == RPY_SD_MD_REF) {
+            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr));
+          } else if (no_dns) {
             snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
           } else {
             dns_lookup = DNS_IPAddress2Name(ip_addr);
index 819977c9330f17d2ab40a145a19899856022cd6b..e2d2ded864d3847249b8040708792fc37de9be37 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -50,6 +50,7 @@
 #include "rtc.h"
 #include "pktlength.h"
 #include "clientlog.h"
+#include "refclock.h"
 
 /* ================================================== */
 
@@ -871,7 +872,14 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
   /* Get data */
   LCL_ReadCookedTime(&now_corr, &local_clock_err);
   if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
-    NSR_ReportSource(&report, &now_corr);
+    switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
+      case SRC_NTP:
+        NSR_ReportSource(&report, &now_corr);
+        break;
+      case SRC_REFCLOCK:
+        RCL_ReportSource(&report, &now_corr);
+        break;
+    }
     
     tx_message->status = htons(STT_SUCCESS);
     tx_message->reply  = htons(RPY_SOURCE_DATA);
diff --git a/conf.c b/conf.c
index 06ff10406a7abc96696349c10b5ad0e5f49e3645..99144131489688da312bf60827fa510230c7a3f7 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -44,6 +44,7 @@
 #include "conf.h"
 #include "ntp_sources.h"
 #include "ntp_core.h"
+#include "refclock.h"
 #include "cmdmon.h"
 #include "srcparams.h"
 #include "logging.h"
@@ -73,6 +74,7 @@ static void parse_peer(const char *);
 static void parse_acquisitionport(const char *);
 static void parse_port(const char *);
 static void parse_server(const char *);
+static void parse_refclock(const char *);
 static void parse_local(const char *);
 static void parse_manual(const char *);
 static void parse_initstepslew(const char *);
@@ -187,6 +189,7 @@ typedef struct {
 static const Command commands[] = {
   {"server", 6, parse_server},
   {"peer", 4, parse_peer},
+  {"refclock", 8, parse_refclock},
   {"acquisitionport", 15, parse_acquisitionport},
   {"port", 4, parse_port},
   {"driftfile", 9, parse_driftfile},
@@ -250,6 +253,11 @@ typedef struct {
 static NTP_Source ntp_sources[MAX_NTP_SOURCES];
 static int n_ntp_sources = 0;
 
+#define MAX_RCL_SOURCES 8
+
+static RefclockParameters refclock_sources[MAX_RCL_SOURCES];
+static int n_refclock_sources = 0;
+
 /* ================================================== */
 
 typedef struct _AllowDeny {
@@ -417,6 +425,61 @@ parse_peer(const char *line)
 
 /* ================================================== */
 
+static void
+parse_refclock(const char *line)
+{
+  int i, n, param, poll;
+  unsigned long ref_id;
+  double offset;
+  char name[5], cmd[10 + 1];
+  unsigned char ref[5];
+
+  i = n_refclock_sources;
+  if (i >= MAX_RCL_SOURCES)
+    return;
+
+  poll = 4;
+  offset = 0.0;
+  ref_id = 0;
+
+  if (sscanf(line, "%4s %d%n", name, &param, &n) != 2) {
+    LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name and parameter at line %d", line_number);
+    return;
+  }
+
+  line += n;
+
+  while (sscanf(line, "%10s%n", cmd, &n) == 1) {
+    line += n;
+    if (!strncasecmp(cmd, "refid", 5)) {
+      if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
+        break;
+      ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
+    } else if (!strncasecmp(cmd, "poll", 4)) {
+      if (sscanf(line, "%d%n", &poll, &n) != 1) {
+        break;
+      }
+    } else if (!strncasecmp(cmd, "offset", 6)) {
+      if (sscanf(line, "%lf%n", &offset, &n) != 1)
+        break;
+    } else {
+      LOG(LOGS_WARN, LOGF_Configure, "Unknown refclock parameter %s at line %d", cmd, line_number);
+      break;
+    }
+    line += n;
+  }
+
+  strncpy(refclock_sources[i].driver_name, name, 4);
+  refclock_sources[i].driver_parameter = param;
+  refclock_sources[i].poll = poll;
+  refclock_sources[i].offset = offset;
+  refclock_sources[i].ref_id = ref_id;
+
+  n_refclock_sources++;
+}
+
+/* ================================================== */
+
 static void
 parse_some_port(const char *line, int *portvar)
 {
@@ -1004,6 +1067,17 @@ CNF_AddSources(void) {
 
 /* ================================================== */
 
+void
+CNF_AddRefclocks(void) {
+  int i;
+
+  for (i=0; i<n_refclock_sources; i++) {
+    RCL_AddRefclock(&refclock_sources[i]);
+  }
+}
+
+/* ================================================== */
+
 void
 CNF_AddBroadcasts(void)
 {
diff --git a/conf.h b/conf.h
index fa967aeb25b5f9023e540d256a855fde96366a21..d2dd3613ed925a18b83b84ca5cef34872882a364 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -37,6 +37,7 @@ extern void CNF_ReadFile(const char *filename);
 
 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);
 
index 6e73dbb6abf5c0778c3d506e8fa0b9f343a32f95..8ec9b935323fb99b7ebebdcf094e7063b10ebc04 100644 (file)
--- a/logging.h
+++ b/logging.h
@@ -64,7 +64,8 @@ typedef enum {
   LOGF_SysSolaris,
   LOGF_SysSunOS,
   LOGF_SysWinnt,
-  LOGF_RtcLinux
+  LOGF_RtcLinux,
+  LOGF_Refclock
 } LOG_Facility;
 
 /* Init function */
diff --git a/main.c b/main.c
index 42f44f74d085210c368613e7ee96c7825df82b98..17c1b8b1b52aef340cab5fc7cc200e6b7e7b3f24 100644 (file)
--- a/main.c
+++ b/main.c
@@ -58,6 +58,7 @@
 #include "manual.h"
 #include "version.h"
 #include "rtc.h"
+#include "refclock.h"
 #include "clientlog.h"
 #include "broadcast.h"
 
@@ -103,6 +104,7 @@ MAI_CleanupAndExit(void)
   SRC_Finalise();
   SST_Finalise();
   REF_Finalise();
+  RCL_Finalise();
   RTC_Finalise();
   CAM_Finalise();
   NIO_Finalise();
@@ -145,6 +147,7 @@ post_acquire_hook(void *anything)
   CNF_SetupAccessRestrictions();
 
   RTC_StartMeasurements();
+  RCL_StartRefclocks();
 }
 
 /* ================================================== */
@@ -309,6 +312,7 @@ int main
   NIO_Initialise();
   CAM_Initialise();
   RTC_Initialise();
+  RCL_Initialise();
 
   if (SchedPriority > 0) {
     SYS_SetScheduler(SchedPriority);
index d2f67cb640615aef5928c351d8eef8ce85085df6..4a33f72253de4040b3f1b72199889548b2b02ed5 100644 (file)
@@ -319,7 +319,7 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
   result->local_poll = params->minpoll;
 
   /* Create a source instance for this NTP source */
-  result->source = SRC_CreateNewInstance(remote_addr->ip_addr); /* Will need extra params eventually */
+  result->source = SRC_CreateNewInstance(remote_addr->ip_addr, SRC_NTP);
 
   result->local_rx.tv_sec = 0;
   result->local_rx.tv_usec = 0;
diff --git a/refclock.c b/refclock.c
new file mode 100644 (file)
index 0000000..372767a
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+  chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Richard P. Curnow  2009
+ * 
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * 
+ **********************************************************************
+
+  =======================================================================
+
+  Routines implementing reference clocks.
+
+  */
+
+#include "refclock.h"
+#include "conf.h"
+#include "local.h"
+#include "util.h"
+#include "sources.h"
+#include "logging.h"
+#include "sched.h"
+
+struct RCL_Instance_Record {
+  RefclockDriver *driver;
+  void *data;
+  int driver_parameter;
+  int poll;
+  int missed_samples;
+  unsigned long ref_id;
+  double offset;
+  SCH_TimeoutID timeout_id;
+  SRC_Instance source;
+};
+
+#define MAX_RCL_SOURCES 8
+
+static struct RCL_Instance_Record refclocks[MAX_RCL_SOURCES];
+static int n_sources = 0;
+
+static void poll_timeout(void *arg);
+
+void
+RCL_Initialise(void)
+{
+  CNF_AddRefclocks();
+}
+
+void
+RCL_Finalise(void)
+{
+  int i;
+
+  for (i = 0; i < n_sources; i++) {
+    RCL_Instance inst = (RCL_Instance)&refclocks[i];
+
+    if (inst->driver->fini)
+      inst->driver->fini(inst);
+  }
+}
+
+int
+RCL_AddRefclock(RefclockParameters *params)
+{
+  RCL_Instance inst = &refclocks[n_sources];
+
+  if (n_sources == MAX_RCL_SOURCES)
+    return 0;
+
+  if (0) {
+  } else {
+    LOG_FATAL(LOGF_Refclock, "unknown refclock driver %s", params->driver_name);
+    return 0;
+  }
+
+  inst->data = NULL;
+  inst->driver_parameter = params->driver_parameter;
+  inst->poll = params->poll;
+  inst->missed_samples = 0;
+  inst->offset = params->offset;
+  inst->timeout_id = -1;
+  inst->source = NULL;
+
+  if (params->ref_id)
+    inst->ref_id = params->ref_id;
+  else {
+    unsigned char ref[5] = { 0, 0, 0, 0, 0 };
+
+    snprintf((char *)ref, 5, "%s%d", params->driver_name, params->driver_parameter);
+    inst->ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
+  }
+
+  if (inst->driver->init)
+    if (!inst->driver->init(inst)) {
+      LOG_FATAL(LOGF_Refclock, "refclock %s initialisation failed", params->driver_name);
+      return 0;
+    }
+
+#if 0
+  LOG(LOGS_INFO, LOGF_Refclock, "refclock added");
+#endif
+  n_sources++;
+
+  return 1;
+}
+
+void
+RCL_StartRefclocks(void)
+{
+  int i;
+
+  for (i = 0; i < n_sources; i++) {
+    RCL_Instance inst = &refclocks[i];
+
+    inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK);
+    if (inst->driver->poll)
+      inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
+  }
+}
+
+void
+RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
+{
+  int i;
+  unsigned long ref_id;
+
+  ref_id = report->ip_addr;
+
+  for (i = 0; i < n_sources; i++) {
+    RCL_Instance inst = &refclocks[i];
+    if (inst->ref_id == ref_id) {
+      report->poll = inst->poll;
+      report->mode = RPT_LOCAL_REFERENCE;
+      break;
+    }
+  }
+}
+
+void
+RCL_SetDriverData(RCL_Instance instance, void *data)
+{
+  instance->data = data;
+}
+
+void *
+RCL_GetDriverData(RCL_Instance instance)
+{
+  return instance->data;
+}
+
+int
+RCL_GetDriverParameter(RCL_Instance instance)
+{
+  return instance->driver_parameter;
+}
+
+int
+RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status)
+{
+  double correction;
+  struct timeval cooked_time;
+  SRC_Instance inst = instance->source;
+
+#if 0
+  LOG(LOGS_INFO, LOGF_Refclock, "refclock offset: %f", offset);
+#endif
+
+  SRC_SetReachable(inst);
+
+  correction = LCL_GetOffsetCorrection(sample_time);
+  UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
+
+  SRC_AccumulateSample(inst, &cooked_time, offset - correction + instance->offset,
+      1e-6, 0.0, 0.0, 0.0, 0, leap_status);
+
+  instance->missed_samples = 0;
+
+  return 1;
+}
+
+static void
+poll_timeout(void *arg)
+{
+  double next;
+
+  RCL_Instance inst = (RCL_Instance)arg;
+
+  inst->missed_samples++;
+  inst->driver->poll(inst);
+  
+  if (inst->missed_samples > 9)
+    SRC_UnsetReachable(inst->source);
+
+  if (inst->poll >= 0)
+    next = 1 << inst->poll;
+  else
+    next = 1.0 / (1 << -inst->poll);
+
+  inst->timeout_id = SCH_AddTimeoutByDelay(next, poll_timeout, arg);
+}
+
diff --git a/refclock.h b/refclock.h
new file mode 100644 (file)
index 0000000..4260616
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+  chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Richard P. Curnow  2009
+ * 
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * 
+ **********************************************************************
+
+  =======================================================================
+
+  Header file for refclocks.
+
+  */
+
+#ifndef GOT_REFCLOCK_H
+#define GOT_REFCLOCK_H
+
+#include "srcparams.h"
+#include "sources.h"
+
+typedef struct {
+  char driver_name[4];
+  int driver_parameter;
+  int poll;
+  unsigned long ref_id;
+  double offset;
+} RefclockParameters;
+
+typedef struct RCL_Instance_Record *RCL_Instance;
+
+typedef struct {
+  int (*init)(RCL_Instance instance);
+  void (*fini)(RCL_Instance instance);
+  int (*poll)(RCL_Instance instance);
+} RefclockDriver;
+
+extern void RCL_Initialise(void);
+extern void RCL_Finalise(void);
+extern int RCL_AddRefclock(RefclockParameters *params);
+extern void RCL_StartRefclocks(void);
+extern void RCL_StartRefclocks(void);
+extern void RCL_ReportSource(RPT_SourceReport *report, struct timeval *now);
+
+/* functions used by drivers */
+extern void RCL_SetDriverData(RCL_Instance instance, void *data);
+extern void *RCL_GetDriverData(RCL_Instance instance);
+extern int RCL_GetDriverParameter(RCL_Instance instance);
+extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
+
+#endif
index d90eb99727ab65beeea8459fe6e3ee00d237b72b..db8795b6f2ca8e43298a0b63249263798427f596 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -96,6 +96,9 @@ struct SRC_Instance_Record {
   /* Flag indicating the status of the source */
   SRC_Status status;
 
+  /* Type of the source */
+  SRC_Type type;
+
   struct SelectInfo sel_info;
 };
 
@@ -126,6 +129,8 @@ static int selected_source_index; /* Which source index is currently
 static void
 slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
              double doffset, int is_step_change, void *anything);
+static char *
+source_to_string(SRC_Instance inst);
 
 /* ================================================== */
 /* Initialisation function */
@@ -155,7 +160,7 @@ void SRC_Finalise(void)
 /* Function to create a new instance.  This would be called by one of
    the individual source-type instance creation routines. */
 
-SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
+SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
 {
   SRC_Instance result;
 
@@ -186,6 +191,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
   result->ref_id = ref_id;
   result->reachable = 0;
   result->status = SRC_BAD_STATS;
+  result->type = type;
 
   n_sources++;
 
@@ -280,7 +286,7 @@ void SRC_AccumulateSample
 
 #ifdef TRACEON
   LOG(LOGS_INFO, LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
-      UTI_IPToDottedQuad(inst->ref_id), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
+      source_to_string(inst), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
 #endif
 
   /* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
@@ -301,7 +307,7 @@ SRC_SetReachable(SRC_Instance inst)
   inst->reachable = 1;
 
 #ifdef TRACEON
-  LOG(LOGS_INFO, LOGF_Sources, "%s", UTI_IPToDottedQuad(inst->ref_id));
+  LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
 #endif
 
   /* Don't do selection at this point, though - that will come about
@@ -316,7 +322,7 @@ SRC_UnsetReachable(SRC_Instance inst)
   inst->reachable = 0;
 
 #ifdef TRACEON
-  LOG(LOGS_INFO, LOGF_Sources, "%s%s", UTI_IPToDottedQuad(inst->ref_id),
+  LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
       (inst->index == selected_source_index) ? "(REF)":"");
 #endif
 
@@ -349,6 +355,22 @@ compare_sort_elements(const void *a, const void *b)
   }
 }
 
+/* ================================================== */
+
+static char *
+source_to_string(SRC_Instance inst)
+{
+  switch (inst->type) {
+    case SRC_NTP:
+      return UTI_IPToDottedQuad(inst->ref_id);
+    case SRC_REFCLOCK:
+      return UTI_RefidToString(inst->ref_id);
+    default:
+      CROAK("Unknown source type");
+  }
+  return NULL;
+}
+
 /* ================================================== */
 /* This function selects the current reference from amongst the pool
    of sources we are holding. 
@@ -418,7 +440,7 @@ SRC_SelectSource(unsigned long match_addr)
 
 #if 0
       LOG(LOGS_INFO, LOGF_Sources, "%s off=%f dist=%f lo=%f hi=%f",
-          UTI_IPToDottedQuad(sources[i]->ref_id),
+          source_to_string(sources[i]),
           si->best_offset, si->root_distance,
           si->lo_limit, si->hi_limit);
 #endif
@@ -491,7 +513,7 @@ SRC_SelectSource(unsigned long match_addr)
     for (i=0; i<n_endpoints; i++) {
 #if 0
       LOG(LOGS_INFO, LOGF_Sources, "i=%d t=%f tag=%d addr=%s", i, sort_list[i].offset, sort_list[i].tag,
-          UTI_IPToDottedQuad(sources[sort_list[i].index]->ref_id));
+          source_to_string(sources[sort_list[i].index]));
 #endif
       switch(sort_list[i].tag) {
         case LOW:
@@ -565,12 +587,12 @@ SRC_SelectSource(unsigned long match_addr)
 
             sel_sources[n_sel_sources++] = i;
 #if 0
-            LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is valid", i, UTI_IPToDottedQuad(sources[i]->ref_id));
+            LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is valid", i, source_to_string(sources[i]));
 #endif
           } else {
             sources[i]->status = SRC_FALSETICKER;
 #if 0
-            LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is a falseticker", i, UTI_IPToDottedQuad(sources[i]->ref_id));
+            LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is a falseticker", i, source_to_string(sources[i]));
 #endif
           }
         }
@@ -603,7 +625,7 @@ SRC_SelectSource(unsigned long match_addr)
           sel_sources[i] = INVALID_SOURCE;
           sources[index]->status = SRC_JITTERY;
 #if 0
-          LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s has too much variance", i, UTI_IPToDottedQuad(sources[i]->ref_id));
+          LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s has too much variance", i, source_to_string(sources[i]));
 #endif
         }
       }
@@ -658,7 +680,7 @@ SRC_SelectSource(unsigned long match_addr)
 
           selected_source_index = min_distance_index;
           LOG(LOGS_INFO, LOGF_Sources, "Selected source %s",
-              UTI_IPToDottedQuad(sources[selected_source_index]->ref_id));
+                source_to_string(sources[selected_source_index]));
                                  
 
 #if 0
@@ -935,6 +957,16 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
 
 /* ================================================== */
 
+SRC_Type
+SRC_GetType(int index)
+{
+  if ((index >= n_sources) || (index < 0))
+    return -1;
+  return sources[index]->type;
+}
+
+/* ================================================== */
+
 SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
 {
   SRC_Skew_Direction result = SRC_Skew_Nochange;
index c895cacfa7192421663c6084ee854585a577f42e..3afd80636a7f77860c780019cc29af1234c4121d 100644 (file)
--- a/sources.h
+++ b/sources.h
@@ -50,10 +50,15 @@ extern void SRC_Initialise(void);
 /* Finalisation function */
 extern void SRC_Finalise(void);
 
+typedef enum {
+  SRC_NTP,                      /* NTP client/peer */
+  SRC_REFCLOCK                  /* Rerefence clock */
+} SRC_Type;
+
 /* Function to create a new instance.  This would be called by one of
    the individual source-type instance creation routines. */
 
-extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id);
+extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type);
 
 /* Function to get rid of a source when it is being unconfigured.
    This may cause the current reference source to be reselected, if this
@@ -143,6 +148,8 @@ extern int SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval
 
 extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report);
 
+extern SRC_Type SRC_GetType(int index);
+
 typedef enum {
   SRC_Skew_Decrease,
   SRC_Skew_Nochange,
diff --git a/util.c b/util.c
index d506ffdaaa44495c2e26e70526689d251b5d1a9f..30cbd48c3bfb3eaf645f05757b50d0e8284e9f7e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -247,6 +247,22 @@ UTI_TimestampToString(NTP_int64 *ts)
 
 /* ================================================== */
 
+char *
+UTI_RefidToString(unsigned long ref_id)
+{
+  unsigned int a, b, c, d;
+  char *result;
+  a = (ref_id>>24) & 0xff;
+  b = (ref_id>>16) & 0xff;
+  c = (ref_id>> 8) & 0xff;
+  d = (ref_id>> 0) & 0xff;
+  result = NEXT_BUFFER;
+  snprintf(result, BUFFER_LENGTH, "%c%c%c%c", a, b, c, d);
+  return result;
+}
+
+/* ================================================== */
+
 char *
 UTI_IPToDottedQuad(unsigned long ip)
 {
diff --git a/util.h b/util.h
index 7ab9bb83d0952085746c88726f45180a389aba6a..7ec7d2cf4b2a371c03448b63f365e03221f88c75 100644 (file)
--- a/util.h
+++ b/util.h
@@ -72,6 +72,9 @@ extern char *UTI_TimevalToString(struct timeval *tv);
    diagnostic display */
 extern char *UTI_TimestampToString(NTP_int64 *ts);
 
+/* Convert ref_id into a temporary string, for diagnostics */
+extern char *UTI_RefidToString(unsigned long ref_id);
+
 /* Convert an IP address to dotted quad notation, for diagnostics */
 extern char *UTI_IPToDottedQuad(unsigned long ip);