mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 15:55:07 -05:00
Compare commits
7 Commits
3c39afa13c
...
6fe4a60a1d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fe4a60a1d | ||
|
|
2da8fbc4c3 | ||
|
|
c252e52ee2 | ||
|
|
c8a9ca4cf0 | ||
|
|
4659b574bf | ||
|
|
5436618c05 | ||
|
|
a0f460569e |
4
client.c
4
client.c
@@ -2576,10 +2576,10 @@ process_cmd_selectdata(char *line)
|
||||
n_sources = ntohl(reply.data.n_sources.n_sources);
|
||||
|
||||
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( "| 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");
|
||||
printf( "| Effective options ---------. (N - noselect, P - prefer\n");
|
||||
printf( "| Configured options ----. \\ T - trust, R - require)\n");
|
||||
printf( "| Auth. enabled (Y/N) -. \\ \\ Offset interval --.\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 double max_distance = 3.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 stratum_weight = 1e-3;
|
||||
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);
|
||||
} else if (!strcasecmp(command, "maxslewrate")) {
|
||||
parse_double(p, &max_slew_rate);
|
||||
} else if (!strcasecmp(command, "maxstratum")) {
|
||||
parse_int(p, &max_stratum, 0, INT_MAX);
|
||||
} else if (!strcasecmp(command, "maxupdateskew")) {
|
||||
parse_double(p, &max_update_skew);
|
||||
} else if (!strcasecmp(command, "minsamples")) {
|
||||
parse_int(p, &min_samples, 0, INT_MAX);
|
||||
} else if (!strcasecmp(command, "minsources")) {
|
||||
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")) {
|
||||
parse_int(p, &no_cert_time_check, 0, INT_MAX);
|
||||
} 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
|
||||
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 double CNF_GetMaxDistance(void);
|
||||
extern double CNF_GetMaxJitter(void);
|
||||
extern int CNF_GetMaxStratum(void);
|
||||
extern int CNF_GetMinStratum(void);
|
||||
extern double CNF_GetReselectDistance(void);
|
||||
extern double CNF_GetStratumWeight(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
|
||||
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
|
||||
agree with a majority of other sources), or the root distance is too large (the
|
||||
limit can be configured by the <<maxdistance,*maxdistance*>> directive). The
|
||||
agree with a majority of other sources), the root distance is too large (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
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
sources are unreachable.
|
||||
sources are unreachable. Note that the <<minstratum,*minstratum*>> directive
|
||||
is distinct from this option.
|
||||
*version* _version_:::
|
||||
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
|
||||
@@ -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.
|
||||
|
||||
[[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_::
|
||||
The *minsources* directive sets the minimum number of sources that need to be
|
||||
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.
|
||||
* _s_ - is not synchronised.
|
||||
* _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
|
||||
<<maxdistance,*maxdistance*>> directive).
|
||||
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
||||
|
||||
@@ -474,6 +474,9 @@ synchronisation:
|
||||
* _N_ - has the *noselect* option.
|
||||
* _M_ - does not have enough measurements.
|
||||
* _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
|
||||
<<chrony.conf.adoc#maxdistance,*maxdistance*>> directive).
|
||||
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
||||
|
||||
45
sources.c
45
sources.c
@@ -54,7 +54,6 @@ static int initialised = 0;
|
||||
/* ================================================== */
|
||||
/* Structure used to hold info for selecting between sources */
|
||||
struct SelectInfo {
|
||||
int select_ok;
|
||||
double std_dev;
|
||||
double root_distance;
|
||||
double lo_limit;
|
||||
@@ -70,6 +69,7 @@ typedef enum {
|
||||
SRC_UNSELECTABLE, /* Has noselect option set */
|
||||
SRC_BAD_STATS, /* Doesn't have valid stats data */
|
||||
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_JITTERY, /* Had std dev larger than allowed maximum */
|
||||
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
|
||||
@@ -198,6 +198,8 @@ static int forced_first_report; /* Flag to allow one failed selection to be
|
||||
|
||||
static double max_distance;
|
||||
static double max_jitter;
|
||||
static int max_stratum;
|
||||
static int min_stratum;
|
||||
static double reselect_distance;
|
||||
static double stratum_weight;
|
||||
static double combine_limit;
|
||||
@@ -231,6 +233,8 @@ void SRC_Initialise(void) {
|
||||
selected_source_index = INVALID_SOURCE;
|
||||
max_distance = CNF_GetMaxDistance();
|
||||
max_jitter = CNF_GetMaxJitter();
|
||||
max_stratum = CNF_GetMaxStratum();
|
||||
min_stratum = CNF_GetMinStratum();
|
||||
reselect_distance = CNF_GetReselectDistance();
|
||||
stratum_weight = CNF_GetStratumWeight();
|
||||
combine_limit = CNF_GetCombineLimit();
|
||||
@@ -739,7 +743,8 @@ set_source_status(SRC_Instance inst, SRC_Status status)
|
||||
distance or jitter larger than the allowed maximums */
|
||||
if (inst == last_updated_inst) {
|
||||
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++;
|
||||
else
|
||||
inst->bad = 0;
|
||||
@@ -783,6 +788,14 @@ mark_source(SRC_Instance inst, SRC_Status status)
|
||||
|
||||
if (!inst->reported_status[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:
|
||||
if (inst->bad < BAD_HANDLE_THRESHOLD)
|
||||
break;
|
||||
@@ -955,7 +968,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
int max_badstat_reach, max_badstat_reach_size, n_badstats_sources;
|
||||
int max_sel_reach, max_sel_reach_size, n_unreach_sources;
|
||||
int depth, best_depth, trust_depth, best_trust_depth, n_sel_trust_sources;
|
||||
int combined, stratum, min_stratum, max_score_index;
|
||||
int combined, stratum, min_sel_stratum, max_score_index;
|
||||
int orphan_stratum, orphan_source;
|
||||
double src_offset, src_offset_sd, src_frequency, src_frequency_sd, src_skew;
|
||||
double src_root_delay, src_root_dispersion;
|
||||
@@ -1010,12 +1023,10 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
n_unreach_sources++;
|
||||
|
||||
si = &sources[i]->sel_info;
|
||||
SST_GetSelectionData(sources[i]->stats, &now,
|
||||
&si->lo_limit, &si->hi_limit, &si->root_distance,
|
||||
&si->std_dev, &first_sample_ago,
|
||||
&si->last_sample_ago, &si->select_ok);
|
||||
|
||||
if (!si->select_ok) {
|
||||
if (!SST_GetSelectionData(sources[i]->stats, &now, &si->lo_limit, &si->hi_limit,
|
||||
&si->root_distance, &si->std_dev, &first_sample_ago,
|
||||
&si->last_sample_ago)) {
|
||||
++n_badstats_sources;
|
||||
mark_source(sources[i], SRC_BAD_STATS);
|
||||
if (max_badstat_reach < sources[i]->reachability)
|
||||
@@ -1031,6 +1042,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
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
|
||||
have new samples (the last sample is older than span of all samples) */
|
||||
if (first_sample_ago < 2.0 * si->last_sample_ago) {
|
||||
@@ -1364,12 +1381,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
/* Find minimum stratum */
|
||||
|
||||
index = sel_sources[0];
|
||||
min_stratum = sources[index]->stratum;
|
||||
min_sel_stratum = sources[index]->stratum;
|
||||
for (i = 1; i < n_sel_sources; i++) {
|
||||
index = sel_sources[i];
|
||||
stratum = sources[index]->stratum;
|
||||
if (stratum < min_stratum)
|
||||
min_stratum = stratum;
|
||||
if (min_sel_stratum > stratum)
|
||||
min_sel_stratum = stratum;
|
||||
}
|
||||
|
||||
/* Update scores and find the source with maximum score */
|
||||
@@ -1380,7 +1397,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
|
||||
if (selected_source_index != INVALID_SOURCE)
|
||||
sel_src_distance = sources[selected_source_index]->sel_info.root_distance +
|
||||
(sources[selected_source_index]->stratum - min_stratum) * stratum_weight;
|
||||
(sources[selected_source_index]->stratum - min_sel_stratum) * stratum_weight;
|
||||
|
||||
for (i = 0; i < n_sources; i++) {
|
||||
/* Reset score for non-selectable sources */
|
||||
@@ -1392,7 +1409,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
}
|
||||
|
||||
distance = sources[i]->sel_info.root_distance +
|
||||
(sources[i]->stratum - min_stratum) * stratum_weight;
|
||||
(sources[i]->stratum - min_sel_stratum) * stratum_weight;
|
||||
if (sources[i]->type == SRC_NTP)
|
||||
distance += reselect_distance;
|
||||
|
||||
@@ -1917,6 +1934,8 @@ get_status_char(SRC_Status status)
|
||||
return 'M';
|
||||
case SRC_UNSYNCHRONISED:
|
||||
return 's';
|
||||
case SRC_BAD_STRATUM:
|
||||
return 'r';
|
||||
case SRC_BAD_DISTANCE:
|
||||
return 'd';
|
||||
case SRC_JITTERY:
|
||||
|
||||
@@ -644,22 +644,16 @@ SST_GetFrequencyRange(SST_Stats inst,
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
SST_GetSelectionData(SST_Stats inst, struct timespec *now,
|
||||
double *offset_lo_limit,
|
||||
double *offset_hi_limit,
|
||||
double *root_distance,
|
||||
double *std_dev,
|
||||
double *first_sample_ago,
|
||||
double *last_sample_ago,
|
||||
int *select_ok)
|
||||
int
|
||||
SST_GetSelectionData(SST_Stats inst, struct timespec *now, double *offset_lo_limit,
|
||||
double *offset_hi_limit, double *root_distance, double *std_dev,
|
||||
double *first_sample_ago, double *last_sample_ago)
|
||||
{
|
||||
double offset, sample_elapsed;
|
||||
int i, j;
|
||||
|
||||
if (!inst->n_samples) {
|
||||
*select_ok = 0;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = get_runsbuf_index(inst, inst->best_single_sample);
|
||||
@@ -675,38 +669,25 @@ SST_GetSelectionData(SST_Stats inst, struct timespec *now,
|
||||
*offset_lo_limit = offset - *root_distance;
|
||||
*offset_hi_limit = offset + *root_distance;
|
||||
|
||||
#if 0
|
||||
double average_offset, elapsed;
|
||||
int average_ok;
|
||||
/* average_ok ignored for now */
|
||||
elapsed = UTI_DiffTimespecsToDouble(now, &inst->offset_time);
|
||||
average_offset = inst->estimated_offset + inst->estimated_frequency * elapsed;
|
||||
if (fabs(average_offset - offset) <=
|
||||
inst->peer_dispersions[j] + 0.5 * inst->peer_delays[i]) {
|
||||
average_ok = 1;
|
||||
} else {
|
||||
average_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = get_runsbuf_index(inst, 0);
|
||||
*first_sample_ago = UTI_DiffTimespecsToDouble(now, &inst->sample_times[i]);
|
||||
i = get_runsbuf_index(inst, inst->n_samples - 1);
|
||||
*last_sample_ago = UTI_DiffTimespecsToDouble(now, &inst->sample_times[i]);
|
||||
|
||||
*select_ok = inst->regression_ok;
|
||||
|
||||
/* If maxsamples is too small to have a successful regression, enable the
|
||||
selection as a special case for a fast update/print-once reference mode */
|
||||
if (!*select_ok && inst->n_samples < MIN_SAMPLES_FOR_REGRESS &&
|
||||
if (!inst->regression_ok && inst->n_samples < MIN_SAMPLES_FOR_REGRESS &&
|
||||
inst->n_samples == inst->max_samples) {
|
||||
*std_dev = CNF_GetMaxJitter();
|
||||
*select_ok = 1;
|
||||
} else if (!inst->regression_ok) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_LOG("n=%d off=%f dist=%f sd=%f first_ago=%f last_ago=%f selok=%d",
|
||||
DEBUG_LOG("n=%d off=%f dist=%f sd=%f first_ago=%f last_ago=%f",
|
||||
inst->n_samples, offset, *root_distance, *std_dev,
|
||||
*first_sample_ago, *last_sample_ago, *select_ok);
|
||||
*first_sample_ago, *last_sample_ago);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -67,15 +67,10 @@ extern void SST_DoNewRegression(SST_Stats inst);
|
||||
extern void SST_GetFrequencyRange(SST_Stats inst, double *lo, double *hi);
|
||||
|
||||
/* Get data needed for selection */
|
||||
extern void
|
||||
SST_GetSelectionData(SST_Stats inst, struct timespec *now,
|
||||
double *offset_lo_limit,
|
||||
double *offset_hi_limit,
|
||||
double *root_distance,
|
||||
double *variance,
|
||||
double *first_sample_ago,
|
||||
double *last_sample_ago,
|
||||
int *select_ok);
|
||||
extern int SST_GetSelectionData(SST_Stats inst, struct timespec *now,
|
||||
double *offset_lo_limit, double *offset_hi_limit,
|
||||
double *root_distance, double *variance,
|
||||
double *first_sample_ago, double *last_sample_ago);
|
||||
|
||||
/* Get data needed when setting up tracking on this source */
|
||||
extern void
|
||||
|
||||
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
|
||||
@@ -68,7 +68,7 @@ check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atm
|
||||
run_chronyc "clients" || test_fail
|
||||
check_chronyc_output "^Hostname NTP Drop Int IntL Last Cmd Drop Int Last
|
||||
===============================================================================
|
||||
.*127\.0\.0\.1 [0-9 ]+ 0 [-0-9 ]+ - [ 0-9]+ 0 0 - -.*$" \
|
||||
.*127\.0\.0\.1 [0-9 ]+ 0 [-0-9 ]+ - [-0-9 ]+ 0 0 - -.*$" \
|
||||
|| test_fail
|
||||
|
||||
run_chronyc "ntpdata $server" || test_fail
|
||||
|
||||
Reference in New Issue
Block a user