/* ================================================== */
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;
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;
}
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);
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 */
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;
}
/* ================================================== */
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;
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;
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;
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;
/* ================================================== */
+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,
}
}
+ /* Update timer that activates the local reference */
+ update_local_timeout();
+
/* Update fallback drifts */
if (fb_drifts) {
update_fb_drifts(abs_freq_ppm, update_interval);
update_leap_status(LEAP_Unsynchronised, 0, 0);
are_we_synchronised = 0;
+ update_local_timeout();
LCL_SetSyncStatus(0, 0.0, 0.0);