/* 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;
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")) {
/* ================================================== */
+double
+CNF_GetHwTsTimeout(void)
+{
+ return hwts_timeout;
+}
+
+/* ================================================== */
+
int
CNF_GetPtpPort(void)
{
} CNF_HwTsInterface;
extern int CNF_GetHwTsInterface(unsigned int index, CNF_HwTsInterface **iface);
+extern double CNF_GetHwTsTimeout(void);
extern int CNF_GetPtpPort(void);
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
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;
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);