Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Nov 2017 09:46:27 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r325507 - in head/sys: netinet netinet6 sys
Message-ID:  <201711070946.vA79kRs0003937@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Nov  7 09:46:26 2017
New Revision: 325507
URL: https://svnweb.freebsd.org/changeset/base/325507

Log:
  Use hardware timestamps to report packet timestamps for SO_TIMESTAMP
  and other similar socket options.
  
  Provide new control message SCM_TIME_INFO to supply information about
  timestamp.  Currently it indicates that the timestamp was
  hardware-assisted and high-precision, for software timestamps the
  message is not returned.  Reserved fields are added to ABI to report
  additional info about it, it is expected that raw hardware clock value
  might be useful for some applications.
  
  Reviewed by:	gallatin (previous version), hselasky
  Sponsored by:	Mellanox Technologies
  MFC after:	2 weeks
  X-Differential revision:	https://reviews.freebsd.org/D12638

Modified:
  head/sys/netinet/ip_input.c
  head/sys/netinet6/ip6_input.c
  head/sys/sys/socket.h

Modified: head/sys/netinet/ip_input.c
==============================================================================
--- head/sys/netinet/ip_input.c	Tue Nov  7 09:29:14 2017	(r325506)
+++ head/sys/netinet/ip_input.c	Tue Nov  7 09:46:26 2017	(r325507)
@@ -1143,40 +1143,96 @@ void
 ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
     struct mbuf *m)
 {
+	bool stamped;
 
+	stamped = false;
 	if ((inp->inp_socket->so_options & SO_BINTIME) ||
 	    CHECK_SO_CT(inp->inp_socket, SO_TS_BINTIME)) {
-		struct bintime bt;
+		struct bintime boottimebin, bt;
+		struct timespec ts1;
 
-		bintime(&bt);
+		if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+		    M_TSTMP)) {
+			mbuf_tstmp2timespec(m, &ts1);
+			timespec2bintime(&ts1, &bt);
+			getboottimebin(&boottimebin);
+			bintime_add(&bt, &boottimebin);
+		} else {
+			bintime(&bt);
+		}
 		*mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt),
 		    SCM_BINTIME, SOL_SOCKET);
-		if (*mp)
+		if (*mp != NULL) {
 			mp = &(*mp)->m_next;
+			stamped = true;
+		}
 	}
 	if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME_MICRO)) {
+		struct bintime boottimebin, bt1;
+		struct timespec ts1;;
 		struct timeval tv;
 
-		microtime(&tv);
+		if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+		    M_TSTMP)) {
+			mbuf_tstmp2timespec(m, &ts1);
+			timespec2bintime(&ts1, &bt1);
+			getboottimebin(&boottimebin);
+			bintime_add(&bt1, &boottimebin);
+			bintime2timeval(&bt1, &tv);
+		} else {
+			microtime(&tv);
+		}
 		*mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv),
 		    SCM_TIMESTAMP, SOL_SOCKET);
-		if (*mp)
+		if (*mp != NULL) {
 			mp = &(*mp)->m_next;
+			stamped = true;
+		}
 	} else if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME)) {
-		struct timespec ts;
+		struct bintime boottimebin;
+		struct timespec ts, ts1;
 
-		nanotime(&ts);
+		if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+		    M_TSTMP)) {
+			mbuf_tstmp2timespec(m, &ts);
+			getboottimebin(&boottimebin);
+			bintime2timespec(&boottimebin, &ts1);
+			timespecadd(&ts, &ts1);
+		} else {
+			nanotime(&ts);
+		}
 		*mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts),
 		    SCM_REALTIME, SOL_SOCKET);
-		if (*mp)
+		if (*mp != NULL) {
 			mp = &(*mp)->m_next;
+			stamped = true;
+		}
 	} else if (CHECK_SO_CT(inp->inp_socket, SO_TS_MONOTONIC)) {
 		struct timespec ts;
 
-		nanouptime(&ts);
+		if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+		    M_TSTMP))
+			mbuf_tstmp2timespec(m, &ts);
+		else
+			nanouptime(&ts);
 		*mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts),
 		    SCM_MONOTONIC, SOL_SOCKET);
-		if (*mp)
+		if (*mp != NULL) {
+			mp = &(*mp)->m_next;
+			stamped = true;
+		}
+	}
+	if (stamped && (m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+	    M_TSTMP)) {
+		struct sock_timestamp_info sti;
+
+		bzero(&sti, sizeof(sti));
+		sti.st_info_flags = ST_INFO_HW;
+		if ((m->m_flags & M_TSTMP_HPREC) != 0)
+			sti.st_info_flags |= ST_INFO_HW_HPREC;
+		*mp = sbcreatecontrol((caddr_t)&sti, sizeof(sti), SCM_TIME_INFO,
+		    SOL_SOCKET);
+		if (*mp != NULL)
 			mp = &(*mp)->m_next;
 	}
 	if (inp->inp_flags & INP_RECVDSTADDR) {

Modified: head/sys/netinet6/ip6_input.c
==============================================================================
--- head/sys/netinet6/ip6_input.c	Tue Nov  7 09:29:14 2017	(r325506)
+++ head/sys/netinet6/ip6_input.c	Tue Nov  7 09:46:26 2017	(r325507)
@@ -1221,42 +1221,96 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, 
 			struct bintime bt;
 			struct timespec ts;
 		} t;
