]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sources: add trust option
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 7 Jan 2016 10:12:55 +0000 (11:12 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 7 Jan 2016 15:20:27 +0000 (16:20 +0100)
Assume time from a source that is specified with the trust option is
always true.  It can't be rejected as falseticker in the source
selection if sources that are specified without this option don't agree
with it.

candm.h
chrony.texi.in
client.c
cmdmon.c
cmdparse.c
conf.c
sources.c
srcparams.h

diff --git a/candm.h b/candm.h
index a740aa22d04aacb6cb3efdf770491ed758676b52..5b7c8d285223274369e54e2b08d0f199401471de 100644 (file)
--- a/candm.h
+++ b/candm.h
@@ -243,6 +243,7 @@ typedef struct {
 #define REQ_ADDSRC_IBURST 0x4
 #define REQ_ADDSRC_PREFER 0x8
 #define REQ_ADDSRC_NOSELECT 0x10
+#define REQ_ADDSRC_TRUST 0x20
 
 typedef struct {
   IPAddr ip_addr;
@@ -478,6 +479,7 @@ typedef struct {
 
 #define RPY_SD_FLAG_NOSELECT 0x1
 #define RPY_SD_FLAG_PREFER 0x2
+#define RPY_SD_FLAG_TRUST 0x4
 
 typedef struct {
   IPAddr ip_addr;
index 59caf74121d5a9c90ead7d79936bd0bbb454635b..73f90234242b47c88e977b4eac5ead41e91dafac 100644 (file)
@@ -2720,6 +2720,10 @@ Prefer this source over sources without prefer option.
 @item noselect
 Never select this source.  This is useful for monitoring or with sources
 which are not very accurate, but are locked with a PPS refclock.
+@item trust
+Assume time from this source is always true.  It can't be rejected as a
+falseticker in the source selection if sources that are specified without this
+option don't agree with it.
 @item minsamples
 Set the minimum number of samples kept for this source.  This overrides the
 @code{minsamples} directive (@pxref{minsamples directive}).
@@ -3024,6 +3028,11 @@ Prefer this source over sources without prefer option.
 @item noselect
 Never select this source.  This is particularly useful for monitoring.
 
+@item trust
+Assume time from this source is always true.  It can't be rejected as a
+falseticker in the source selection if sources that are specified without this
+option don't agree with it.
+
 @item minsamples
 Set the minimum number of samples kept for this source.  This overrides the
 @code{minsamples} directive (@pxref{minsamples directive}).
index d19ec849e1a1fad0d35dafe224763e4122e7aa9c..aa7271a36253291c97f6fab992ffc5a0c5f008d8 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1118,7 +1118,8 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
           (data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) |
           (data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
           (data.params.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) |
-          (data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0));
+          (data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) |
+          (data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0));
       result = 1;
 
       break;
index bf22de95ff829e0569c7c7830e39c2ed238f37d8..ae2a10c255d6a8e6ed20a4f459999b49742fe254 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -663,7 +663,8 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
     }
     tx_message->data.source_data.flags =
                   htons((report.sel_options & SRC_SELECT_PREFER ? RPY_SD_FLAG_PREFER : 0) |
-                        (report.sel_options & SRC_SELECT_NOSELECT ? RPY_SD_FLAG_NOSELECT : 0));
+                        (report.sel_options & SRC_SELECT_NOSELECT ? RPY_SD_FLAG_NOSELECT : 0) |
+                        (report.sel_options & SRC_SELECT_TRUST ? RPY_SD_FLAG_TRUST : 0));
     tx_message->data.source_data.reachability = htons(report.reachability);
     tx_message->data.source_data.since_sample = htonl(report.latest_meas_ago);
     tx_message->data.source_data.orig_latest_meas = UTI_FloatHostToNetwork(report.orig_latest_meas);
@@ -758,7 +759,8 @@ handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_m
   params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
   params.sel_options =
     (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SELECT_PREFER : 0) |
-    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0);
+    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0) |
+    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_TRUST ? SRC_SELECT_TRUST : 0);
   params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
   params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
 
