From 9c7fd48fee8ee1a1eaa79d584b93c18b9b9eccc8 Mon Sep 17 00:00:00 2001 From: Rastislav Cernay Date: Mon, 15 Jul 2019 14:03:03 +0200 Subject: [PATCH] net/nfb: support timestamp This patch adds timestamping support to nfb driver. Signed-off-by: Rastislav Cernay --- doc/guides/nics/nfb.rst | 20 +++++++++++++++ drivers/net/nfb/Makefile | 2 +- drivers/net/nfb/nfb.h | 4 +++ drivers/net/nfb/nfb_ethdev.c | 18 ++++++++++++++ drivers/net/nfb/nfb_rx.c | 47 ++++++++++++++++++++++++++++++++++++ drivers/net/nfb/nfb_rx.h | 21 ++++++++++++++++ 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/nfb.rst b/doc/guides/nics/nfb.rst index 3d93904040..10f33a025e 100644 --- a/doc/guides/nics/nfb.rst +++ b/doc/guides/nics/nfb.rst @@ -69,6 +69,26 @@ These configuration options can be modified before compilation in the Value **y** enables compilation of nfb PMD. + +Timestamps + +The PMD supports hardware timestamps of frame receipt on physical network interface. In order to use +the timestamps, the hardware timestamping unit must be enabled (follow the documentation of the NFB +products) and the device argument `timestamp=1` must be used. + +.. code-block:: console + + $RTE_TARGET/app/testpmd -w b3:00.0,timestamp=1 -- + +When the timestamps are enabled with the *devarg*, a timestamp validity flag is set in the MBUFs +containing received frames and timestamp is inserted into the `rte_mbuf` struct. + +The timestamp is an `uint64_t` field. Its lower 32 bits represent *seconds* portion of the timestamp +(number of seconds elapsed since 1.1.1970 00:00:00 UTC) and its higher 32 bits represent +*nanosecond* portion of the timestamp (number of nanoseconds elapsed since the beginning of the +second in the *seconds* portion. + + Using the NFB PMD ---------------------- diff --git a/drivers/net/nfb/Makefile b/drivers/net/nfb/Makefile index a84b42335a..8bba2ac046 100644 --- a/drivers/net/nfb/Makefile +++ b/drivers/net/nfb/Makefile @@ -16,7 +16,7 @@ INCLUDES :=-I$(SRCDIR) CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) CFLAGS += $(shell command -v pkg-config > /dev/null 2>&1 && pkg-config --cflags netcope-common) -LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool +LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_kvargs LDLIBS += -lrte_ethdev -lrte_net LDLIBS += -lrte_bus_pci LDLIBS += $(shell command -v pkg-config > /dev/null 2>&1 && pkg-config --libs netcope-common) diff --git a/drivers/net/nfb/nfb.h b/drivers/net/nfb/nfb.h index 9d477ba3ac..59d3ab4986 100644 --- a/drivers/net/nfb/nfb.h +++ b/drivers/net/nfb/nfb.h @@ -36,6 +36,10 @@ #define RTE_NFB_DRIVER_NAME net_nfb +/* Device arguments */ +#define TIMESTAMP_ARG "timestamp" +static const char * const VALID_KEYS[] = {TIMESTAMP_ARG, NULL}; + struct pmd_internals { uint16_t max_rxmac; uint16_t max_txmac; diff --git a/drivers/net/nfb/nfb_ethdev.c b/drivers/net/nfb/nfb_ethdev.c index 3472a8df60..c3119a058a 100644 --- a/drivers/net/nfb/nfb_ethdev.c +++ b/drivers/net/nfb/nfb_ethdev.c @@ -10,6 +10,7 @@ #include #include +#include #include "nfb_stats.h" #include "nfb_rx.h" @@ -419,6 +420,7 @@ nfb_eth_dev_init(struct rte_eth_dev *dev) struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_pci_addr *pci_addr = &pci_dev->addr; struct rte_ether_addr eth_addr_init; + struct rte_kvargs *kvlist; RTE_LOG(INFO, PMD, "Initializing NFB device (" PCI_PRI_FMT ")\n", pci_addr->domain, pci_addr->bus, pci_addr->devid, @@ -429,6 +431,21 @@ nfb_eth_dev_init(struct rte_eth_dev *dev) pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function); + /* Check validity of device args */ + if (dev->device->devargs != NULL && + dev->device->devargs->args != NULL && + strlen(dev->device->devargs->args) > 0) { + kvlist = rte_kvargs_parse(dev->device->devargs->args, + VALID_KEYS); + if (kvlist == NULL) { + RTE_LOG(ERR, PMD, "Failed to parse device arguments %s", + dev->device->devargs->args); + rte_kvargs_free(kvlist); + return -EINVAL; + } + rte_kvargs_free(kvlist); + } + /* * Get number of available DMA RX and TX queues, which is maximum * number of queues that can be created and store it in private device @@ -577,3 +594,4 @@ static struct rte_pci_driver nfb_eth_driver = { RTE_PMD_REGISTER_PCI(RTE_NFB_DRIVER_NAME, nfb_eth_driver); RTE_PMD_REGISTER_PCI_TABLE(RTE_NFB_DRIVER_NAME, nfb_pci_id_table); RTE_PMD_REGISTER_KMOD_DEP(RTE_NFB_DRIVER_NAME, "* nfb"); +RTE_PMD_REGISTER_PARAM_STRING(RTE_NFB_DRIVER_NAME, TIMESTAMP_ARG "=<0|1>"); diff --git a/drivers/net/nfb/nfb_rx.c b/drivers/net/nfb/nfb_rx.c index 9147b00b0a..d97179f818 100644 --- a/drivers/net/nfb/nfb_rx.c +++ b/drivers/net/nfb/nfb_rx.c @@ -4,9 +4,51 @@ * All rights reserved. */ +#include + #include "nfb_rx.h" #include "nfb.h" +static int +timestamp_check_handler(__rte_unused const char *key, + const char *value, __rte_unused void *opaque) +{ + if (strcmp(value, "1")) + return -1; + + return 0; +} + + +static int +nfb_check_timestamp(struct rte_devargs *devargs) +{ + struct rte_kvargs *kvlist; + + if (devargs == NULL) + return 0; + + kvlist = rte_kvargs_parse(devargs->args, NULL); + if (kvlist == NULL) + return 0; + + if (!rte_kvargs_count(kvlist, TIMESTAMP_ARG)) { + rte_kvargs_free(kvlist); + return 0; + } + /* Timestamps are enabled when there is + * key-value pair: enable_timestamp=1 + */ + if (rte_kvargs_process(kvlist, TIMESTAMP_ARG, + timestamp_check_handler, NULL) < 0) { + rte_kvargs_free(kvlist); + return 0; + } + rte_kvargs_free(kvlist); + + return 1; +} + int nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id) { @@ -70,6 +112,8 @@ nfb_eth_rx_queue_setup(struct rte_eth_dev *dev, return -ENOMEM; } + rxq->flags = 0; + ret = nfb_eth_rx_queue_init(internals->nfb, rx_queue_id, dev->data->port_id, @@ -81,6 +125,9 @@ nfb_eth_rx_queue_setup(struct rte_eth_dev *dev, else rte_free(rxq); + if (nfb_check_timestamp(dev->device->devargs)) + rxq->flags |= NFB_TIMESTAMP_FLAG; + return ret; } diff --git a/drivers/net/nfb/nfb_rx.h b/drivers/net/nfb/nfb_rx.h index 88a03074fb..cf3899b2fb 100644 --- a/drivers/net/nfb/nfb_rx.h +++ b/drivers/net/nfb/nfb_rx.h @@ -13,11 +13,14 @@ #include #include +#define NFB_TIMESTAMP_FLAG (1 << 0) + struct ndp_rx_queue { struct nfb_device *nfb; /* nfb dev structure */ struct ndp_queue *queue; /* rx queue */ uint16_t rx_queue_id; /* index */ uint8_t in_port; /* port */ + uint8_t flags; /* setup flags */ struct rte_mempool *mb_pool; /* memory pool to allocate packets */ uint16_t buf_size; /* mbuf size */ @@ -129,6 +132,7 @@ nfb_eth_ndp_rx(void *queue, uint16_t nb_pkts) { struct ndp_rx_queue *ndp = queue; + uint8_t timestamping_enabled; uint16_t packet_size; uint64_t num_bytes = 0; uint16_t num_rx; @@ -146,6 +150,8 @@ nfb_eth_ndp_rx(void *queue, return 0; } + timestamping_enabled = ndp->flags & NFB_TIMESTAMP_FLAG; + /* returns either all or nothing */ i = rte_pktmbuf_alloc_bulk(ndp->mb_pool, mbufs, nb_pkts); if (unlikely(i != 0)) @@ -181,6 +187,21 @@ nfb_eth_ndp_rx(void *queue, mbuf->pkt_len = packet_size; mbuf->port = ndp->in_port; + mbuf->ol_flags = 0; + + if (timestamping_enabled) { + /* nanoseconds */ + mbuf->timestamp = + rte_le_to_cpu_32(*((uint32_t *) + (packets[i].header + 4))); + mbuf->timestamp <<= 32; + /* seconds */ + mbuf->timestamp |= + rte_le_to_cpu_32(*((uint32_t *) + (packets[i].header + 8))); + mbuf->ol_flags |= PKT_RX_TIMESTAMP; + } + bufs[num_rx++] = mbuf; num_bytes += packet_size; } else {