tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

reviving SO_TIMESTAMPING/SO_TIMESTAMPNS from GSoC 2012



Hello,

Since ntpd will start supporting SO_TIMESTAMPING, I thought it would
be nice to revive and commit the GSoC 2012 timestamping code from Vlad Balan.
This copies the linux timestamping API, shown in the first part of the
diff as <net/tstamp.h>. Support for the Intel gigabit card is provided,
although I don't have one, so I can't test. If I don't hear anything,
I will commit it over the weekend.

christos

--- /dev/null	2017-07-06 16:44:45.175864498 -0400
+++ net/tstamp.h	2017-07-06 16:29:43.773323726 -0400
@@ -0,0 +1,136 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright 2012 Vlad Balan
+ *
+ * Written by Vlad Balan for the NetBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _NET_TSTAMP_H_
+#define _NET_TSTAMP_H_
+
+#define	SOF_TIMESTAMPING_TX_HARDWARE	0x01
+#define	SOF_TIMESTAMPING_TX_SOFTWARE	0x02
+#define	SOF_TIMESTAMPING_RX_HARDWARE	0x04
+#define	SOF_TIMESTAMPING_RX_SOFTWARE	0x08
+#define	SOF_TIMESTAMPING_SOFTWARE	0x10
+#define	SOF_TIMESTAMPING_SYS_HARDWARE	0x20
+#define	SOF_TIMESTAMPING_RAW_HARDWARE	0x40
+#define	SOF_TIMESTAMPING_MASK 		0x7f
+
+struct hwtstamp_config {
+	int flags;
+	int tx_type;
+	int rx_filter;
+};
+
+enum hwtstamp_tx_types {
+	HWTSTAMP_TX_OFF,
+	HWTSTAMP_TX_ON,
+	HWTSTAMP_TX_ONESTEP_SYNC,
+};
+
+enum hwtstamp_rx_filters {
+	HWTSTAMP_FILTER_NONE,
+	HWTSTAMP_FILTER_ALL,
+	HWTSTAMP_FILTER_SOME,
+	HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
+	HWTSTAMP_FILTER_PTP_V1_L4_SYNC,
+	HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ,
+	HWTSTAMP_FILTER_PTP_V2_L4_EVENT,
+	HWTSTAMP_FILTER_PTP_V2_L4_SYNC,
+	HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ,
+	HWTSTAMP_FILTER_PTP_V2_L2_EVENT,
+	HWTSTAMP_FILTER_PTP_V2_L2_SYNC,
+	HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ,
+	HWTSTAMP_FILTER_PTP_V2_EVENT,
+	HWTSTAMP_FILTER_PTP_V2_SYNC,
+	HWTSTAMP_FILTER_PTP_V2_DELAY_REQ,
+};
+
+#ifdef _KERNEL
+
+/* This is the structure used in the recvmsg call*/
+struct scm_timestamping {
+	struct timespec systime;
+	struct timespec hwtimetrans;
+	struct timespec hwtimeraw;
+};
+
+#define TSTAMP_OUTPUT_TAG(m0) m_tag_find((m0), PACKET_TAG_TSTAMP, NULL)
+
+static inline int
+tstamp_input_tag(struct ifnet *ifp, struct mbuf *m,
+    const struct scm_timestamping *tstamp)
+{
+	struct m_tag *mtag;	
+	
+	mtag = m_tag_get(PACKET_TAG_TSTAMP, sizeof(*tstamp), M_NOWAIT);
+	if (mtag == NULL) {
+		ifp->if_ierrors++;
+#ifdef DIAGNOSTIC
+		printf("%s: unable to allocate TSTAMP tag\n", ifp->if_xname);
+#endif
+		return -1;
+	}
+
+	memcpy(mtag + 1, tstamp, sizeof(*tstamp));
+	m_tag_prepend(m, mtag);
+	return 0;
+}
+
+/* 
+ * struct timespec can be two uint32_t, one for seconds, one for nanoseconds
+ * we split a 64-bit cycle count among the seconds and the nanoseconds
+ */
+static inline void
+tstamp_set_hwtimeraw(struct scm_timestamping *tstamp, uint64_t cycles,
+    int flags, bool rx)
+{
+	const bool hwstamp = (rx && (flags & SOF_TIMESTAMPING_RX_HARDWARE)) ||
+	    (!rx && (flags & SOF_TIMESTAMPING_TX_HARDWARE)) ||
+	    SOF_TIMESTAMPING_RAW_HARDWARE;
+
+	if (hwstamp) {	     
+		tstamp->hwtimeraw.tv_sec = (uint32_t)(cycles >> 32);
+		tstamp->hwtimeraw.tv_nsec = (uint32_t)(cycles & 0xffffffff);
+#ifdef DIAGNOSTIC
+		printf("%s: cycles %" PRIu64 " tv_sec:%jx tv_nsec:%lx\n",
+		    __func__, cycles, (uintmax_t)tstamp->hwtimeraw.tv_sec,
+		    (unsigned long)tstamp->hwtimeraw.tv_nsec);
+#endif
+	}
+
+	const bool systime = (rx && (flags & SOF_TIMESTAMPING_RX_SOFTWARE)) ||
+	    (!rx && (flags & SOF_TIMESTAMPING_TX_SOFTWARE)) ||
+	    SOF_TIMESTAMPING_SOFTWARE;
+
+	if (systime)
+		nanotime(&tstamp->systime);
+}
+
+#endif /* _KERNEL */
+
+#endif /* _NET_TSTAMP_H_ */