+		struct bintime boottimebin, bt1;
+		struct timespec ts1;
+		bool stamped;
 
+		stamped = false;
 		switch (inp->inp_socket->so_ts_clock) {
 		case SO_TS_REALTIME_MICRO:
-			microtime(&t.tv);
+			if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+			    M_TSTMP)) {
+				mbuf_tstmp2timespec(m, &ts1);
+				timespec2bintime(&ts1, &bt1);
+				getboottimebin(&boottimebin);
+				bintime_add(&bt1, &boottimebin);
+				bintime2timeval(&bt1, &t.tv);
+			} else {
+				microtime(&t.tv);
+			}
 			*mp = sbcreatecontrol((caddr_t) &t.tv, sizeof(t.tv),
 			    SCM_TIMESTAMP, SOL_SOCKET);
-			if (*mp)
+			if (*mp != NULL) {
 				mp = &(*mp)->m_next;
+				stamped = true;
+			}
 			break;
 
 		case SO_TS_BINTIME:
-			bintime(&t.bt);
+			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((caddr_t)&t.bt, sizeof(t.bt),
 			    SCM_BINTIME, SOL_SOCKET);
-			if (*mp)
+			if (*mp != NULL) {
 				mp = &(*mp)->m_next;
+				stamped = true;
+			}
 			break;
 
 		case SO_TS_REALTIME:
-			nanotime(&t.ts);
+			if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+			    M_TSTMP)) {
+				mbuf_tstmp2timespec(m, &t.ts);
+				getboottimebin(&boottimebin);
+				bintime2timespec(&boottimebin, &ts1);
+				timespecadd(&t.ts, &ts1);
+			} else {
+				nanotime(&t.ts);
+			}
 			*mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts),
 			    SCM_REALTIME, SOL_SOCKET);
-			if (*mp)
+			if (*mp != NULL) {
 				mp = &(*mp)->m_next;
+				stamped = true;
+			}
 			break;
 
 		case SO_TS_MONOTONIC:
-			nanouptime(&t.ts);
+			if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR |
+			    M_TSTMP))
+				mbuf_tstmp2timespec(m, &t.ts);
+			else
+				nanouptime(&t.ts);
 			*mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts),
 			    SCM_MONOTONIC, SOL_SOCKET);
-			if (*mp)
+			if (*mp != NULL) {
 				mp = &(*mp)->m_next;
+				stamped = true;
+			}
 			break;
 
 		default:
 			panic("unknown (corrupted) so_ts_clock");
+		}
+		if (stamped && (m->m_flags & (M_PKTHDR | M_TSTMP)) ==
+		    (M_PKTHDR | M_TSTMP)) {
+			struct sock_timestamp_info sti;
+
+			bzero(&sti, sizeof(sti));
+			sti.st_info_flags = ST_INFO_HW;
+			if ((m->m_flags & M_TSTMP_HPREC) != 0)
+				sti.st_info_flags |= ST_INFO_HW_HPREC;
+			*mp = sbcreatecontrol((caddr_t)&sti, sizeof(sti),
+			    SCM_TIME_INFO, SOL_SOCKET);
+			if (*mp != NULL)
+				mp = &(*mp)->m_next;
 		}
 	}
 #endif

Modified: head/sys/sys/socket.h
==============================================================================
--- head/sys/sys/socket.h	Tue Nov  7 09:29:14 2017	(r325506)
+++ head/sys/sys/socket.h	Tue Nov  7 09:46:26 2017	(r325507)
@@ -563,6 +563,17 @@ struct sockcred {
 #define	SCM_BINTIME	0x04		/* timestamp (struct bintime) */
 #define	SCM_REALTIME	0x05		/* timestamp (struct timespec) */
 #define	SCM_MONOTONIC	0x06		/* timestamp (struct timespec) */
+#define	SCM_TIME_INFO	0x07		/* timestamp info */
+
+struct sock_timestamp_info {
+	__uint32_t	st_info_flags;
+	__uint32_t	st_info_pad0;
+	__uint64_t	st_info_rsv[7];
+};
+
+#define	ST_INFO_HW		0x0001		/* SCM_TIMESTAMP was hw */
+#define	ST_INFO_HW_HPREC	0x0002		/* SCM_TIMESTAMP was hw-assisted
+						   on entrance */
 #endif
 
 #if __BSD_VISIBLE



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201711070946.vA79kRs0003937>