Compare commits

..

5 Commits

Author SHA1 Message Date
Miroslav Lichvar
120dfb8b36 update copyright years 2023-12-05 14:22:10 +01:00
Miroslav Lichvar
598b893e1d doc: update FAQ on improving accuracy 2023-12-05 14:22:10 +01:00
Miroslav Lichvar
89aa8fa342 doc: mention dependency of net corrections on HW timestamping 2023-12-05 14:22:08 +01:00
Miroslav Lichvar
42fdad5dcc doc: improve description of reload sources command 2023-12-04 16:50:51 +01:00
Miroslav Lichvar
3ee7b3e786 sources: rework logging of selection loss
The commit 5dd288dc0c ("sources: reselect earlier when removing
selected source") didn't cover all paths that can lead to a missing log
message when all sources are removed.

Add a flag to track the loss of selection and postpone the log message
in transient states where no message is logged to avoid spamming in
normal operation. Call SRC_SelectSource() after removing the source
to get a log message if there are no (selectable) sources left.

Reported-by: Thomas Lange <thomas@corelatus.se>
2023-11-28 12:21:23 +01:00
7 changed files with 63 additions and 23 deletions

View File

@@ -339,8 +339,10 @@ Protocol (PTP) correction field in NTP-over-PTP messages updated by one-step
end-to-end transparent clocks in network switches and routers to significantly end-to-end transparent clocks in network switches and routers to significantly
improve accuracy and stability of the synchronisation. NTP-over-PTP can be improve accuracy and stability of the synchronisation. NTP-over-PTP can be
enabled by the <<ptpport,*ptpport*>> directive and setting the *port* option to enabled by the <<ptpport,*ptpport*>> directive and setting the *port* option to
the PTP port. This field should be enabled only for servers known to be running the PTP port. The corrections are applied only to NTP measurements with HW
*chronyd* version 4.5 or later. timestamps (enabled by the <<hwtimestamp,*hwtimestamp*>> directive). This
field should be enabled only for servers known to be running *chronyd* version
4.5 or later.
{blank}::: {blank}:::
[[pool]]*pool* _name_ [_option_]...:: [[pool]]*pool* _name_ [_option_]...::

View File

@@ -986,6 +986,10 @@ command might replace the addresses even if they are still in the pool.
The *reload sources* command causes *chronyd* to re-read all _*.sources_ files The *reload sources* command causes *chronyd* to re-read all _*.sources_ files
from the directories specified by the from the directories specified by the
<<chrony.conf.adoc#sourcedir,*sourcedir*>> directive. <<chrony.conf.adoc#sourcedir,*sourcedir*>> directive.
+
Note that modified sources (e.g. specified with a new option) are not modified
in memory. They are removed and added again, which causes them to lose old
measurements and reset the selection state.
[[sourcename]]*sourcename* _address_:: [[sourcename]]*sourcename* _address_::
The *sourcename* command prints the original hostname or address that was The *sourcename* command prints the original hostname or address that was

View File

@@ -1,6 +1,7 @@
// This file is part of chrony // This file is part of chrony
// //
// Copyright (C) Richard P. Curnow 1997-2003 // Copyright (C) Richard P. Curnow 1997-2003
// Copyright (C) Luke Valenta 2023
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2023 // Copyright (C) Miroslav Lichvar 2014-2016, 2020-2023
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
@@ -381,7 +382,7 @@ outliers corrupting the minimum delay. For example:
server ntp.local minpoll -7 maxpoll -7 filter 31 maxdelayquant 0.3 xleave server ntp.local minpoll -7 maxpoll -7 filter 31 maxdelayquant 0.3 xleave
---- ----
As an experimental feature added in version 4.2, `chronyd` supports an NTPv4 Since version 4.2, `chronyd` supports an NTPv4
extension field containing an additional timestamp to enable frequency transfer extension field containing an additional timestamp to enable frequency transfer
and significantly improve stability of synchronisation. It can be enabled by and significantly improve stability of synchronisation. It can be enabled by
the `extfield F323` option. For example: the `extfield F323` option. For example:
@@ -390,6 +391,18 @@ the `extfield F323` option. For example:
server ntp.local minpoll 0 maxpoll 0 xleave extfield F323 server ntp.local minpoll 0 maxpoll 0 xleave extfield F323
---- ----
Since version 4.5, `chronyd` can apply corrections from PTP one-step end-to-end
transparent clocks (e.g. network switches) to significantly improve accuracy of
synchronisation in local networks. It requires the PTP transport to be enabled
by the `ptpport` directive, HW timestamping, and the `extfield F324` option.
For example:
----
server ntp.local minpoll -4 maxpoll -4 xleave extfield F323 extfield F324 port 319
ptpport 319
hwtimestamp eth0 minpoll -4
----
=== Does `chronyd` have an ntpdate mode? === Does `chronyd` have an ntpdate mode?
Yes. With the `-q` option `chronyd` will set the system clock once and exit. Yes. With the `-q` option `chronyd` will set the system clock once and exit.

View File

@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Miroslav Lichvar 2020 * Copyright (C) Miroslav Lichvar 2020, 2023
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -5,6 +5,7 @@
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009 * Copyright (C) Timo Teras 2009
* Copyright (C) Miroslav Lichvar 2009, 2013-2020 * Copyright (C) Miroslav Lichvar 2009, 2013-2020
* Copyright (C) Luke Valenta 2023
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -174,6 +174,9 @@ static int selected_source_index; /* Which source index is currently
if no current valid reference) */ if no current valid reference) */
static int reported_no_majority; /* Flag to avoid repeated log message static int reported_no_majority; /* Flag to avoid repeated log message
about no majority */ about no majority */
static int report_selection_loss; /* Flag to force logging a message if
selection is lost in a transient state
(SRC_WAITS_STATS, SRC_WAITS_UPDATE) */
/* Score needed to replace the currently selected source */ /* Score needed to replace the currently selected source */
#define SCORE_LIMIT 10.0 #define SCORE_LIMIT 10.0
@@ -201,6 +204,8 @@ static LOG_FileID logfileid;
/* Forward prototype */ /* Forward prototype */
static void update_sel_options(void); static void update_sel_options(void);
static void unselect_selected_source(LOG_Severity severity, const char *format,
const char *arg);
static void slew_sources(struct timespec *raw, struct timespec *cooked, double dfreq, static void slew_sources(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything); double doffset, LCL_ChangeType change_type, void *anything);
static void add_dispersion(double dispersion, void *anything); static void add_dispersion(double dispersion, void *anything);
@@ -314,12 +319,8 @@ void SRC_DestroyInstance(SRC_Instance instance)
if (last_updated_inst == instance) if (last_updated_inst == instance)
last_updated_inst = NULL; last_updated_inst = NULL;
/* Force reselection if currently selected */
SRC_ResetInstance(instance);
assert(initialised); assert(initialised);
if (instance->index < 0 || instance->index >= n_sources || if (instance->index < 0 || instance->index >= n_sources ||
instance->index == selected_source_index ||
instance != sources[instance->index]) instance != sources[instance->index])
assert(0); assert(0);
@@ -336,6 +337,10 @@ void SRC_DestroyInstance(SRC_Instance instance)
if (selected_source_index > dead_index) if (selected_source_index > dead_index)
--selected_source_index; --selected_source_index;
else if (selected_source_index == dead_index)
unselect_selected_source(LOGS_INFO, NULL, NULL);
SRC_SelectSource(NULL);
} }
/* ================================================== */ /* ================================================== */
@@ -737,6 +742,26 @@ mark_ok_sources(SRC_Status status)
} }
} }
/* ================================================== */
/* Reset the index of selected source and report the selection loss. If no
message is provided, assume it is a transient state and wait for another
call providing a message or selection of another source, which resets the
report_selection_loss flag. */
static void
unselect_selected_source(LOG_Severity severity, const char *format, const char *arg)
{
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);
report_selection_loss = 0;
}
}
/* ================================================== */ /* ================================================== */
static int static int
@@ -854,9 +879,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
} }
if (n_sources == 0) { if (n_sources == 0) {
/* Removed sources are unselected before actual removal */ unselect_selected_source(LOGS_INFO, "Can't synchronise: no sources", NULL);
if (selected_source_index != INVALID_SOURCE)
assert(0);
return; return;
} }
@@ -1041,15 +1064,13 @@ SRC_SelectSource(SRC_Instance updated_inst)
if (n_badstats_sources && n_sel_sources && selected_source_index == INVALID_SOURCE && 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) { max_sel_reach_size < SOURCE_REACH_BITS && max_sel_reach >> 1 == max_badstat_reach) {
mark_ok_sources(SRC_WAITS_STATS); mark_ok_sources(SRC_WAITS_STATS);
unselect_selected_source(LOGS_INFO, NULL, NULL);
return; return;
} }
if (n_endpoints == 0) { if (n_endpoints == 0) {
/* No sources provided valid endpoints */ /* No sources provided valid endpoints */
if (selected_source_index != INVALID_SOURCE) { unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources", NULL);
log_selection_message(LOGS_INFO, "Can't synchronise: no selectable sources", NULL);
selected_source_index = INVALID_SOURCE;
}
return; return;
} }
@@ -1130,6 +1151,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
if (!reported_no_majority) { 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", NULL);
reported_no_majority = 1; reported_no_majority = 1;
report_selection_loss = 0;
} }
if (selected_source_index != INVALID_SOURCE) { if (selected_source_index != INVALID_SOURCE) {
@@ -1186,12 +1208,9 @@ SRC_SelectSource(SRC_Instance updated_inst)
} }
if (!n_sel_sources || sel_req_source || n_sel_sources < CNF_GetMinSources()) { if (!n_sel_sources || sel_req_source || n_sel_sources < CNF_GetMinSources()) {
if (selected_source_index != INVALID_SOURCE) { unselect_selected_source(LOGS_INFO, "Can't synchronise: %s selectable sources",
log_selection_message(LOGS_INFO, "Can't synchronise: %s selectable sources",
!n_sel_sources ? "no" : !n_sel_sources ? "no" :
sel_req_source ? "no required source in" : "not enough"); sel_req_source ? "no required source in" : "not enough");
selected_source_index = INVALID_SOURCE;
}
mark_ok_sources(SRC_WAITS_SOURCES); mark_ok_sources(SRC_WAITS_SOURCES);
return; return;
} }
@@ -1298,7 +1317,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
/* Before selecting the new synchronisation source wait until the reference /* Before selecting the new synchronisation source wait until the reference
can be updated */ can be updated */
if (sources[max_score_index]->updates == 0) { if (sources[max_score_index]->updates == 0) {
selected_source_index = INVALID_SOURCE; unselect_selected_source(LOGS_INFO, NULL, NULL);
mark_ok_sources(SRC_WAITS_UPDATE); mark_ok_sources(SRC_WAITS_UPDATE);
return; return;
} }
@@ -1314,6 +1333,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
} }
reported_no_majority = 0; reported_no_majority = 0;
report_selection_loss = 0;
} }
mark_source(sources[selected_source_index], SRC_SELECTED); mark_source(sources[selected_source_index], SRC_SELECTED);

View File

@@ -1,6 +1,6 @@
/* /*
********************************************************************** **********************************************************************
* Copyright (C) Miroslav Lichvar 2017-2018, 2021 * Copyright (C) Miroslav Lichvar 2017-2018, 2021, 2023
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as