|
|
8b2c89 |
diff -up chrony-3.2/configure.timestamping chrony-3.2/configure
|
|
|
8b2c89 |
--- chrony-3.2/configure.timestamping 2017-09-19 13:58:21.093194558 +0200
|
|
|
8b2c89 |
+++ chrony-3.2/configure 2017-09-19 13:57:56.109116276 +0200
|
|
|
8b2c89 |
@@ -683,15 +683,15 @@ if [ $feat_timestamping = "1" ] && [ $tr
|
|
|
ab3630 |
test_code 'SW/HW timestamping' 'sys/types.h sys/socket.h linux/net_tstamp.h
|
|
|
ab3630 |
linux/errqueue.h linux/ptp_clock.h' '' '' '
|
|
|
ab3630 |
int val = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE |
|
|
|
ab3630 |
- SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_OPT_CMSG;
|
|
|
ab3630 |
- return sizeof (struct scm_timestamping) + SCM_TSTAMP_SND + PTP_SYS_OFFSET +
|
|
|
ab3630 |
+ SOF_TIMESTAMPING_RAW_HARDWARE | 1;
|
|
|
ab3630 |
+ return 3 * sizeof (struct timespec) + 0 + PTP_SYS_OFFSET +
|
|
|
ab3630 |
setsockopt(0, SOL_SOCKET, SO_SELECT_ERR_QUEUE + SO_TIMESTAMPING,
|
|
|
ab3630 |
&val, sizeof (val));'
|
|
|
ab3630 |
then
|
|
|
8b2c89 |
add_def HAVE_LINUX_TIMESTAMPING
|
|
|
8b2c89 |
EXTRA_OBJECTS="$EXTRA_OBJECTS hwclock.o ntp_io_linux.o"
|
|
|
8b2c89 |
|
|
|
8b2c89 |
- if test_code 'other timestamping options' \
|
|
|
8b2c89 |
+ if true || test_code 'other timestamping options' \
|
|
|
8b2c89 |
'sys/types.h sys/socket.h linux/net_tstamp.h' '' '' '
|
|
|
8b2c89 |
struct scm_ts_pktinfo pktinfo;
|
|
|
8b2c89 |
pktinfo.if_index = pktinfo.pkt_length = 0;
|
|
|
8b2c89 |
diff -up chrony-3.2/doc/chrony.conf.man.in.timestamping chrony-3.2/doc/chrony.conf.man.in
|
|
|
8b2c89 |
--- chrony-3.2/doc/chrony.conf.man.in.timestamping 2017-09-15 10:17:41.000000000 +0200
|
|
|
8b2c89 |
+++ chrony-3.2/doc/chrony.conf.man.in 2017-09-19 13:52:59.544187046 +0200
|
|
|
8b2c89 |
@@ -3201,13 +3201,12 @@ timestamping. If the server or peer supp
|
|
|
ab3630 |
be enabled by the \fBxleave\fP option in the \fBserver\fP or the
|
|
|
ab3630 |
\fBpeer\fP directive.
|
|
|
ab3630 |
.sp
|
|
|
ab3630 |
-This directive is supported on Linux 3.19 and newer. The NIC must support HW
|
|
|
ab3630 |
+This directive is supported on Linux. The NIC must support HW
|
|
|
ab3630 |
timestamping, which can be verified with the \fBethtool \-T\fP command. The list of
|
|
|
ab3630 |
capabilities should include \fISOF_TIMESTAMPING_RAW_HARDWARE\fP,
|
|
|
8b2c89 |
\fISOF_TIMESTAMPING_TX_HARDWARE\fP, and \fISOF_TIMESTAMPING_RX_HARDWARE\fP. Receive
|
|
|
8b2c89 |
filter \fIHWTSTAMP_FILTER_ALL\fP, or \fIHWTSTAMP_FILTER_NTP_ALL\fP, is necessary for
|
|
|
8b2c89 |
-timestamping of received packets. Timestamping of packets received from bridged
|
|
|
8b2c89 |
-and bonded interfaces is supported on Linux 4.13 and newer. When \fBchronyd\fP is
|
|
|
8b2c89 |
+timestamping of received packets. When \fBchronyd\fP is
|
|
|
8b2c89 |
running, no other process (e.g. a PTP daemon) should be working with the NIC
|
|
|
8b2c89 |
clock.
|
|
|
8b2c89 |
.sp
|
|
|
8b2c89 |
diff -up chrony-3.2/ntp_io_linux.c.timestamping chrony-3.2/ntp_io_linux.c
|
|
|
8b2c89 |
--- chrony-3.2/ntp_io_linux.c.timestamping 2017-09-15 08:32:09.000000000 +0200
|
|
|
8b2c89 |
+++ chrony-3.2/ntp_io_linux.c 2017-09-19 13:52:59.544187046 +0200
|
|
|
8b2c89 |
@@ -35,6 +35,16 @@
|
|
|
ab3630 |
#include <linux/sockios.h>
|
|
|
ab3630 |
#include <net/if.h>
|
|
|
ab3630 |
|
|
|
ab3630 |
+/* Missing in older kernel headers */
|
|
|
ab3630 |
+#define SOF_TIMESTAMPING_OPT_CMSG (1<<10)
|
|
|
8b2c89 |
+#define SOF_TIMESTAMPING_OPT_PKTINFO (1<<13)
|
|
|
8b2c89 |
+#define SOF_TIMESTAMPING_OPT_TX_SWHW (1<<14)
|
|
|
ab3630 |
+#define SCM_TSTAMP_SND 0
|
|
|
8b2c89 |
+#define HWTSTAMP_FILTER_NTP_ALL 15
|
|
|
8b2c89 |
+#ifndef SCM_TIMESTAMPING_PKTINFO
|
|
|
8b2c89 |
+#define SCM_TIMESTAMPING_PKTINFO 58
|
|
|
8b2c89 |
+#endif
|
|
|
ab3630 |
+
|
|
|
ab3630 |
#include "array.h"
|
|
|
ab3630 |
#include "conf.h"
|
|
|
ab3630 |
#include "hwclock.h"
|
|
|
8b2c89 |
@@ -94,6 +104,10 @@ static int ts_tx_flags;
|
|
|
ab3630 |
/* Flag indicating the socket options can't be changed in control messages */
|
|
|
ab3630 |
static int permanent_ts_options;
|
|
|
ab3630 |
|
|
|
ab3630 |
+/* Index of a HW-timestamping interface, but only if the machine has not more
|
|
|
ab3630 |
+ than one */
|
|
|
ab3630 |
+static int single_hwts_if_index;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
/* ================================================== */
|
|
|
ab3630 |
|
|
|
ab3630 |
static int
|
|
|
8b2c89 |
@@ -278,7 +292,7 @@ update_interface_speed(struct Interface
|
|
|
8b2c89 |
|
|
|
8b2c89 |
/* ================================================== */
|
|
|
8b2c89 |
|
|
|
8b2c89 |
-#if defined(HAVE_LINUX_TIMESTAMPING_OPT_PKTINFO) || defined(HAVE_LINUX_TIMESTAMPING_OPT_TX_SWHW)
|
|
|
8b2c89 |
+#if 1
|
|
|
8b2c89 |
static int
|
|
|
8b2c89 |
check_timestamping_option(int option)
|
|
|
8b2c89 |
{
|
|
|
8b2c89 |
@@ -301,6 +315,61 @@ check_timestamping_option(int option)
|
|
|
ab3630 |
|
|
|
ab3630 |
/* ================================================== */
|
|
|
ab3630 |
|
|
|
ab3630 |
+static int
|
|
|
ab3630 |
+get_single_hwts_index()
|
|
|
ab3630 |
+{
|
|
|
ab3630 |
+ struct ifaddrs *ifaddr, *ifa;
|
|
|
ab3630 |
+ struct ethtool_ts_info ts_info;
|
|
|
ab3630 |
+ struct ifreq req;
|
|
|
ab3630 |
+ int sock_fd, if_index, hwts_if_index = INVALID_IF_INDEX;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
ab3630 |
+ if (sock_fd < 0)
|
|
|
ab3630 |
+ return INVALID_IF_INDEX;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (getifaddrs(&ifaddr)) {
|
|
|
8b2c89 |
+ DEBUG_LOG("getifaddrs() failed : %s", strerror(errno));
|
|
|
ab3630 |
+ close(sock_fd);
|
|
|
ab3630 |
+ return INVALID_IF_INDEX;
|
|
|
ab3630 |
+ }
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
|
|
ab3630 |
+ memset(&req, 0, sizeof (req));
|
|
|
ab3630 |
+ memset(&ts_info, 0, sizeof (ts_info));
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (snprintf(req.ifr_name, sizeof (req.ifr_name), "%s", ifa->ifa_name) >=
|
|
|
ab3630 |
+ sizeof (req.ifr_name))
|
|
|
ab3630 |
+ break;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (ioctl(sock_fd, SIOCGIFINDEX, &req))
|
|
|
ab3630 |
+ break;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if_index = req.ifr_ifindex;
|
|
|
ab3630 |
+ ts_info.cmd = ETHTOOL_GET_TS_INFO;
|
|
|
ab3630 |
+ req.ifr_data = (char *)&ts_info;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (ioctl(sock_fd, SIOCETHTOOL, &req))
|
|
|
ab3630 |
+ break;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (ts_info.phc_index < 0)
|
|
|
ab3630 |
+ continue;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (hwts_if_index != INVALID_IF_INDEX && hwts_if_index != if_index)
|
|
|
ab3630 |
+ break;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ hwts_if_index = if_index;
|
|
|
ab3630 |
+ }
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ close(sock_fd);
|
|
|
ab3630 |
+ freeifaddrs(ifaddr);
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ if (ifa)
|
|
|
ab3630 |
+ return INVALID_IF_INDEX;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ return hwts_if_index;
|
|
|
ab3630 |
+}
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+/* ================================================== */
|
|
|
ab3630 |
void
|
|
|
ab3630 |
NIO_Linux_Initialise(void)
|
|
|
ab3630 |
{
|
|
|
8b2c89 |
@@ -345,8 +414,20 @@ NIO_Linux_Initialise(void)
|
|
|
8b2c89 |
#endif
|
|
|
ab3630 |
}
|
|
|
ab3630 |
|
|
|
ab3630 |
- /* Enable IP_PKTINFO in messages looped back to the error queue */
|
|
|
ab3630 |
- ts_flags |= SOF_TIMESTAMPING_OPT_CMSG;
|
|
|
ab3630 |
+ single_hwts_if_index = INVALID_IF_INDEX;
|
|
|
ab3630 |
+
|
|
|
ab3630 |
+ /* Enable IP_PKTINFO in messages looped back to the error queue if possible.
|
|
|
ab3630 |
+ If not, HW timestamping of IPv4 packets can be supported only with one
|
|
|
ab3630 |
+ interface capable of HW timestamping. */
|
|
|
8b2c89 |
+ if (check_timestamping_option(SOF_TIMESTAMPING_OPT_CMSG)) {
|
|
|
ab3630 |
+ ts_flags |= SOF_TIMESTAMPING_OPT_CMSG;
|
|
|
ab3630 |
+ } else if (ARR_GetSize(interfaces) > 0) {
|
|
|
ab3630 |
+ single_hwts_if_index = get_single_hwts_index();
|
|
|
ab3630 |
+ if (single_hwts_if_index == INVALID_IF_INDEX)
|
|
|
8b2c89 |
+ LOG(LOGS_WARN, "Missing SOF_TIMESTAMPING_OPT_CMSG option for HW timestamping with multiple HW-timestamping interfaces");
|
|
|
ab3630 |
+ else
|
|
|
8b2c89 |
+ LOG(LOGS_INFO, "Enabled single-interface HW-timestamping mode");
|
|
|
ab3630 |
+ }
|
|
|
ab3630 |
|
|
|
ab3630 |
/* Kernels before 4.7 ignore timestamping flags set in control messages */
|
|
|
ab3630 |
permanent_ts_options = !SYS_Linux_CheckKernelVersion(4, 7);
|
|
|
8b2c89 |
@@ -590,7 +671,11 @@ NIO_Linux_ProcessMessage(NTP_Remote_Addr
|
|
|
ab3630 |
for (cmsg = CMSG_FIRSTHDR(hdr); cmsg; cmsg = CMSG_NXTHDR(hdr, cmsg)) {
|
|
|
8b2c89 |
#ifdef HAVE_LINUX_TIMESTAMPING_OPT_PKTINFO
|
|
|
8b2c89 |
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPING_PKTINFO) {
|
|
|
8b2c89 |
- struct scm_ts_pktinfo ts_pktinfo;
|
|
|
8b2c89 |
+ struct {
|
|
|
8b2c89 |
+ __u32 if_index;
|
|
|
8b2c89 |
+ __u32 pkt_length;
|
|
|
8b2c89 |
+ __u32 reserved[2];
|
|
|
8b2c89 |
+ } ts_pktinfo;
|
|
|
8b2c89 |
|
|
|
8b2c89 |
memcpy(&ts_pktinfo, CMSG_DATA(cmsg), sizeof (ts_pktinfo));
|
|
|
8b2c89 |
|
|
|
8b2c89 |
@@ -602,11 +687,16 @@ NIO_Linux_ProcessMessage(NTP_Remote_Addr
|
|
|
8b2c89 |
#endif
|
|
|
8b2c89 |
|
|
|
ab3630 |
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPING) {
|
|
|
ab3630 |
- struct scm_timestamping ts3;
|
|
|
ab3630 |
+ struct {
|
|
|
ab3630 |
+ struct timespec ts[3];
|
|
|
ab3630 |
+ } ts3;
|
|
|
ab3630 |
|
|
|
ab3630 |
memcpy(&ts3, CMSG_DATA(cmsg), sizeof (ts3));
|
|
|
ab3630 |
|
|
|
8b2c89 |
if (!UTI_IsZeroTimespec(&ts3.ts[2])) {
|
|
|
8b2c89 |
+ if (ts_if_index == INVALID_IF_INDEX)
|
|
|
8b2c89 |
+ ts_if_index = single_hwts_if_index;
|
|
|
8b2c89 |
+
|
|
|
8b2c89 |
iface = get_interface(ts_if_index);
|
|
|
ab3630 |
if (iface) {
|
|
|
ab3630 |
process_hw_timestamp(iface, &ts3.ts[2], local_ts, !is_tx ? length : 0,
|