Index: dev/pci/if_wm.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wm.c,v
retrieving revision 1.518
diff -u -u -r1.518 if_wm.c
--- dev/pci/if_wm.c	6 Jul 2017 08:50:52 -0000	1.518
+++ dev/pci/if_wm.c	6 Jul 2017 20:44:46 -0000
@@ -114,6 +114,7 @@
 #include <net/if_dl.h>
 #include <net/if_media.h>
 #include <net/if_ether.h>
+#include <net/tstamp.h>
 
 #include <net/bpf.h>
 
@@ -143,6 +144,8 @@
 #include <dev/pci/if_wmreg.h>
 #include <dev/pci/if_wmvar.h>
 
+#define WM_TIMESTAMP
+
 #ifdef WM_DEBUG
 #define	WM_DEBUG_LINK		__BIT(0)
 #define	WM_DEBUG_TX		__BIT(1)
@@ -152,8 +155,10 @@
 #define	WM_DEBUG_NVM		__BIT(5)
 #define	WM_DEBUG_INIT		__BIT(6)
 #define	WM_DEBUG_LOCK		__BIT(7)
+#define	WM_DEBUG_TIMESTAMP	__BIT(8)
 int	wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII
-    | WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT | WM_DEBUG_LOCK;
+    | WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT | WM_DEBUG_LOCK
+    | WM_DEBUG_TIMESTAMP;
 
 #define	DPRINTF(x, y)	if (wm_debug & (x)) printf y
 #else
@@ -564,6 +569,10 @@
 	kmutex_t *sc_ich_nvmmtx;	/* ICH/PCH specific NVM mutex */
 
 	struct wm_phyop phy;
+#ifdef WM_TIMESTAMP
+	/* hardware timestamp config */
+	struct hwtstamp_config sc_hwtstamp_config;
+#endif
 };
 
 #define WM_CORE_LOCK(_sc)	if ((_sc)->sc_core_lock) mutex_enter((_sc)->sc_core_lock)
@@ -3015,6 +3024,318 @@
 	return rc;
 }
 
