ntp: make socket resume timeout configurable

In some cases even the new timeout of 1 millisecond is not sufficient to
get all HW TX timestamps. Add a new directive to allow users to
specify longer timeouts.
This commit is contained in:
Miroslav Lichvar 2023-03-09 11:09:33 +01:00
parent ccebec3eb6
commit ab776ed9d8
4 changed files with 42 additions and 4 deletions

13
conf.c
View file

@ -274,6 +274,9 @@ static int no_system_cert = 0;
/* Array of CNF_HwTsInterface */
static ARR_Instance hwts_interfaces;
/* Timeout for resuming reading from sockets waiting for HW TX timestamp */
static double hwts_timeout = 0.001;
/* PTP event port (disabled by default) */
static int ptp_port = 0;
@ -602,6 +605,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
parse_string(p, &hwclock_file);
} else if (!strcasecmp(command, "hwtimestamp")) {
parse_hwtimestamp(p);
} else if (!strcasecmp(command, "hwtstimeout")) {
parse_double(p, &hwts_timeout);
} else if (!strcasecmp(command, "include")) {
parse_include(p);
} else if (!strcasecmp(command, "initstepslew")) {
@ -2505,6 +2510,14 @@ CNF_GetHwTsInterface(unsigned int index, CNF_HwTsInterface **iface)
/* ================================================== */
double
CNF_GetHwTsTimeout(void)
{
return hwts_timeout;
}
/* ================================================== */
int
CNF_GetPtpPort(void)
{

1
conf.h
View file

@ -154,6 +154,7 @@ typedef struct {
} CNF_HwTsInterface;
extern int CNF_GetHwTsInterface(unsigned int index, CNF_HwTsInterface **iface);
extern double CNF_GetHwTsTimeout(void);
extern int CNF_GetPtpPort(void);

View file

@ -2606,6 +2606,31 @@ hwtimestamp eth1 txcomp 300e-9 rxcomp 645e-9
hwtimestamp *
----
[[hwtstimeout]]*hwtstimeout* _timeout_::
If hardware timestamping is used with a close NTP server, or the NIC or its
driver is slow in providing the transmit timestamp of NTP requests, a response
from the server can be received before the transmit timestamp of the request.
To avoid calculating the offset with a less accurate transmit timestamp,
*chronyd* suspends reading of NTP packets from the socket until the hardware
transmit timestamp is provided. There is no guarantee that the timestamp will
actually be provided (NICs typically have a limited rate of transmit
timestamping). This directive configures how long should *chronyd* wait
for the timestamp before resuming reading from the socket.
+
The suspension is activated only on sockets that are not expected to receive
requests, i.e. it does not work with the *peer* directive and also with the
*server* and *pool* directives if the ports specified by the *port* and
*acquisitionport* directives are equal.
+
The default value is 0.001 seconds, which should be sufficient with most
hardware. If you frequently see kernel transmit timestamps in the
_measurements.log_ file or <<chronyc.adoc#ntpdata,*ntpdata*>> report, and it is
not a server handling a high rate of requests in the interleaved mode on the
same interface (which would compete with timestamping of the server's own
requests), increasing the timeout to 0.01 or possibly even longer might help.
Note that setting a timeout longer than the NTP polling interval causes the
responses to be ignored when the timestamp is missing.
[[keyfile]]*keyfile* _file_::
This directive is used to specify the location of the file containing symmetric
keys which are shared between NTP servers and clients, or peers, in order to

View file

@ -91,8 +91,6 @@ static int permanent_ts_options;
suspend reading of packets from the receive queue until a HW transmit
timestamp is received from the error queue or a timeout reached. */
#define RESUME_TIMEOUT 0.001
struct HwTsSocket {
int sock_fd;
int suspended;
@ -546,15 +544,16 @@ static void
suspend_socket(int sock_fd)
{
struct HwTsSocket *ts_sock = get_hw_ts_socket(sock_fd, 1);
double timeout = CNF_GetHwTsTimeout();
if (!ts_sock)
if (!ts_sock || timeout <= 0.0)
return;
/* Remove previous timeout if there is one */
SCH_RemoveTimeout(ts_sock->timeout_id);
ts_sock->suspended = 1;
ts_sock->timeout_id = SCH_AddTimeoutByDelay(RESUME_TIMEOUT, resume_timeout, ts_sock);
ts_sock->timeout_id = SCH_AddTimeoutByDelay(timeout, resume_timeout, ts_sock);
SCH_SetFileHandlerEvent(ts_sock->sock_fd, SCH_FILE_INPUT, 0);
DEBUG_LOG("Suspended RX processing fd=%d", ts_sock->sock_fd);