This is just a quick patch to get better resolution receive timestamps from
the kernel.  As far as I can tell, the timestamps are supposed to be using
the unix epoch.  If not, I can switch it up from SO_TS_REALTIME to
SO_TS_MONOTONIC which does marginally less work but its epoch isn't January
1, 1970 - it's essentially the uptime.

Let me know if I missed anything.

Jeff.
>From a5a967a270233afcbdb7e5374ad9990362a884f8 Mon Sep 17 00:00:00 2001
From: Josef 'Jeff' Sipek <jef...@josefsipek.net>
Date: Wed, 9 Aug 2023 07:58:38 -0400
Subject: [PATCH] socket: enable nanosecond resolution receive timestamp on
 FreeBSD

FreeBSD allows switching the receive timestamp format to struct timespec by
setting the SO_TS_CLOCK socket option to SO_TS_REALTIME after enabling
SO_TIMESTAMP.  If successful, the kernel then starts adding SCM_REALTIME
control messages instead of SCM_TIMESTAMP.
---
 socket.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/socket.c b/socket.c
index 8a5d046..f4bae6d 100644
--- a/socket.c
+++ b/socket.c
@@ -869,6 +869,11 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
       memcpy(&message->timestamp.kernel, CMSG_DATA(cmsg), sizeof (message->timestamp.kernel));
     }
 #endif
+#ifdef SCM_REALTIME
+    else if (match_cmsg(cmsg, SOL_SOCKET, SCM_REALTIME, sizeof (message->timestamp.kernel))) {
+      memcpy(&message->timestamp.kernel, CMSG_DATA(cmsg), sizeof (message->timestamp.kernel));
+    }
+#endif
 #ifdef HAVE_LINUX_TIMESTAMPING
 #ifdef HAVE_LINUX_TIMESTAMPING_OPT_PKTINFO
     else if (match_cmsg(cmsg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
@@ -1386,8 +1391,16 @@ SCK_EnableKernelRxTimestamping(int sock_fd)
     return 1;
 #endif
 #ifdef SO_TIMESTAMP
-  if (SCK_SetIntOption(sock_fd, SOL_SOCKET, SO_TIMESTAMP, 1))
+  if (SCK_SetIntOption(sock_fd, SOL_SOCKET, SO_TIMESTAMP, 1)) {
+#if defined(SO_TS_CLOCK) && defined(SO_TS_REALTIME)
+    /*
+     * We don't care about the return value - we'll get either a
+     * SCM_REALTIME (if we succeded) or a SCM_TIMESTAMP (if we failed).
+     */
+    SCK_SetIntOption(sock_fd, SOL_SOCKET, SO_TS_CLOCK, SO_TS_REALTIME);
+#endif
     return 1;
+  }
 #endif
 
   return 0;
-- 
2.41.0

Reply via email to