+#ifdef WM_TIMESTAMP
+
+static int
+wm_txtimestamp(struct wm_softc *sc, uint64_t *cycles)
+{
+	DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s\n",
+	    device_xname(sc->sc_dev), __func__));
+
+	switch (sc->sc_type) {
+	case WM_T_82574:
+	case WM_T_82576:
+		*cycles = CSR_READ(sc, WM_TXSTMPL);
+		*cycles |= ((uint64_t) CSR_READ(sc, WM_TXSTMPH)) << 32;
+		
+		DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s cycles: %#" PRIx64 "\n",
+		    device_xname(sc->sc_dev), __func__, *cycles));
+		return 0;
+	default:
+		return EOPNOTSUPP;
+	}
+}
+
+static int
+wm_rxtimestamp(struct wm_softc *sc, uint64_t *cycles)
+{
+
+	DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s\n",
+	    device_xname(sc->sc_dev), __func__));
+
+	switch (sc->sc_type) {
+	case WM_T_82574:
+	case WM_T_82576:
+		*cycles = CSR_READ(sc, WM_RXSTMPL);
+		*cycles |= ((uint64_t) CSR_READ(sc, WM_RXSTMPH)) << 32;
+
+		DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s cycles: %#" PRIx64 "\n",
+		    device_xname(sc->sc_dev), __func__, *cycles));
+		return 0;
+	default:
+		return EINVAL;
+	}
+}
+
+static int
+wm_txtimestamp_mbuf(struct wm_softc *sc, struct mbuf *m)
+{
+	uint64_t cycles;
+	struct scm_timestamping tstamp;
+	int error;
+
+	DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s\n",
+	    device_xname(sc->sc_dev), __func__));
+	
+	if ((error = wm_txtimestamp(sc, &cycles)) != 0)
+		return error;
+
+	/* only if hw tstamp timestamp */
+	tstamp_set_hwtimeraw(&tstamp, cycles, sc->sc_hwtstamp_config.flags, 0);
+
+	/* system timestamp here */
+	tstamp_input_tag(&sc->sc_ethercom.ec_if, m, &tstamp);
+
+	return 0;
+}
+	
+static int
+wm_rxtimestamp_mbuf(struct wm_softc *sc, struct mbuf *m)
+{
+	uint64_t cycles;
+ 	struct scm_timestamping tstamp; 
+	int error;
+
+	DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s\n",
+	    device_xname(sc->sc_dev), __func__));
+	
+        if ((error = wm_rxtimestamp(sc, &cycles)) != 0)
+		return error;
+
+	memset(&tstamp, 0, sizeof(tstamp));
+	
+	/* only if hw tstamp timestamp */
+	tstamp_set_hwtimeraw(&tstamp, cycles, sc->sc_hwtstamp_config.flags, 1);
+	
+	/* system timestamp here */
+ 	tstamp_input_tag(&sc->sc_ethercom.ec_if, m, &tstamp); 
+	
+	return 0;
+}
+
+static int
+wm_enablectl(struct wm_softc *sc, int reg)
+{
+	int ctrl = CSR_READ(sc, reg);
+
+	ctrl |= 0x10;		/* bit 4 enables timestamping */
+	CSR_WRITE(sc, reg, ctrl);
+	ctrl = CSR_READ(sc, reg);
+	if (!(ctrl & 0x10)) {
+		log(LOG_DEBUG,
+		    "%s: enabling %s timestamping failed\n",
+		    device_xname(sc->sc_dev),
+		    reg == WM_TSYNCTXCTL ? "tx" : "rx");
+		return ENXIO;
+	}
+	return 0;
+}
+	
+static int
+wm_disablectl(struct wm_softc *sc, int reg)
+{
+	int ctrl = CSR_READ(sc, reg);
+
+	ctrl &= ~0x10; /* bit 4 enables timestamping */
+	CSR_WRITE(sc, reg, ctrl);
+	ctrl = CSR_READ(sc, reg);
+	if (ctrl & 0x10) {
+		log(LOG_DEBUG, "%s: disabling %s timestamping failed\n",
+		    device_xname(sc->sc_dev),
+		    reg == WM_TSYNCTXCTL ? "tx" : "rx");
+		return ENXIO;
+	}
+	return 0;
+}
+
+static int
+wm_getrxctl(struct wm_softc *sc)
+{
+	switch (sc->sc_hwtstamp_config.rx_filter) {
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_ALL:
+		return WM_TSYNCRXCTL_TYPE_ALL;
+
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		return WM_TSYNCRXCTL_TYPE_L4_V1;
+
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		return WM_TSYNCRXCTL_TYPE_L2_L4_V2;
+
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		return WM_TSYNCRXCTL_TYPE_EVENT_V2;
+
+	default:
+		panic("%s: bad rx filter %#x\n", __func__,
+		    sc->sc_hwtstamp_config.rx_filter);
+	}
+}
+
+static int 
+wm_getrxfilter(struct wm_softc *sc)
+{
+	switch (sc->sc_hwtstamp_config.rx_filter) {
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		return 0;
+
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+		return PTPV1_SYNC_MESSAGE;
+
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		return PTPV1_DELAY_REQ_MESSAGE;
+
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+		return PTPV2_SYNC_MESSAGE;
+
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		return PTPV2_DELAY_REQ_MESSAGE;
+
+	default:
+		panic("%s: bad rx filter %#x\n", __func__,
+		    sc->sc_hwtstamp_config.rx_filter);
+	}
+}
+
+static int
+wm_tstampconfig(struct wm_softc *sc)
+{
+	const uint32_t	incperiod = 1;	/* update every 16ns */
+	const uint32_t	incadj	  = 1;	/* increase by one every period */
+	int error;
+
+	DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s\n",
+	    device_xname(sc->sc_dev), __func__));
+	
+	switch (sc->sc_type) {
+	case WM_T_82574:
+	case WM_T_82576:
+		DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s sc->type %s\n",
+		    device_xname(sc->sc_dev), __func__, sc->sc_type));
+
+		DPRINTF(WM_DEBUG_TIMESTAMP,
+		    ("%s: %s sc->sc_hwtstamp_config.txtype: %#x\n",
+		    device_xname(sc->sc_dev), __func__,
+		    sc->sc_hwtstamp_config.tx_type));
+
+		/* Set the cycle increase */
+		CSR_WRITE(sc, WM_TIMINCA, (incperiod << 24) | incadj);
+
+		if (sc->sc_hwtstamp_config.tx_type != HWTSTAMP_TX_OFF) {
+			/* Enable TX timestamping */
+			if ((error = wm_enablectl(sc, WM_TSYNCTXCTL)) != 0)
+				return error;
+		} else {
+			/* Disable TX timestamping */
+			if ((error = wm_disablectl(sc, WM_TSYNCTXCTL)) != 0)
+				return error;
+		}
+	
+		if (sc->sc_hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
+                        /* Enable RX timestamping */
+			int rxctrl = CSR_READ(sc, WM_TSYNCRXCTL);
+			rxctrl &= ~(WM_TSYNCRXCTL_TYPE_ALL
+			    | WM_TSYNCRXCTL_TYPE_L4_V1
+			    | WM_TSYNCRXCTL_TYPE_L2_L4_V2
+			    | WM_TSYNCRXCTL_TYPE_EVENT_V2) | wm_getrxctl(sc);
+			CSR_WRITE(sc, WM_TSYNCRXCTL, rxctrl);
+			
+			/* Enable RX timestamping */
+			if ((error = wm_enablectl(sc, WM_TSYNCRXCTL)) != 0)
+				return error;
+
+			uint32_t filter_cfg = wm_getrxfilter(sc);
+			CSR_WRITE(sc, WM_TSYNCRXCFG, filter_cfg);
+		} else {
+			/* Disable RX timestamping */
+			if ((error = wm_disablectl(sc, WM_TSYNCRXCTL)) != 0)
+				return error;
+		}
+		return 0;
+	default:
+		return EOPNOTSUPP;
+	}
+}
+
+static int
+wm_sethwtstamp(struct wm_softc *sc, struct ifreq *ifr)
+{
+	DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s\n",
+	    device_xname(sc->sc_dev), __func__));
+
+	switch (sc->sc_type) {
+	case WM_T_82574:
+	case WM_T_82576:
+		break;
+	default:
+		return EOPNOTSUPP;
+	}
+
+	int error;
+	struct hwtstamp_config usercfg;
+	    
+	if ((error = copyin(ifr->ifr_data, &usercfg, sizeof(usercfg))) != 0)
+		return error;
+
+	switch (usercfg.rx_filter) {
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_NONE:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+		break;
+	default:
+		DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s bad rx filter %d\n",
+		    device_xname(sc->sc_dev), __func__, usercfg.rx_filter));
+		return EINVAL;
+	}
+
+	if (usercfg.flags & ~SOF_TIMESTAMPING_MASK) {
+		DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s bad flags %#x\n",
+		    device_xname(sc->sc_dev), __func__, usercfg.flags));
+		return EINVAL;
+	}
+
+	switch (usercfg.tx_type) {
+	case HWTSTAMP_TX_OFF:
+	case HWTSTAMP_TX_ON:
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		break;
+	default:
+		DPRINTF(WM_DEBUG_TIMESTAMP, ("%s: %s tx type %#x\n",
+		    device_xname(sc->sc_dev), __func__, usercfg.tx_type));
+		return EINVAL;
+	}
+	    
+	sc->sc_hwtstamp_config = usercfg;
+	    
+	return wm_tstampconfig(sc);
+}
+#endif
+
 /*
  * wm_ioctl:		[ifnet interface function]
  *
@@ -3036,6 +3357,11 @@
 	s = splnet();
 #endif
 	switch (cmd) {
+#ifdef WM_TIMESTAMP
+	case SIOCSHWTSTAMP:
+		error = wm_sethwtstamp(sc, ifr);
+		break;
+#endif /* WM_TIMESTAMP */
 	case SIOCSIFMEDIA:
 	case SIOCGIFMEDIA:
 		WM_CORE_LOCK(sc);
