]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
reference: activate local reference with large root distance
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 30 Mar 2016 15:12:12 +0000 (17:12 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 31 Mar 2016 14:08:45 +0000 (16:08 +0200)
Since the update to NTPv4, when the clock is in the synchronised state
and the clock updates stop (e.g. sources become unreachable), it doesn't
switch to the unsynchronised state and the local reference is never
activate. This can be a problem for clients that rely on the server to
always have root distance below some value (e.g. chronyd's maxdistance).

Add a timer that will activate the local reference when the root
distance reaches a specified threshold. It can be configured with the
distance option in the local directive (by default 1.0 second).

cmdparse.c
cmdparse.h
conf.c
conf.h
reference.c

index a24324fd9d1cc966cae137589cc0ab77f50edd43..37d15813e8e5db03c2c22a3b4957173219b14e6b 100644 (file)
@@ -224,12 +224,13 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
 /* ================================================== */
 
 int
-CPS_ParseLocal(char *line, int *stratum)
+CPS_ParseLocal(char *line, int *stratum, double *distance)
 {
   int n;
   char *cmd;
 
   *stratum = 10;
+  *distance = 1.0;
 
   while (*line) {
     cmd = line;
@@ -238,6 +239,9 @@ CPS_ParseLocal(char *line, int *stratum)
     if (!strcasecmp(cmd, "stratum")) {
       if (sscanf(line, "%d%n", stratum, &n) != 1)
         return 0;
+    } else if (!strcasecmp(cmd, "distance")) {
+      if (sscanf(line, "%lf%n", distance, &n) != 1)
+        return 0;
     } else {
       return 0;
     }
index eb1714dbfd87aef982190610bcc4615ac0742636..69444753d30be3707cef3f64dad3272976000fbd 100644 (file)
@@ -60,7 +60,7 @@ typedef struct {
 extern CPS_Status CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src);
   
 /* Parse a command to enable local reference */
-extern int CPS_ParseLocal(char *line, int *stratum);
+extern int CPS_ParseLocal(char *line, int *stratum, double *distance);
 
 /* Get a string describing error status */
 extern void CPS_StatusToString(CPS_Status status, char *dest, int len);
diff --git a/conf.c b/conf.c
index d989a5e03c39b70d429c451841bd32ecb6e7e91f..8c125fffd0be246b790add831ef6f36864a992cd 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -108,6 +108,7 @@ static char *dumpdir;
 
 static int enable_local=0;
 static int local_stratum;
+static double local_distance;
 
 /* Threshold (in seconds) - if absolute value of initial error is less
    than this, slew instead of stepping */
@@ -817,7 +818,7 @@ parse_log(char *line)
 static void
 parse_local(char *line)
 {
-  if (!CPS_ParseLocal(line, &local_stratum))
+  if (!CPS_ParseLocal(line, &local_stratum, &local_distance))
     command_parse_error();
   enable_local = 1;
 }
@@ -1565,10 +1566,11 @@ CNF_GetCommandPort(void) {
 /* ================================================== */
 
 int
-CNF_AllowLocalReference(int *stratum)
+CNF_AllowLocalReference(int *stratum, double *distance)
 {
   if (enable_local) {
     *stratum = local_stratum;
+    *distance = local_distance;
     return 1;
   } else {
     return 0;
diff --git a/conf.h b/conf.h
index 34c7e41e63ef3a955edf3fc195ffa35293c21dcf..6ded8f52171b03410e4a7c760a7712cf542d747b 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -92,7 +92,7 @@ extern double CNF_GetReselectDistance(void);
 extern double CNF_GetStratumWeight(void);
 extern double CNF_GetCombineLimit(void);
 
-extern int CNF_AllowLocalReference(int *stratum);
+extern int CNF_AllowLocalReference(int *stratum, double *distance);
 
 extern void CNF_SetupAccessRestrictions(void);
 
index f9b4ad40862cfc4913da4d3b11d3027d673edc28..2b51f0149c4e362834211e52cbee9561202cd394 100644 (file)
@@ -45,6 +45,7 @@
 static int are_we_synchronised;
 static int enable_local_stratum;
 static int local_stratum;
+static double local_distance;
 static NTP_Leap our_leap_status;
 static int our_leap_sec;
 static int our_stratum;
@@ -112,6 +113,11 @@ static char *leap_tzname;
 static time_t last_tz_leap_check;
 static NTP_Leap tz_leap;
 
+#define MAX_LOCAL_TIMEOUT (30 * 24 * 3600.0)
+
+/* Timer for local reference */
+static SCH_TimeoutID local_timeout_id;
+
 /* ================================================== */
 
 static LOG_FileID logfileid;
@@ -230,7 +236,8 @@ REF_Initialise(void)
 
   correction_time_ratio = CNF_GetCorrectionTimeRatio();
 
-  enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
+  enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_distance);
+  local_timeout_id = 0;
 
   leap_timeout_id = 0;
   leap_in_progress = 0;
@@ -801,6 +808,38 @@ update_leap_status(NTP_Leap leap, time_t now, int reset)
 
 /* ================================================== */
 
+static void
+local_timeout(void *arg)
+{
+  local_timeout_id = 0;
+  REF_SetUnsynchronised();
+}
+
+/* ================================================== */
+
+static void
+update_local_timeout(void)
+{
+  double delay;
+
+  SCH_RemoveTimeout(local_timeout_id);
+  local_timeout_id = 0;
+
+  if (!enable_local_stratum || !are_we_synchronised)
+    return;
+
+  /* Add a timer that will activate the local reference approximately at the
+     point when our root distance reaches the configured root distance */
+  delay = (local_distance - (our_root_delay / 2.0 + our_root_dispersion)) /
+          (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError());
+  delay = CLAMP(0.0, delay, MAX_LOCAL_TIMEOUT);
+  local_timeout_id = SCH_AddTimeoutByDelay(delay, local_timeout, NULL);
+
+  DEBUG_LOG(LOGF_Reference, "Local reference timeout %f", delay);
+}
+
+/* ================================================== */
+
 static void
 write_log(struct timeval *ref_time, char *ref, int stratum, NTP_Leap leap,
     double freq, double skew, double offset, int combined_sources,
@@ -1063,6 +1102,9 @@ REF_SetReference(int stratum,
     }
   }
 
+  /* Update timer that activates the local reference */
+  update_local_timeout();
+
   /* Update fallback drifts */
   if (fb_drifts) {
     update_fb_drifts(abs_freq_ppm, update_interval);
@@ -1127,6 +1169,7 @@ REF_SetUnsynchronised(void)
 
   update_leap_status(LEAP_Unsynchronised, 0, 0);
   are_we_synchronised = 0;
+  update_local_timeout();
 
   LCL_SetSyncStatus(0, 0.0, 0.0);