reference: activate local reference with large root distance
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).
This commit is contained in:
parent
981f897c96
commit
81f440a882
5 changed files with 55 additions and 6 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
6
conf.c
6
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;
|
||||
|
|
2
conf.h
2
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);
|
||||
|
||||
|
|
45
reference.c
45
reference.c
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue