import CS chrony-4.6.1-2.el9

This commit is contained in:
eabdullin 2025-09-15 11:48:32 +00:00
parent d55e5e5a4c
commit 195be10c99
7 changed files with 1041 additions and 9 deletions

View File

@ -1,2 +1,2 @@
35b070fdd446080232844ac9f70f84ca1823206f SOURCES/chrony-4.6.1.tar.gz
a3289d3e8688b0818e67d3b7338e8b73501bef1e SOURCES/clknetsim-40bb97.tar.gz
c29c27ef95a3c80737a97ae6e3ee386e1af625de SOURCES/clknetsim-cdd694.tar.gz

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/chrony-4.6.1.tar.gz
SOURCES/clknetsim-40bb97.tar.gz
SOURCES/clknetsim-cdd694.tar.gz

View File

@ -0,0 +1,55 @@
commit b889627998ba584528d1c1145a212fb2b97e5289
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 27 10:04:41 2025 +0100
doc: improve description of refresh directive
diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc
index 7ccdd20c..eb00e029 100644
--- a/doc/chrony.conf.adoc
+++ b/doc/chrony.conf.adoc
@@ -941,14 +941,15 @@ time, assuming the first update corrects the clock and later checks can work
with correct time.
[[refresh]]*refresh* _interval_::
-This directive specifies the interval (in seconds) between refreshing IP
-addresses of NTP sources specified by hostname. If the hostname no longer
+This directive specifies the minimum interval (in seconds) between refreshing
+IP addresses of NTP sources specified by hostname. If the hostname no longer
resolves to the currently used address, it will be replaced with one of the new
addresses to avoid using a server which is no longer intended for service, even
if it is still responding correctly and would not be replaced as unreachable.
-Only one source is refreshed at a time. The default value is 1209600 (2 weeks)
-and the maximum value is 2^31-1 (68 years). A value of 0 disables the periodic
-refreshment.
+Only one source is refreshed at a time and only when a valid response is
+received (unreachable sources are replaced independently). The default value is
+1209600 (2 weeks) and the maximum value is 2^31-1 (68 years). A value of 0
+disables the periodic refreshment.
+
The <<chronyc.adoc#refresh,*refresh*>> command can be used to refresh all
sources immediately.
diff -up chrony-4.6.1/doc/chrony.conf.man.in.docrefresh chrony-4.6.1/doc/chrony.conf.man.in
--- chrony-4.6.1/doc/chrony.conf.man.in.docrefresh 2025-05-15 17:04:33.824077026 +0200
+++ chrony-4.6.1/doc/chrony.conf.man.in 2025-05-15 17:04:53.308070453 +0200
@@ -1270,14 +1270,15 @@ with correct time.
.sp
\fBrefresh\fP \fIinterval\fP
.RS 4
-This directive specifies the interval (in seconds) between refreshing IP
-addresses of NTP sources specified by hostname. If the hostname no longer
+This directive specifies the minimum interval (in seconds) between refreshing
+IP addresses of NTP sources specified by hostname. If the hostname no longer
resolves to the currently used address, it will be replaced with one of the new
addresses to avoid using a server which is no longer intended for service, even
if it is still responding correctly and would not be replaced as unreachable.
-Only one source is refreshed at a time. The default value is 1209600 (2 weeks)
-and the maximum value is 2^31\-1 (68 years). A value of 0 disables the periodic
-refreshment.
+Only one source is refreshed at a time and only when a valid response is
+received (unreachable sources are replaced independently). The default value is
+1209600 (2 weeks) and the maximum value is 2^31\-1 (68 years). A value of 0
+disables the periodic refreshment.
.sp
The \fBrefresh\fP command can be used to refresh all
sources immediately.

View File

@ -0,0 +1,612 @@
commit 620210218c4d2e9634035b3c3d01b0a329708111
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Mar 3 15:48:37 2025 +0100
sources: refactor logging of source-specific selection status
Move logging of falsetickers and system peers to the mark_source()
function. Use an array to flag already logged messages in preparation
for logging of other status. Support variable number of arguments in the
logging functions.
diff --git a/sources.c b/sources.c
index e292e4d6..bfb1c45b 100644
--- a/sources.c
+++ b/sources.c
@@ -66,7 +66,7 @@ struct SelectInfo {
/* This enum contains the flag values that are used to label
each source */
typedef enum {
- SRC_OK, /* OK so far, not a final status! */
+ SRC_OK = 0, /* OK so far, not a final status! */
SRC_UNSELECTABLE, /* Has noselect option set */
SRC_BAD_STATS, /* Doesn't have valid stats data */
SRC_UNSYNCHRONISED, /* Provides samples, but not synchronised */
@@ -144,9 +144,9 @@ struct SRC_Instance_Record {
/* Flag indicating the source has a leap second vote */
int leap_vote;
- /* Flag indicating the source was already reported as
- a falseticker since the last selection change */
- int reported_falseticker;
+ /* Flags indicating which status was already reported for
+ the source since the last change of the system peer */
+ char reported_status[SRC_SELECTED + 1];
};
/* ================================================== */
@@ -360,8 +360,8 @@ SRC_ResetInstance(SRC_Instance instance)
instance->stratum = 0;
instance->leap = LEAP_Unsynchronised;
instance->leap_vote = 0;
- instance->reported_falseticker = 0;
+ memset(instance->reported_status, 0, sizeof (instance->reported_status));
memset(&instance->sel_info, 0, sizeof (instance->sel_info));
SST_ResetInstance(instance->stats);
@@ -620,20 +620,45 @@ update_sel_options(void)
/* ================================================== */
+FORMAT_ATTRIBUTE_PRINTF(2, 3)
static void
-log_selection_message(LOG_Severity severity, const char *format, const char *arg)
+log_selection_message(LOG_Severity severity, const char *format, ...)
{
+ char buf[256];
+ va_list ap;
+
if (REF_GetMode() != REF_ModeNormal)
return;
- LOG(severity, format, arg);
+
+ va_start(ap, format);
+ vsnprintf(buf, sizeof (buf), format, ap);
+ va_end(ap);
+
+ LOG(severity, "%s", buf);
}
/* ================================================== */
+FORMAT_ATTRIBUTE_PRINTF(3, 4)
static void
-log_selection_source(LOG_Severity severity, const char *format, SRC_Instance inst)
+log_selection_source(LOG_Severity severity, SRC_Instance inst, const char *format, ...)
{
- char buf[320], *name, *ntp_name;
+ char buf[320], buf2[256], *name, *ntp_name, *s;
+ va_list ap;
+
+ if (REF_GetMode() != REF_ModeNormal)
+ return;
+
+ va_start(ap, format);
+ vsnprintf(buf2, sizeof (buf2), format, ap);
+ va_end(ap);
+
+ /* Replace ## with %s in the formatted string to be the source name */
+ s = strstr(buf2, "##");
+ if (!s || strchr(buf2, '%'))
+ return;
+ s[0] = '%';
+ s[1] = 's';
name = source_to_string(inst);
ntp_name = inst->type == SRC_NTP ? NSR_GetName(inst->ip_addr) : NULL;
@@ -643,7 +668,9 @@ log_selection_source(LOG_Severity severity, const char *format, SRC_Instance ins
else
snprintf(buf, sizeof (buf), "%s", name);
- log_selection_message(severity, format, buf);
+ LOG(severity, buf2, buf);
+
+ inst->reported_status[inst->status] = 1;
}
/* ================================================== */
@@ -686,7 +713,7 @@ source_to_string(SRC_Instance inst)
/* ================================================== */
static void
-mark_source(SRC_Instance inst, SRC_Status status)
+set_source_status(SRC_Instance inst, SRC_Status status)
{
struct timespec now;
@@ -731,6 +758,30 @@ mark_source(SRC_Instance inst, SRC_Status status)
/* ================================================== */
+static void
+mark_source(SRC_Instance inst, SRC_Status status)
+{
+ set_source_status(inst, status);
+
+ if (status < SRC_OK || status >= sizeof (inst->reported_status))
+ assert(0);
+
+ if (!inst->reported_status[status]) {
+ switch (status) {
+ case SRC_FALSETICKER:
+ log_selection_source(LOGS_WARN, inst, "Detected falseticker ##");
+ break;
+ case SRC_SELECTED:
+ log_selection_source(LOGS_INFO, inst, "Selected source ##");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/* ================================================== */
+
static void
mark_ok_sources(SRC_Status status)
{
@@ -739,7 +790,8 @@ mark_ok_sources(SRC_Status status)
for (i = 0; i < n_sources; i++) {
if (sources[i]->status != SRC_OK)
continue;
- mark_source(sources[i], status);
+ /* Don't log the status in this case (multiple sources at once) */
+ set_source_status(sources[i], status);
}
}
@@ -1161,7 +1213,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
/* Could not even get half the reachable (trusted) sources to agree */
if (!reported_no_majority) {
- log_selection_message(LOGS_WARN, "Can't synchronise: no majority", NULL);
+ log_selection_message(LOGS_WARN, "Can't synchronise: no majority");
reported_no_majority = 1;
report_selection_loss = 0;
}
@@ -1212,10 +1264,6 @@ SRC_SelectSource(SRC_Instance updated_inst)
sel_req_source = 0;
} else {
mark_source(sources[i], SRC_FALSETICKER);
- if (!sources[i]->reported_falseticker) {
- log_selection_source(LOGS_WARN, "Detected falseticker %s", sources[i]);
- sources[i]->reported_falseticker = 1;
- }
}
}
@@ -1335,13 +1383,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
}
selected_source_index = max_score_index;
- log_selection_source(LOGS_INFO, "Selected source %s", sources[selected_source_index]);
/* New source has been selected, reset all scores */
for (i = 0; i < n_sources; i++) {
sources[i]->sel_score = 1.0;
sources[i]->distant = 0;
- sources[i]->reported_falseticker = 0;
+ memset(sources[i]->reported_status, 0, sizeof (sources[i]->reported_status));
}
reported_no_majority = 0;
commit 52237b7d0da75fcd750c5d5ee80e87b97474f7fd
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Mar 5 10:45:20 2025 +0100
sources: warn about sources exceeding maxdistance or maxjitter
Log a warning message if a source is rejected in the source selecting
due to exceeding the maxdistance or maxjitter limit to make it more
obvious when synchronization is failing for this reason. Delay the
message until the reachability register is full (8 updates), or a
replacement of the source is attempted.
diff --git a/sources.c b/sources.c
index bfb1c45b..2ba595b5 100644
--- a/sources.c
+++ b/sources.c
@@ -768,6 +768,20 @@ mark_source(SRC_Instance inst, SRC_Status status)
if (!inst->reported_status[status]) {
switch (status) {
+ case SRC_BAD_DISTANCE:
+ if (inst->reachability_size < SOURCE_REACH_BITS && inst->bad < BAD_HANDLE_THRESHOLD)
+ break;
+ log_selection_source(LOGS_WARN, inst,
+ "Root distance of ## exceeds maxdistance of %.3f seconds",
+ max_distance);
+ break;
+ case SRC_JITTERY:
+ if (inst->reachability_size < SOURCE_REACH_BITS && inst->bad < BAD_HANDLE_THRESHOLD)
+ break;
+ log_selection_source(LOGS_WARN, inst,
+ "Jitter of ## exceeds maxjitter of %.3f seconds",
+ max_jitter);
+ break;
case SRC_FALSETICKER:
log_selection_source(LOGS_WARN, inst, "Detected falseticker ##");
break;
commit 1c06925d439d8699cc52df71a7a4e809b5b7348f
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Mar 6 12:46:09 2025 +0100
sources: improve no majority log message
Add the number of sources that form an agreement (overlapping
intervals), if at least two agree with each other, and number of
reachable sources to the "Can't synchronize: no majority" log message to
better explain why synchronization is failing and hint that adding more
sources might help.
diff --git a/sources.c b/sources.c
index 2ba595b5..3b1766be 100644
--- a/sources.c
+++ b/sources.c
@@ -1222,12 +1222,23 @@ SRC_SelectSource(SRC_Instance updated_inst)
assert(depth == 0 && trust_depth == 0);
assert(2 * n_sel_sources == n_endpoints);
- if ((best_trust_depth == 0 && best_depth <= n_sel_sources / 2) ||
- (best_trust_depth > 0 && best_trust_depth <= n_sel_trust_sources / 2)) {
+ if (best_trust_depth > 0) {
+ best_depth = best_trust_depth;
+ n_sel_sources = n_sel_trust_sources;
+ }
+
+ if (best_depth <= n_sel_sources / 2) {
/* Could not even get half the reachable (trusted) sources to agree */
if (!reported_no_majority) {
- log_selection_message(LOGS_WARN, "Can't synchronise: no majority");
+ if (best_depth < 2)
+ log_selection_message(LOGS_WARN, "%s (no agreement among %d %ssources)",
+ "Can't synchronise: no majority", n_sel_sources,
+ best_trust_depth > 0 ? "trusted " : "");
+ else
+ log_selection_message(LOGS_WARN, "%s (only %d of %d %ssources agree)",
+ "Can't synchronise: no majority", best_depth,
+ n_sel_sources, best_trust_depth > 0 ? "trusted " : "");
reported_no_majority = 1;
report_selection_loss = 0;
}
diff --git a/test/simulation/009-sourceselection b/test/simulation/009-sourceselection
index 547c376c..139b6aa2 100755
--- a/test/simulation/009-sourceselection
+++ b/test/simulation/009-sourceselection
@@ -24,6 +24,12 @@ for falsetickers in 3 4; do
# These check are expected to fail
check_source_selection && test_fail
check_sync && test_fail
+
+ if [ $falsetickers = 3 ]; then
+ check_log_messages "Can't synchronise: no majority (only 2 of 5 sources agree)" 1 1 || test_fail
+ else
+ check_log_messages "Can't synchronise: no majority (no agreement among 5 sources)" 1 1 || test_fail
+ fi
done
# Sources with large asymmetric delay should be excluded
diff --git a/test/simulation/148-replacement b/test/simulation/148-replacement
index d09fba6e..ee8b2e23 100755
--- a/test/simulation/148-replacement
+++ b/test/simulation/148-replacement
@@ -68,7 +68,7 @@ check_source_selection && test_fail
check_packet_interval || test_fail
check_sync || test_fail
-check_log_messages "Can't synchronise: no majority" 1 1 || test_fail
+check_log_messages "Can't synchronise: no majority (no agreement among 2 sources)" 1 1 || test_fail
check_log_messages "Detected falseticker" 0 2 || test_fail
check_log_messages "Source 192.168.123.. replaced with" 3 60 || test_fail
check_log_messages "Source 192.168.123.1 replaced with" 1 25 || test_fail
commit 2fc7fc2e227f85dcde0953d47e1815432a4a2bf7
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Mar 12 15:21:18 2025 +0100
sources: delay maxjitter/maxdistance warning messages
Avoid logging the new warning messages about exceeded maxjitter or
maxdistance when only a small number of samples is collected after the
source becomes reachable and the values are unstable. Log the messages
only when a replacement attempt is made.
diff --git a/sources.c b/sources.c
index 3b1766be..c8d96af4 100644
--- a/sources.c
+++ b/sources.c
@@ -769,14 +769,14 @@ mark_source(SRC_Instance inst, SRC_Status status)
if (!inst->reported_status[status]) {
switch (status) {
case SRC_BAD_DISTANCE:
- if (inst->reachability_size < SOURCE_REACH_BITS && inst->bad < BAD_HANDLE_THRESHOLD)
+ if (inst->bad < BAD_HANDLE_THRESHOLD)
break;
log_selection_source(LOGS_WARN, inst,
"Root distance of ## exceeds maxdistance of %.3f seconds",
max_distance);
break;
case SRC_JITTERY:
- if (inst->reachability_size < SOURCE_REACH_BITS && inst->bad < BAD_HANDLE_THRESHOLD)
+ if (inst->bad < BAD_HANDLE_THRESHOLD)
break;
log_selection_source(LOGS_WARN, inst,
"Jitter of ## exceeds maxjitter of %.3f seconds",
commit 0c7e72304aac05020cbaeb4ccab73ce0c441e1ca
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Mar 13 15:40:47 2025 +0100
sources: switch unselect_selected_source() to variable arguments
Switch the function to the full printf style, which will be needed to
log an integer.
diff --git a/sources.c b/sources.c
index c8d96af4..b43ef8dc 100644
--- a/sources.c
+++ b/sources.c
@@ -206,8 +206,7 @@ static LOG_FileID logfileid;
/* Forward prototype */
static void update_sel_options(void);
-static void unselect_selected_source(LOG_Severity severity, const char *format,
- const char *arg);
+static void unselect_selected_source(LOG_Severity severity, const char *format, ...);
static void slew_sources(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything);
static void add_dispersion(double dispersion, void *anything);
@@ -340,7 +339,7 @@ void SRC_DestroyInstance(SRC_Instance instance)
if (selected_source_index > dead_index)
--selected_source_index;
else if (selected_source_index == dead_index)
- unselect_selected_source(LOGS_INFO, NULL, NULL);
+ unselect_selected_source(LOGS_INFO, NULL);
SRC_SelectSource(NULL);
}
@@ -815,16 +814,24 @@ mark_ok_sources(SRC_Status status)
call providing a message or selection of another source, which resets the
report_selection_loss flag. */
+FORMAT_ATTRIBUTE_PRINTF(2, 3)
static void
-unselect_selected_source(LOG_Severity severity, const char *format, const char *arg)
+unselect_selected_source(LOG_Severity severity, const char *format, ...)
{
+ char buf[256];
+ va_list ap;
+
if (selected_source_index != INVALID_SOURCE) {
selected_source_index = INVALID_SOURCE;
report_selection_loss = 1;
}
if (report_selection_loss && format) {
- log_selection_message(severity, format, arg);
+ va_start(ap, format);
+ vsnprintf(buf, sizeof (buf), format, ap);
+ va_end(ap);
+
+ log_selection_message(severity, "%s", buf);
report_selection_loss = 0;
}
}
@@ -947,7 +954,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
}
if (n_sources == 0) {
- unselect_selected_source(LOGS_INFO, "Can't synchronise: no sources", NULL);
+ unselect_selected_source(LOGS_INFO, "Can't synchronise: no sources");
return;
}
@@ -1134,7 +1141,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
if (n_badstats_sources && n_sel_sources && selected_source_index == INVALID_SOURCE &&
max_sel_reach_size < SOURCE_REACH_BITS && max_sel_reach >> 1 == max_badstat_reach) {
mark_ok_sources(SRC_WAITS_STATS);
- unselect_selected_source(LOGS_INFO, NULL, NULL);
+ unselect_selected_source(LOGS_INFO, NULL);
return;
}
@@ -1148,7 +1155,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
if (n_endpoints == 0) {
/* No sources provided valid endpoints */
- unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources", NULL);
+ unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources");
return;
}
@@ -1402,7 +1409,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
/* Before selecting the new synchronisation source wait until the reference
can be updated */
if (sources[max_score_index]->updates == 0) {
- unselect_selected_source(LOGS_INFO, NULL, NULL);
+ unselect_selected_source(LOGS_INFO, NULL);
mark_ok_sources(SRC_WAITS_UPDATE);
return;
}
commit a8094716b0c21a037e3f21d2f3c2e45f14060b07
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Nov 14 13:41:41 2024 +0100
test: add 014-intermittent test
diff --git a/test/simulation/014-intermittent b/test/simulation/014-intermittent
new file mode 100755
index 00000000..2f018ed0
--- /dev/null
+++ b/test/simulation/014-intermittent
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "intermittent connection"
+
+# Pass packets only for 1200 seconds every 10000 seconds
+base_delay=$(cat <<-EOF | tr -d '\n'
+ (+ 1e-4
+ (* -1
+ (equal 0.1 (min (% time 10000) 1200) 1200)))
+EOF
+)
+
+time_max_limit=1e-1
+freq_max_limit=1e-2
+time_rms_limit=2e-3
+freq_rms_limit=2e-5
+limit=100000
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_sync || test_fail
+
+check_log_messages "Can't.*no selectable sources" 9 10 || test_fail
+check_log_messages "Selected source 192.168.123.1" 9 10 || test_fail
+
+# Pass every 20th request
+base_delay=$(cat <<-EOF | tr -d '\n'
+ (+ 1e-4
+ (* -1
+ (equal 0.1 from 2)
+ (equal 0.1 (min (% (sum 1) 20) 1) 1)))
+EOF
+)
+
+time_max_limit=1e-2
+freq_max_limit=1e-4
+time_rms_limit=5e-3
+max_sync_time=22000
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_sync || test_fail
+
+check_log_messages "Can't.*no selectable sources" 5 15 || test_fail
+check_log_messages "Selected source 192.168.123.1" 5 15 || test_fail
+
+test_pass
commit aa3660256a83768aa3fb640f6032780000c7a4fb
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Mar 13 15:55:32 2025 +0100
sources: improve no-selectable-sources log message
Include the number of unreachable sources in the "Can't synchronise: no
selectable sources" log message to provide a hint whether it might be a
networking issue.
diff --git a/sources.c b/sources.c
index b43ef8dc..406c2f86 100644
--- a/sources.c
+++ b/sources.c
@@ -937,7 +937,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
struct timespec now, ref_time;
int i, j, j1, j2, index, sel_prefer, n_endpoints, n_sel_sources, sel_req_source;
int max_badstat_reach, max_badstat_reach_size, n_badstats_sources;
- int max_sel_reach, max_sel_reach_size;
+ 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 orphan_stratum, orphan_source;
@@ -966,6 +966,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
n_endpoints = 0;
n_sel_sources = n_sel_trust_sources = 0;
n_badstats_sources = 0;
+ n_unreach_sources = 0;
sel_req_source = 0;
max_sel_reach = max_badstat_reach = 0;
max_sel_reach_size = max_badstat_reach_size = 0;
@@ -988,6 +989,10 @@ SRC_SelectSource(SRC_Instance updated_inst)
continue;
}
+ /* Count unreachable sources for a warning message */
+ if (sources[i]->reachability == 0)
+ n_unreach_sources++;
+
si = &sources[i]->sel_info;
SST_GetSelectionData(sources[i]->stats, &now,
&si->lo_limit, &si->hi_limit, &si->root_distance,
@@ -1155,7 +1160,8 @@ SRC_SelectSource(SRC_Instance updated_inst)
if (n_endpoints == 0) {
/* No sources provided valid endpoints */
- unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources");
+ unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources"
+ " (%d unreachable sources)", n_unreach_sources);
return;
}
diff --git a/test/simulation/014-intermittent b/test/simulation/014-intermittent
index 2f018ed0..4af574b7 100755
--- a/test/simulation/014-intermittent
+++ b/test/simulation/014-intermittent
@@ -22,7 +22,7 @@ run_test || test_fail
check_chronyd_exit || test_fail
check_sync || test_fail
-check_log_messages "Can't.*no selectable sources" 9 10 || test_fail
+check_log_messages "Can't.*no selectable sources (1 unreachable" 9 10 || test_fail
check_log_messages "Selected source 192.168.123.1" 9 10 || test_fail
# Pass every 20th request
@@ -43,7 +43,7 @@ run_test || test_fail
check_chronyd_exit || test_fail
check_sync || test_fail
-check_log_messages "Can't.*no selectable sources" 5 15 || test_fail
+check_log_messages "Can't.*no selectable sources (1 unreachable" 5 15 || test_fail
check_log_messages "Selected source 192.168.123.1" 5 15 || test_fail
test_pass
commit 402d5d9eb5767797e3af150119b63a08adf43813
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Mar 13 16:03:59 2025 +0100
sources: increase severity of can't-synchronise log messages
Switch the info-level "Can't synchronise" selection messages to
warnings.
diff --git a/sources.c b/sources.c
index 406c2f86..cfe7f260 100644
--- a/sources.c
+++ b/sources.c
@@ -954,7 +954,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
}
if (n_sources == 0) {
- unselect_selected_source(LOGS_INFO, "Can't synchronise: no sources");
+ unselect_selected_source(LOGS_WARN, "Can't synchronise: no sources");
return;
}
@@ -1160,7 +1160,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
if (n_endpoints == 0) {
/* No sources provided valid endpoints */
- unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources"
+ unselect_selected_source(LOGS_WARN, "Can't synchronise: no selectable sources"
" (%d unreachable sources)", n_unreach_sources);
return;
}
@@ -1306,7 +1306,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
}
if (!n_sel_sources || sel_req_source || n_sel_sources < CNF_GetMinSources()) {
- unselect_selected_source(LOGS_INFO, "Can't synchronise: %s selectable sources",
+ unselect_selected_source(LOGS_WARN, "Can't synchronise: %s selectable sources",
!n_sel_sources ? "no" :
sel_req_source ? "no required source in" : "not enough");
mark_ok_sources(SRC_WAITS_SOURCES);

View File

@ -0,0 +1,279 @@
commit d6aab8da1533b169385c749f8d1320c2b568a149
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Jun 2 10:53:47 2025 +0200
conf: fix sourcedir reloading to not multiply sources
The sourcedir reload triggered by the chronyc "reload sources"
command incorrectly assumed that NSR_AddSourceByName() can return
only the NSR_Success status when a source is added. It ignored the
NSR_UnresolvedName status returned for a source whose name needs to
be resolved after the call (i.e. not specified with an IP address)
and added the source again, effectively multiplying it if the name
can be resolved to a different IP address.
Fix the code to check for the NSR_UnresolvedName status to correctly
determine whether the source was already added before and should not be
added again.
Reported-by: MichaelR <MichaelR42@runbox.com>
Fixes: 916ed70c4a81 ("conf: save source status in sourcedir reload")
diff --git a/conf.c b/conf.c
index cbb11304..59a2e5c9 100644
--- a/conf.c
+++ b/conf.c
@@ -1742,8 +1742,8 @@ reload_source_dirs(void)
NTP_Source *prev_sources, *new_sources, *source;
unsigned int i, j, prev_size, new_size, unresolved;
char buf[MAX_LINE_LENGTH];
+ int d, pass, was_added;
NSR_Status s;
- int d, pass;
/* Ignore reload command before adding configured sources */
if (!conf_ntp_sources_added)
@@ -1782,13 +1782,16 @@ reload_source_dirs(void)
else
d = i < prev_size ? -1 : 1;
+ was_added = d <= 0 && (prev_sources[i].status == NSR_Success ||
+ prev_sources[i].status == NSR_UnresolvedName);
+
/* Remove missing sources before adding others to avoid conflicts */
- if (pass == 0 && d < 0 && prev_sources[i].status == NSR_Success) {
+ if (pass == 0 && d < 0 && was_added) {
NSR_RemoveSourcesById(prev_sources[i].conf_id);
}
/* Add new sources and sources that could not be added before */
- if (pass == 1 && (d > 0 || (d == 0 && prev_sources[i].status != NSR_Success))) {
+ if (pass == 1 && (d > 0 || (d == 0 && !was_added))) {
source = &new_sources[j];
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
source->pool, source->type, &source->params.params,
commit 778331092436c2f2077a7d0b6253ca1771fb8e27
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Jun 3 10:58:00 2025 +0200
test: add 149-sourcedir test
diff --git a/test/simulation/149-sourcedir b/test/simulation/149-sourcedir
new file mode 100755
index 00000000..77b8499f
--- /dev/null
+++ b/test/simulation/149-sourcedir
@@ -0,0 +1,189 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "sourcedir directive"
+
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
+servers=4
+limit=191
+update_executable="tmp/update-sourcedir"
+client_server_conf="sourcedir tmp"
+base_delay="(+ 1e-4 (* 5 (equal 0.1 from $[servers + 2])))"
+chronyc_start=1
+chronyc_conf="timeout 6000
+activity
+$(for i in $(seq 1 18); do echo "reload sources"; echo activity; done)"
+
+cat > tmp/sources.sources <<EOF
+pool nodes-1-2-3-4.net1.clk iburst
+EOF
+
+cat > tmp/update-sourcedir <<EOF
+#!/usr/bin/env bash
+case "\$1" in
+ 19) s="pool nodes-1-2-3-4.net1.clk";;
+ 39) s="pool nodes-1-2-3-4.net1.clk maxsources 3";;
+ 59) s="pool nodes-1-2-3.net1.clk";;
+ 79) s="pool nodes-1-2-3.net1.clk
+ server nodes-3-4.net1.clk";;
+ 99) s="server nodes-3-4.net1.clk";;
+ 119) s="server nodes-1-2-3.net1.clk";;
+ 139) s="server 192.168.123.2";;
+ 159) s="server 192.168.123.2 maxdelay 0.1";;
+ 179) s="";;
+ *) exit 0;;
+esac
+echo "\$s" > tmp/sources.sources
+EOF
+chmod 755 tmp/update-sourcedir
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+
+check_log_messages "T00:0.:[135].Z \(Added\|Removed\)" 0 0 || test_fail
+check_log_messages "T00:0.:..Z Added pool nodes-1-2-3-4\." 3 3 || test_fail
+check_log_messages "T00:0.:..Z Removed pool nodes-1-2-3-4\." 3 3 || test_fail
+check_log_messages "T00:0.:..Z Added pool nodes-1-2-3\." 1 1 || test_fail
+check_log_messages "T00:0.:..Z Removed pool nodes-1-2-3\." 1 1 || test_fail
+check_log_messages "T00:0.:..Z Added source ID#" 2 2 || test_fail
+check_log_messages "T00:0.:..Z Added source 192.168.123.[1234]" 2 2 || test_fail
+check_log_messages "T00:0.:..Z Removed source 192.168.123.[1234]" 4 4 || test_fail
+
+check_chronyc_output "^200 OK
+0 sources online
+0 sources offline
+4 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+0 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address$" || test_fail
+
+check_packet_interval || test_fail
+
+test_pass
diff --git a/test/simulation/test.common b/test/simulation/test.common
index 42a2917b..7eb348e3 100644
--- a/test/simulation/test.common
+++ b/test/simulation/test.common
@@ -39,6 +39,7 @@ default_refclock_jitter=""
default_refclock_offset=0.0
default_update_interval=0
+default_update_executable=""
default_shift_pll=2
default_server_strata=1
@@ -442,7 +443,9 @@ run_simulation() {
-o tmp/log.offset -f tmp/log.freq -p tmp/log.packets \
-R $(awk "BEGIN {print $update_interval < 0 ? 2^-($update_interval) : 1}") \
-r $(awk "BEGIN {print $max_sync_time * 2^$update_interval}") \
- -l $(awk "BEGIN {print $limit * 2^$update_interval}") && test_ok || test_error
+ -l $(awk "BEGIN {print $limit * 2^$update_interval}") \
+ $([ "$update_executable" != "" ] && printf "%s" "-e $update_executable") && \
+ test_ok || test_error
}
run_test() {

View File

@ -0,0 +1,64 @@
commit 1205197f2e15166a47fa1817feaf3587738fb37a
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Nov 27 16:03:19 2024 +0100
avoid timestamps from future in PTP_SYS_OFFSET_EXTENDED
diff --git a/client.c b/client.c
index 065eddf..32796e0 100644
--- a/client.c
+++ b/client.c
@@ -2065,24 +2065,24 @@ int ioctl(int fd, unsigned long request, ...) {
} else if (request == PTP_SYS_OFFSET_EXTENDED && fd == REFCLK_FD) {
struct ptp_sys_offset_extended *sys_off = va_arg(ap, struct ptp_sys_offset_extended *);
struct timespec ts, ts1, ts2;
+ double delay;
int i;
if (sys_off->n_samples > PTP_MAX_SAMPLES)
sys_off->n_samples = PTP_MAX_SAMPLES;
for (i = 0; i < sys_off->n_samples; i++) {
+ clock_gettime(CLOCK_REALTIME, &ts2);
clock_gettime(REFCLK_ID, &ts);
- sys_off->ts[i][1].sec = ts.tv_sec;
- sys_off->ts[i][1].nsec = ts.tv_nsec;
- }
-
- clock_gettime(CLOCK_REALTIME, &ts);
- for (i = 0; i < sys_off->n_samples; i++) {
- ts1 = ts, ts2 = ts;
- add_to_timespec(&ts1, -get_phc_delay(-1));
- add_to_timespec(&ts2, get_phc_delay(1));
+ delay = get_phc_delay(1);
+ add_to_timespec(&ts, -delay);
+ delay += get_phc_delay(-1);
+ ts1 = ts2;
+ add_to_timespec(&ts1, -delay);
sys_off->ts[i][0].sec = ts1.tv_sec;
sys_off->ts[i][0].nsec = ts1.tv_nsec;
+ sys_off->ts[i][1].sec = ts.tv_sec;
+ sys_off->ts[i][1].nsec = ts.tv_nsec;
sys_off->ts[i][2].sec = ts2.tv_sec;
sys_off->ts[i][2].nsec = ts2.tv_nsec;
}
commit 8b8831d98df1fca21288a9bc18c6a8fbfe6874a6
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Nov 27 16:06:40 2024 +0100
round nanoseconds in PTP_SYS_OFFSET* delay adjustments
diff --git a/client.c b/client.c
index 32796e0..0e235a6 100644
--- a/client.c
+++ b/client.c
@@ -794,7 +794,7 @@ static void normalize_timespec(struct timespec *tp) {
static void add_to_timespec(struct timespec *tp, double offset) {
tp->tv_sec += floor(offset);
- tp->tv_nsec += (offset - floor(offset)) * 1e9;
+ tp->tv_nsec += round((offset - floor(offset)) * 1e9);
normalize_timespec(tp);
}

View File

@ -1,5 +1,5 @@
%global _hardened_build 1
%global clknetsim_ver 40bb97
%global clknetsim_ver cdd694
%bcond_without debug
%bcond_without nts
@ -9,7 +9,7 @@
Name: chrony
Version: 4.6.1
Release: 1%{?dist}
Release: 2%{?dist}
Summary: An NTP client/server
License: GPLv2
@ -33,6 +33,15 @@ Patch3: chrony-services.patch
Patch4: chrony-defconfig.patch
# keep PHC refclock reachable when dropping samples due to high delay
Patch5: chrony-refclkreach.patch
# improve description of refresh directive
Patch6: chrony-docrefresh.patch
# improve logging of selection failures
Patch7: chrony-logselect.patch
# fix sourcedir reloading to not multiply sources
Patch8: chrony-sourcedir.patch
# revert clknetsim changes in PHC breaking old refclock tests
Patch20: clknetsim-revert-phc.patch
BuildRequires: gnutls-devel libcap-devel libedit-devel pps-tools-devel
BuildRequires: gcc gcc-c++ make bison systemd gnupg2
@ -63,11 +72,18 @@ service to other computers in the network.
%{gpgverify} --keyring=%{SOURCE2} --signature=%{SOURCE1} --data=%{SOURCE0}
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
%{?gitpatch:%patch0 -p1}
%patch1 -p1 -b .nm-dispatcher-dhcp
%patch2 -p1 -b .keys
%patch3 -p1 -b .services
%patch4 -p1 -b .defconfig
%patch5 -p1
%patch -P 1 -p1 -b .nm-dispatcher-dhcp
%patch -P 2 -p1 -b .keys
%patch -P 3 -p1 -b .services
%patch -P 4 -p1 -b .defconfig
%patch -P 5 -p1
%patch -P 6 -p1 -b .docrefresh
%patch -P 7 -p1
%patch -P 8 -p1
pushd clknetsim-*-%{clknetsim_ver}*
%patch -P 20 -R -p1
popd
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
@ -220,6 +236,12 @@ fi
%dir %attr(750,chrony,chrony) %{_localstatedir}/log/chrony
%changelog
* Wed Jun 04 2025 Miroslav Lichvar <mlichvar@redhat.com> 4.6.1-2
- improve description of refresh directive (RHEL-82096)
- improve logging of selection failures (RHEL-80388 RHEL-80413 RHEL-80415)
- fix sourcedir reloading to not multiply sources (RHEL-95016)
- switch from patchX to patch -P X
* Wed Nov 06 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.6.1-1
- update to 4.6.1 (RHEL-61877)
- keep PHC refclock reachable when dropping samples due to high delay