Date: Wed, 8 May 1996 01:04:08 -0400 (EDT) From: Louis Mamakos <louie@TransSys.COM> To: FreeBSD-gnats-submit@freebsd.org Subject: kern/1179: Add socket option to timestamp arriving UDP data queued to socket Message-ID: <199605080504.BAA07011@whizzo.transsys.com> Resent-Message-ID: <199605080510.WAA23719@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 1179 >Category: kern >Synopsis: Add socket option to timestamp arriving UDP data queued to socket >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue May 7 22:10:01 PDT 1996 >Last-Modified: >Originator: Louis Mamakos >Organization: >Release: FreeBSD 2.2-CURRENT i386 >Environment: Desire for accurate time synchronization and timestamps. >Description: The attached code adds a new socket option which arranges for data received on a UDP socket to be timestamped when it's queued to the socket data structures. This then allows the associated user process to read the data at it's leisure (or when it actually is scheduled to run by the kernel), yet still have access to the actual arrival time. The arrival time is critical to the operation of xntpd, which uses the arrival timestamp to compute clock offset and delay samples. >How-To-Repeat: Hmm.. By inspection, or you can install this code, plus a custom version of xntpd which logs the delta times between the recorded time from the socket option, and the time recored when it is running the SIGIO handler. >Fix: Patches to a recent -current kernel. I've been running this code for two weeks with no problems. For best results, the previous PR for a fix to the recvmsg() system call code will allow more than one piece of control information to be returned. Index: kern/uipc_socket.c =================================================================== RCS file: /usr/local/FreeBSD/cvs/CVSROOT/../src/sys/kern/uipc_socket.c,v retrieving revision 1.17 diff -u -r1.17 uipc_socket.c --- uipc_socket.c 1996/04/16 03:50:08 1.17 +++ uipc_socket.c 1996/05/04 04:07:50 @@ -893,6 +893,7 @@ case SO_REUSEADDR: case SO_REUSEPORT: case SO_OOBINLINE: + case SO_TIMESTAMP: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; goto bad; @@ -1017,6 +1018,7 @@ case SO_REUSEPORT: case SO_BROADCAST: case SO_OOBINLINE: + case SO_TIMESTAMP: *mtod(m, int *) = so->so_options & optname; break; Index: netinet/udp_usrreq.c =================================================================== RCS file: /usr/local/FreeBSD/cvs/CVSROOT/../src/sys/netinet/udp_usrreq.c,v retrieving revision 1.25 diff -u -r1.25 udp_usrreq.c --- udp_usrreq.c 1996/05/02 05:54:14 1.25 +++ udp_usrreq.c 1996/05/04 04:08:12 @@ -95,6 +95,7 @@ struct mbuf *)); static void udp_notify __P((struct inpcb *, int)); static struct mbuf *udp_saveopt __P((caddr_t, int, int)); +static struct mbuf *udp_timestamp __P((void)); void udp_init() @@ -304,9 +305,14 @@ */ udp_in.sin_port = uh->uh_sport; udp_in.sin_addr = ip->ip_src; - if (inp->inp_flags & INP_CONTROLOPTS) { + if (inp->inp_flags & INP_CONTROLOPTS + || inp->inp_socket->so_options & SO_TIMESTAMP) { struct mbuf **mp = &opts; + if (inp->inp_socket->so_options & SO_TIMESTAMP) { + if (*mp = udp_timestamp()) + mp = &(*mp)->m_next; + } if (inp->inp_flags & INP_RECVDSTADDR) { *mp = udp_saveopt((caddr_t) &ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR); @@ -369,6 +375,32 @@ cp->cmsg_len = size; cp->cmsg_level = IPPROTO_IP; cp->cmsg_type = type; + return (m); +} + +/* + * Create an mbuf with the SCM_TIMESTAMP socket option data (struct timeval) + * inside. This really isn't UDP specific; but there's not really a better + * place for it yet.. + */ +static struct mbuf * +udp_timestamp() +{ + register struct cmsghdr *cp; + struct mbuf *m; + struct timeval tv; + + MGET(m, M_DONTWAIT, MT_CONTROL); + if (m == 0) + return (struct mbuf *) 0; + + microtime(&tv); + cp = (struct cmsghdr *) mtod(m, struct cmsghdr *); + cp->cmsg_len = + m->m_len = sizeof(*cp) + sizeof(struct timeval); + cp->cmsg_level = SOL_SOCKET; + cp->cmsg_type = SCM_TIMESTAMP; + (void) memcpy(CMSG_DATA(cp), &tv, sizeof(struct timeval)); return (m); } Index: sys/socket.h =================================================================== RCS file: /usr/local/FreeBSD/cvs/CVSROOT/../src/sys/sys/socket.h,v retrieving revision 1.10 diff -u -r1.10 socket.h --- socket.h 1996/02/07 16:19:02 1.10 +++ socket.h 1996/04/09 03:06:21 @@ -63,6 +63,7 @@ #define SO_LINGER 0x0080 /* linger on close if data present */ #define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ #define SO_REUSEPORT 0x0200 /* allow local address & port reuse */ +#define SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */ /* * Additional options, not kept in so_options. @@ -296,6 +297,7 @@ /* "Socket"-level control message types: */ #define SCM_RIGHTS 0x01 /* access rights (array of int) */ +#define SCM_TIMESTAMP 0x02 /* timestamp (struct timeval) */ /* * 4.3 compat sockaddr, move to compat file later >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605080504.BAA07011>