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