]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Make importance of stratum in source selection configurable
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Jan 2011 16:22:00 +0000 (17:22 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Jan 2011 16:40:46 +0000 (17:40 +0100)
Instead of always selecting the source with minimum stratum, add weighted
stratum to the distance when comparing selectable sources. The weight
can be configured with new stratumweight directive and can be set to
zero to ignore stratum completely, by default 1.0.

chrony.texi
conf.c
conf.h
sources.c

index d498e7c236110084c6f6204521754e831ea8834b..f3502a6219f550ee0aa34bab778315747886a473 100644 (file)
@@ -1206,6 +1206,7 @@ directives can occur in any order in the file.
 * rtcsync directive::           Specify that RTC should be automatically synchronised by kernel
 * server directive::            Specify an NTP server
 * sched_priority directive::    Require real-time scheduling and specify a priority for it.
+* stratumweight directive::     Specify how important is stratum when selecting source
 * lock_all directive::          Require that chronyd be locked into RAM. 
 * tempcomp directive::          Specify temperature sensor and compensation coefficients
 
@@ -2543,6 +2544,26 @@ resource requirements are modest, but it should result in lower and
 more consistent latency since Chronyd will not need to wait for the
 scheduler to get around to running it.  You should not use this unless
 you really need it.  The sched_setscheduler man page has more details.
+@c }}}
+@c {{{ stratumweight
+@node stratumweight directive
+@subsection stratumweight
+
+The @code{stratumweight} directive sets how much distance should be added
+per stratum to the synchronisation distance when @code{chronyd} selects
+the synchronisation source from available sources.
+
+The syntax is
+
+@example
+stratumweight <dist-in-seconds>
+@end example
+
+By default, it is 1 second.  This usually means that sources with lower stratum
+will be preferred to sources with higher stratum even when their distance is
+significantly worse.  Setting @code{stratumweight} to 0 makes @code{chronyd}
+ignore stratum when selecting the source.
+
 @c }}}
 @c {{{ lock_all
 @node lock_all directive
diff --git a/conf.c b/conf.c
index 0715219aa963c2aad2fda253feabe6f986a27827..f06940dcb176ac34c78e128a9c401f733821c8b5 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -79,6 +79,7 @@ static void parse_logdir(const char *);
 static void parse_maxupdateskew(const char *);
 static void parse_maxclockerror(const char *);
 static void parse_reselectdist(const char *);
+static void parse_stratumweight(const char *);
 static void parse_peer(const char *);
 static void parse_acquisitionport(const char *);
 static void parse_port(const char *);
@@ -125,6 +126,7 @@ static double max_update_skew = 1000.0;
 static double max_clock_error = 10; /* in ppm */
 
 static double reselect_distance = 1e-4;
+static double stratum_weight = 1.0;
 
 static int cmd_port = -1;
 
@@ -262,6 +264,7 @@ static const Command commands[] = {
   {"broadcast", 9, parse_broadcast},
   {"tempcomp", 8, parse_tempcomp},
   {"reselectdist", 12, parse_reselectdist},
+  {"stratumweight", 13, parse_stratumweight},
   {"linux_hz", 8, parse_linux_hz},
   {"linux_freq_scale", 16, parse_linux_freq_scale},
   {"sched_priority", 14, parse_sched_priority},
@@ -623,6 +626,16 @@ parse_reselectdist(const char *line)
 
 /* ================================================== */
 
+static void
+parse_stratumweight(const char *line)
+{
+  if (sscanf(line, "%lf", &stratum_weight) != 1) {
+    LOG(LOGS_WARN, LOGF_Configure, "Could not read stratum weight at line %d in file", line_number);
+  }
+}
+
+/* ================================================== */
+
 static void
 parse_driftfile(const char *line)
 {
@@ -1453,6 +1466,14 @@ CNF_GetReselectDistance(void)
 
 /* ================================================== */
 
+double
+CNF_GetStratumWeight(void)
+{
+  return stratum_weight;
+}
+
+/* ================================================== */
+
 int
 CNF_GetManualEnabled(void)
 {
diff --git a/conf.h b/conf.h
index b1fb77631891086d542e3e87519ced0aa830343b..f4b8248c7e37f12831c25823aec743d3c6e1d40d 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -78,7 +78,10 @@ extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
 /* Value returned in ppm, as read from file */
 extern double CNF_GetMaxUpdateSkew(void);
 extern double CNF_GetMaxClockError(void);
+
 extern double CNF_GetReselectDistance(void);
+extern double CNF_GetStratumWeight(void);
+
 extern int CNF_AllowLocalReference(int *stratum);
 
 extern void CNF_SetupAccessRestrictions(void);
index 14e1372ace9be658216c6ad1ec70d172d105cbeb..50a5470f0c3b91ba6b332f9f1649f8ea7509c147 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -139,6 +139,7 @@ static int selected_source_index; /* Which source index is currently
 #define SCORE_LIMIT 10.0
 
 static double reselect_distance;
+static double stratum_weight;
 
 /* ================================================== */
 /* Forward prototype */
@@ -160,6 +161,7 @@ void SRC_Initialise(void) {
   max_n_sources = 0;
   selected_source_index = INVALID_SOURCE;
   reselect_distance = CNF_GetReselectDistance();
+  stratum_weight = CNF_GetStratumWeight();
   initialised = 1;
 
   LCL_AddParameterChangeHandler(slew_sources, NULL);
@@ -428,7 +430,7 @@ SRC_SelectSource(unsigned long match_addr)
   double best_lo, best_hi;
   int depth, best_depth;
   int n_sel_sources;
-  double distance;
+  double distance, sel_src_distance;
   int stratum, min_stratum;
   struct SelectInfo *si;
   double total_root_dispersion;
@@ -755,6 +757,12 @@ SRC_SelectSource(unsigned long match_addr)
 
         max_score_index = INVALID_SOURCE;
         max_score = 0.0;
+        sel_src_distance = 0.0;
+
+        if (selected_source_index != INVALID_SOURCE) {
+          sel_src_distance = sources[selected_source_index]->sel_info.root_distance +
+            (sources[selected_source_index]->sel_info.stratum - min_stratum) * stratum_weight;
+        }
 
         for (i = 0; i < n_sources; i++) {
 
@@ -764,13 +772,8 @@ SRC_SelectSource(unsigned long match_addr)
             continue;
           }
             
-          /* And for sources with stratum higher than the minimum */
-          if (sources[i]->sel_info.stratum > min_stratum) {
-            sources[i]->sel_score = 1.0;
-            continue;
-          }
-
-          distance = sources[i]->sel_info.root_distance + reselect_distance;
+          distance = sources[i]->sel_info.root_distance + reselect_distance +
+            (sources[i]->sel_info.stratum - min_stratum) * stratum_weight;
 
           if (selected_source_index != INVALID_SOURCE) {
 
@@ -779,8 +782,7 @@ SRC_SelectSource(unsigned long match_addr)
             if (sources[i]->ref_id == match_addr ||
                 sources[selected_source_index]->ref_id == match_addr) {
 
-              sources[i]->sel_score *=
-                sources[selected_source_index]->sel_info.root_distance / distance;
+              sources[i]->sel_score *= sel_src_distance / distance;
 
               if (sources[i]->sel_score < 1.0)
                 sources[i]->sel_score = 1.0;
@@ -808,12 +810,11 @@ SRC_SelectSource(unsigned long match_addr)
 
         assert(max_score_index != INVALID_SOURCE);
 
-        /* Does the current source have this stratum, is it still a survivor
+        /* Is the current source still a survivor
            and no other source has reached the score limit? */
 
         if ((selected_source_index == INVALID_SOURCE) ||
             (sources[selected_source_index]->status != SRC_SELECTABLE) ||
-            (sources[selected_source_index]->sel_info.stratum > min_stratum) ||
             (max_score_index != selected_source_index && max_score > SCORE_LIMIT)) {
           
           /* We have to elect a new synchronisation source */