Add argument to ring PMD creation to force packets going
into ring to be timestamped.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/ring/rte_eth_ring.c | 44 +++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
@@ -20,15 +20,18 @@
#define ETH_RING_ACTION_CREATE "CREATE"
#define ETH_RING_ACTION_ATTACH "ATTACH"
#define ETH_RING_ACTION_MAX_LEN 8 /* CREATE | ACTION */
+
#define ETH_RING_INTERNAL_ARG "internal"
#define ETH_RING_INTERNAL_ARG_MAX_LEN 19 /* "0x..16chars..\0" */
#define ETH_RING_RING_ARG "ring"
+#define ETH_RING_TIMESTAMP_ARG "timestamp"
static const char *valid_arguments[] = {
ETH_RING_NUMA_NODE_ACTION_ARG,
ETH_RING_INTERNAL_ARG,
ETH_RING_RING_ARG,
+ ETH_RING_TIMESTAMP_ARG,
NULL
};
@@ -41,6 +44,9 @@ struct ring_internal_args {
void *addr; /* self addr for sanity check */
};
+static uint64_t timestamp_dynflag;
+static int timestamp_dynfield_offset = -1;
+
enum dev_action {
DEV_CREATE,
DEV_ATTACH
@@ -49,6 +55,8 @@ enum dev_action {
struct ring_queue {
struct rte_ring *rng;
uint16_t in_port;
+ uint8_t timestamp;
+
RTE_ATOMIC(uint64_t) rx_pkts;
RTE_ATOMIC(uint64_t) tx_pkts;
};
@@ -56,6 +64,7 @@ struct ring_queue {
struct pmd_internals {
unsigned int max_rx_queues;
unsigned int max_tx_queues;
+ uint8_t timestamp;
struct ring_queue rx_ring_queues[RTE_PMD_RING_MAX_RX_RINGS];
struct ring_queue tx_ring_queues[RTE_PMD_RING_MAX_TX_RINGS];
@@ -64,6 +73,7 @@ struct pmd_internals {
enum dev_action action;
};
+
static struct rte_eth_link pmd_link = {
.link_speed = RTE_ETH_SPEED_NUM_10G,
.link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
@@ -99,8 +109,23 @@ eth_ring_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
{
void **ptrs = (void *)&bufs[0];
struct ring_queue *r = q;
- const uint16_t nb_tx = (uint16_t)rte_ring_enqueue_burst(r->rng,
- ptrs, nb_bufs, NULL);
+ uint16_t nb_tx;
+
+ if (r->timestamp) {
+ unsigned int i;
+ uint64_t cycles = rte_get_tsc_cycles();
+
+ for (i = 0; i < nb_bufs; i++) {
+ struct rte_mbuf *m = bufs[i];
+ *RTE_MBUF_DYNFIELD(m, timestamp_dynfield_offset,
+ rte_mbuf_timestamp_t *) = cycles;
+ m->ol_flags |= timestamp_dynflag;
+ }
+ }
+
+
+ nb_tx = (uint16_t)rte_ring_enqueue_burst(r->rng, ptrs, nb_bufs, NULL);
+
if (r->rng->flags & RING_F_SP_ENQ)
r->tx_pkts += nb_tx;
else
@@ -176,6 +201,7 @@ eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
{
struct pmd_internals *internals = dev->data->dev_private;
+ internals->tx_ring_queues[tx_queue_id].timestamp = internals->timestamp;
dev->data->tx_queues[tx_queue_id] = &internals->tx_ring_queues[tx_queue_id];
return 0;
}
@@ -835,6 +861,20 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
}
}
}
+
+ if (rte_kvargs_count(kvlist, ETH_RING_TIMESTAMP_ARG) == 1) {
+ struct pmd_internals *internals = eth_dev->data->dev_private;
+
+ if (timestamp_dynfield_offset == -1) {
+ ret = rte_mbuf_dyn_rx_timestamp_register(×tamp_dynfield_offset,
+ ×tamp_dynflag);
+ if (ret < 0)
+ return ret;
+ }
+
+ internals->timestamp = 1;
+ }
+
}
out_free: