sources: add option to limit selection by root distance

Add maxdistance directive to set the maximum root distance the sources
are allowed to have to be selected. This is useful to reject NTPv4
sources that are no longer synchronized and report large dispersion.
The default value is 3 seconds.
This commit is contained in:
Miroslav Lichvar 2015-08-25 16:27:36 +02:00
parent b7a54f8cd8
commit 5039f959e0
5 changed files with 41 additions and 0 deletions

View file

@ -1152,6 +1152,7 @@ the configuration file is ignored.
* manual directive:: Allow manual entry using chronyc's settime cmd
* maxchange directive:: Set maximum allowed offset
* maxclockerror directive:: Set maximum frequency error of local clock
* maxdistance directive:: Set maximum allowed distance of sources
* maxsamples directive:: Set maximum number of samples per source
* maxslewrate directive:: Set maximum slew rate
* maxupdateskew directive:: Stop bad estimates upsetting machine clock
@ -2441,6 +2442,23 @@ Typical values for <error-in-ppm> might be 10 for a low quality clock
to 0.1 for a high quality clock using a temperature compensated
crystal oscillator.
@c }}}
@c {{{ maxdistance
@node maxdistance directive
@subsection maxdistance
The @code{maxdistance} directive sets the maximum allowed root distance of the
sources to not be rejected by the source selection algorithm. The distance
includes the accumulated dispersion, which may be large when the source is no
longer synchronised, and half of the total round-trip delay to the primary
source.
By default, the maximum distance is 3 seconds.
The syntax is
@example
maxdistance <seconds>
@end example
@c }}}
@c {{{ maxsamples
@node maxsamples directive
@subsection maxsamples

11
conf.c
View file

@ -90,6 +90,7 @@ static double correction_time_ratio = 3.0;
static double max_clock_error = 1.0; /* in ppm */
static double max_slew_rate = 1e6 / 12.0; /* in ppm */
static double max_distance = 3.0;
static double reselect_distance = 1e-4;
static double stratum_weight = 1e-3;
static double combine_limit = 3.0;
@ -477,6 +478,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
parse_maxchange(p);
} else if (!strcasecmp(command, "maxclockerror")) {
parse_double(p, &max_clock_error);
} else if (!strcasecmp(command, "maxdistance")) {
parse_double(p, &max_distance);
} else if (!strcasecmp(command, "maxsamples")) {
parse_int(p, &max_samples);
} else if (!strcasecmp(command, "maxslewrate")) {
@ -1524,6 +1527,14 @@ CNF_GetMaxSlewRate(void)
/* ================================================== */
double
CNF_GetMaxDistance(void)
{
return max_distance;
}
/* ================================================== */
double
CNF_GetReselectDistance(void)
{

1
conf.h
View file

@ -86,6 +86,7 @@ extern double CNF_GetMaxClockError(void);
extern double CNF_GetCorrectionTimeRatio(void);
extern double CNF_GetMaxSlewRate(void);
extern double CNF_GetMaxDistance(void);
extern double CNF_GetReselectDistance(void);
extern double CNF_GetStratumWeight(void);
extern double CNF_GetCombineLimit(void);

View file

@ -70,6 +70,7 @@ typedef enum {
SRC_OK, /* OK so far, not a final status! */
SRC_UNSELECTABLE, /* Has noselect option set */
SRC_BAD_STATS, /* Doesn't have valid stats data */
SRC_BAD_DISTANCE, /* Has root distance longer than allowed maximum */
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
SRC_STALE, /* Has older samples than others */
SRC_FALSETICKER, /* Doesn't agree with others */
@ -155,6 +156,7 @@ static int selected_source_index; /* Which source index is currently
/* Number of updates needed to reset the distant status */
#define DISTANT_PENALTY 32
static double max_distance;
static double reselect_distance;
static double stratum_weight;
static double combine_limit;
@ -179,6 +181,7 @@ void SRC_Initialise(void) {
n_sources = 0;
max_n_sources = 0;
selected_source_index = INVALID_SOURCE;
max_distance = CNF_GetMaxDistance();
reselect_distance = CNF_GetReselectDistance();
stratum_weight = CNF_GetStratumWeight();
combine_limit = CNF_GetCombineLimit();
@ -653,6 +656,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
continue;
}
/* Require the root distance to be below the allowed maximum */
if (si->root_distance > max_distance) {
sources[i]->status = SRC_BAD_DISTANCE;
continue;
}
sources[i]->status = SRC_OK; /* For now */
if (sources[i]->reachability && max_reach_sample_ago < first_sample_ago)
@ -1216,6 +1225,7 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
switch (src->status) {
case SRC_UNSELECTABLE:
case SRC_BAD_STATS:
case SRC_BAD_DISTANCE:
case SRC_STALE:
case SRC_WAITS_STATS:
report->state = RPT_UNREACH;

View file

@ -6,6 +6,7 @@ test_start "presend option"
min_sync_time=140
max_sync_time=260
client_server_options="presend 6 maxdelay 16"
client_conf="maxdistance 10"
run_test || test_fail
check_chronyd_exit || test_fail