]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: always try to enable SW timestamping on Linux
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 5 Jun 2017 16:47:05 +0000 (18:47 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 27 Jun 2017 13:29:01 +0000 (15:29 +0200)
Request SW timestamps with SCM_TIMESTAMPING even if HW timestamping is
enabled. This replaces SCM_TIMESTAMP(NS) for RX and enables TX SW
timestamping on interfaces that don't support HW timestamping (or don't
have it enabled) if another interface has HW timestamping enabled.

ntp_io.c
ntp_io_linux.c

index 902425fece922e5e21a81ca7e8a4613dd8157698..c93e52fb9f45918e4bc7d7ab0dce11d06b032a3d 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -204,21 +204,18 @@ prepare_socket(int family, int port_number, int client_only)
     /* Don't quit - we might survive anyway */
   }
 
-#ifdef SO_TIMESTAMP
-  /* Enable receiving of timestamp control messages */
-#ifdef SO_TIMESTAMPNS
-  /* Try nanosecond resolution first */
-  if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, (char *)&on_off, sizeof(on_off)) < 0)
+  /* Enable kernel/HW timestamping of packets */
+#ifdef HAVE_LINUX_TIMESTAMPING
+  if (!NIO_Linux_SetTimestampSocketOptions(sock_fd, client_only, &events))
 #endif
-  if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMP, (char *)&on_off, sizeof(on_off)) < 0) {
-    LOG(LOGS_ERR, "Could not set %s socket option", "SO_TIMESTAMP");
-    /* Don't quit - we might survive anyway */
-  }
+#ifdef SO_TIMESTAMPNS
+    if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, (char *)&on_off, sizeof(on_off)) < 0)
 #endif
-
-#ifdef HAVE_LINUX_TIMESTAMPING
-  NIO_Linux_SetTimestampSocketOptions(sock_fd, client_only, &events);
+#ifdef SO_TIMESTAMP
+      if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMP, (char *)&on_off, sizeof(on_off)) < 0)
+        LOG(LOGS_ERR, "Could not set %s socket option", "SO_TIMESTAMP");
 #endif
+      ;
 
 #ifdef IP_FREEBIND
   /* Allow binding to address that doesn't exist yet */
index cb77dd7e57d11fc2ff09beb82f08a03ad843990c..8c12e5c22e7a8b36879410fe478a4a2eda54d6db 100644 (file)
@@ -280,12 +280,12 @@ NIO_Linux_Initialise(void)
     break;
   }
 
+  ts_flags = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE;
+  ts_tx_flags = SOF_TIMESTAMPING_TX_SOFTWARE;
+
   if (hwts) {
-    ts_flags = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE;
-    ts_tx_flags = SOF_TIMESTAMPING_TX_HARDWARE;
-  } else {
-    ts_flags = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE;
-    ts_tx_flags = SOF_TIMESTAMPING_TX_SOFTWARE;
+    ts_flags |= SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE;
+    ts_tx_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
   }
 
   /* Enable IP_PKTINFO in messages looped back to the error queue */
@@ -504,10 +504,7 @@ NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *loc
 
       memcpy(&ts3, CMSG_DATA(cmsg), sizeof (ts3));
 
-      if (!UTI_IsZeroTimespec(&ts3.ts[0])) {
-        LCL_CookTime(&ts3.ts[0], &local_ts->ts, &local_ts->err);
-        local_ts->source = NTP_TS_KERNEL;
-      } else if (!UTI_IsZeroTimespec(&ts3.ts[2])) {
+      if (!UTI_IsZeroTimespec(&ts3.ts[2])) {
         iface = get_interface(local_addr->if_index);
         if (iface) {
           process_hw_timestamp(iface, &ts3.ts[2], local_ts, !is_tx ? length : 0,
@@ -516,6 +513,12 @@ NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *loc
           DEBUG_LOG("HW clock not found for interface %d", local_addr->if_index);
         }
       }
+
+      if (local_ts->source == NTP_TS_DAEMON && !UTI_IsZeroTimespec(&ts3.ts[0]) &&
+          (!is_tx || UTI_IsZeroTimespec(&ts3.ts[2]))) {
+        LCL_CookTime(&ts3.ts[0], &local_ts->ts, &local_ts->err);
+        local_ts->source = NTP_TS_KERNEL;
+      }
     }
 
     if ((cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) ||
@@ -555,9 +558,9 @@ NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *loc
       iface->l2_udp6_ntp_start = l2_length - length;
   }
 
-  /* Drop the message if HW timestamp is missing or its processing failed */
-  if ((ts_flags & SOF_TIMESTAMPING_RAW_HARDWARE) && local_ts->source != NTP_TS_HARDWARE) {
-    DEBUG_LOG("Missing HW timestamp");
+  /* Drop the message if it has no timestamp or its processing failed */
+  if (local_ts->source == NTP_TS_DAEMON) {
+    DEBUG_LOG("Missing TX timestamp");
     return 1;
   }