Skip site navigation (1)Skip section navigation (2)
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>