The branch main has been updated by jtl:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=cd02a8a9f8be2085d5242606a79668dc3720e7b0

commit cd02a8a9f8be2085d5242606a79668dc3720e7b0
Author:     Jonathan T. Looney <j...@freebsd.org>
AuthorDate: 2025-09-12 17:49:17 +0000
Commit:     Jonathan T. Looney <j...@freebsd.org>
CommitDate: 2025-09-15 16:46:03 +0000

    ip6: add SO_BINTIME support
    
    This adds support for obtaining timestamps from IPv6 packets using the
    SO_BINTIME socket option, bringing it in parity with IPv4 behavior.
    
    Enable testing the SO_BINTIME option in the relevant (manual) regression
    test.
    
    PR:             289423
    Reviewed by:    markj
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D52504
---
 sys/netinet6/ip6_input.c                           | 53 +++++++++++++++-------
 .../regression/sockets/udp_pingpong/udp_pingpong.c |  8 ++--
 2 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 45fd23ea6c21..b22491a6007f 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -1197,8 +1197,8 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, 
struct mbuf **mp,
 {
        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
 
-#ifdef SO_TIMESTAMP
-       if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) {
+#if defined(SO_TIMESTAMP) && defined(SO_BINTIME)
+       if ((inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) != 0) {
                union {
                        struct timeval tv;
                        struct bintime bt;
@@ -1206,47 +1206,66 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, 
struct mbuf **mp,
                } t;
                struct bintime boottimebin, bt1;
                struct timespec ts1;
+               int ts_clock;
                bool stamped;
 
+               ts_clock = inp->inp_socket->so_ts_clock;
                stamped = false;
-               switch (inp->inp_socket->so_ts_clock) {
-               case SO_TS_REALTIME_MICRO:
+
+               /*
+                * Handle BINTIME first. We create the same output options
+                * for both SO_BINTIME and the case where SO_TIMESTAMP is
+                * set with the timestamp clock set to SO_TS_BINTIME.
+                */
+               if ((inp->inp_socket->so_options & SO_BINTIME) != 0 ||
+                   ts_clock == SO_TS_BINTIME) {
                        if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
                            M_TSTMP)) {
                                mbuf_tstmp2timespec(m, &ts1);
-                               timespec2bintime(&ts1, &bt1);
+                               timespec2bintime(&ts1, &t.bt);
                                getboottimebin(&boottimebin);
-                               bintime_add(&bt1, &boottimebin);
-                               bintime2timeval(&bt1, &t.tv);
+                               bintime_add(&t.bt, &boottimebin);
                        } else {
-                               microtime(&t.tv);
+                               bintime(&t.bt);
                        }
-                       *mp = sbcreatecontrol(&t.tv, sizeof(t.tv),
-                           SCM_TIMESTAMP, SOL_SOCKET, M_NOWAIT);
+                       *mp = sbcreatecontrol(&t.bt, sizeof(t.bt), SCM_BINTIME,
+                           SOL_SOCKET, M_NOWAIT);
                        if (*mp != NULL) {
                                mp = &(*mp)->m_next;
                                stamped = true;
                        }
-                       break;
 
-               case SO_TS_BINTIME:
+                       /*
+                        * Suppress other timestamps if SO_TIMESTAMP is not
+                        * set.
+                        */
+                       if ((inp->inp_socket->so_options & SO_TIMESTAMP) == 0)
+                               ts_clock = SO_TS_BINTIME;
+               }
+
+               switch (ts_clock) {
+               case SO_TS_REALTIME_MICRO:
                        if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
                            M_TSTMP)) {
                                mbuf_tstmp2timespec(m, &ts1);
-                               timespec2bintime(&ts1, &t.bt);
+                               timespec2bintime(&ts1, &bt1);
                                getboottimebin(&boottimebin);
-                               bintime_add(&t.bt, &boottimebin);
+                               bintime_add(&bt1, &boottimebin);
+                               bintime2timeval(&bt1, &t.tv);
                        } else {
-                               bintime(&t.bt);
+                               microtime(&t.tv);
                        }
-                       *mp = sbcreatecontrol(&t.bt, sizeof(t.bt), SCM_BINTIME,
-                           SOL_SOCKET, M_NOWAIT);
+                       *mp = sbcreatecontrol(&t.tv, sizeof(t.tv),
+                           SCM_TIMESTAMP, SOL_SOCKET, M_NOWAIT);
                        if (*mp != NULL) {
                                mp = &(*mp)->m_next;
                                stamped = true;
                        }
                        break;
 
+               case SO_TS_BINTIME:
+                       break;
+
                case SO_TS_REALTIME:
                        if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
                            M_TSTMP)) {
diff --git a/tools/regression/sockets/udp_pingpong/udp_pingpong.c 
b/tools/regression/sockets/udp_pingpong/udp_pingpong.c
index 2fe342debdc6..e852f7a7af87 100644
--- a/tools/regression/sockets/udp_pingpong/udp_pingpong.c
+++ b/tools/regression/sockets/udp_pingpong/udp_pingpong.c
@@ -601,11 +601,9 @@ main(void)
         test_run(TT_TIMESTAMP, i, 1,
           "send()/recvmsg(), setsockopt(SO_TIMESTAMP, 1)");
         printf("OK\n");
-        if (i == 0) {
-            test_run(TT_BINTIME, i, 1,
-              "send()/recvmsg(), setsockopt(SO_BINTIME, 1)");
-            printf("OK\n");
-        }
+        test_run(TT_BINTIME, i, 1,
+          "send()/recvmsg(), setsockopt(SO_BINTIME, 1)");
+        printf("OK\n");
         test_run(TT_REALTIME_MICRO, i, 1,
           "send()/recvmsg(), setsockopt(SO_TS_CLOCK, SO_TS_REALTIME_MICRO)");
         printf("OK\n");

Reply via email to