@@ -7838,6 +8164,13 @@
 		} else
 			ifp->if_opackets++;
 
+#ifdef WM_TIMESTAMP
+		/*
+		 * Try to timestamp this mbuf. The function checks for the
+		 * status bit
+		 */
+		wm_txtimestamp_mbuf(sc, txs->txs_mbuf);
+#endif
 		txq->txq_packets++;
 		txq->txq_bytes += txs->txs_mbuf->m_pkthdr.len;
 
@@ -8243,6 +8576,14 @@
 		if (!wm_rxdesc_input_vlantag(rxq, status, vlantag, m))
 			continue;
 
+#ifdef WM_TIMESTAMP
+		/*
+		 * Try to timestamp this mbuf. The function checks for the
+		 * status bit
+		 */
+		wm_rxtimestamp_mbuf(sc, m); 
+#endif
+
 		/* Set up checksum info for this packet. */
 		wm_rxdesc_ensure_checksum(rxq, status, errors, m);
 		/*
Index: dev/pci/if_wmreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wmreg.h,v
retrieving revision 1.100
diff -u -u -r1.100 if_wmreg.h
--- dev/pci/if_wmreg.h	26 Jun 2017 04:22:46 -0000	1.100
+++ dev/pci/if_wmreg.h	6 Jul 2017 20:44:46 -0000
@@ -400,6 +400,113 @@
 #define	WTX_TCPIP_SEG_HDRLEN(x)	((x) << 8)
 #define	WTX_TCPIP_SEG_MSS(x)	((x) << 16)
 
+/* Intel advanced tx descriptors */
+typedef struct wiseman_atxdesc {
+	wiseman_addr_t	watx_addr;	/* buffer address */
+	uint64_t	watx_fields;	/* fields */
+} __packed wiseman_atxdesc_t;
+
+#define	WATX_MAX_LEN	16384	/* maximum payload */
+#define	WATX_DLEN_MASK	0xffff	/* data length field mask */
+
+/* flags */
+#define	WATX_1588	(1U << 19)	/* timestamp packet */
+#define	WATX_DTYP	(3U << 20)	/* type for advanced data descriptors */
+#define	WATX_DTYP_SHIFT	20		/* the descriptor type shift*/
+#define	WATX_TSE	(1U << (24+7))	/* TCP/UDP segmentation enable */
+#define	WATX_VLE	(1U << (24+6))	/* VLAN enable */
+#define	WATX_DEXT	(1U << (24+5))	/* Descriptor extension */
+#define	WATX_RS		(1U << (24+3))	/* Report status */
+#define	WATX_IFCS	(1U << (24+1))	/* Insert FCS */
+#define	WATX_EOP	(1U << (24+0))  /* EOP - end of packet */
+#define	WATX_STA	(0xf << 32)	/* status - 1 is descriptor done */
+#define	WATX_IDX	(7U << 36)	/* context index */
+#define	WATX_POPT_IPSEC	(1U << (40+2))	/* IPSEC offload */
+#define	WATX_POPT_TXSM	(1U << (40+1))	/* Layer 4 checksum offload */
+#define	WATX_POPT_IXSM	(1U << (40))	/* IP checksum offload */
+
+#define	WATX_PLEN_MASK	(0x3ffff << 46) /* payload length field */
+#define	WATX_PLEN_SHIFT	46		/* payload length field shift */
+
+/* Intel advanced tx descriptors */
+typedef struct wiseman_arxdesc {
+	union {
+		struct {
+			/* rx buffer address */
+			wiseman_addr_t	warxb_addr;
+			/* header buffer address */
+			wiseman_addr_t	warxh_addr;
+		};
+		struct {
+			uint32_t rss_hash;
+			uint32_t flags;
+			uint16_t vlan;
+			uint16_t pktlen;
+			uint16_t exterr;
+			uint16_t extst;
+		};
+	};	
+} __packed wiseman_arxdesc_t;
+
+/* RSS type flags */
+#define WARX_RSSTYPE_NONE		0x0 /* no hash for this packet. */
+#define WARX_RSSTYPE_TCP_IPV4		0x1
+#define WARX_RSSTYPE_IPV4		0x2
+#define WARX_RSSTYPE_TCP_IPV6		0x3
+#define WARX_RSSTYPE_IPV6_EX		0x4
+#define WARX_RSSTYPE_IPV6		0x5
+#define WARX_RSSTYPE_TCP_IPV6_EX	0x6
+#define WARX_RSSTYPE_UDP_IPV4		0x7
+#define WARX_RSSTYPE_UDP_IPV6		0x8
+#define WARX_RSSTYPE_UDP_IPV6_EX	0x9
+
+#define WARX_SPH		(1U << 32)      /* split header */
+#define WARX_HDRLEN_MASK	(0x3ff << 21)   /* header len mask */
+#define WARX_HDRLEN_SHIFT	21		/* header len shift */
+
+/*packet type  flags */
+#define WARX_LSB_IPV4		(1U << (4+0))   /* IPv4 header */
+#define WARX_LSB_IPV4E		(1U << (4+1))   /* IPv4 extended header */
+#define WARX_LSB_IPV6		(1U << (4+2))   /* IPv6 header */
+#define WARX_LSB_IPV6E		(1U << (4+3))   /* IPv6 extended header */
+#define WARX_LSB_TCP		(1U << (4+4))   /* TCP header */
+#define WARX_LSB_UDP		(1U << (4+5))   /* UDP header */
+#define WARX_LSB_SCTP		(1U << (4+6))   /* SCTP header */
+#define WARX_LSB_NFS		(1U << (4+7))   /* NFS header */
+#define WARX_LSB_IPSECESP	(1U << (4+8))	/* IPSEC ESP header */
+#define WARX_LSB_IPSECAH	(1U << (4+9))	/* IPSEC AH header */
+#define WARX_RSSTYPE_MASK	0xf		/* RSS type */
+
+/* in rss_hash masks */
+#define WARX_FRAGMENT_CSUM_MASK 0xff00		/* fragment checksum mask */
+#define WARX_IP_ID_MASK		0xff00		/* IP identification mask */
+#define WARX_RSSHASH_MASK	0xffff		/* RSS hash mask */
+
+/* extended status flags */
+#define WARX_ST_DD		(1U << 0)	/* descriptor done */
+#define WARX_ST_EOP		(1U << 1)	/* end of packet */
+#define WARX_ST_VP		(1U << 3)	/* VLAN packet */
+#define WARX_ST_UDPCS		(1U << 4)	/* ??? */
+#define WARX_ST_L4CS		(1U << 5)	/* Layer 4 checksum performed */
+#define WARX_ST_IPCS		(1U << 6)	/* IP checksum performed */
+#define WARX_ST_PIF		(1U << 7)	/* passed in-exact filter */
+#define WARX_ST_VEXT		(1U << 9)	/* double VLAN */
+#define WARX_ST_UDPV		(1U << 10)	/* UDP checksum */
+#define WARX_ST_LINT		(1U << 11)	/* this packet caused a low-latency interrupt */
+#define WARX_ST_SECP		(1U << 17)	/* IPSEC encap processed */
+#define WARX_ST_LB		(1U << 18)	/* local VM-to-VM packet */
+
+/* receive error flags */
+#define WARX_ER_L4E		(1U << 9)	/* Layer 4 checksum error */
+#define WARX_ER_IPE		(1U << 10)	/* IP checksum error */
+#define WARX_ER_RXE		(1U << 11)	/* Rx data error */
+
+#define WARX_ER_IPSEC_NOERR	(0U << 7)	/* IPSEC no error */
+#define WARX_ER_IPSEC_INV	(1U << 7)	/* IPSEC invalid protocol */
+#define WARX_ER_IPSEC_PLEN	(2U << 7)	/* IPSEC packet length error */
+#define WARX_ER_IPSEC_AUTH	(3U << 7)	/* IPSEC authentication error */
+#define WARX_ER_HBO		(1U << 3)	/* header buffer overflow */
+
 /*
  * PCI config registers used by the Wiseman.
  */
