Date: Wed, 12 Sep 2018 18:52:19 +0000 (UTC) From: Maxim Sobolev <sobomax@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r338617 - in stable/11: lib/libc/sys sys/compat/freebsd32 sys/kern sys/netinet sys/netinet6 sys/sys tools/regression/sockets/udp_pingpong tools/regression/sockets/unix_cmsg Message-ID: <201809121852.w8CIqJrm046105@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sobomax Date: Wed Sep 12 18:52:18 2018 New Revision: 338617 URL: https://svnweb.freebsd.org/changeset/base/338617 Log: MFC r312296 and r323254, which is new a socket option SO_TS_CLOCK to pick from several different clock sources to return timestamps when SO_TIMESTAMP is enabled and two new nanosecond-precision timestamp types. This also fixes recvmsg32() system call to properly down-convert layout of the 64-bit structures to match what 32-bit app(s) expect. Bump __FreeBSD_version to indicate presence of a new functionality. Differential Revision: https://reviews.freebsd.org/D9171 Added: stable/11/tools/regression/sockets/udp_pingpong/ - copied from r312296, head/tools/regression/sockets/udp_pingpong/ Modified: stable/11/lib/libc/sys/getsockopt.2 stable/11/sys/compat/freebsd32/freebsd32.h stable/11/sys/compat/freebsd32/freebsd32_misc.c stable/11/sys/kern/uipc_socket.c stable/11/sys/kern/uipc_usrreq.c stable/11/sys/netinet/ip_input.c stable/11/sys/netinet6/ip6_input.c stable/11/sys/sys/param.h stable/11/sys/sys/socket.h stable/11/sys/sys/socketvar.h stable/11/tools/regression/sockets/unix_cmsg/Makefile stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c Directory Properties: stable/11/ (props changed) Modified: stable/11/lib/libc/sys/getsockopt.2 ============================================================================== --- stable/11/lib/libc/sys/getsockopt.2 Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/lib/libc/sys/getsockopt.2 Wed Sep 12 18:52:18 2018 (r338617) @@ -187,6 +187,7 @@ The following options are recognized in .It Dv SO_LISTENQLEN Ta "get complete queue length of the socket (get only)" .It Dv SO_LISTENINCQLEN Ta "get incomplete queue length of the socket (get only)" .It Dv SO_USER_COOKIE Ta "set the 'so_user_cookie' value for the socket (uint32_t, set only)" +.It Dv SO_TS_CLOCK Ta "set specific format of timestamp returned by SO_TIMESTAMP" .El .Pp .Dv SO_DEBUG @@ -435,7 +436,7 @@ for .Dv SO_BINTIME . The .Vt cmsghdr -fields have the following values for TIMESTAMP: +fields have the following values for TIMESTAMP by default: .Bd -literal cmsg_len = CMSG_LEN(sizeof(struct timeval)); cmsg_level = SOL_SOCKET; @@ -449,6 +450,24 @@ and for cmsg_level = SOL_SOCKET; cmsg_type = SCM_BINTIME; .Ed +.Pp +Additional timestamp types are available by following +.Dv SO_TIMESTAMP +with +.Dv SO_TS_CLOCK , +which requests specific timestamp format to be returned instead of +.Dv SCM_TIMESTAMP when +.Dv SO_TIMESTAMP is enabled. +The following +.Dv SO_TS_CLOCK +values are recognized in +.Fx : +.Bl -column SO_TS_CLOCK -offset indent +.It Dv SO_TS_REALTIME_MICRO Ta "realtime (SCM_TIMESTAMP, struct timeval), default" +.It Dv SO_TS_BINTIME Ta "realtime (SCM_BINTIME, struct bintime)" +.It Dv SO_TS_REALTIME Ta "realtime (SCM_REALTIME, struct timespec)" +.It Dv SO_TS_MONOTONIC Ta "monotonic time (SCM_MONOTONIC, struct timespec)" +.El .Pp .Dv SO_ACCEPTCONN , .Dv SO_TYPE , Modified: stable/11/sys/compat/freebsd32/freebsd32.h ============================================================================== --- stable/11/sys/compat/freebsd32/freebsd32.h Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/compat/freebsd32/freebsd32.h Wed Sep 12 18:52:18 2018 (r338617) @@ -78,6 +78,15 @@ struct itimerspec32 { TS_CP((src), (dst), it_value); \ } while (0) +struct bintime32 { + uint32_t sec; + uint32_t frac[2]; +}; +#define BT_CP(src, dst, fld) do { \ + CP((src).fld, (dst).fld, sec); \ + *(uint64_t *)&(dst).fld.frac[0] = (src).fld.frac; \ +} while (0) + struct rusage32 { struct timeval32 ru_utime; struct timeval32 ru_stime; Modified: stable/11/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- stable/11/sys/compat/freebsd32/freebsd32_misc.c Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/compat/freebsd32/freebsd32_misc.c Wed Sep 12 18:52:18 2018 (r338617) @@ -117,6 +117,7 @@ FEATURE(compat_freebsd_32bit, "Compatible with 32-bit CTASSERT(sizeof(struct timeval32) == 8); CTASSERT(sizeof(struct timespec32) == 8); CTASSERT(sizeof(struct itimerval32) == 16); +CTASSERT(sizeof(struct bintime32) == 12); #endif CTASSERT(sizeof(struct statfs32) == 256); #ifndef __mips__ @@ -904,12 +905,67 @@ freebsd32_copyoutmsghdr(struct msghdr *msg, struct msg #define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ FREEBSD32_ALIGN(sizeof(struct cmsghdr))) + +static size_t +freebsd32_cmsg_convert(struct cmsghdr *cm, void *data, socklen_t datalen) +{ + size_t copylen; + union { + struct timespec32 ts; + struct timeval32 tv; + struct bintime32 bt; + } tmp32; + + union { + struct timespec ts; + struct timeval tv; + struct bintime bt; + } *in; + + in = data; + copylen = 0; + switch (cm->cmsg_level) { + case SOL_SOCKET: + switch (cm->cmsg_type) { + case SCM_TIMESTAMP: + TV_CP(*in, tmp32, tv); + copylen = sizeof(tmp32.tv); + break; + + case SCM_BINTIME: + BT_CP(*in, tmp32, bt); + copylen = sizeof(tmp32.bt); + break; + + case SCM_REALTIME: + case SCM_MONOTONIC: + TS_CP(*in, tmp32, ts); + copylen = sizeof(tmp32.ts); + break; + + default: + break; + } + + default: + break; + } + + if (copylen == 0) + return (datalen); + + KASSERT((datalen >= copylen), ("corrupted cmsghdr")); + + bcopy(&tmp32, data, copylen); + return (copylen); +} + static int freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) { struct cmsghdr *cm; void *data; - socklen_t clen, datalen; + socklen_t clen, datalen, datalen_out; int error; caddr_t ctlbuf; int len, maxlen, copylen; @@ -933,16 +989,16 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf cm->cmsg_len > clen) { error = EINVAL; break; - } + } data = CMSG_DATA(cm); datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; + datalen_out = freebsd32_cmsg_convert(cm, data, datalen); /* Adjust message length */ cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + - datalen; + datalen_out; - /* Copy cmsghdr */ copylen = sizeof(struct cmsghdr); if (len < copylen) { @@ -950,7 +1006,7 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf copylen = len; } - error = copyout(cm,ctlbuf,copylen); + error = copyout(cm, ctlbuf, copylen); if (error) goto exit; @@ -961,13 +1017,13 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf break; /* Copy data */ - copylen = datalen; + copylen = datalen_out; if (len < copylen) { msg->msg_flags |= MSG_CTRUNC; copylen = len; } - error = copyout(data,ctlbuf,copylen); + error = copyout(data, ctlbuf, copylen); if (error) goto exit; Modified: stable/11/sys/kern/uipc_socket.c ============================================================================== --- stable/11/sys/kern/uipc_socket.c Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/kern/uipc_socket.c Wed Sep 12 18:52:18 2018 (r338617) @@ -2696,6 +2696,18 @@ sosetopt(struct socket *so, struct sockopt *sopt) #endif break; + case SO_TS_CLOCK: + error = sooptcopyin(sopt, &optval, sizeof optval, + sizeof optval); + if (error) + goto bad; + if (optval < 0 || optval > SO_TS_CLOCK_MAX) { + error = EINVAL; + goto bad; + } + so->so_ts_clock = optval; + break; + default: if (V_socket_hhh[HHOOK_SOCKET_OPT]->hhh_nhooks > 0) error = hhook_run_socket(so, sopt, @@ -2881,6 +2893,10 @@ integer: case SO_LISTENINCQLEN: optval = so->so_incqlen; + goto integer; + + case SO_TS_CLOCK: + optval = so->so_ts_clock; goto integer; default: Modified: stable/11/sys/kern/uipc_usrreq.c ============================================================================== --- stable/11/sys/kern/uipc_usrreq.c Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/kern/uipc_usrreq.c Wed Sep 12 18:52:18 2018 (r338617) @@ -1908,6 +1908,7 @@ unp_internalize(struct mbuf **controlp, struct thread struct filedescent *fde, **fdep, *fdev; struct file *fp; struct timeval *tv; + struct timespec *ts; int i, *fdp; void *data; socklen_t clen = control->m_len, datalen; @@ -2026,6 +2027,30 @@ unp_internalize(struct mbuf **controlp, struct thread bt = (struct bintime *) CMSG_DATA(mtod(*controlp, struct cmsghdr *)); bintime(bt); + break; + + case SCM_REALTIME: + *controlp = sbcreatecontrol(NULL, sizeof(*ts), + SCM_REALTIME, SOL_SOCKET); + if (*controlp == NULL) { + error = ENOBUFS; + goto out; + } + ts = (struct timespec *) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + nanotime(ts); + break; + + case SCM_MONOTONIC: + *controlp = sbcreatecontrol(NULL, sizeof(*ts), + SCM_MONOTONIC, SOL_SOCKET); + if (*controlp == NULL) { + error = ENOBUFS; + goto out; + } + ts = (struct timespec *) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + nanouptime(ts); break; default: Modified: stable/11/sys/netinet/ip_input.c ============================================================================== --- stable/11/sys/netinet/ip_input.c Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/netinet/ip_input.c Wed Sep 12 18:52:18 2018 (r338617) @@ -1138,30 +1138,48 @@ ip_forward(struct mbuf *m, int srcrt) icmp_error(mcopy, type, code, dest.s_addr, mtu); } +#define CHECK_SO_CT(sp, ct) \ + (((sp->so_options & SO_TIMESTAMP) && (sp->so_ts_clock == ct)) ? 1 : 0) + void ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, struct mbuf *m) { - if (inp->inp_socket->so_options & (SO_BINTIME | SO_TIMESTAMP)) { + if ((inp->inp_socket->so_options & SO_BINTIME) || + CHECK_SO_CT(inp->inp_socket, SO_TS_BINTIME)) { struct bintime bt; bintime(&bt); - if (inp->inp_socket->so_options & SO_BINTIME) { - *mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt), - SCM_BINTIME, SOL_SOCKET); - if (*mp) - mp = &(*mp)->m_next; - } - if (inp->inp_socket->so_options & SO_TIMESTAMP) { - struct timeval tv; + *mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt), + SCM_BINTIME, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + } + if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME_MICRO)) { + struct timeval tv; - bintime2timeval(&bt, &tv); - *mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv), - SCM_TIMESTAMP, SOL_SOCKET); - if (*mp) - mp = &(*mp)->m_next; - } + microtime(&tv); + *mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv), + SCM_TIMESTAMP, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + } else if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME)) { + struct timespec ts; + + nanotime(&ts); + *mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts), + SCM_REALTIME, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + } else if (CHECK_SO_CT(inp->inp_socket, SO_TS_MONOTONIC)) { + struct timespec ts; + + nanouptime(&ts); + *mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts), + SCM_MONOTONIC, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVDSTADDR) { *mp = sbcreatecontrol((caddr_t)&ip->ip_dst, Modified: stable/11/sys/netinet6/ip6_input.c ============================================================================== --- stable/11/sys/netinet6/ip6_input.c Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/netinet6/ip6_input.c Wed Sep 12 18:52:18 2018 (r338617) @@ -1213,13 +1213,48 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, #ifdef SO_TIMESTAMP if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) { - struct timeval tv; + union { + struct timeval tv; + struct bintime bt; + struct timespec ts; + } t; - microtime(&tv); - *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), - SCM_TIMESTAMP, SOL_SOCKET); - if (*mp) - mp = &(*mp)->m_next; + switch (inp->inp_socket->so_ts_clock) { + case SO_TS_REALTIME_MICRO: + microtime(&t.tv); + *mp = sbcreatecontrol((caddr_t) &t.tv, sizeof(t.tv), + SCM_TIMESTAMP, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + break; + + case SO_TS_BINTIME: + bintime(&t.bt); + *mp = sbcreatecontrol((caddr_t)&t.bt, sizeof(t.bt), + SCM_BINTIME, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + break; + + case SO_TS_REALTIME: + nanotime(&t.ts); + *mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts), + SCM_REALTIME, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + break; + + case SO_TS_MONOTONIC: + nanouptime(&t.ts); + *mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts), + SCM_MONOTONIC, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + break; + + default: + panic("unknown (corrupted) so_ts_clock"); + } } #endif Modified: stable/11/sys/sys/param.h ============================================================================== --- stable/11/sys/sys/param.h Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/sys/param.h Wed Sep 12 18:52:18 2018 (r338617) @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1102501 /* Master, propagated to newvers */ +#define __FreeBSD_version 1102502 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, Modified: stable/11/sys/sys/socket.h ============================================================================== --- stable/11/sys/sys/socket.h Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/sys/socket.h Wed Sep 12 18:52:18 2018 (r338617) @@ -158,8 +158,18 @@ typedef __uintptr_t uintptr_t; #define SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */ #define SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */ #define SO_PROTOTYPE SO_PROTOCOL /* alias for SO_PROTOCOL (SunOS name) */ +#define SO_TS_CLOCK 0x1017 /* clock type used for SO_TIMESTAMP */ #endif +#if __BSD_VISIBLE +#define SO_TS_REALTIME_MICRO 0 /* microsecond resolution, realtime */ +#define SO_TS_BINTIME 1 /* sub-nanosecond resolution, realtime */ +#define SO_TS_REALTIME 2 /* nanosecond resolution, realtime */ +#define SO_TS_MONOTONIC 3 /* nanosecond resolution, monotonic */ +#define SO_TS_DEFAULT SO_TS_REALTIME_MICRO +#define SO_TS_CLOCK_MAX SO_TS_MONOTONIC +#endif + /* * Space reserved for new socket options added by third-party vendors. * This range applies to all socket option levels. New socket options @@ -534,6 +544,8 @@ struct sockcred { #define SCM_TIMESTAMP 0x02 /* timestamp (struct timeval) */ #define SCM_CREDS 0x03 /* process creds (struct cmsgcred) */ #define SCM_BINTIME 0x04 /* timestamp (struct bintime) */ +#define SCM_REALTIME 0x05 /* timestamp (struct timespec) */ +#define SCM_MONOTONIC 0x06 /* timestamp (struct timespec) */ #endif #if __BSD_VISIBLE Modified: stable/11/sys/sys/socketvar.h ============================================================================== --- stable/11/sys/sys/socketvar.h Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/sys/sys/socketvar.h Wed Sep 12 18:52:18 2018 (r338617) @@ -127,6 +127,8 @@ struct socket { int so_fibnum; /* routing domain for this socket */ uint32_t so_user_cookie; + int so_ts_clock; /* type of the clock used for timestamps */ + void *so_pspare[2]; /* packet pacing / general use */ int so_ispare[2]; /* packet pacing / general use */ }; Modified: stable/11/tools/regression/sockets/unix_cmsg/Makefile ============================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/Makefile Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/tools/regression/sockets/unix_cmsg/Makefile Wed Sep 12 18:52:18 2018 (r338617) @@ -4,4 +4,29 @@ PROG= unix_cmsg MAN= WARNS?= 3 +REXP_bintime= 's|%%TTYPE%%|bintime|g ; s|%%DTYPE%%|bintime|g ; \ + s|%%SCM_TTYPE%%|SCM_BINTIME|g ; \ + s|%%MAJ_MEMB%%|sec|g ; s|%%MIN_MEMB%%|frac|g' +REXP_timeval= 's|%%TTYPE%%|timeval|g ; s|%%DTYPE%%|timeval|g ; \ + s|%%SCM_TTYPE%%|SCM_TIMESTAMP|g ; \ + s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_usec|g' +REXP_timespec_real= 's|%%TTYPE%%|timespec_real|g ; s|%%DTYPE%%|timespec|g ; \ + s|%%SCM_TTYPE%%|SCM_REALTIME|g ; \ + s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_nsec|g' +REXP_timespec_mono= 's|%%TTYPE%%|timespec_mono|g ; s|%%DTYPE%%|timespec|g ; \ + s|%%SCM_TTYPE%%|SCM_MONOTONIC|g ; \ + s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_nsec|g' + +.for ttype in bintime timeval timespec_real timespec_mono +AUTOSRCS+= t_${ttype}.h t_${ttype}.c + +t_${ttype}.o: t_${ttype}.c t_${ttype}.h + +t_${ttype}.c: t_xxxtime.c.in + sed ${REXP_${ttype}} < ${.ALLSRC} > ${.TARGET} + +t_${ttype}.h: t_xxxtime.h.in + sed ${REXP_${ttype}} < ${.ALLSRC} > ${.TARGET} +.endfor + .include <bsd.prog.mk> Modified: stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c ============================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c Wed Sep 12 15:06:30 2018 (r338616) +++ stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c Wed Sep 12 18:52:18 2018 (r338617) @@ -52,6 +52,18 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> +#include "uc_common.h" +#include "t_cmsgcred.h" +#include "t_bintime.h" +#include "t_generic.h" +#include "t_peercred.h" +#include "t_timeval.h" +#include "t_sockcred.h" +#include "t_cmsgcred_sockcred.h" +#include "t_cmsg_len.h" +#include "t_timespec_real.h" +#include "t_timespec_mono.h" + /* * There are tables with tests descriptions and pointers to test * functions. Each t_*() function returns 0 if its test passed, @@ -135,7 +147,19 @@ static const struct test_func test_stream_tbl[] = { { .func = t_peercred, .desc = "Check LOCAL_PEERCRED socket option" + }, +#if defined(SCM_REALTIME) + { + .func = t_timespec_real, + .desc = "Sending, receiving realtime" + }, +#endif +#if defined(SCM_MONOTONIC) + { + .func = t_timespec_mono, + .desc = "Sending, receiving monotonic time (uptime)" } +#endif }; #define TEST_STREAM_TBL_SIZE \ @@ -170,6 +194,18 @@ static const struct test_func test_dgram_tbl[] = { { .func = t_cmsg_len, .desc = "Check cmsghdr.cmsg_len" + }, +#endif +#if defined(SCM_REALTIME) + { + .func = t_timespec_real, + .desc = "Sending, receiving realtime" + }, +#endif +#if defined(SCM_MONOTONIC) + { + .func = t_timespec_mono, + .desc = "Sending, receiving monotonic time (uptime)" } #endif };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201809121852.w8CIqJrm046105>