mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 15:45:07 -05:00
sources: add configurable limits for stratum
Add minstratum and maxstratum directives to specify the minimum and maximum allowed stratum of sources to be selected. The default values are 0 and 15 respectively, allowing all NTP sources and refclocks. Sources that are rejected due to having too large or too small stratum are marked with 'r' in the selection log and selectdata report. This is similar to the "tos floor" and "tos ceiling" settings of ntpd, except that maxstratum is interpreted as one below the ceiling.
This commit is contained in:
2
client.c
2
client.c
@@ -2576,7 +2576,7 @@ process_cmd_selectdata(char *line)
|
|||||||
n_sources = ntohl(reply.data.n_sources.n_sources);
|
n_sources = ntohl(reply.data.n_sources.n_sources);
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf( " . State: N - noselect, s - unsynchronised, M - missing samples,\n");
|
printf( " . State: N - noselect, s - unsynchronised, M - missing samples, r - stratum\n");
|
||||||
printf( " / d/D - large distance, ~ - jittery, w/W - waits for others,\n");
|
printf( " / d/D - large distance, ~ - jittery, w/W - waits for others,\n");
|
||||||
printf( "| S - stale, O - orphan, T - not trusted, P - not preferred,\n");
|
printf( "| S - stale, O - orphan, T - not trusted, P - not preferred,\n");
|
||||||
printf( "| U - waits for update,, x - falseticker, + - combined, * - best.\n");
|
printf( "| U - waits for update,, x - falseticker, + - combined, * - best.\n");
|
||||||
|
|||||||
22
conf.c
22
conf.c
@@ -115,6 +115,8 @@ static double clock_precision = 0.0; /* in seconds */
|
|||||||
static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX;
|
static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX;
|
||||||
static double max_distance = 3.0;
|
static double max_distance = 3.0;
|
||||||
static double max_jitter = 1.0;
|
static double max_jitter = 1.0;
|
||||||
|
static int max_stratum = NTP_MAX_STRATUM - 1;
|
||||||
|
static int min_stratum = 0;
|
||||||
static double reselect_distance = 1e-4;
|
static double reselect_distance = 1e-4;
|
||||||
static double stratum_weight = 1e-3;
|
static double stratum_weight = 1e-3;
|
||||||
static double combine_limit = 3.0;
|
static double combine_limit = 3.0;
|
||||||
@@ -702,12 +704,16 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
parse_int(p, &max_samples, 0, INT_MAX);
|
parse_int(p, &max_samples, 0, INT_MAX);
|
||||||
} else if (!strcasecmp(command, "maxslewrate")) {
|
} else if (!strcasecmp(command, "maxslewrate")) {
|
||||||
parse_double(p, &max_slew_rate);
|
parse_double(p, &max_slew_rate);
|
||||||
|
} else if (!strcasecmp(command, "maxstratum")) {
|
||||||
|
parse_int(p, &max_stratum, 0, INT_MAX);
|
||||||
} else if (!strcasecmp(command, "maxupdateskew")) {
|
} else if (!strcasecmp(command, "maxupdateskew")) {
|
||||||
parse_double(p, &max_update_skew);
|
parse_double(p, &max_update_skew);
|
||||||
} else if (!strcasecmp(command, "minsamples")) {
|
} else if (!strcasecmp(command, "minsamples")) {
|
||||||
parse_int(p, &min_samples, 0, INT_MAX);
|
parse_int(p, &min_samples, 0, INT_MAX);
|
||||||
} else if (!strcasecmp(command, "minsources")) {
|
} else if (!strcasecmp(command, "minsources")) {
|
||||||
parse_int(p, &min_sources, 1, INT_MAX);
|
parse_int(p, &min_sources, 1, INT_MAX);
|
||||||
|
} else if (!strcasecmp(command, "minstratum")) {
|
||||||
|
parse_int(p, &min_stratum, 0, INT_MAX);
|
||||||
} else if (!strcasecmp(command, "nocerttimecheck")) {
|
} else if (!strcasecmp(command, "nocerttimecheck")) {
|
||||||
parse_int(p, &no_cert_time_check, 0, INT_MAX);
|
parse_int(p, &no_cert_time_check, 0, INT_MAX);
|
||||||
} else if (!strcasecmp(command, "noclientlog")) {
|
} else if (!strcasecmp(command, "noclientlog")) {
|
||||||
@@ -2311,6 +2317,22 @@ CNF_GetMaxJitter(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
CNF_GetMaxStratum(void)
|
||||||
|
{
|
||||||
|
return max_stratum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
CNF_GetMinStratum(void)
|
||||||
|
{
|
||||||
|
return min_stratum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
double
|
double
|
||||||
CNF_GetReselectDistance(void)
|
CNF_GetReselectDistance(void)
|
||||||
{
|
{
|
||||||
|
|||||||
2
conf.h
2
conf.h
@@ -106,6 +106,8 @@ extern double CNF_GetClockPrecision(void);
|
|||||||
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
|
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
|
||||||
extern double CNF_GetMaxDistance(void);
|
extern double CNF_GetMaxDistance(void);
|
||||||
extern double CNF_GetMaxJitter(void);
|
extern double CNF_GetMaxJitter(void);
|
||||||
|
extern int CNF_GetMaxStratum(void);
|
||||||
|
extern int CNF_GetMinStratum(void);
|
||||||
extern double CNF_GetReselectDistance(void);
|
extern double CNF_GetReselectDistance(void);
|
||||||
extern double CNF_GetStratumWeight(void);
|
extern double CNF_GetStratumWeight(void);
|
||||||
extern double CNF_GetCombineLimit(void);
|
extern double CNF_GetCombineLimit(void);
|
||||||
|
|||||||
@@ -71,8 +71,10 @@ also when the <<chronyc.adoc#online,*online*>> command is issued in *chronyc*.
|
|||||||
The DNS record can change over time. The used address will be replaced with a
|
The DNS record can change over time. The used address will be replaced with a
|
||||||
newly resolved address when the server becomes unreachable (i.e. no valid
|
newly resolved address when the server becomes unreachable (i.e. no valid
|
||||||
response to the last 8 requests), unsynchronised, a falseticker (i.e. does not
|
response to the last 8 requests), unsynchronised, a falseticker (i.e. does not
|
||||||
agree with a majority of other sources), or the root distance is too large (the
|
agree with a majority of other sources), the root distance is too large (the
|
||||||
limit can be configured by the <<maxdistance,*maxdistance*>> directive). The
|
limit can be configured by the <<maxdistance,*maxdistance*>> directive), or
|
||||||
|
the stratum is too small or too large (the limits can be configured by the
|
||||||
|
<<minstratum,*minstratum*>> and <<maxstratum,*maxstratum*>> directives). The
|
||||||
automatic replacement happens at most once per 30 minutes and only one
|
automatic replacement happens at most once per 30 minutes and only one
|
||||||
server can be replaced at a time. The address is also refreshed periodically
|
server can be replaced at a time. The address is also refreshed periodically
|
||||||
when the server is working normally (the interval can be configured by the
|
when the server is working normally (the interval can be configured by the
|
||||||
@@ -318,7 +320,8 @@ with lower stratum are normally slightly preferred. This option can be used to
|
|||||||
increase stratum of the source to the specified minimum, so *chronyd* will
|
increase stratum of the source to the specified minimum, so *chronyd* will
|
||||||
avoid selecting that source. This is useful with low-stratum sources that are
|
avoid selecting that source. This is useful with low-stratum sources that are
|
||||||
known to be unreliable or inaccurate and that should be used only when other
|
known to be unreliable or inaccurate and that should be used only when other
|
||||||
sources are unreachable.
|
sources are unreachable. Note that the <<minstratum,*minstratum*>> directive
|
||||||
|
is distinct from this option.
|
||||||
*version* _version_:::
|
*version* _version_:::
|
||||||
This option sets the NTP version of packets sent to the server. This can be
|
This option sets the NTP version of packets sent to the server. This can be
|
||||||
useful when the server runs an old NTP implementation that does not respond to
|
useful when the server runs an old NTP implementation that does not respond to
|
||||||
@@ -1102,6 +1105,16 @@ with sources that have a small root distance, but their time is too variable.
|
|||||||
+
|
+
|
||||||
By default, the maximum jitter is 1 second.
|
By default, the maximum jitter is 1 second.
|
||||||
|
|
||||||
|
[[maxstratum]]*maxstratum* _stratum_::
|
||||||
|
The *maxstratum* directive sets the maximum allowed stratum of the sources to
|
||||||
|
be selected for synchronisation. The default value is 15. The useful range is 0
|
||||||
|
to 15.
|
||||||
|
|
||||||
|
[[minstratum]]*minstratum* _stratum_::
|
||||||
|
The *minstratum* directive sets the minimum allowed stratum of the sources to
|
||||||
|
be selected for synchronisation. The default value is 0. The useful range is 0
|
||||||
|
to 15.
|
||||||
|
|
||||||
[[minsources]]*minsources* _sources_::
|
[[minsources]]*minsources* _sources_::
|
||||||
The *minsources* directive sets the minimum number of sources that need to be
|
The *minsources* directive sets the minimum number of sources that need to be
|
||||||
considered as selectable in the source selection algorithm before the local
|
considered as selectable in the source selection algorithm before the local
|
||||||
@@ -2450,6 +2463,9 @@ Not considered selectable for synchronisation:
|
|||||||
* _N_ - has the *noselect* option.
|
* _N_ - has the *noselect* option.
|
||||||
* _s_ - is not synchronised.
|
* _s_ - is not synchronised.
|
||||||
* _M_ - does not have enough measurements.
|
* _M_ - does not have enough measurements.
|
||||||
|
* _r_ - has a stratum outside of the allowed range (configured by the
|
||||||
|
<<minstratum,*minstratum*>> and <<maxstratum,*maxstratum*>>
|
||||||
|
directives).
|
||||||
* _d_ - has a root distance larger than the maximum distance (configured by the
|
* _d_ - has a root distance larger than the maximum distance (configured by the
|
||||||
<<maxdistance,*maxdistance*>> directive).
|
<<maxdistance,*maxdistance*>> directive).
|
||||||
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
||||||
|
|||||||
@@ -474,6 +474,9 @@ synchronisation:
|
|||||||
* _N_ - has the *noselect* option.
|
* _N_ - has the *noselect* option.
|
||||||
* _M_ - does not have enough measurements.
|
* _M_ - does not have enough measurements.
|
||||||
* _s_ - is not synchronised.
|
* _s_ - is not synchronised.
|
||||||
|
* _r_ - has a stratum outside of the allowed range (configured by the
|
||||||
|
<<chrony.conf.adoc#minstratum,*minstratum*>> and
|
||||||
|
<<chrony.conf.adoc#maxstratum,*maxstratum*>> directives).
|
||||||
* _d_ - has a root distance larger than the maximum distance (configured by the
|
* _d_ - has a root distance larger than the maximum distance (configured by the
|
||||||
<<chrony.conf.adoc#maxdistance,*maxdistance*>> directive).
|
<<chrony.conf.adoc#maxdistance,*maxdistance*>> directive).
|
||||||
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
||||||
|
|||||||
24
sources.c
24
sources.c
@@ -69,6 +69,7 @@ typedef enum {
|
|||||||
SRC_UNSELECTABLE, /* Has noselect option set */
|
SRC_UNSELECTABLE, /* Has noselect option set */
|
||||||
SRC_BAD_STATS, /* Doesn't have valid stats data */
|
SRC_BAD_STATS, /* Doesn't have valid stats data */
|
||||||
SRC_UNSYNCHRONISED, /* Provides samples, but not synchronised */
|
SRC_UNSYNCHRONISED, /* Provides samples, but not synchronised */
|
||||||
|
SRC_BAD_STRATUM, /* Has stratum outside of allowed range */
|
||||||
SRC_BAD_DISTANCE, /* Has root distance longer than allowed maximum */
|
SRC_BAD_DISTANCE, /* Has root distance longer than allowed maximum */
|
||||||
SRC_JITTERY, /* Had std dev larger than allowed maximum */
|
SRC_JITTERY, /* Had std dev larger than allowed maximum */
|
||||||
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
|
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
|
||||||
@@ -197,6 +198,8 @@ static int forced_first_report; /* Flag to allow one failed selection to be
|
|||||||
|
|
||||||
static double max_distance;
|
static double max_distance;
|
||||||
static double max_jitter;
|
static double max_jitter;
|
||||||
|
static int max_stratum;
|
||||||
|
static int min_stratum;
|
||||||
static double reselect_distance;
|
static double reselect_distance;
|
||||||
static double stratum_weight;
|
static double stratum_weight;
|
||||||
static double combine_limit;
|
static double combine_limit;
|
||||||
@@ -230,6 +233,8 @@ void SRC_Initialise(void) {
|
|||||||
selected_source_index = INVALID_SOURCE;
|
selected_source_index = INVALID_SOURCE;
|
||||||
max_distance = CNF_GetMaxDistance();
|
max_distance = CNF_GetMaxDistance();
|
||||||
max_jitter = CNF_GetMaxJitter();
|
max_jitter = CNF_GetMaxJitter();
|
||||||
|
max_stratum = CNF_GetMaxStratum();
|
||||||
|
min_stratum = CNF_GetMinStratum();
|
||||||
reselect_distance = CNF_GetReselectDistance();
|
reselect_distance = CNF_GetReselectDistance();
|
||||||
stratum_weight = CNF_GetStratumWeight();
|
stratum_weight = CNF_GetStratumWeight();
|
||||||
combine_limit = CNF_GetCombineLimit();
|
combine_limit = CNF_GetCombineLimit();
|
||||||
@@ -738,7 +743,8 @@ set_source_status(SRC_Instance inst, SRC_Status status)
|
|||||||
distance or jitter larger than the allowed maximums */
|
distance or jitter larger than the allowed maximums */
|
||||||
if (inst == last_updated_inst) {
|
if (inst == last_updated_inst) {
|
||||||
if (inst->bad < INT_MAX &&
|
if (inst->bad < INT_MAX &&
|
||||||
(status == SRC_FALSETICKER || status == SRC_BAD_DISTANCE || status == SRC_JITTERY))
|
(status == SRC_FALSETICKER || status == SRC_BAD_DISTANCE ||
|
||||||
|
status == SRC_BAD_STRATUM || status == SRC_JITTERY))
|
||||||
inst->bad++;
|
inst->bad++;
|
||||||
else
|
else
|
||||||
inst->bad = 0;
|
inst->bad = 0;
|
||||||
@@ -782,6 +788,14 @@ mark_source(SRC_Instance inst, SRC_Status status)
|
|||||||
|
|
||||||
if (!inst->reported_status[status]) {
|
if (!inst->reported_status[status]) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
case SRC_BAD_STRATUM:
|
||||||
|
if (inst->bad < BAD_HANDLE_THRESHOLD)
|
||||||
|
break;
|
||||||
|
log_selection_source(LOGS_WARN, inst,
|
||||||
|
"Stratum of ## %sstratum of %d",
|
||||||
|
inst->stratum < min_stratum ? "below min" : "above max",
|
||||||
|
inst->stratum < min_stratum ? min_stratum : max_stratum);
|
||||||
|
break;
|
||||||
case SRC_BAD_DISTANCE:
|
case SRC_BAD_DISTANCE:
|
||||||
if (inst->bad < BAD_HANDLE_THRESHOLD)
|
if (inst->bad < BAD_HANDLE_THRESHOLD)
|
||||||
break;
|
break;
|
||||||
@@ -1028,6 +1042,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Require the stratum to be in the allowed range */
|
||||||
|
if (sources[i]->stratum < min_stratum || sources[i]->stratum > max_stratum) {
|
||||||
|
mark_source(sources[i], SRC_BAD_STRATUM);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Include extra dispersion in the root distance of sources that don't
|
/* Include extra dispersion in the root distance of sources that don't
|
||||||
have new samples (the last sample is older than span of all samples) */
|
have new samples (the last sample is older than span of all samples) */
|
||||||
if (first_sample_ago < 2.0 * si->last_sample_ago) {
|
if (first_sample_ago < 2.0 * si->last_sample_ago) {
|
||||||
@@ -1914,6 +1934,8 @@ get_status_char(SRC_Status status)
|
|||||||
return 'M';
|
return 'M';
|
||||||
case SRC_UNSYNCHRONISED:
|
case SRC_UNSYNCHRONISED:
|
||||||
return 's';
|
return 's';
|
||||||
|
case SRC_BAD_STRATUM:
|
||||||
|
return 'r';
|
||||||
case SRC_BAD_DISTANCE:
|
case SRC_BAD_DISTANCE:
|
||||||
return 'd';
|
return 'd';
|
||||||
case SRC_JITTERY:
|
case SRC_JITTERY:
|
||||||
|
|||||||
38
test/simulation/151-stratumlimit
Executable file
38
test/simulation/151-stratumlimit
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
. ./test.common
|
||||||
|
|
||||||
|
test_start "minstratum and maxstratum options"
|
||||||
|
|
||||||
|
client_conf="
|
||||||
|
minstratum 3
|
||||||
|
maxstratum 5"
|
||||||
|
|
||||||
|
for s in 3 5; do
|
||||||
|
server_conf="local stratum $s"
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
check_log_messages "Stratum of .* stratum" 0 0 || test_fail
|
||||||
|
done
|
||||||
|
|
||||||
|
for s in 2 6; do
|
||||||
|
server_conf="local stratum $s"
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection && test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync && test_fail
|
||||||
|
|
||||||
|
check_log_messages "Stratum of .* stratum" 0 0 || test_fail
|
||||||
|
if [ $s -lt 3 ]; then
|
||||||
|
check_log_messages "Stratum of .* below minstratum of 3" 1 1 || test_fail
|
||||||
|
else
|
||||||
|
check_log_messages "Stratum of .* above maxstratum of 5" 1 1 || test_fail
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
test_pass
|
||||||
Reference in New Issue
Block a user