]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sources: add option to limit selection by root distance
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Aug 2015 14:27:36 +0000 (16:27 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Aug 2015 15:35:34 +0000 (17:35 +0200)
Add maxdistance directive to set the maximum root distance the sources
are allowed to have to be selected. This is useful to reject NTPv4
sources that are no longer synchronized and report large dispersion.
The default value is 3 seconds.

chrony.texi.in
conf.c
conf.h
sources.c
test/simulation/114-presend

index d44399ad4bfd24e5dc315544c714e9a1b9900871..50cccfc3f27ea00585ba032d7ac65e50b416ceed 100644 (file)
@@ -1152,6 +1152,7 @@ the configuration file is ignored.
 * manual directive::            Allow manual entry using chronyc's settime cmd
 * maxchange directive::         Set maximum allowed offset
 * maxclockerror directive::     Set maximum frequency error of local clock
+* maxdistance directive::       Set maximum allowed distance of sources
 * maxsamples directive::        Set maximum number of samples per source
 * maxslewrate directive::       Set maximum slew rate
 * maxupdateskew directive::     Stop bad estimates upsetting machine clock
@@ -2441,6 +2442,23 @@ Typical values for <error-in-ppm> might be 10 for a low quality clock
 to 0.1 for a high quality clock using a temperature compensated
 crystal oscillator.
 @c }}}
+@c {{{ maxdistance
+@node maxdistance directive
+@subsection maxdistance
+The @code{maxdistance} directive sets the maximum allowed root distance of the
+sources to not be rejected by the source selection algorithm.  The distance
+includes the accumulated dispersion, which may be large when the source is no
+longer synchronised, and half of the total round-trip delay to the primary
+source.
+
+By default, the maximum distance is 3 seconds.
+
+The syntax is
+
+@example
+maxdistance <seconds>
+@end example
+@c }}}
 @c {{{ maxsamples
 @node maxsamples directive
 @subsection maxsamples
diff --git a/conf.c b/conf.c
index 0d58b0eecb8456edec314d9f1cb74c5ebef0ea23..25a5705ecfef837bd2e65969e7a52b324abca3de 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -90,6 +90,7 @@ static double correction_time_ratio = 3.0;
 static double max_clock_error = 1.0; /* in ppm */
 static double max_slew_rate = 1e6 / 12.0; /* in ppm */
 
+static double max_distance = 3.0;
 static double reselect_distance = 1e-4;
 static double stratum_weight = 1e-3;
 static double combine_limit = 3.0;
@@ -477,6 +478,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
     parse_maxchange(p);
   } else if (!strcasecmp(command, "maxclockerror")) {
     parse_double(p, &max_clock_error);
+  } else if (!strcasecmp(command, "maxdistance")) {
+    parse_double(p, &max_distance);
   } else if (!strcasecmp(command, "maxsamples")) {
     parse_int(p, &max_samples);
   } else if (!strcasecmp(command, "maxslewrate")) {
@@ -1524,6 +1527,14 @@ CNF_GetMaxSlewRate(void)
 
 /* ================================================== */
 
+double
+CNF_GetMaxDistance(void)
+{
+  return max_distance;
+}
+
+/* ================================================== */
+
 double
 CNF_GetReselectDistance(void)
 {
diff --git a/conf.h b/conf.h
index d8e7cca33e9f512c2a1722bb403bef9a7157f34d..75f2764f8cf2d5606941430a482ac6c2781a9685 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -86,6 +86,7 @@ extern double CNF_GetMaxClockError(void);
 extern double CNF_GetCorrectionTimeRatio(void);
 extern double CNF_GetMaxSlewRate(void);
 
+extern double CNF_GetMaxDistance(void);
 extern double CNF_GetReselectDistance(void);
 extern double CNF_GetStratumWeight(void);
 extern double CNF_GetCombineLimit(void);
index 4ddee254efb66feb93a69acebcaf3cea2cdb1bed..017f3bc9b1af8ad66a4477a77a79908927f1aa58 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -70,6 +70,7 @@ typedef enum {
   SRC_OK,               /* OK so far, not a final status! */
   SRC_UNSELECTABLE,     /* Has noselect option set */
   SRC_BAD_STATS,        /* Doesn't have valid stats data */
+  SRC_BAD_DISTANCE,     /* Has root distance longer than allowed maximum */
   SRC_WAITS_STATS,      /* Others have bad stats, selection postponed */
   SRC_STALE,            /* Has older samples than others */
   SRC_FALSETICKER,      /* Doesn't agree with others */
@@ -155,6 +156,7 @@ static int selected_source_index; /* Which source index is currently
 /* Number of updates needed to reset the distant status */
 #define DISTANT_PENALTY 32
 
+static double max_distance;
 static double reselect_distance;
 static double stratum_weight;
 static double combine_limit;
@@ -179,6 +181,7 @@ void SRC_Initialise(void) {
   n_sources = 0;
   max_n_sources = 0;
   selected_source_index = INVALID_SOURCE;
+  max_distance = CNF_GetMaxDistance();
   reselect_distance = CNF_GetReselectDistance();
   stratum_weight = CNF_GetStratumWeight();
   combine_limit = CNF_GetCombineLimit();
@@ -653,6 +656,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
       continue;
     }
 
+    /* Require the root distance to be below the allowed maximum */
+    if (si->root_distance > max_distance) {
+      sources[i]->status = SRC_BAD_DISTANCE;
+      continue;
+    }
+
     sources[i]->status = SRC_OK; /* For now */
 
     if (sources[i]->reachability && max_reach_sample_ago < first_sample_ago)
@@ -1216,6 +1225,7 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
     switch (src->status) {
       case SRC_UNSELECTABLE:
       case SRC_BAD_STATS:
+      case SRC_BAD_DISTANCE:
       case SRC_STALE:
       case SRC_WAITS_STATS:
         report->state = RPT_UNREACH;
index e9fe66e390bb067c6c7a47b2d3b6ab6f1d055b4f..88725256bcab94d5f1b6d8b0d6d7ed208f7a7a1d 100755 (executable)
@@ -6,6 +6,7 @@ test_start "presend option"
 min_sync_time=140
 max_sync_time=260
 client_server_options="presend 6 maxdelay 16"
+client_conf="maxdistance 10"
 
 run_test || test_fail
 check_chronyd_exit || test_fail