@@ -1542,6 +1649,62 @@
 /* for PCI express Capability registers */
 #define	WM_PCIE_DCSR2_16MS	0x00000005
 
+/* Time Sync registers */
+#define	WM_TSYNCRXCTL	0x0B620	/* RX Time Sync Control Register RW */
+#define	WM_RXSTMPL	0x0B624	/* RX timestamp Low RO */
+#define	WM_RXSTMPH	0x0B628	/* RX timestamp High RO */
+#define	WM_RXSATRL	0x0B62C	/* RX timestamp attributes low RO */
+#define	WM_RXSATRH	0x0B630	/* RX timestamp attributes low RO */
+#define	WM_TSYNCTXCTL	0x0B614	/* TX Time Sync Control register RW */
+#define	WM_TXSTMPL	0x0B618	/* TX timestamp value Low RO */
+#define	WM_TXSTMPH	0x0B61C	/* TX timestamp value High RO */
+#define	WM_SYSTIML	0x0B600	/* System time register Low RWS */
+#define	WM_SYSTIMH	0x0B604	/* System time register High RWS */
+#define	WM_TIMINCA	0x0B608	/* Increment attributes register RW */
+#define	WM_TIMADJL	0x0B60C	/* Time adjustment offset register low RW */
+#define	WM_TIMADJH	0x0B610	/* Time adjustment offset register high RW */
+#define	WM_TSAUXC	0x0B640	/* Auxiliary Control Register RW */
+#define	WM_TRGTTIML0	0x0B644	/* Target Time register 0 Low RW */
+#define	WM_TRGTTIMH0	0x0B648	/* Target Time register 0 High RW */
+#define	WM_TRGTTIML1	0x0B64C	/* Target Time register 1 Low RW */
+#define	WM_TRGTTIMH1	0x0B650	/* Target Time register 1 High RW */
+#define	WM_AUXSTMPL0	0x0B65C	/* Auxiliary Time Stamp 0 register Low RO */
+#define	WM_AUXSTMPH0	0x0B660	/* Auxiliary Time Stamp 0 register High */
+#define	WM_AUXSTMPL1	0x0B664	/* Auxiliary Time Stamp 1 register Low RO */
+#define	WM_AUXSTMPH1	0x0B668	/* Auxiliary Time Stamp 1 register High RO */
+#define	WM_TSYNCRXCFG	0x05F50	/* Time Sync RX Configuration RW */
+#define	WM_TSSDP	0x0003C	/* Time Sync SDP Config Reg RW */
+
+#define	PTPV1_EVENTS_MASK 0xFF
+
+enum ptpv1_types {
+	PTPV1_SYNC_MESSAGE = 0,
+	PTPV1_DELAY_REQ_MESSAGE = 1,
+	PTPV1_FOLLOWUP_MESSAGE = 2,
+	PTPV1_DELAY_RESP_MESSAGE = 3,
+	PTPV1_MANAGEMENT_MESSAGE = 4,
+};
+
+#define	PTPV2_EVENTS_MASK      0x0F00
+
+enum ptpv2_events {
+	PTPV2_SYNC_MESSAGE = 0,
+	PTPV2_DELAY_REQ_MESSAGE = 1 << 2,
+	PTPV2_PATH_DELAY_REQ_MESSAGE = 2 << 2,
+	PTPV2_PATH_DELAY_RESP_MESSAGE = 3 << 2,
+	PTPV2_FOLLOWUP_MESSAGE = 8 << 2,
+	PTPV2_DELAY_RESP_MESSAGE = 9 << 2,
+	PTPV2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA << 2,
+	PTPV2_ANNOUNCE_MESSAGE = 0xB << 2,
+	PTPV2_SIGNALLING_MESSAGE = 0xC << 2,
+	PTPV2_MANAGEMENT_MESSAGE = 0xD << 2,
+};
+
+#define	WM_TSYNCRXCTL_TYPE_L4_V1       0x02
+#define	WM_TSYNCRXCTL_TYPE_L2_L4_V2    0x04
+#define	WM_TSYNCRXCTL_TYPE_ALL         0x08
+#define	WM_TSYNCRXCTL_TYPE_EVENT_V2    0x0A
+
 /* SFF SFP ROM data */
 #define SFF_SFP_ID_OFF		0x00
 #define SFF_SFP_ID_UNKNOWN	0x00	/* Unknown */
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvsroot/src/sys/kern/uipc_socket.c,v
retrieving revision 1.256
diff -u -u -r1.256 uipc_socket.c
--- kern/uipc_socket.c	6 Jul 2017 17:42:39 -0000	1.256
+++ kern/uipc_socket.c	6 Jul 2017 20:44:46 -0000
@@ -1751,6 +1751,8 @@
 	case SO_REUSEPORT:
 	case SO_OOBINLINE:
 	case SO_TIMESTAMP:
