From db312a5ff6696fe9eec4b14cce2aa2da4c0f550d Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Wed, 14 Dec 2016 12:15:32 +0100 Subject: [PATCH] ntp: allow wildcard in hwtimestamp directive If "*" was specified, use getifaddrs() to get a list of all interfaces, and try to enable HW timestamping on all of them. --- doc/chrony.conf.adoc | 3 +++ ntp_io_linux.c | 55 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc index 88f6b94..8f4598e 100644 --- a/doc/chrony.conf.adoc +++ b/doc/chrony.conf.adoc @@ -1800,6 +1800,9 @@ interfaces. The timestamping used in measurements is indicated in the _measurements.log_ file if enabled by the <> directive, and the <> report in *chronyc*. + +If the specified interface is _*_, *chronyd* will try to enable HW timestamping +on all available interfaces. ++ An example of the directive is: + ---- diff --git a/ntp_io_linux.c b/ntp_io_linux.c index 9cf791b..8d0eea9 100644 --- a/ntp_io_linux.c +++ b/ntp_io_linux.c @@ -28,6 +28,7 @@ #include "sysincl.h" +#include #include #include #include @@ -90,9 +91,16 @@ add_interface(const char *name) struct hwtstamp_config ts_config; struct ifreq req; int sock_fd, if_index, phc_index, phc_fd; + unsigned int i; struct Interface *iface; char phc_path[64]; + /* Check if the interface was not already added */ + for (i = 0; i < ARR_GetSize(interfaces); i++) { + if (!strcmp(name, ((struct Interface *)ARR_GetElement(interfaces, i))->name)) + return 1; + } + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) return 0; @@ -160,11 +168,37 @@ add_interface(const char *name) iface->clock = HCL_CreateInstance(); + DEBUG_LOG(LOGF_NtpIOLinux, "Enabled HW timestamping on %s", name); + return 1; } /* ================================================== */ +static int +add_all_interfaces(void) +{ + struct ifaddrs *ifaddr, *ifa; + int r; + + if (getifaddrs(&ifaddr)) { + DEBUG_LOG(LOGF_NtpIOLinux, "getifaddrs() failed : %s", strerror(errno)); + return 0; + } + + for (r = 0, ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + if (add_interface(ifa->ifa_name)) + r = 1; + } + + freeifaddrs(ifaddr); + + /* Return success if at least one interface was added */ + return r; +} + +/* ================================================== */ + static void update_interface_speed(struct Interface *iface) { @@ -202,19 +236,34 @@ NIO_Linux_Initialise(void) ARR_Instance config_hwts_ifaces; char *if_name; unsigned int i; + int wildcard, hwts; interfaces = ARR_CreateInstance(sizeof (struct Interface)); config_hwts_ifaces = CNF_GetHwTsInterfaces(); - /* Enable HW timestamping on all specified interfaces. If no interface was - specified, use SW timestamping. */ - if (ARR_GetSize(config_hwts_ifaces)) { + /* Enable HW timestamping on specified interfaces. If "*" was specified, try + all interfaces. If no interface was specified, enable SW timestamping. */ + + for (i = wildcard = 0; i < ARR_GetSize(config_hwts_ifaces); i++) { + if (!strcmp("*", *(char **)ARR_GetElement(config_hwts_ifaces, i))) + wildcard = 1; + } + + if (!wildcard && ARR_GetSize(config_hwts_ifaces)) { for (i = 0; i < ARR_GetSize(config_hwts_ifaces); i++) { if_name = *(char **)ARR_GetElement(config_hwts_ifaces, i); if (!add_interface(if_name)) LOG_FATAL(LOGF_NtpIO, "Could not enable HW timestamping on %s", if_name); } + hwts = 1; + } else if (wildcard && add_all_interfaces()) { + hwts = 1; + } else { + hwts = 0; + } + + if (hwts) { ts_flags = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; ts_tx_flags = SOF_TIMESTAMPING_TX_HARDWARE; } else {