From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
Bruce Richardson <bruce.richardson@intel.com>
Subject: [RFC v2 04/12] net/ring: add new devargs for dumpcap use
Date: Wed, 9 Jul 2025 10:33:30 -0700 [thread overview]
Message-ID: <20250709173611.6390-5-stephen@networkplumber.org> (raw)
In-Reply-To: <20250709173611.6390-1-stephen@networkplumber.org>
Need ability to allow process like dumpcap to make a ring ethdev
with a pre-existing ring. Do this via devargs so it can work
with hotplug. It looked like the API rte_eth_from_ring() would
work for this, but it doesn't do the right thing.
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 | 74 ++++++++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index 966c64d9a5..0f97cd1262 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -20,12 +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
};
@@ -38,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
@@ -46,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;
};
@@ -53,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];
@@ -61,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,
@@ -96,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
@@ -173,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;
}
@@ -693,6 +722,20 @@ parse_internal_args(const char *key __rte_unused, const char *value,
return 0;
}
+static int
+parse_ring_arg(const char *key __rte_unused, const char *value, void *data)
+{
+ struct rte_ring **rp = data;
+
+ *rp = rte_ring_lookup(value);
+ if (*rp == NULL) {
+ PMD_LOG(ERR, "ring '%s' not found", value);
+ return -1;
+ }
+
+ return 0;
+}
+
static int
rte_pmd_ring_probe(struct rte_vdev_device *dev)
{
@@ -770,6 +813,18 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
ð_dev);
if (ret >= 0)
ret = 0;
+ } else if (rte_kvargs_count(kvlist, ETH_RING_RING_ARG) == 1) {
+ struct rte_ring *rxtx[1] = { };
+
+ ret = rte_kvargs_process(kvlist, ETH_RING_RING_ARG, parse_ring_arg, rxtx);
+ if (ret < 0)
+ goto out_free;
+
+ /* Note: rte_eth_from_ring() does not do what is expected here! */
+ ret = do_eth_dev_ring_create(name, dev, rxtx, 1, rxtx, 1,
+ rte_socket_id(), DEV_ATTACH, ð_dev);
+ if (ret < 0)
+ goto out_free;
} else {
ret = rte_kvargs_count(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG);
info = rte_zmalloc("struct node_action_list",
@@ -806,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:
@@ -843,4 +912,5 @@ static struct rte_vdev_driver pmd_ring_drv = {
RTE_PMD_REGISTER_VDEV(net_ring, pmd_ring_drv);
RTE_PMD_REGISTER_ALIAS(net_ring, eth_ring);
RTE_PMD_REGISTER_PARAM_STRING(net_ring,
+ ETH_RING_RING_ARG "=<string> "
ETH_RING_NUMA_NODE_ACTION_ARG "=name:node:action(ATTACH|CREATE)");
--
2.47.2
next prev parent reply other threads:[~2025-07-09 17:36 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <0250411234927.114568-1-stephen@networkplumber.org>
2025-07-09 17:33 ` [RFC v2 00/12] Packet capture using port mirroring Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 01/12] ethdev: allow start/stop from secondary process Stephen Hemminger
2025-07-09 17:47 ` Khadem Ullah
2025-07-09 17:33 ` [RFC v2 02/12] test: add test for hotplug and secondary process operations Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 03/12] net/ring: allow lockfree transmit if ring supports it Stephen Hemminger
2025-07-09 17:33 ` Stephen Hemminger [this message]
2025-07-09 17:33 ` [RFC v2 05/12] mbuf: add dynamic flag for use by port mirroring Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 06/12] ethdev: add port mirroring feature Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 07/12] pcapng: split packet copy from header insertion Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 08/12] pcapng: make queue optional Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 09/12] test: add tests for ethdev mirror Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 10/12] app/testpmd: support for port mirroring Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 11/12] app/dumpcap: use port mirror instead of pdump Stephen Hemminger
2025-07-09 17:33 ` [RFC v2 12/12] pdump: mark API and application as deprecated Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250709173611.6390-5-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=bruce.richardson@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).