index 51a93641c5ff616c14abfef0621110461cc55105..976e69650ce19d9723826d0fc736b821c1bd79fe 100644 (file)
@@ -170,6 +170,9 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
         } else if (!strcasecmp(cmd, "prefer")) {
           src->params.sel_options |= SRC_SELECT_PREFER;
         
+        } else if (!strcasecmp(cmd, "trust")) {
+          src->params.sel_options |= SRC_SELECT_TRUST;
+
         } else if (!strcasecmp(cmd, "version")) {
           if (sscanf(line, "%d%n", &src->params.version, &n) != 1) {
             result = CPS_BadVersion;
diff --git a/conf.c b/conf.c
index c5564766e23f4d08032889d70f5f4e5ff79e9b6d..8260de622cf4472b69d402f1786a3b9b1f7cf65b 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -743,6 +743,9 @@ parse_refclock(char *line)
     } else if (!strcasecmp(cmd, "prefer")) {
       n = 0;
       sel_options |= SRC_SELECT_PREFER;
+    } else if (!strcasecmp(cmd, "trust")) {
+      n = 0;
+      sel_options |= SRC_SELECT_TRUST;
     } else {
       other_parse_error("Invalid refclock option");
       return;
index c67cf51e482df31dfcff60c4bbeaa5890fa4551c..2e48c5fc38836c1d2f8b2509e483f788c3527783 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -603,7 +603,8 @@ SRC_SelectSource(SRC_Instance updated_inst)
   struct timeval now, ref_time;
   int i, j, j1, j2, index, sel_prefer, n_endpoints, n_sel_sources;
   int n_badstats_sources, max_sel_reach, max_badstat_reach;
-  int depth, best_depth, combined, stratum, min_stratum, max_score_index;
+  int depth, best_depth, trust_depth, best_trust_depth;
+  int combined, stratum, min_stratum, max_score_index;
   double src_offset, src_offset_sd, src_frequency, src_skew;
   double src_root_delay, src_root_dispersion;
   double best_lo, best_hi, distance, sel_src_distance, max_score;
@@ -751,8 +752,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
      The first case is just bad luck - we need extra sources to
      detect the falseticker, so just make an arbitrary choice based
      on stratum & stability etc.
+
+     Intervals from sources specified with the trust option have higher
+     priority in the search.
      */
 
+  trust_depth = best_trust_depth = 0;
   depth = best_depth = 0;
   best_lo = best_hi = 0.0;
 
@@ -760,14 +765,20 @@ SRC_SelectSource(SRC_Instance updated_inst)
     switch (sort_list[i].tag) {
       case LOW:
         depth++;
-        if (depth > best_depth) {
+        if (sources[sort_list[i].index]->sel_options & SRC_SELECT_TRUST)
+          trust_depth++;
+        if (trust_depth > best_trust_depth ||
+            (trust_depth == best_trust_depth && depth > best_depth)) {
+          best_trust_depth = trust_depth;
           best_depth = depth;
           best_lo = sort_list[i].offset;
         }
         break;
       case HIGH:
-        if (depth == best_depth)
+        if (trust_depth == best_trust_depth && depth == best_depth)
           best_hi = sort_list[i].offset;
+        if (sources[sort_list[i].index]->sel_options & SRC_SELECT_TRUST)
+          trust_depth--;
         depth--;
         break;
       default:
@@ -775,9 +786,9 @@ SRC_SelectSource(SRC_Instance updated_inst)
     }
   }
 
-  if (best_depth <= n_sel_sources / 2) {
-    /* Could not even get half the reachable sources to agree -
-       clearly we can't synchronise. */
+  if (best_depth <= n_sel_sources / 2 && !best_trust_depth) {
+    /* Could not even get half the reachable sources to agree and there
+       are no trusted sources - clearly we can't synchronise */
 
     if (selected_source_index != INVALID_SOURCE) {
       log_selection_message("Can't synchronise: no majority", NULL);
@@ -798,14 +809,17 @@ SRC_SelectSource(SRC_Instance updated_inst)
   n_sel_sources = 0;
 
   for (i = 0; i < n_sources; i++) {
+    /* This should be the same condition to get into the endpoint
+       list */
     if (sources[i]->status != SRC_OK)
       continue;
 
-    /* This should be the same condition to get into the endpoint
-       list */
-    /* Check if source's interval contains the best interval, or
-       is wholly contained within it */
-    if ((sources[i]->sel_info.lo_limit <= best_lo &&
+    /* Check if source's interval contains the best interval, or is wholly
+       contained within it.  If there are any trusted sources the first
+       condition is applied only to them to not allow non-trusted sources to
+       move the final offset outside the interval. */
+    if (((!best_trust_depth || sources[i]->sel_options & SRC_SELECT_TRUST) &&
+         sources[i]->sel_info.lo_limit <= best_lo &&
          sources[i]->sel_info.hi_limit >= best_hi) ||
         (sources[i]->sel_info.lo_limit >= best_lo &&
          sources[i]->sel_info.hi_limit <= best_hi)) {
index 1e15af6b738d33d7615e2ac8e10070062084474f..15fb6f28aa670fcb3cc46dfa3c7cc92cbfcc8ba2 100644 (file)
@@ -66,5 +66,6 @@ typedef struct {
 /* Flags for source selection */
 #define SRC_SELECT_NOSELECT 0x1
 #define SRC_SELECT_PREFER 0x2
+#define SRC_SELECT_TRUST 0x4
 
 #endif /* GOT_SRCPARAMS_H */