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

(cherry picked from commit cd02a8a9f8be2085d5242606a79668dc3720e7b0)
This commit is contained in:
Jonathan T. Looney 2025-09-12 17:49:17 +00:00
parent 16de4bc011
commit 5b59ff1e16
2 changed files with 40 additions and 23 deletions

View file

@ -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,10 +1206,44 @@ 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) {
/*
* 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, &t.bt);
getboottimebin(&boottimebin);
bintime_add(&t.bt, &boottimebin);
} else {
bintime(&t.bt);
}
*mp = sbcreatecontrol(&t.bt, sizeof(t.bt), SCM_BINTIME,
SOL_SOCKET, M_NOWAIT);
if (*mp != NULL) {
mp = &(*mp)->m_next;
stamped = true;
}
/*
* 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)) {
@ -1230,21 +1264,6 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
break;
case SO_TS_BINTIME:
if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
M_TSTMP)) {
mbuf_tstmp2timespec(m, &ts1);
timespec2bintime(&ts1, &t.bt);
getboottimebin(&boottimebin);
bintime_add(&t.bt, &boottimebin);
} else {
bintime(&t.bt);
}
*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_REALTIME:

View file

@ -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");