[chrony-dev] [PATCH v2 2/2] refclock: Add a new "tai" option

[ Thread Index | Date Index | More chrony.tuxfamily.org/chrony-dev Archives ]


This option is for indicating to chronyd that the reference clock is
kept in TAI and that chrony should attempt to convert from TAI to UTC by
using the timezone configured by the "leapsectz" directive.
---
 conf.c               |  7 ++++++-
 doc/chrony.conf.adoc |  9 +++++++++
 refclock.c           | 20 ++++++++++++++++++++
 refclock.h           |  1 +
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/conf.c b/conf.c
index 363e8b8..3859d74 100644
--- a/conf.c
+++ b/conf.c
@@ -681,7 +681,7 @@ static void
 parse_refclock(char *line)
 {
   int n, poll, dpoll, filter_length, pps_rate, min_samples, max_samples, sel_options;
-  int max_lock_age, pps_forced, stratum;
+  int max_lock_age, pps_forced, stratum, tai;
   uint32_t ref_id, lock_ref_id;
   double offset, delay, precision, max_dispersion, pulse_width;
   char *p, *cmd, *name, *param;
@@ -705,6 +705,7 @@ parse_refclock(char *line)
   max_lock_age = 2;
   lock_ref_id = 0;
   stratum = 0;
+  tai = 0;
 
   if (!*line) {
     command_parse_error();
@@ -779,6 +780,9 @@ parse_refclock(char *line)
       if (sscanf(line, "%d%n", &stratum, &n) != 1 ||
           stratum >= NTP_MAX_STRATUM || stratum < 0)
         break;
+    } else if (!strcasecmp(cmd, "tai")) {
+      n = 0;
+      tai = 1;
     } else if (!strcasecmp(cmd, "width")) {
       if (sscanf(line, "%lf%n", &pulse_width, &n) != 1)
         break;
@@ -817,6 +821,7 @@ parse_refclock(char *line)
   refclock->max_samples = max_samples;
   refclock->sel_options = sel_options;
   refclock->stratum = stratum;
+  refclock->tai = tai;
   refclock->offset = offset;
   refclock->delay = delay;
   refclock->precision = precision;
diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc
index 82c56c1..b79e2b6 100644
--- a/doc/chrony.conf.adoc
+++ b/doc/chrony.conf.adoc
@@ -555,6 +555,15 @@ Set the minimum number of samples kept for this source. This overrides the
 *maxsamples* _samples_:::
 Set the maximum number of samples kept for this source. This overrides the
 <<maxsamples,*maxsamples*>> directive.
+*tai* _tai_:::
+This option can be set to indicate that the time on the given
+reference clock is kept in TAI and that chrony should attempt to apply
+the current TAI-UTC offset to samples taken from this refclock.  To
+use this, the *leapsectz* directive must be used as chrony uses the
+timezone files to compute the current TAI-UTC offset.  If the
+*leapsectz* directive is not in use, a fatal error will be logged.
+This option does not make sense if the given refclock is only being
+used for PPS input.
 
 [[manual]]*manual*::
 The *manual* directive enables support at run-time for the
diff --git a/refclock.c b/refclock.c
index bcb3064..9a2bf19 100644
--- a/refclock.c
+++ b/refclock.c
@@ -80,6 +80,7 @@ struct RCL_Instance_Record {
   int pps_active;
   int max_lock_age;
   int stratum;
+  int tai;
   struct MedianFilter filter;
   uint32_t ref_id;
   uint32_t lock_ref;
@@ -190,6 +191,10 @@ RCL_AddRefclock(RefclockParameters *params)
     return 0;
   }
 
+  if (params->tai && !CNF_GetLeapSecTimezone()) {
+    LOG_FATAL("refclock tai option requires leapsectz");
+  }
+
   inst->data = NULL;
   inst->driver_parameter = params->driver_parameter;
   inst->driver_parameter_length = 0;
@@ -202,6 +207,7 @@ RCL_AddRefclock(RefclockParameters *params)
   inst->pps_active = 0;
   inst->max_lock_age = params->max_lock_age;
   inst->stratum = params->stratum;
+  inst->tai = params->tai;
   inst->lock_ref = params->lock_ref_id;
   inst->offset = params->offset;
   inst->delay = params->delay;
@@ -362,6 +368,7 @@ int
 RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap)
 {
   double correction, dispersion;
+  int tai_offset;
   struct timespec cooked_time;
 
   if (instance->pps_forced)
@@ -387,6 +394,19 @@ RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset
       return 0;
   }
 
+  if (instance->tai) {
+    tai_offset = REF_GetTaiOffset(sample_time);
+    if (!tai_offset) {
+      DEBUG_LOG("refclock sample ignored unknown TAI offset");
+      return 0;
+    }
+
+    /* REF_GetTaiOffset returns the number of leap seconds that have
+       been inserted into UTC.  To get from TAI to UTC, we have to
+       remove those seconds from the sample */
+    offset -= tai_offset;
+  }
+
   filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
   instance->pps_active = 0;
 
diff --git a/refclock.h b/refclock.h
index 7508f3d..724f620 100644
--- a/refclock.h
+++ b/refclock.h
@@ -44,6 +44,7 @@ typedef struct {
   int sel_options;
   int max_lock_age;
   int stratum;
+  int tai;
   uint32_t ref_id;
   uint32_t lock_ref_id;
   double offset;
-- 
2.13.5


-- 
To unsubscribe email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "unsubscribe" in the subject.
For help email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "help" in the subject.
Trouble?  Email listmaster@xxxxxxxxxxxxxxxxxxxx.


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/