From: Rastislav Cernay <cer...@netcope.com>

This patch adds timestamping support to nfb driver.

Signed-off-by: Rastislav Cernay <cer...@netcope.com>
---
v2: rewrite timestamp enable to devargs
v3: check valid devargs
    move timestamp part of doc to configuration
    fix shared build
 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 8df76c0..0e36c7e 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 <other EAL params> -- 
<testpmd params>
+
+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 a84b423..8bba2ac 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 9d477ba..59d3ab4 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 7782195..ff2e5c7 100644
--- a/drivers/net/nfb/nfb_ethdev.c
+++ b/drivers/net/nfb/nfb_ethdev.c
@@ -10,6 +10,7 @@
 #include <netcope/txmac.h>
 
 #include <rte_ethdev_pci.h>
+#include <rte_kvargs.h>
 
 #include "nfb_stats.h"
 #include "nfb_rx.h"
@@ -419,6 +420,7 @@
        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 @@
                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
@@ -579,3 +596,4 @@
 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 9147b00..d97179f 100644
--- a/drivers/net/nfb/nfb_rx.c
+++ b/drivers/net/nfb/nfb_rx.c
@@ -4,9 +4,51 @@
  * All rights reserved.
  */
 
+#include <rte_kvargs.h>
+
 #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 @@
                return -ENOMEM;
        }
 
+       rxq->flags = 0;
+
        ret = nfb_eth_rx_queue_init(internals->nfb,
                rx_queue_id,
                dev->data->port_id,
@@ -81,6 +125,9 @@
        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 88a0307..cf3899b 100644
--- a/drivers/net/nfb/nfb_rx.h
+++ b/drivers/net/nfb/nfb_rx.h
@@ -13,11 +13,14 @@
 #include <rte_mbuf.h>
 #include <rte_ethdev.h>
 
+#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 @@ struct ndp_rx_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 @@ struct ndp_rx_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 @@ struct ndp_rx_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 {
-- 
1.8.3.1

Reply via email to