mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-05 08:45:06 -05:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
113d1134d1 | ||
|
|
b363af754d | ||
|
|
0f5cf57bc2 | ||
|
|
5a43f0c39b | ||
|
|
5a6fbe7a4b | ||
|
|
bb34e92f96 | ||
|
|
78b9c13a11 | ||
|
|
1ab5b88939 | ||
|
|
e30f937f6a | ||
|
|
08b67dba98 | ||
|
|
61f15fedcd | ||
|
|
6d59234995 | ||
|
|
d4a4f89329 | ||
|
|
916ed70c4a | ||
|
|
8ba2da52df | ||
|
|
fd9e956d27 |
1
NEWS
1
NEWS
@@ -8,6 +8,7 @@ Enhancements
|
|||||||
* Add kod option to ratelimit directive for server KoD RATE support
|
* Add kod option to ratelimit directive for server KoD RATE support
|
||||||
* Add leapseclist directive to read NIST/IERS leap-seconds.list file
|
* Add leapseclist directive to read NIST/IERS leap-seconds.list file
|
||||||
* Add ptpdomain directive to set PTP domain for NTP over PTP
|
* Add ptpdomain directive to set PTP domain for NTP over PTP
|
||||||
|
* Allow disabling pidfile
|
||||||
* Improve copy server option to accept unsynchronised status instantly
|
* Improve copy server option to accept unsynchronised status instantly
|
||||||
* Log one selection failure on start
|
* Log one selection failure on start
|
||||||
* Add offset command to modify source offset correction
|
* Add offset command to modify source offset correction
|
||||||
|
|||||||
1
README
1
README
@@ -75,6 +75,7 @@ Lonnie Abelbeck <lonnie@abelbeck.com>
|
|||||||
Benny Lyne Amorsen <benny@amorsen.dk>
|
Benny Lyne Amorsen <benny@amorsen.dk>
|
||||||
Andrew Bishop <amb@gedanken.demon.co.uk>
|
Andrew Bishop <amb@gedanken.demon.co.uk>
|
||||||
Vincent Blut <vincent.debian@free.fr>
|
Vincent Blut <vincent.debian@free.fr>
|
||||||
|
Luca Boccassi <bluca@debian.org>
|
||||||
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
||||||
David Bohman <debohman@gmail.com>
|
David Bohman <debohman@gmail.com>
|
||||||
Goswin Brederlow <brederlo@informatik.uni-tuebingen.de>
|
Goswin Brederlow <brederlo@informatik.uni-tuebingen.de>
|
||||||
|
|||||||
4
client.c
4
client.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Lonnie Abelbeck 2016, 2018
|
* Copyright (C) Lonnie Abelbeck 2016, 2018
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2023
|
* Copyright (C) Miroslav Lichvar 2009-2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -3440,7 +3440,7 @@ static void
|
|||||||
display_gpl(void)
|
display_gpl(void)
|
||||||
{
|
{
|
||||||
printf("chrony version %s\n"
|
printf("chrony version %s\n"
|
||||||
"Copyright (C) 1997-2003, 2007, 2009-2023 Richard P. Curnow and others\n"
|
"Copyright (C) 1997-2003, 2007, 2009-2024 Richard P. Curnow and others\n"
|
||||||
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
||||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||||
"GNU General Public License version 2 for details.\n\n",
|
"GNU General Public License version 2 for details.\n\n",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009, 2015-2017, 2021
|
* Copyright (C) Miroslav Lichvar 2009, 2015-2017, 2021, 2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
2
cmdmon.c
2
cmdmon.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2016, 2018-2023
|
* Copyright (C) Miroslav Lichvar 2009-2016, 2018-2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
63
conf.c
63
conf.c
@@ -78,6 +78,7 @@ static void parse_makestep(char *);
|
|||||||
static void parse_maxchange(char *);
|
static void parse_maxchange(char *);
|
||||||
static void parse_ntsserver(char *, ARR_Instance files);
|
static void parse_ntsserver(char *, ARR_Instance files);
|
||||||
static void parse_ntstrustedcerts(char *);
|
static void parse_ntstrustedcerts(char *);
|
||||||
|
static void parse_pidfile(char *line);
|
||||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||||
int *burst, int *leak, int *kod);
|
int *burst, int *leak, int *kod);
|
||||||
static void parse_refclock(char *);
|
static void parse_refclock(char *);
|
||||||
@@ -294,15 +295,15 @@ typedef struct {
|
|||||||
NTP_Source_Type type;
|
NTP_Source_Type type;
|
||||||
int pool;
|
int pool;
|
||||||
CPS_NTP_Source params;
|
CPS_NTP_Source params;
|
||||||
|
NSR_Status status;
|
||||||
|
uint32_t conf_id;
|
||||||
} NTP_Source;
|
} NTP_Source;
|
||||||
|
|
||||||
/* Array of NTP_Source */
|
/* Array of NTP_Source */
|
||||||
static ARR_Instance ntp_sources;
|
static ARR_Instance ntp_sources;
|
||||||
/* Array of (char *) */
|
/* Array of (char *) */
|
||||||
static ARR_Instance ntp_source_dirs;
|
static ARR_Instance ntp_source_dirs;
|
||||||
/* Array of uint32_t corresponding to ntp_sources (for sourcedirs reload) */
|
/* Flag indicating ntp_sources is used for sourcedirs after config load */
|
||||||
static ARR_Instance ntp_source_ids;
|
|
||||||
/* Flag indicating ntp_sources and ntp_source_ids are used for sourcedirs */
|
|
||||||
static int conf_ntp_sources_added = 0;
|
static int conf_ntp_sources_added = 0;
|
||||||
|
|
||||||
/* Array of RefclockParameters */
|
/* Array of RefclockParameters */
|
||||||
@@ -403,7 +404,6 @@ CNF_Initialise(int r, int client_only)
|
|||||||
init_sources = ARR_CreateInstance(sizeof (IPAddr));
|
init_sources = ARR_CreateInstance(sizeof (IPAddr));
|
||||||
ntp_sources = ARR_CreateInstance(sizeof (NTP_Source));
|
ntp_sources = ARR_CreateInstance(sizeof (NTP_Source));
|
||||||
ntp_source_dirs = ARR_CreateInstance(sizeof (char *));
|
ntp_source_dirs = ARR_CreateInstance(sizeof (char *));
|
||||||
ntp_source_ids = ARR_CreateInstance(sizeof (uint32_t));
|
|
||||||
refclock_sources = ARR_CreateInstance(sizeof (RefclockParameters));
|
refclock_sources = ARR_CreateInstance(sizeof (RefclockParameters));
|
||||||
broadcasts = ARR_CreateInstance(sizeof (NTP_Broadcast_Destination));
|
broadcasts = ARR_CreateInstance(sizeof (NTP_Broadcast_Destination));
|
||||||
|
|
||||||
@@ -463,7 +463,6 @@ CNF_Finalise(void)
|
|||||||
ARR_DestroyInstance(init_sources);
|
ARR_DestroyInstance(init_sources);
|
||||||
ARR_DestroyInstance(ntp_sources);
|
ARR_DestroyInstance(ntp_sources);
|
||||||
ARR_DestroyInstance(ntp_source_dirs);
|
ARR_DestroyInstance(ntp_source_dirs);
|
||||||
ARR_DestroyInstance(ntp_source_ids);
|
|
||||||
ARR_DestroyInstance(refclock_sources);
|
ARR_DestroyInstance(refclock_sources);
|
||||||
ARR_DestroyInstance(broadcasts);
|
ARR_DestroyInstance(broadcasts);
|
||||||
|
|
||||||
@@ -705,7 +704,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
} else if (!strcasecmp(command, "peer")) {
|
} else if (!strcasecmp(command, "peer")) {
|
||||||
parse_source(p, command, 1);
|
parse_source(p, command, 1);
|
||||||
} else if (!strcasecmp(command, "pidfile")) {
|
} else if (!strcasecmp(command, "pidfile")) {
|
||||||
parse_string(p, &pidfile);
|
parse_pidfile(p);
|
||||||
} else if (!strcasecmp(command, "pool")) {
|
} else if (!strcasecmp(command, "pool")) {
|
||||||
parse_source(p, command, 1);
|
parse_source(p, command, 1);
|
||||||
} else if (!strcasecmp(command, "port")) {
|
} else if (!strcasecmp(command, "port")) {
|
||||||
@@ -837,6 +836,9 @@ parse_source(char *line, char *type, int fatal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
source.params.name = Strdup(source.params.name);
|
source.params.name = Strdup(source.params.name);
|
||||||
|
source.status = NSR_NoSuchSource;
|
||||||
|
source.conf_id = 0;
|
||||||
|
|
||||||
ARR_AppendElement(ntp_sources, &source);
|
ARR_AppendElement(ntp_sources, &source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1528,6 +1530,20 @@ parse_hwtimestamp(char *line)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_pidfile(char *line)
|
||||||
|
{
|
||||||
|
parse_string(line, &pidfile);
|
||||||
|
|
||||||
|
/* / disables the PID file handling */
|
||||||
|
if (strcmp(pidfile, "/") == 0) {
|
||||||
|
Free(pidfile);
|
||||||
|
pidfile = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
get_basename(const char *path)
|
get_basename(const char *path)
|
||||||
{
|
{
|
||||||
@@ -1694,7 +1710,6 @@ reload_source_dirs(void)
|
|||||||
{
|
{
|
||||||
NTP_Source *prev_sources, *new_sources, *source;
|
NTP_Source *prev_sources, *new_sources, *source;
|
||||||
unsigned int i, j, prev_size, new_size, unresolved;
|
unsigned int i, j, prev_size, new_size, unresolved;
|
||||||
uint32_t *prev_ids, *new_ids;
|
|
||||||
char buf[MAX_LINE_LENGTH];
|
char buf[MAX_LINE_LENGTH];
|
||||||
NSR_Status s;
|
NSR_Status s;
|
||||||
int d, pass;
|
int d, pass;
|
||||||
@@ -1703,13 +1718,9 @@ reload_source_dirs(void)
|
|||||||
if (!conf_ntp_sources_added)
|
if (!conf_ntp_sources_added)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prev_size = ARR_GetSize(ntp_source_ids);
|
prev_size = ARR_GetSize(ntp_sources);
|
||||||
if (ARR_GetSize(ntp_sources) != prev_size)
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
/* Save the current sources and their configuration IDs */
|
/* Save the current sources */
|
||||||
prev_ids = MallocArray(uint32_t, prev_size);
|
|
||||||
memcpy(prev_ids, ARR_GetElements(ntp_source_ids), prev_size * sizeof (prev_ids[0]));
|
|
||||||
prev_sources = MallocArray(NTP_Source, prev_size);
|
prev_sources = MallocArray(NTP_Source, prev_size);
|
||||||
memcpy(prev_sources, ARR_GetElements(ntp_sources), prev_size * sizeof (prev_sources[0]));
|
memcpy(prev_sources, ARR_GetElements(ntp_sources), prev_size * sizeof (prev_sources[0]));
|
||||||
|
|
||||||
@@ -1727,8 +1738,6 @@ reload_source_dirs(void)
|
|||||||
|
|
||||||
new_size = ARR_GetSize(ntp_sources);
|
new_size = ARR_GetSize(ntp_sources);
|
||||||
new_sources = ARR_GetElements(ntp_sources);
|
new_sources = ARR_GetElements(ntp_sources);
|
||||||
ARR_SetSize(ntp_source_ids, new_size);
|
|
||||||
new_ids = ARR_GetElements(ntp_source_ids);
|
|
||||||
unresolved = 0;
|
unresolved = 0;
|
||||||
|
|
||||||
LOG_SetContext(LOGC_SourceFile);
|
LOG_SetContext(LOGC_SourceFile);
|
||||||
@@ -1743,31 +1752,31 @@ reload_source_dirs(void)
|
|||||||
d = i < prev_size ? -1 : 1;
|
d = i < prev_size ? -1 : 1;
|
||||||
|
|
||||||
/* Remove missing sources before adding others to avoid conflicts */
|
/* Remove missing sources before adding others to avoid conflicts */
|
||||||
if (pass == 0 && d < 0 && prev_sources[i].params.name[0] != '\0') {
|
if (pass == 0 && d < 0 && prev_sources[i].status == NSR_Success) {
|
||||||
NSR_RemoveSourcesById(prev_ids[i]);
|
NSR_RemoveSourcesById(prev_sources[i].conf_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new sources */
|
/* Add new sources and sources that could not be added before */
|
||||||
if (pass == 1 && d > 0) {
|
if (pass == 1 && (d > 0 || (d == 0 && prev_sources[i].status != NSR_Success))) {
|
||||||
source = &new_sources[j];
|
source = &new_sources[j];
|
||||||
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
|
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
|
||||||
source->pool, source->type, &source->params.params,
|
source->pool, source->type, &source->params.params,
|
||||||
&new_ids[j]);
|
&source->conf_id);
|
||||||
|
source->status = s;
|
||||||
|
|
||||||
if (s == NSR_UnresolvedName) {
|
if (s == NSR_UnresolvedName) {
|
||||||
unresolved++;
|
unresolved++;
|
||||||
} else if (s != NSR_Success) {
|
} else if (s != NSR_Success && (d > 0 || s != prev_sources[i].status)) {
|
||||||
LOG(LOGS_ERR, "Could not add source %s : %s",
|
LOG(LOGS_ERR, "Could not add source %s : %s",
|
||||||
source->params.name, NSR_StatusToString(s));
|
source->params.name, NSR_StatusToString(s));
|
||||||
|
|
||||||
/* Mark the source as not present */
|
|
||||||
source->params.name[0] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep unchanged sources */
|
/* Keep unchanged sources */
|
||||||
if (pass == 1 && d == 0)
|
if (pass == 1 && d == 0) {
|
||||||
new_ids[j] = prev_ids[i];
|
new_sources[j].status = prev_sources[i].status;
|
||||||
|
new_sources[j].conf_id = prev_sources[i].conf_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1776,7 +1785,6 @@ reload_source_dirs(void)
|
|||||||
for (i = 0; i < prev_size; i++)
|
for (i = 0; i < prev_size; i++)
|
||||||
Free(prev_sources[i].params.name);
|
Free(prev_sources[i].params.name);
|
||||||
Free(prev_sources);
|
Free(prev_sources);
|
||||||
Free(prev_ids);
|
|
||||||
|
|
||||||
if (unresolved > 0)
|
if (unresolved > 0)
|
||||||
NSR_ResolveSources();
|
NSR_ResolveSources();
|
||||||
@@ -1875,7 +1883,6 @@ CNF_AddSources(void)
|
|||||||
|
|
||||||
/* The arrays will be used for sourcedir (re)loading */
|
/* The arrays will be used for sourcedir (re)loading */
|
||||||
ARR_SetSize(ntp_sources, 0);
|
ARR_SetSize(ntp_sources, 0);
|
||||||
ARR_SetSize(ntp_source_ids, 0);
|
|
||||||
conf_ntp_sources_added = 1;
|
conf_ntp_sources_added = 1;
|
||||||
|
|
||||||
reload_source_dirs();
|
reload_source_dirs();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Stephen Wadeley 2016
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
// Copyright (C) Bryan Christianson 2017
|
// Copyright (C) Bryan Christianson 2017
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2023
|
// Copyright (C) Miroslav Lichvar 2009-2024
|
||||||
//
|
//
|
||||||
// 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
|
||||||
@@ -126,6 +126,15 @@ mechanism. Unlike with the *key* option, the server and client do not need to
|
|||||||
share a key in a key file. NTS has a Key Establishment (NTS-KE) protocol using
|
share a key in a key file. NTS has a Key Establishment (NTS-KE) protocol using
|
||||||
the Transport Layer Security (TLS) protocol to get the keys and cookies
|
the Transport Layer Security (TLS) protocol to get the keys and cookies
|
||||||
required by NTS for authentication of NTP packets.
|
required by NTS for authentication of NTP packets.
|
||||||
|
+
|
||||||
|
With this option, the hostname specified in the server or pool directive is the
|
||||||
|
NTS-KE server or pool of NTS-KE servers respectively. The NTP server usually
|
||||||
|
runs on the same host, but it can be separated from the NTS-KE server (the
|
||||||
|
hostname or address of the NTP server is provided to the client by the NTS-KE
|
||||||
|
server).
|
||||||
|
+
|
||||||
|
The NTS-KE server can be specified by IP address if it is included in the
|
||||||
|
server's certificate as a Subject Alternative Name (SAN).
|
||||||
*certset* _ID_:::
|
*certset* _ID_:::
|
||||||
This option specifies which set of trusted certificates should be used to verify
|
This option specifies which set of trusted certificates should be used to verify
|
||||||
the server's certificate when the *nts* option is enabled. Sets of certificates
|
the server's certificate when the *nts* option is enabled. Sets of certificates
|
||||||
@@ -2772,6 +2781,8 @@ e.g.:
|
|||||||
----
|
----
|
||||||
pidfile /run/chronyd.pid
|
pidfile /run/chronyd.pid
|
||||||
----
|
----
|
||||||
|
+
|
||||||
|
Setting this directive to _/_ disables writing and checking of the PID file.
|
||||||
|
|
||||||
[[ptpport]]*ptpport* _port_::
|
[[ptpport]]*ptpport* _port_::
|
||||||
The *ptpport* directive enables *chronyd* to send and receive NTP messages
|
The *ptpport* directive enables *chronyd* to send and receive NTP messages
|
||||||
|
|||||||
60
doc/faq.adoc
60
doc/faq.adoc
@@ -2,7 +2,7 @@
|
|||||||
//
|
//
|
||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Luke Valenta 2023
|
// Copyright (C) Luke Valenta 2023
|
||||||
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2023
|
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2024
|
||||||
//
|
//
|
||||||
// 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
|
||||||
@@ -772,6 +772,17 @@ print all sources, even those that do not have a known address yet, with their
|
|||||||
names as they were specified in the configuration. This can be useful to verify
|
names as they were specified in the configuration. This can be useful to verify
|
||||||
that the names specified in the configuration are used as expected.
|
that the names specified in the configuration are used as expected.
|
||||||
|
|
||||||
|
When DNSSEC is enabled, it will not work until the time is synchronized, as it
|
||||||
|
requires validating a signature timestamp and its expiration date, so if the
|
||||||
|
system time is too far in the future or the past DNSSEC validation will fail and
|
||||||
|
`chronyd` will be unable to resolve the address of the NTP server. In such cases,
|
||||||
|
if hostnames are the only options and bare IP addresses cannot be used, DNSSEC
|
||||||
|
can be disabled for `chronyd` using resolver-specific mechanisms, if available,
|
||||||
|
although of course that means losing the protection afforded by DNSSEC.
|
||||||
|
For example, when using systemd-resolved, the `SYSTEMD_NSS_RESOLVE_VALIDATE=0`
|
||||||
|
environment variable can be set, for example in the `chronyd` systemd unit via
|
||||||
|
`Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0`.
|
||||||
|
|
||||||
=== Is `chronyd` allowed to step the system clock?
|
=== Is `chronyd` allowed to step the system clock?
|
||||||
|
|
||||||
By default, `chronyd` adjusts the clock gradually by slowing it down or
|
By default, `chronyd` adjusts the clock gradually by slowing it down or
|
||||||
@@ -1155,6 +1166,53 @@ There are several different clocks used by `chronyd`:
|
|||||||
synchronised by `chronyd`. Its offset is tracked relative to the NTP clock in
|
synchronised by `chronyd`. Its offset is tracked relative to the NTP clock in
|
||||||
order to convert the hardware timestamps.
|
order to convert the hardware timestamps.
|
||||||
|
|
||||||
|
=== How accurate is my system clock?
|
||||||
|
|
||||||
|
`chronyd` does not know how accurate really is the clock it is synchronizing.
|
||||||
|
Even if the measured offset of the clock is stable to nanoseconds, it could be
|
||||||
|
off by milliseconds due to asymmetric network delay, e.g. caused by asymmetric
|
||||||
|
routing or queuing delays in network switches. NTP provides root delay and root
|
||||||
|
dispersion to enable clients to estimate the maximum error of their clock.
|
||||||
|
|
||||||
|
Root delay measures the sum of round-trip times between all NTP servers on the
|
||||||
|
path from the client to the primary time source (e.g. a GPS receiver). Half of
|
||||||
|
the root delay is the maximum error due to asymmetric delays, assuming one
|
||||||
|
direction (e.g. from the client to the server) has a zero delay and the other
|
||||||
|
direction (from the server to the client) takes all of the measured delay. The
|
||||||
|
root delay also covers timestamping errors if the server implementation and
|
||||||
|
hardware meet the NTP requirement for transmit timestamps to never be late and
|
||||||
|
receive timestamps to never be early.
|
||||||
|
|
||||||
|
If you have additional information about the hardware and network between the
|
||||||
|
client and primary time source, you could modify the root delay to get a better
|
||||||
|
estimate of the maximum error. For example, from the physical distance of the
|
||||||
|
server and signal propagation speed in the cables a minimum symmetric
|
||||||
|
round-trip delay can be calculated and subtracted from the root delay measured
|
||||||
|
by NTP.
|
||||||
|
|
||||||
|
Root dispersion estimates errors due to instability of clocks and NTP
|
||||||
|
measurements. `chronyd` adjusts the rate at which root dispersion grows between
|
||||||
|
updates of the clock according to the stability of its NTP measurements. The
|
||||||
|
minimum rate is set by the the `maxclockerror` directive. By default it is 1
|
||||||
|
ppm (1 microsecond per second).
|
||||||
|
|
||||||
|
The estimated maximum error of the NTP clock is the sum of the root dispersion
|
||||||
|
and half of the root delay. This value is called root distance. The current
|
||||||
|
values of root dispersion and delay are included in the `tracking` report.
|
||||||
|
|
||||||
|
The estimated maximum error of the system clock, which is synchronized to the
|
||||||
|
NTP clock, is the sum of the root distance and remaining correction of the
|
||||||
|
system clock provided as `System time` in the `tracking` report. A maximum
|
||||||
|
value of this estimate between updates of the clock is included in the
|
||||||
|
`tracking` log.
|
||||||
|
|
||||||
|
Note that the resolution of the root delay and root dispersion fields in NTP
|
||||||
|
messages is about 15 microseconds and `chronyd` rounds the values up, i.e. the
|
||||||
|
minimum root distance an NTP client can normally observe is about 22.5
|
||||||
|
microseconds. An NTP extension field containing root delay and dispersion in a
|
||||||
|
better resolution of about 4 nanoseconds can be enabled by the `extfield F323`
|
||||||
|
option.
|
||||||
|
|
||||||
== Operating systems
|
== Operating systems
|
||||||
|
|
||||||
=== Does `chrony` support Windows?
|
=== Does `chrony` support Windows?
|
||||||
|
|||||||
2
leapdb.h
2
leapdb.h
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Patrick Oppenlander 2023
|
* Copyright (C) Patrick Oppenlander 2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2023
|
* Copyright (C) Miroslav Lichvar 2009-2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020-2023
|
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020-2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -219,8 +219,14 @@ NSR_Finalise(void)
|
|||||||
ARR_DestroyInstance(pools);
|
ARR_DestroyInstance(pools);
|
||||||
|
|
||||||
SCH_RemoveTimeout(resolving_id);
|
SCH_RemoveTimeout(resolving_id);
|
||||||
while (unresolved_sources)
|
|
||||||
remove_unresolved_source(unresolved_sources);
|
/* Leave the unresolved sources allocated if the async resolver is running
|
||||||
|
to avoid reading the name from freed memory. The handler will not be
|
||||||
|
called as the scheduler should no longer be running at this point. */
|
||||||
|
if (!resolving_source) {
|
||||||
|
while (unresolved_sources)
|
||||||
|
remove_unresolved_source(unresolved_sources);
|
||||||
|
}
|
||||||
|
|
||||||
initialised = 0;
|
initialised = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2018, 2020, 2022
|
* Copyright (C) Miroslav Lichvar 2009-2018, 2020, 2022
|
||||||
|
* Copyright (C) Andy Fiddaman 2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
11
sources.c
11
sources.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020-2023
|
* Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020-2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -526,11 +526,6 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
|
|||||||
if (inst->reachability_size < SOURCE_REACH_BITS)
|
if (inst->reachability_size < SOURCE_REACH_BITS)
|
||||||
inst->reachability_size++;
|
inst->reachability_size++;
|
||||||
|
|
||||||
/* Source selection can change with unreachable sources */
|
|
||||||
if (inst->reachability == 0) {
|
|
||||||
SRC_SelectSource(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if special reference update mode failed */
|
/* Check if special reference update mode failed */
|
||||||
if (REF_GetMode() != REF_ModeNormal && special_mode_end()) {
|
if (REF_GetMode() != REF_ModeNormal && special_mode_end()) {
|
||||||
REF_SetUnsynchronised();
|
REF_SetUnsynchronised();
|
||||||
@@ -539,6 +534,10 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
|
|||||||
/* Try to replace unreachable NTP sources */
|
/* Try to replace unreachable NTP sources */
|
||||||
if (inst->reachability == 0 && inst->reachability_size == SOURCE_REACH_BITS)
|
if (inst->reachability == 0 && inst->reachability_size == SOURCE_REACH_BITS)
|
||||||
handle_bad_source(inst);
|
handle_bad_source(inst);
|
||||||
|
|
||||||
|
/* Source selection can change with unreachable sources */
|
||||||
|
if (inst->reachability == 0)
|
||||||
|
SRC_SelectSource(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Update interval : 16\.. seconds
|
|||||||
.*$" || test_fail
|
.*$" || test_fail
|
||||||
|
|
||||||
if echo "$refclock" | grep -q 'PHC.*nocrossts'; then
|
if echo "$refclock" | grep -q 'PHC.*nocrossts'; then
|
||||||
check_file_messages "20.* GPS.*[0-9] N " 650 750 refclocks.log || test_fail
|
check_file_messages "20.* GPS.*[0-9] N " 620 750 refclocks.log || test_fail
|
||||||
else
|
else
|
||||||
check_file_messages "20.* GPS.*[0-9] N " 997 1001 refclocks.log || test_fail
|
check_file_messages "20.* GPS.*[0-9] N " 997 1001 refclocks.log || test_fail
|
||||||
fi
|
fi
|
||||||
@@ -64,7 +64,7 @@ Stratum.*: 1
|
|||||||
Root delay : 0\.000000001 seconds
|
Root delay : 0\.000000001 seconds
|
||||||
.*$" || test_fail
|
.*$" || test_fail
|
||||||
|
|
||||||
check_file_messages "20.* PPS1.*[0-9] N " 620 740 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*[0-9] N " 610 740 refclocks.log || test_fail
|
||||||
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
||||||
rm -f tmp/refclocks.log
|
rm -f tmp/refclocks.log
|
||||||
|
|
||||||
@@ -89,14 +89,15 @@ Root delay : 0\.000000001 seconds
|
|||||||
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
||||||
rm -f tmp/refclocks.log
|
rm -f tmp/refclocks.log
|
||||||
|
|
||||||
min_sync_time=100
|
min_sync_time=80
|
||||||
max_sync_time=220
|
max_sync_time=180
|
||||||
chronyc_start=220
|
chronyc_start=220
|
||||||
client_conf="
|
client_conf="
|
||||||
refclock SHM 0 refid NMEA offset 0.35 delay 0.1
|
refclock SHM 0 refid NMEA offset 0.35 delay 0.1
|
||||||
refclock PPS /dev/pps0
|
refclock PPS /dev/pps0
|
||||||
logdir tmp
|
logdir tmp
|
||||||
log refclocks"
|
log refclocks
|
||||||
|
maxupdateskew 10000"
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
@@ -108,7 +109,7 @@ Stratum.*: 1
|
|||||||
Root delay : 0\.000000001 seconds
|
Root delay : 0\.000000001 seconds
|
||||||
.*$" || test_fail
|
.*$" || test_fail
|
||||||
|
|
||||||
check_file_messages "20.* PPS1.*[0-9] N " 800 940 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*[0-9] N " 800 960 refclocks.log || test_fail
|
||||||
check_file_messages "20.* PPS1.*- N " 50 63 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*- N " 50 63 refclocks.log || test_fail
|
||||||
rm -f tmp/refclocks.log
|
rm -f tmp/refclocks.log
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ EOF
|
|||||||
|
|
||||||
clients=2
|
clients=2
|
||||||
peers=2
|
peers=2
|
||||||
|
freq_max_limit=1e-3
|
||||||
max_sync_time=1000
|
max_sync_time=1000
|
||||||
client_server_options="minpoll 6 maxpoll 6"
|
client_server_options="minpoll 6 maxpoll 6"
|
||||||
client_peer_options="minpoll 6 maxpoll 6"
|
client_peer_options="minpoll 6 maxpoll 6"
|
||||||
@@ -30,6 +31,7 @@ check_chronyd_exit || test_fail
|
|||||||
check_source_selection || test_fail
|
check_source_selection || test_fail
|
||||||
check_sync || test_fail
|
check_sync || test_fail
|
||||||
|
|
||||||
|
freq_max_limit=$default_freq_max_limit
|
||||||
base_delay="(+ 1e-4 (* -1 (equal 0.1 from 3) (equal 0.1 to 1)))"
|
base_delay="(+ 1e-4 (* -1 (equal 0.1 from 3) (equal 0.1 to 1)))"
|
||||||
client_peer_options=""
|
client_peer_options=""
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ MS Name/IP address Stratum Poll Reach LastRx Last sample
|
|||||||
\^\? 192\.168\.123\.2 0 [0-9]+ 0 - \+0ns\[ \+0ns\] \+/- 0ns
|
\^\? 192\.168\.123\.2 0 [0-9]+ 0 - \+0ns\[ \+0ns\] \+/- 0ns
|
||||||
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
|
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
|
||||||
==============================================================================
|
==============================================================================
|
||||||
SHM0 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
SHM0 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][012]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||||
192\.168\.123\.1 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
192\.168\.123\.1 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||||
192\.168\.123\.2 0 0 0 \+0\.000 2000\.000 \+0ns 4000ms
|
192\.168\.123\.2 0 0 0 \+0\.000 2000\.000 \+0ns 4000ms
|
||||||
210 n_samples = 0
|
210 n_samples = 0
|
||||||
|
|||||||
@@ -53,4 +53,28 @@ check_log_messages "2010-01-01T0[5-9]:.*Source 192.168.123.. replaced with" 0 15
|
|||||||
check_file_messages "20.*192.168.123.* 11.1 6 6 " 20 500 measurements.log || test_fail
|
check_file_messages "20.*192.168.123.* 11.1 6 6 " 20 500 measurements.log || test_fail
|
||||||
rm -f tmp/measurements.log
|
rm -f tmp/measurements.log
|
||||||
|
|
||||||
|
# 2 replaceable falsetickers and 1 replaceable unreachable server
|
||||||
|
servers=6
|
||||||
|
falsetickers=2
|
||||||
|
base_delay="(+ 1e-4 (* -1 (equal 0.1 to 3)))"
|
||||||
|
client_server_conf="
|
||||||
|
server nodes-4-1.net1.clk
|
||||||
|
server nodes-5-2.net1.clk
|
||||||
|
server nodes-6-3.net1.clk"
|
||||||
|
|
||||||
|
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 "Can't synchronise: no majority" 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
|
||||||
|
check_log_messages "Source 192.168.123.2 replaced with" 1 25 || test_fail
|
||||||
|
check_log_messages "Source 192.168.123.3 replaced with" 1 25 || test_fail
|
||||||
|
check_file_messages "20.*192.168.123.* 11.1 6 6 " 50 800 measurements.log || test_fail
|
||||||
|
rm -f tmp/measurements.log
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|||||||
@@ -77,7 +77,32 @@ check_chronyc_output "^[^=]*
|
|||||||
.. 127\.123\.5\.3 *[05] 7 [^^]*
|
.. 127\.123\.5\.3 *[05] 7 [^^]*
|
||||||
.. 127\.123\.5\.6 [^^]*$" || test_fail
|
.. 127\.123\.5\.6 [^^]*$" || test_fail
|
||||||
|
|
||||||
|
run_chronyc "reload sources" || test_fail
|
||||||
|
run_chronyc "reload sources" || test_fail
|
||||||
|
|
||||||
|
rm $TEST_DIR/conf5.d/{3,5,6}.sources
|
||||||
|
echo "server 127.123.5.7" > $TEST_DIR/conf5.d/7.sources
|
||||||
|
|
||||||
|
run_chronyc "reload sources" || test_fail
|
||||||
|
|
||||||
|
run_chronyc "sources" || test_fail
|
||||||
|
check_chronyc_output "^[^=]*
|
||||||
|
=*
|
||||||
|
.. 127\.123\.1\.1 [^^]*
|
||||||
|
.. 127\.123\.1\.3 [^^]*
|
||||||
|
.. 127\.123\.1\.4 [^^]*
|
||||||
|
.. 127\.123\.3\.1 [^^]*
|
||||||
|
.. 127\.123\.2\.2 [^^]*
|
||||||
|
.. 127\.123\.2\.3 [^^]*
|
||||||
|
.. 127\.123\.4\.4 [^^]*
|
||||||
|
.. 127\.123\.1\.2 *[05] 6 [^^]*
|
||||||
|
.. 127\.123\.5\.2 *[05] 5 [^^]*
|
||||||
|
.. 127\.123\.5\.7 [^^]*$" || test_fail
|
||||||
|
|
||||||
|
run_chronyc "reload sources" || test_fail
|
||||||
|
|
||||||
stop_chronyd || test_fail
|
stop_chronyd || test_fail
|
||||||
|
check_chronyd_message_count "Could not add source.*\.5\.5.*in use" 1 1 || test_fail
|
||||||
check_chronyd_message_count "Could not add source" 1 1 || test_fail
|
check_chronyd_message_count "Could not add source" 1 1 || test_fail
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016, 2021
|
* Copyright (C) Miroslav Lichvar 2016, 2021, 2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Patrick Oppenlander 2023
|
* Copyright (C) Patrick Oppenlander 2024
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
Reference in New Issue
Block a user