+	case SO_TIMESTAMPNS:
+	case SO_TIMESTAMPING:
 	case SO_NOSIGPIPE:
 #ifdef SO_OTIMESTAMP
 	case SO_OTIMESTAMP:
@@ -1952,6 +1954,8 @@
 	case SO_BROADCAST:
 	case SO_OOBINLINE:
 	case SO_TIMESTAMP:
+	case SO_TIMESTAMPNS:
+	case SO_TIMESTAMPING:
 	case SO_NOSIGPIPE:
 #ifdef SO_OTIMESTAMP
 	case SO_OTIMESTAMP:
@@ -2410,8 +2414,54 @@
 	return revents;
 }
 
-struct mbuf **
-sbsavetimestamp(int opt, struct mbuf *m, struct mbuf **mp)
+#include <net/tstamp.h>
+
+static struct mbuf **
+sbsavetimespec(int opt, struct mbuf *m, struct mbuf **mp)
+{
+
+	struct timespec ts;
+	struct m_tag *ttag;
+	struct scm_timestamping *tagtm;
+#ifdef DEBUG
+	printf("%s: checking for tag\n", __func__);
+#endif
+	/* get timespec from m_tags */
+	ttag = TSTAMP_OUTPUT_TAG(m);
+	tagtm = ttag ? (struct scm_timestamping *)(ttag + 1) : NULL;
+
+	if (opt & SO_TIMESTAMPNS) {
+		if (tagtm) {
+#ifdef DEBUG
+			printf("%s: SO_TIMESTAMPNS found tag\n",
+			    __func__);
+#endif
+			ts = tagtm->systime;
+		} else {
+			nanotime(&ts);
+		}
+		*mp = sbcreatecontrol(&ts, sizeof(ts), SCM_TIMESPEC,
+		    SOL_SOCKET);
+		if (*mp)
+			mp = &(*mp)->m_next;
+	} 
+
+	if (opt & SO_TIMESTAMPING) {
+		if (tagtm) {
+#ifdef DEBUG
+			printf("%s: SO_TIMESTAMPING found tag\n");
+#endif
+			*mp = sbcreatecontrol(tagtm, sizeof(*tagtm),
+			    SCM_TIMESTAMPING, SOL_SOCKET);
+			if (*mp)
+				mp = &(*mp)->m_next;
+		}
+	}
+	return mp;
+}
+
+static struct mbuf **
+sbsavetimeval(int opt, struct mbuf *m, struct mbuf **mp)
 {
 	struct timeval tv;
 	microtime(&tv);
@@ -2437,6 +2487,18 @@
 	return mp;
 }
 
+struct mbuf **
+sbsavetimestamp(int opt, struct mbuf *m, struct mbuf **mp)
+{
+
+	if (opt & (SO_TIMESTAMPNS|SO_TIMESTAMPING))
+		mp = sbsavetimespec(opt, m, mp);
+
+	if (opt & (SO_TIMESTAMP|0x400 /*SO_OTIMESTAMP*/))
+		mp = sbsavetimeval(opt, m, mp);
+
+	return mp;
+}
 
 #include <sys/sysctl.h>
 
Index: net/Makefile
===================================================================
RCS file: /cvsroot/src/sys/net/Makefile,v
retrieving revision 1.33
diff -u -u -r1.33 Makefile
--- net/Makefile	16 Feb 2017 08:12:44 -0000	1.33
+++ net/Makefile	6 Jul 2017 20:44:46 -0000
@@ -8,7 +8,7 @@
 	if_pflog.h if_ppp.h if_pppoe.h if_l2tp.h if_sppp.h if_srt.h if_stf.h \
 	if_tap.h if_token.h if_tun.h if_types.h if_vlanvar.h net_stats.h \
 	netisr.h pfil.h pfkeyv2.h pfvar.h ppp-comp.h ppp_defs.h radix.h \
-	raw_cb.h route.h slcompress.h slip.h zlib.h
+	raw_cb.h route.h slcompress.h slip.h zlib.h tstamp.h
 
 SUBDIR=	agr npf
 
Index: sys/mbuf.h
===================================================================
RCS file: /cvsroot/src/sys/sys/mbuf.h,v
retrieving revision 1.170
diff -u -u -r1.170 mbuf.h
--- sys/mbuf.h	27 May 2017 21:02:56 -0000	1.170
+++ sys/mbuf.h	6 Jul 2017 20:44:46 -0000
@@ -924,6 +924,8 @@
 
 #define	PACKET_TAG_MPLS				29 /* Indicate it's for MPLS */
 #define	PACKET_TAG_SRCROUTE			30 /* IPv4 source routing */
+#define	PACKET_TAG_TSTAMP			31 /* hardware or system clock
+						    * generated timestamp */
 
 /*
  * Return the number of bytes in the mbuf chain, m.
Index: sys/socket.h
===================================================================
RCS file: /cvsroot/src/sys/sys/socket.h,v
retrieving revision 1.123
diff -u -u -r1.123 socket.h
--- sys/socket.h	1 Jul 2017 16:59:12 -0000	1.123
+++ sys/socket.h	6 Jul 2017 20:44:46 -0000
@@ -132,7 +132,8 @@
 #define	SO_NOSIGPIPE	0x0800		/* no SIGPIPE from EPIPE */
 #define	SO_ACCEPTFILTER	0x1000		/* there is an accept filter */
 #define	SO_TIMESTAMP	0x2000		/* timestamp received dgram traffic */
-
+#define	SO_TIMESTAMPNS	0x4000		/* timestamp in nanosecond format */
+#define	SO_TIMESTAMPING	0x8000		/* hardware timestamping */
 
 /*
  * Additional options, not kept in so_options.
@@ -602,12 +603,14 @@
 #define CMSG_LEN(l)	(__CMSG_ASIZE + (l))
 
 /* "Socket"-level control message types: */
-#define	SCM_RIGHTS	0x01		/* access rights (array of int) */
+#define	SCM_RIGHTS		0x01	/* access rights (array of int) */
 #if defined(_NETBSD_SOURCE)
-/*			0x02		   timestamp (struct timeval50) */
-/*			0x04		   credentials (struct sockcred70) */
-#define	SCM_TIMESTAMP	0x08		/* timestamp (struct timeval) */
-#define	SCM_CREDS	0x10		/* credentials (struct sockcred) */
+/*				0x02	   timestamp (struct timeval50) */
+/*				0x04	   credentials (struct sockcred70) */
+#define	SCM_TIMESTAMP		0x08	/* timestamp (struct timeval) */
+#define	SCM_CREDS		0x10	/* credentials (struct sockcred) */
+#define	SCM_TIMESPEC		0x20	/* timestamp (struct timespec) */
+#define	SCM_TIMESTAMPING	0x40	/* timestamp (struct scm_timestamping)*/
 #endif
 
 /*
Index: sys/socketvar.h
===================================================================
RCS file: /cvsroot/src/sys/sys/socketvar.h,v
retrieving revision 1.145
diff -u -u -r1.145 socketvar.h
--- sys/socketvar.h	6 Jul 2017 17:08:57 -0000	1.145
+++ sys/socketvar.h	6 Jul 2017 20:44:46 -0000
@@ -251,8 +251,9 @@
 
 struct	mbuf *getsombuf(struct socket *, int);
 
-/* 0x400 is SO_OTIMESTAMP */
-#define SOOPT_TIMESTAMP(o)	((o) & (SO_TIMESTAMP | 0x400))
+#define SOOPT_TIMESTAMP(o)				\
+    ((o) & (SO_TIMESTAMP | 0x400 /*SO_OTIMESTAMP*/ |	\
+    SO_TIMESTAMPNS | SO_TIMESTAMPING))
 
 /*
  * File operations on sockets.
Index: sys/sockio.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sockio.h,v
retrieving revision 1.33
diff -u -u -r1.33 sockio.h
--- sys/sockio.h	2 May 2015 14:41:32 -0000	1.33
+++ sys/sockio.h	6 Jul 2017 20:44:46 -0000
@@ -139,6 +139,10 @@
 #define	SIOCGETHERCAP	_IOWR('i', 139, struct eccapreq) /* get ethercap */
 #define SIOCGIFINDEX  _IOWR('i', 140, struct ifreq)   /* get ifnet index */
 
+#define	SIOCGSTAMP      _IOR('i', 141, struct timeval)
+#define	SIOCGSTAMPNS    _IOR('i', 142, struct timespec)
+#define	SIOCSHWTSTAMP   _IOW('i', 143, struct hwtstamp_config)
+
 #define	SIOCSETPFSYNC	_IOW('i', 247, struct ifreq)	
 #define	SIOCGETPFSYNC	_IOWR('i', 248, struct ifreq)


Home | Main Index | Thread Index | Old Index