xref: /dpdk/lib/pdump/rte_pdump.c (revision 0f1dc8cb671203d52488fd66936f2fe6dcca03cc)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2016-2018 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
572b452c5SDmitry Kozlyuk #include <stdlib.h>
672b452c5SDmitry Kozlyuk 
799a2dd95SBruce Richardson #include <rte_mbuf.h>
899a2dd95SBruce Richardson #include <rte_ethdev.h>
999a2dd95SBruce Richardson #include <rte_lcore.h>
1099a2dd95SBruce Richardson #include <rte_log.h>
1110f726efSStephen Hemminger #include <rte_memzone.h>
1299a2dd95SBruce Richardson #include <rte_errno.h>
1399a2dd95SBruce Richardson #include <rte_string_fns.h>
1410f726efSStephen Hemminger #include <rte_pcapng.h>
1599a2dd95SBruce Richardson 
1699a2dd95SBruce Richardson #include "rte_pdump.h"
1799a2dd95SBruce Richardson 
18eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(pdump_logtype, NOTICE);
190e21c7c0SDavid Marchand #define RTE_LOGTYPE_PDUMP pdump_logtype
2099a2dd95SBruce Richardson 
21*0f1dc8cbSTyler Retzlaff #define PDUMP_LOG_LINE(level, ...) \
22*0f1dc8cbSTyler Retzlaff 	RTE_LOG_LINE_PREFIX(level, PDUMP, "%s(): ", __func__, __VA_ARGS__)
2399a2dd95SBruce Richardson 
2499a2dd95SBruce Richardson /* Used for the multi-process communication */
2599a2dd95SBruce Richardson #define PDUMP_MP	"mp_pdump"
2699a2dd95SBruce Richardson 
2799a2dd95SBruce Richardson enum pdump_operation {
2899a2dd95SBruce Richardson 	DISABLE = 1,
2999a2dd95SBruce Richardson 	ENABLE = 2
3099a2dd95SBruce Richardson };
3199a2dd95SBruce Richardson 
3210f726efSStephen Hemminger /* Internal version number in request */
3399a2dd95SBruce Richardson enum pdump_version {
3410f726efSStephen Hemminger 	V1 = 1,		    /* no filtering or snap */
3510f726efSStephen Hemminger 	V2 = 2,
3699a2dd95SBruce Richardson };
3799a2dd95SBruce Richardson 
3899a2dd95SBruce Richardson struct pdump_request {
3999a2dd95SBruce Richardson 	uint16_t ver;
4099a2dd95SBruce Richardson 	uint16_t op;
4199a2dd95SBruce Richardson 	uint32_t flags;
4299a2dd95SBruce Richardson 	char device[RTE_DEV_NAME_MAX_LEN];
4399a2dd95SBruce Richardson 	uint16_t queue;
4499a2dd95SBruce Richardson 	struct rte_ring *ring;
4599a2dd95SBruce Richardson 	struct rte_mempool *mp;
4610f726efSStephen Hemminger 
4710f726efSStephen Hemminger 	const struct rte_bpf_prm *prm;
4810f726efSStephen Hemminger 	uint32_t snaplen;
4999a2dd95SBruce Richardson };
5099a2dd95SBruce Richardson 
5199a2dd95SBruce Richardson struct pdump_response {
5299a2dd95SBruce Richardson 	uint16_t ver;
5399a2dd95SBruce Richardson 	uint16_t res_op;
5499a2dd95SBruce Richardson 	int32_t err_value;
5599a2dd95SBruce Richardson };
5699a2dd95SBruce Richardson 
5799a2dd95SBruce Richardson static struct pdump_rxtx_cbs {
5899a2dd95SBruce Richardson 	struct rte_ring *ring;
5999a2dd95SBruce Richardson 	struct rte_mempool *mp;
6099a2dd95SBruce Richardson 	const struct rte_eth_rxtx_callback *cb;
6110f726efSStephen Hemminger 	const struct rte_bpf *filter;
6210f726efSStephen Hemminger 	enum pdump_version ver;
6310f726efSStephen Hemminger 	uint32_t snaplen;
6499a2dd95SBruce Richardson } rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
6599a2dd95SBruce Richardson tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
6699a2dd95SBruce Richardson 
6799a2dd95SBruce Richardson 
6810f726efSStephen Hemminger /*
6910f726efSStephen Hemminger  * The packet capture statistics keep track of packets
7010f726efSStephen Hemminger  * accepted, filtered and dropped. These are per-queue
7110f726efSStephen Hemminger  * and in memory between primary and secondary processes.
7210f726efSStephen Hemminger  */
7310f726efSStephen Hemminger static const char MZ_RTE_PDUMP_STATS[] = "rte_pdump_stats";
7410f726efSStephen Hemminger static struct {
7510f726efSStephen Hemminger 	struct rte_pdump_stats rx[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
7610f726efSStephen Hemminger 	struct rte_pdump_stats tx[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
7753caecb8SKonstantin Ananyev 	const struct rte_memzone *mz;
7810f726efSStephen Hemminger } *pdump_stats;
7910f726efSStephen Hemminger 
8010f726efSStephen Hemminger /* Create a clone of mbuf to be placed into ring. */
8110f726efSStephen Hemminger static void
pdump_copy(uint16_t port_id,uint16_t queue,enum rte_pcapng_direction direction,struct rte_mbuf ** pkts,uint16_t nb_pkts,const struct pdump_rxtx_cbs * cbs,struct rte_pdump_stats * stats)8210f726efSStephen Hemminger pdump_copy(uint16_t port_id, uint16_t queue,
8310f726efSStephen Hemminger 	   enum rte_pcapng_direction direction,
8410f726efSStephen Hemminger 	   struct rte_mbuf **pkts, uint16_t nb_pkts,
8510f726efSStephen Hemminger 	   const struct pdump_rxtx_cbs *cbs,
8610f726efSStephen Hemminger 	   struct rte_pdump_stats *stats)
8799a2dd95SBruce Richardson {
8899a2dd95SBruce Richardson 	unsigned int i;
8999a2dd95SBruce Richardson 	int ring_enq;
9099a2dd95SBruce Richardson 	uint16_t d_pkts = 0;
9199a2dd95SBruce Richardson 	struct rte_mbuf *dup_bufs[nb_pkts];
9299a2dd95SBruce Richardson 	struct rte_ring *ring;
9399a2dd95SBruce Richardson 	struct rte_mempool *mp;
9499a2dd95SBruce Richardson 	struct rte_mbuf *p;
9510f726efSStephen Hemminger 	uint64_t rcs[nb_pkts];
9699a2dd95SBruce Richardson 
9710f726efSStephen Hemminger 	if (cbs->filter)
9810f726efSStephen Hemminger 		rte_bpf_exec_burst(cbs->filter, (void **)pkts, rcs, nb_pkts);
9910f726efSStephen Hemminger 
10099a2dd95SBruce Richardson 	ring = cbs->ring;
10199a2dd95SBruce Richardson 	mp = cbs->mp;
10299a2dd95SBruce Richardson 	for (i = 0; i < nb_pkts; i++) {
10310f726efSStephen Hemminger 		/*
10410f726efSStephen Hemminger 		 * This uses same BPF return value convention as socket filter
10510f726efSStephen Hemminger 		 * and pcap_offline_filter.
10610f726efSStephen Hemminger 		 * if program returns zero
10710f726efSStephen Hemminger 		 * then packet doesn't match the filter (will be ignored).
10810f726efSStephen Hemminger 		 */
10910f726efSStephen Hemminger 		if (cbs->filter && rcs[i] == 0) {
110938c55cbSTyler Retzlaff 			rte_atomic_fetch_add_explicit(&stats->filtered,
111938c55cbSTyler Retzlaff 					   1, rte_memory_order_relaxed);
11210f726efSStephen Hemminger 			continue;
11310f726efSStephen Hemminger 		}
11410f726efSStephen Hemminger 
11510f726efSStephen Hemminger 		/*
11610f726efSStephen Hemminger 		 * If using pcapng then want to wrap packets
11710f726efSStephen Hemminger 		 * otherwise a simple copy.
11810f726efSStephen Hemminger 		 */
11910f726efSStephen Hemminger 		if (cbs->ver == V2)
12010f726efSStephen Hemminger 			p = rte_pcapng_copy(port_id, queue,
12110f726efSStephen Hemminger 					    pkts[i], mp, cbs->snaplen,
12216659193SStephen Hemminger 					    direction, NULL);
12310f726efSStephen Hemminger 		else
12410f726efSStephen Hemminger 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
12510f726efSStephen Hemminger 
12610f726efSStephen Hemminger 		if (unlikely(p == NULL))
127938c55cbSTyler Retzlaff 			rte_atomic_fetch_add_explicit(&stats->nombuf, 1, rte_memory_order_relaxed);
12810f726efSStephen Hemminger 		else
12999a2dd95SBruce Richardson 			dup_bufs[d_pkts++] = p;
13099a2dd95SBruce Richardson 	}
13199a2dd95SBruce Richardson 
132938c55cbSTyler Retzlaff 	rte_atomic_fetch_add_explicit(&stats->accepted, d_pkts, rte_memory_order_relaxed);
13310f726efSStephen Hemminger 
134b1824666SJoyce Kong 	ring_enq = rte_ring_enqueue_burst(ring, (void *)&dup_bufs[0], d_pkts, NULL);
13599a2dd95SBruce Richardson 	if (unlikely(ring_enq < d_pkts)) {
13699a2dd95SBruce Richardson 		unsigned int drops = d_pkts - ring_enq;
13799a2dd95SBruce Richardson 
138938c55cbSTyler Retzlaff 		rte_atomic_fetch_add_explicit(&stats->ringfull, drops, rte_memory_order_relaxed);
13999a2dd95SBruce Richardson 		rte_pktmbuf_free_bulk(&dup_bufs[ring_enq], drops);
14099a2dd95SBruce Richardson 	}
14199a2dd95SBruce Richardson }
14299a2dd95SBruce Richardson 
14399a2dd95SBruce Richardson static uint16_t
pdump_rx(uint16_t port,uint16_t queue,struct rte_mbuf ** pkts,uint16_t nb_pkts,uint16_t max_pkts __rte_unused,void * user_params)14410f726efSStephen Hemminger pdump_rx(uint16_t port, uint16_t queue,
14599a2dd95SBruce Richardson 	struct rte_mbuf **pkts, uint16_t nb_pkts,
14610f726efSStephen Hemminger 	uint16_t max_pkts __rte_unused, void *user_params)
14799a2dd95SBruce Richardson {
14810f726efSStephen Hemminger 	const struct pdump_rxtx_cbs *cbs = user_params;
14910f726efSStephen Hemminger 	struct rte_pdump_stats *stats = &pdump_stats->rx[port][queue];
15010f726efSStephen Hemminger 
15110f726efSStephen Hemminger 	pdump_copy(port, queue, RTE_PCAPNG_DIRECTION_IN,
15210f726efSStephen Hemminger 		   pkts, nb_pkts, cbs, stats);
15399a2dd95SBruce Richardson 	return nb_pkts;
15499a2dd95SBruce Richardson }
15599a2dd95SBruce Richardson 
15699a2dd95SBruce Richardson static uint16_t
pdump_tx(uint16_t port,uint16_t queue,struct rte_mbuf ** pkts,uint16_t nb_pkts,void * user_params)15710f726efSStephen Hemminger pdump_tx(uint16_t port, uint16_t queue,
15899a2dd95SBruce Richardson 		struct rte_mbuf **pkts, uint16_t nb_pkts, void *user_params)
15999a2dd95SBruce Richardson {
16010f726efSStephen Hemminger 	const struct pdump_rxtx_cbs *cbs = user_params;
16110f726efSStephen Hemminger 	struct rte_pdump_stats *stats = &pdump_stats->tx[port][queue];
16210f726efSStephen Hemminger 
16310f726efSStephen Hemminger 	pdump_copy(port, queue, RTE_PCAPNG_DIRECTION_OUT,
16410f726efSStephen Hemminger 		   pkts, nb_pkts, cbs, stats);
16599a2dd95SBruce Richardson 	return nb_pkts;
16699a2dd95SBruce Richardson }
16799a2dd95SBruce Richardson 
16899a2dd95SBruce Richardson static int
pdump_register_rx_callbacks(enum pdump_version ver,uint16_t end_q,uint16_t port,uint16_t queue,struct rte_ring * ring,struct rte_mempool * mp,struct rte_bpf * filter,uint16_t operation,uint32_t snaplen)16910f726efSStephen Hemminger pdump_register_rx_callbacks(enum pdump_version ver,
17010f726efSStephen Hemminger 			    uint16_t end_q, uint16_t port, uint16_t queue,
17199a2dd95SBruce Richardson 			    struct rte_ring *ring, struct rte_mempool *mp,
17210f726efSStephen Hemminger 			    struct rte_bpf *filter,
17310f726efSStephen Hemminger 			    uint16_t operation, uint32_t snaplen)
17499a2dd95SBruce Richardson {
17599a2dd95SBruce Richardson 	uint16_t qid;
17699a2dd95SBruce Richardson 
17799a2dd95SBruce Richardson 	qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue;
17899a2dd95SBruce Richardson 	for (; qid < end_q; qid++) {
17910f726efSStephen Hemminger 		struct pdump_rxtx_cbs *cbs = &rx_cbs[port][qid];
18010f726efSStephen Hemminger 
18110f726efSStephen Hemminger 		if (operation == ENABLE) {
18299a2dd95SBruce Richardson 			if (cbs->cb) {
1830e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
1840e21c7c0SDavid Marchand 					"rx callback for port=%d queue=%d, already exists",
18599a2dd95SBruce Richardson 					port, qid);
18699a2dd95SBruce Richardson 				return -EEXIST;
18799a2dd95SBruce Richardson 			}
18810f726efSStephen Hemminger 			cbs->ver = ver;
18999a2dd95SBruce Richardson 			cbs->ring = ring;
19099a2dd95SBruce Richardson 			cbs->mp = mp;
19110f726efSStephen Hemminger 			cbs->snaplen = snaplen;
19210f726efSStephen Hemminger 			cbs->filter = filter;
19310f726efSStephen Hemminger 
19499a2dd95SBruce Richardson 			cbs->cb = rte_eth_add_first_rx_callback(port, qid,
19599a2dd95SBruce Richardson 								pdump_rx, cbs);
19699a2dd95SBruce Richardson 			if (cbs->cb == NULL) {
1970e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
1980e21c7c0SDavid Marchand 					"failed to add rx callback, errno=%d",
19999a2dd95SBruce Richardson 					rte_errno);
20099a2dd95SBruce Richardson 				return rte_errno;
20199a2dd95SBruce Richardson 			}
20210f726efSStephen Hemminger 		} else if (operation == DISABLE) {
20399a2dd95SBruce Richardson 			int ret;
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 			if (cbs->cb == NULL) {
2060e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
2070e21c7c0SDavid Marchand 					"no existing rx callback for port=%d queue=%d",
20899a2dd95SBruce Richardson 					port, qid);
20999a2dd95SBruce Richardson 				return -EINVAL;
21099a2dd95SBruce Richardson 			}
21199a2dd95SBruce Richardson 			ret = rte_eth_remove_rx_callback(port, qid, cbs->cb);
21299a2dd95SBruce Richardson 			if (ret < 0) {
2130e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
2140e21c7c0SDavid Marchand 					"failed to remove rx callback, errno=%d",
21599a2dd95SBruce Richardson 					-ret);
21699a2dd95SBruce Richardson 				return ret;
21799a2dd95SBruce Richardson 			}
21899a2dd95SBruce Richardson 			cbs->cb = NULL;
21999a2dd95SBruce Richardson 		}
22099a2dd95SBruce Richardson 	}
22199a2dd95SBruce Richardson 
22299a2dd95SBruce Richardson 	return 0;
22399a2dd95SBruce Richardson }
22499a2dd95SBruce Richardson 
22599a2dd95SBruce Richardson static int
pdump_register_tx_callbacks(enum pdump_version ver,uint16_t end_q,uint16_t port,uint16_t queue,struct rte_ring * ring,struct rte_mempool * mp,struct rte_bpf * filter,uint16_t operation,uint32_t snaplen)22610f726efSStephen Hemminger pdump_register_tx_callbacks(enum pdump_version ver,
22710f726efSStephen Hemminger 			    uint16_t end_q, uint16_t port, uint16_t queue,
22899a2dd95SBruce Richardson 			    struct rte_ring *ring, struct rte_mempool *mp,
22910f726efSStephen Hemminger 			    struct rte_bpf *filter,
23010f726efSStephen Hemminger 			    uint16_t operation, uint32_t snaplen)
23199a2dd95SBruce Richardson {
23299a2dd95SBruce Richardson 
23399a2dd95SBruce Richardson 	uint16_t qid;
23499a2dd95SBruce Richardson 
23599a2dd95SBruce Richardson 	qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue;
23699a2dd95SBruce Richardson 	for (; qid < end_q; qid++) {
23710f726efSStephen Hemminger 		struct pdump_rxtx_cbs *cbs = &tx_cbs[port][qid];
23810f726efSStephen Hemminger 
23910f726efSStephen Hemminger 		if (operation == ENABLE) {
24099a2dd95SBruce Richardson 			if (cbs->cb) {
2410e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
2420e21c7c0SDavid Marchand 					"tx callback for port=%d queue=%d, already exists",
24399a2dd95SBruce Richardson 					port, qid);
24499a2dd95SBruce Richardson 				return -EEXIST;
24599a2dd95SBruce Richardson 			}
24610f726efSStephen Hemminger 			cbs->ver = ver;
24799a2dd95SBruce Richardson 			cbs->ring = ring;
24899a2dd95SBruce Richardson 			cbs->mp = mp;
24910f726efSStephen Hemminger 			cbs->snaplen = snaplen;
25010f726efSStephen Hemminger 			cbs->filter = filter;
25110f726efSStephen Hemminger 
25299a2dd95SBruce Richardson 			cbs->cb = rte_eth_add_tx_callback(port, qid, pdump_tx,
25399a2dd95SBruce Richardson 								cbs);
25499a2dd95SBruce Richardson 			if (cbs->cb == NULL) {
2550e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
2560e21c7c0SDavid Marchand 					"failed to add tx callback, errno=%d",
25799a2dd95SBruce Richardson 					rte_errno);
25899a2dd95SBruce Richardson 				return rte_errno;
25999a2dd95SBruce Richardson 			}
26010f726efSStephen Hemminger 		} else if (operation == DISABLE) {
26199a2dd95SBruce Richardson 			int ret;
26299a2dd95SBruce Richardson 
26399a2dd95SBruce Richardson 			if (cbs->cb == NULL) {
2640e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
2650e21c7c0SDavid Marchand 					"no existing tx callback for port=%d queue=%d",
26699a2dd95SBruce Richardson 					port, qid);
26799a2dd95SBruce Richardson 				return -EINVAL;
26899a2dd95SBruce Richardson 			}
26999a2dd95SBruce Richardson 			ret = rte_eth_remove_tx_callback(port, qid, cbs->cb);
27099a2dd95SBruce Richardson 			if (ret < 0) {
2710e21c7c0SDavid Marchand 				PDUMP_LOG_LINE(ERR,
2720e21c7c0SDavid Marchand 					"failed to remove tx callback, errno=%d",
27399a2dd95SBruce Richardson 					-ret);
27499a2dd95SBruce Richardson 				return ret;
27599a2dd95SBruce Richardson 			}
27699a2dd95SBruce Richardson 			cbs->cb = NULL;
27799a2dd95SBruce Richardson 		}
27899a2dd95SBruce Richardson 	}
27999a2dd95SBruce Richardson 
28099a2dd95SBruce Richardson 	return 0;
28199a2dd95SBruce Richardson }
28299a2dd95SBruce Richardson 
28399a2dd95SBruce Richardson static int
set_pdump_rxtx_cbs(const struct pdump_request * p)28499a2dd95SBruce Richardson set_pdump_rxtx_cbs(const struct pdump_request *p)
28599a2dd95SBruce Richardson {
28699a2dd95SBruce Richardson 	uint16_t nb_rx_q = 0, nb_tx_q = 0, end_q, queue;
28799a2dd95SBruce Richardson 	uint16_t port;
28899a2dd95SBruce Richardson 	int ret = 0;
28910f726efSStephen Hemminger 	struct rte_bpf *filter = NULL;
29099a2dd95SBruce Richardson 	uint32_t flags;
29199a2dd95SBruce Richardson 	uint16_t operation;
29299a2dd95SBruce Richardson 	struct rte_ring *ring;
29399a2dd95SBruce Richardson 	struct rte_mempool *mp;
29499a2dd95SBruce Richardson 
29510f726efSStephen Hemminger 	/* Check for possible DPDK version mismatch */
29610f726efSStephen Hemminger 	if (!(p->ver == V1 || p->ver == V2)) {
2970e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
2980e21c7c0SDavid Marchand 			  "incorrect client version %u", p->ver);
29910f726efSStephen Hemminger 		return -EINVAL;
30010f726efSStephen Hemminger 	}
30110f726efSStephen Hemminger 
30210f726efSStephen Hemminger 	if (p->prm) {
30310f726efSStephen Hemminger 		if (p->prm->prog_arg.type != RTE_BPF_ARG_PTR_MBUF) {
3040e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR,
3050e21c7c0SDavid Marchand 				  "invalid BPF program type: %u",
30610f726efSStephen Hemminger 				  p->prm->prog_arg.type);
30710f726efSStephen Hemminger 			return -EINVAL;
30810f726efSStephen Hemminger 		}
30910f726efSStephen Hemminger 
31010f726efSStephen Hemminger 		filter = rte_bpf_load(p->prm);
31110f726efSStephen Hemminger 		if (filter == NULL) {
3120e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR, "cannot load BPF filter: %s",
31310f726efSStephen Hemminger 				  rte_strerror(rte_errno));
31410f726efSStephen Hemminger 			return -rte_errno;
31510f726efSStephen Hemminger 		}
31610f726efSStephen Hemminger 	}
31710f726efSStephen Hemminger 
31899a2dd95SBruce Richardson 	flags = p->flags;
31999a2dd95SBruce Richardson 	operation = p->op;
32010f726efSStephen Hemminger 	queue = p->queue;
32110f726efSStephen Hemminger 	ring = p->ring;
32210f726efSStephen Hemminger 	mp = p->mp;
32310f726efSStephen Hemminger 
32410f726efSStephen Hemminger 	ret = rte_eth_dev_get_port_by_name(p->device, &port);
32599a2dd95SBruce Richardson 	if (ret < 0) {
3260e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
3270e21c7c0SDavid Marchand 			  "failed to get port id for device id=%s",
32810f726efSStephen Hemminger 			  p->device);
32999a2dd95SBruce Richardson 		return -EINVAL;
33099a2dd95SBruce Richardson 	}
33199a2dd95SBruce Richardson 
33299a2dd95SBruce Richardson 	/* validation if packet capture is for all queues */
33399a2dd95SBruce Richardson 	if (queue == RTE_PDUMP_ALL_QUEUES) {
33499a2dd95SBruce Richardson 		struct rte_eth_dev_info dev_info;
33599a2dd95SBruce Richardson 
33699a2dd95SBruce Richardson 		ret = rte_eth_dev_info_get(port, &dev_info);
33799a2dd95SBruce Richardson 		if (ret != 0) {
3380e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR,
3390e21c7c0SDavid Marchand 				"Error during getting device (port %u) info: %s",
34099a2dd95SBruce Richardson 				port, strerror(-ret));
34199a2dd95SBruce Richardson 			return ret;
34299a2dd95SBruce Richardson 		}
34399a2dd95SBruce Richardson 
34499a2dd95SBruce Richardson 		nb_rx_q = dev_info.nb_rx_queues;
34599a2dd95SBruce Richardson 		nb_tx_q = dev_info.nb_tx_queues;
34699a2dd95SBruce Richardson 		if (nb_rx_q == 0 && flags & RTE_PDUMP_FLAG_RX) {
3470e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR,
3480e21c7c0SDavid Marchand 				"number of rx queues cannot be 0");
34999a2dd95SBruce Richardson 			return -EINVAL;
35099a2dd95SBruce Richardson 		}
35199a2dd95SBruce Richardson 		if (nb_tx_q == 0 && flags & RTE_PDUMP_FLAG_TX) {
3520e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR,
3530e21c7c0SDavid Marchand 				"number of tx queues cannot be 0");
35499a2dd95SBruce Richardson 			return -EINVAL;
35599a2dd95SBruce Richardson 		}
35699a2dd95SBruce Richardson 		if ((nb_tx_q == 0 || nb_rx_q == 0) &&
35799a2dd95SBruce Richardson 			flags == RTE_PDUMP_FLAG_RXTX) {
3580e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR,
3590e21c7c0SDavid Marchand 				"both tx&rx queues must be non zero");
36099a2dd95SBruce Richardson 			return -EINVAL;
36199a2dd95SBruce Richardson 		}
36299a2dd95SBruce Richardson 	}
36399a2dd95SBruce Richardson 
36499a2dd95SBruce Richardson 	/* register RX callback */
36599a2dd95SBruce Richardson 	if (flags & RTE_PDUMP_FLAG_RX) {
36699a2dd95SBruce Richardson 		end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_rx_q : queue + 1;
36710f726efSStephen Hemminger 		ret = pdump_register_rx_callbacks(p->ver, end_q, port, queue,
36810f726efSStephen Hemminger 						  ring, mp, filter,
36910f726efSStephen Hemminger 						  operation, p->snaplen);
37099a2dd95SBruce Richardson 		if (ret < 0)
37199a2dd95SBruce Richardson 			return ret;
37299a2dd95SBruce Richardson 	}
37399a2dd95SBruce Richardson 
37499a2dd95SBruce Richardson 	/* register TX callback */
37599a2dd95SBruce Richardson 	if (flags & RTE_PDUMP_FLAG_TX) {
37699a2dd95SBruce Richardson 		end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_tx_q : queue + 1;
37710f726efSStephen Hemminger 		ret = pdump_register_tx_callbacks(p->ver, end_q, port, queue,
37810f726efSStephen Hemminger 						  ring, mp, filter,
37910f726efSStephen Hemminger 						  operation, p->snaplen);
38099a2dd95SBruce Richardson 		if (ret < 0)
38199a2dd95SBruce Richardson 			return ret;
38299a2dd95SBruce Richardson 	}
38399a2dd95SBruce Richardson 
38499a2dd95SBruce Richardson 	return ret;
38599a2dd95SBruce Richardson }
38699a2dd95SBruce Richardson 
38799a2dd95SBruce Richardson static int
pdump_server(const struct rte_mp_msg * mp_msg,const void * peer)38899a2dd95SBruce Richardson pdump_server(const struct rte_mp_msg *mp_msg, const void *peer)
38999a2dd95SBruce Richardson {
39099a2dd95SBruce Richardson 	struct rte_mp_msg mp_resp;
39199a2dd95SBruce Richardson 	const struct pdump_request *cli_req;
39299a2dd95SBruce Richardson 	struct pdump_response *resp = (struct pdump_response *)&mp_resp.param;
39399a2dd95SBruce Richardson 
39499a2dd95SBruce Richardson 	/* recv client requests */
39599a2dd95SBruce Richardson 	if (mp_msg->len_param != sizeof(*cli_req)) {
3960e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR, "failed to recv from client");
39799a2dd95SBruce Richardson 		resp->err_value = -EINVAL;
39899a2dd95SBruce Richardson 	} else {
39999a2dd95SBruce Richardson 		cli_req = (const struct pdump_request *)mp_msg->param;
40099a2dd95SBruce Richardson 		resp->ver = cli_req->ver;
40199a2dd95SBruce Richardson 		resp->res_op = cli_req->op;
40299a2dd95SBruce Richardson 		resp->err_value = set_pdump_rxtx_cbs(cli_req);
40399a2dd95SBruce Richardson 	}
40499a2dd95SBruce Richardson 
40510f726efSStephen Hemminger 	rte_strscpy(mp_resp.name, PDUMP_MP, RTE_MP_MAX_NAME_LEN);
40699a2dd95SBruce Richardson 	mp_resp.len_param = sizeof(*resp);
40799a2dd95SBruce Richardson 	mp_resp.num_fds = 0;
40899a2dd95SBruce Richardson 	if (rte_mp_reply(&mp_resp, peer) < 0) {
4090e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR, "failed to send to client:%s",
41099a2dd95SBruce Richardson 			  strerror(rte_errno));
41199a2dd95SBruce Richardson 		return -1;
41299a2dd95SBruce Richardson 	}
41399a2dd95SBruce Richardson 
41499a2dd95SBruce Richardson 	return 0;
41599a2dd95SBruce Richardson }
41699a2dd95SBruce Richardson 
41799a2dd95SBruce Richardson int
rte_pdump_init(void)41899a2dd95SBruce Richardson rte_pdump_init(void)
41999a2dd95SBruce Richardson {
42010f726efSStephen Hemminger 	const struct rte_memzone *mz;
42199a2dd95SBruce Richardson 	int ret;
42299a2dd95SBruce Richardson 
42310f726efSStephen Hemminger 	mz = rte_memzone_reserve(MZ_RTE_PDUMP_STATS, sizeof(*pdump_stats),
42410f726efSStephen Hemminger 				 rte_socket_id(), 0);
42510f726efSStephen Hemminger 	if (mz == NULL) {
4260e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR, "cannot allocate pdump statistics");
42710f726efSStephen Hemminger 		rte_errno = ENOMEM;
42810f726efSStephen Hemminger 		return -1;
42910f726efSStephen Hemminger 	}
43010f726efSStephen Hemminger 	pdump_stats = mz->addr;
43153caecb8SKonstantin Ananyev 	pdump_stats->mz = mz;
43210f726efSStephen Hemminger 
43399a2dd95SBruce Richardson 	ret = rte_mp_action_register(PDUMP_MP, pdump_server);
43499a2dd95SBruce Richardson 	if (ret && rte_errno != ENOTSUP)
43599a2dd95SBruce Richardson 		return -1;
43699a2dd95SBruce Richardson 	return 0;
43799a2dd95SBruce Richardson }
43899a2dd95SBruce Richardson 
43999a2dd95SBruce Richardson int
rte_pdump_uninit(void)44099a2dd95SBruce Richardson rte_pdump_uninit(void)
44199a2dd95SBruce Richardson {
44299a2dd95SBruce Richardson 	rte_mp_action_unregister(PDUMP_MP);
44399a2dd95SBruce Richardson 
44453caecb8SKonstantin Ananyev 	if (pdump_stats != NULL) {
44553caecb8SKonstantin Ananyev 		rte_memzone_free(pdump_stats->mz);
44653caecb8SKonstantin Ananyev 		pdump_stats = NULL;
44753caecb8SKonstantin Ananyev 	}
44853caecb8SKonstantin Ananyev 
44999a2dd95SBruce Richardson 	return 0;
45099a2dd95SBruce Richardson }
45199a2dd95SBruce Richardson 
45299a2dd95SBruce Richardson static int
pdump_validate_ring_mp(struct rte_ring * ring,struct rte_mempool * mp)45399a2dd95SBruce Richardson pdump_validate_ring_mp(struct rte_ring *ring, struct rte_mempool *mp)
45499a2dd95SBruce Richardson {
45599a2dd95SBruce Richardson 	if (ring == NULL || mp == NULL) {
4560e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR, "NULL ring or mempool");
45799a2dd95SBruce Richardson 		rte_errno = EINVAL;
45899a2dd95SBruce Richardson 		return -1;
45999a2dd95SBruce Richardson 	}
460c47d7b90SAndrew Rybchenko 	if (mp->flags & RTE_MEMPOOL_F_SP_PUT ||
461c47d7b90SAndrew Rybchenko 	    mp->flags & RTE_MEMPOOL_F_SC_GET) {
4620e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
46399a2dd95SBruce Richardson 			  "mempool with SP or SC set not valid for pdump,"
4640e21c7c0SDavid Marchand 			  "must have MP and MC set");
46599a2dd95SBruce Richardson 		rte_errno = EINVAL;
46699a2dd95SBruce Richardson 		return -1;
46799a2dd95SBruce Richardson 	}
46899a2dd95SBruce Richardson 	if (rte_ring_is_prod_single(ring) || rte_ring_is_cons_single(ring)) {
4690e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
47099a2dd95SBruce Richardson 			  "ring with SP or SC set is not valid for pdump,"
4710e21c7c0SDavid Marchand 			  "must have MP and MC set");
47299a2dd95SBruce Richardson 		rte_errno = EINVAL;
47399a2dd95SBruce Richardson 		return -1;
47499a2dd95SBruce Richardson 	}
47599a2dd95SBruce Richardson 
47699a2dd95SBruce Richardson 	return 0;
47799a2dd95SBruce Richardson }
47899a2dd95SBruce Richardson 
47999a2dd95SBruce Richardson static int
pdump_validate_flags(uint32_t flags)48099a2dd95SBruce Richardson pdump_validate_flags(uint32_t flags)
48199a2dd95SBruce Richardson {
48210f726efSStephen Hemminger 	if ((flags & RTE_PDUMP_FLAG_RXTX) == 0) {
4830e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
4840e21c7c0SDavid Marchand 			"invalid flags, should be either rx/tx/rxtx");
48599a2dd95SBruce Richardson 		rte_errno = EINVAL;
48699a2dd95SBruce Richardson 		return -1;
48799a2dd95SBruce Richardson 	}
48899a2dd95SBruce Richardson 
48910f726efSStephen Hemminger 	/* mask off the flags we know about */
49010f726efSStephen Hemminger 	if (flags & ~(RTE_PDUMP_FLAG_RXTX | RTE_PDUMP_FLAG_PCAPNG)) {
4910e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
4920e21c7c0SDavid Marchand 			  "unknown flags: %#x", flags);
49310f726efSStephen Hemminger 		rte_errno = ENOTSUP;
49410f726efSStephen Hemminger 		return -1;
49510f726efSStephen Hemminger 	}
49610f726efSStephen Hemminger 
49799a2dd95SBruce Richardson 	return 0;
49899a2dd95SBruce Richardson }
49999a2dd95SBruce Richardson 
50099a2dd95SBruce Richardson static int
pdump_validate_port(uint16_t port,char * name)50199a2dd95SBruce Richardson pdump_validate_port(uint16_t port, char *name)
50299a2dd95SBruce Richardson {
50399a2dd95SBruce Richardson 	int ret = 0;
50499a2dd95SBruce Richardson 
50599a2dd95SBruce Richardson 	if (port >= RTE_MAX_ETHPORTS) {
5060e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR, "Invalid port id %u", port);
50799a2dd95SBruce Richardson 		rte_errno = EINVAL;
50899a2dd95SBruce Richardson 		return -1;
50999a2dd95SBruce Richardson 	}
51099a2dd95SBruce Richardson 
51199a2dd95SBruce Richardson 	ret = rte_eth_dev_get_name_by_port(port, name);
51299a2dd95SBruce Richardson 	if (ret < 0) {
5130e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR, "port %u to name mapping failed",
51499a2dd95SBruce Richardson 			  port);
51599a2dd95SBruce Richardson 		rte_errno = EINVAL;
51699a2dd95SBruce Richardson 		return -1;
51799a2dd95SBruce Richardson 	}
51899a2dd95SBruce Richardson 
51999a2dd95SBruce Richardson 	return 0;
52099a2dd95SBruce Richardson }
52199a2dd95SBruce Richardson 
52299a2dd95SBruce Richardson static int
pdump_prepare_client_request(const char * device,uint16_t queue,uint32_t flags,uint32_t snaplen,uint16_t operation,struct rte_ring * ring,struct rte_mempool * mp,const struct rte_bpf_prm * prm)52310f726efSStephen Hemminger pdump_prepare_client_request(const char *device, uint16_t queue,
52410f726efSStephen Hemminger 			     uint32_t flags, uint32_t snaplen,
52599a2dd95SBruce Richardson 			     uint16_t operation,
52699a2dd95SBruce Richardson 			     struct rte_ring *ring,
52799a2dd95SBruce Richardson 			     struct rte_mempool *mp,
52810f726efSStephen Hemminger 			     const struct rte_bpf_prm *prm)
52999a2dd95SBruce Richardson {
53099a2dd95SBruce Richardson 	int ret = -1;
53199a2dd95SBruce Richardson 	struct rte_mp_msg mp_req, *mp_rep;
53299a2dd95SBruce Richardson 	struct rte_mp_reply mp_reply;
53399a2dd95SBruce Richardson 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
53499a2dd95SBruce Richardson 	struct pdump_request *req = (struct pdump_request *)mp_req.param;
53599a2dd95SBruce Richardson 	struct pdump_response *resp;
53699a2dd95SBruce Richardson 
5378a0cf0c4SStephen Hemminger 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
5380e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
5390e21c7c0SDavid Marchand 			  "pdump enable/disable not allowed in primary process");
5408a0cf0c4SStephen Hemminger 		return -EINVAL;
5418a0cf0c4SStephen Hemminger 	}
5428a0cf0c4SStephen Hemminger 
54310f726efSStephen Hemminger 	memset(req, 0, sizeof(*req));
54410f726efSStephen Hemminger 
54510f726efSStephen Hemminger 	req->ver = (flags & RTE_PDUMP_FLAG_PCAPNG) ? V2 : V1;
54610f726efSStephen Hemminger 	req->flags = flags & RTE_PDUMP_FLAG_RXTX;
54799a2dd95SBruce Richardson 	req->op = operation;
54810f726efSStephen Hemminger 	req->queue = queue;
54910f726efSStephen Hemminger 	rte_strscpy(req->device, device, sizeof(req->device));
55010f726efSStephen Hemminger 
55199a2dd95SBruce Richardson 	if ((operation & ENABLE) != 0) {
55210f726efSStephen Hemminger 		req->ring = ring;
55310f726efSStephen Hemminger 		req->mp = mp;
55410f726efSStephen Hemminger 		req->prm = prm;
55510f726efSStephen Hemminger 		req->snaplen = snaplen;
55699a2dd95SBruce Richardson 	}
55799a2dd95SBruce Richardson 
55810f726efSStephen Hemminger 	rte_strscpy(mp_req.name, PDUMP_MP, RTE_MP_MAX_NAME_LEN);
55999a2dd95SBruce Richardson 	mp_req.len_param = sizeof(*req);
56099a2dd95SBruce Richardson 	mp_req.num_fds = 0;
56199a2dd95SBruce Richardson 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0) {
56299a2dd95SBruce Richardson 		mp_rep = &mp_reply.msgs[0];
56399a2dd95SBruce Richardson 		resp = (struct pdump_response *)mp_rep->param;
5645ec9575dSStephen Hemminger 		if (resp->err_value == 0)
56599a2dd95SBruce Richardson 			ret = 0;
5665ec9575dSStephen Hemminger 		else
5675ec9575dSStephen Hemminger 			rte_errno = -resp->err_value;
56899a2dd95SBruce Richardson 		free(mp_reply.msgs);
56999a2dd95SBruce Richardson 	}
57099a2dd95SBruce Richardson 
57199a2dd95SBruce Richardson 	if (ret < 0)
5720e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
5730e21c7c0SDavid Marchand 			"client request for pdump enable/disable failed");
57499a2dd95SBruce Richardson 	return ret;
57599a2dd95SBruce Richardson }
57699a2dd95SBruce Richardson 
57710f726efSStephen Hemminger /*
57810f726efSStephen Hemminger  * There are two versions of this function, because although original API
57910f726efSStephen Hemminger  * left place holder for future filter, it never checked the value.
58010f726efSStephen Hemminger  * Therefore the API can't depend on application passing a non
58110f726efSStephen Hemminger  * bogus value.
58210f726efSStephen Hemminger  */
58310f726efSStephen Hemminger static int
pdump_enable(uint16_t port,uint16_t queue,uint32_t flags,uint32_t snaplen,struct rte_ring * ring,struct rte_mempool * mp,const struct rte_bpf_prm * prm)58410f726efSStephen Hemminger pdump_enable(uint16_t port, uint16_t queue,
58510f726efSStephen Hemminger 	     uint32_t flags, uint32_t snaplen,
58610f726efSStephen Hemminger 	     struct rte_ring *ring, struct rte_mempool *mp,
58710f726efSStephen Hemminger 	     const struct rte_bpf_prm *prm)
58899a2dd95SBruce Richardson {
58999a2dd95SBruce Richardson 	int ret;
59099a2dd95SBruce Richardson 	char name[RTE_DEV_NAME_MAX_LEN];
59199a2dd95SBruce Richardson 
59299a2dd95SBruce Richardson 	ret = pdump_validate_port(port, name);
59399a2dd95SBruce Richardson 	if (ret < 0)
59499a2dd95SBruce Richardson 		return ret;
59599a2dd95SBruce Richardson 	ret = pdump_validate_ring_mp(ring, mp);
59699a2dd95SBruce Richardson 	if (ret < 0)
59799a2dd95SBruce Richardson 		return ret;
59899a2dd95SBruce Richardson 	ret = pdump_validate_flags(flags);
59999a2dd95SBruce Richardson 	if (ret < 0)
60099a2dd95SBruce Richardson 		return ret;
60199a2dd95SBruce Richardson 
60210f726efSStephen Hemminger 	if (snaplen == 0)
60310f726efSStephen Hemminger 		snaplen = UINT32_MAX;
60499a2dd95SBruce Richardson 
60510f726efSStephen Hemminger 	return pdump_prepare_client_request(name, queue, flags, snaplen,
60610f726efSStephen Hemminger 					    ENABLE, ring, mp, prm);
60799a2dd95SBruce Richardson }
60899a2dd95SBruce Richardson 
60999a2dd95SBruce Richardson int
rte_pdump_enable(uint16_t port,uint16_t queue,uint32_t flags,struct rte_ring * ring,struct rte_mempool * mp,void * filter __rte_unused)61010f726efSStephen Hemminger rte_pdump_enable(uint16_t port, uint16_t queue, uint32_t flags,
61199a2dd95SBruce Richardson 		 struct rte_ring *ring,
61299a2dd95SBruce Richardson 		 struct rte_mempool *mp,
61310f726efSStephen Hemminger 		 void *filter __rte_unused)
61499a2dd95SBruce Richardson {
61510f726efSStephen Hemminger 	return pdump_enable(port, queue, flags, 0,
61610f726efSStephen Hemminger 			    ring, mp, NULL);
61710f726efSStephen Hemminger }
61810f726efSStephen Hemminger 
61910f726efSStephen Hemminger int
rte_pdump_enable_bpf(uint16_t port,uint16_t queue,uint32_t flags,uint32_t snaplen,struct rte_ring * ring,struct rte_mempool * mp,const struct rte_bpf_prm * prm)62010f726efSStephen Hemminger rte_pdump_enable_bpf(uint16_t port, uint16_t queue,
62110f726efSStephen Hemminger 		     uint32_t flags, uint32_t snaplen,
62210f726efSStephen Hemminger 		     struct rte_ring *ring,
62310f726efSStephen Hemminger 		     struct rte_mempool *mp,
62410f726efSStephen Hemminger 		     const struct rte_bpf_prm *prm)
62510f726efSStephen Hemminger {
62610f726efSStephen Hemminger 	return pdump_enable(port, queue, flags, snaplen,
62710f726efSStephen Hemminger 			    ring, mp, prm);
62810f726efSStephen Hemminger }
62910f726efSStephen Hemminger 
63010f726efSStephen Hemminger static int
pdump_enable_by_deviceid(const char * device_id,uint16_t queue,uint32_t flags,uint32_t snaplen,struct rte_ring * ring,struct rte_mempool * mp,const struct rte_bpf_prm * prm)63110f726efSStephen Hemminger pdump_enable_by_deviceid(const char *device_id, uint16_t queue,
63210f726efSStephen Hemminger 			 uint32_t flags, uint32_t snaplen,
63310f726efSStephen Hemminger 			 struct rte_ring *ring,
63410f726efSStephen Hemminger 			 struct rte_mempool *mp,
63510f726efSStephen Hemminger 			 const struct rte_bpf_prm *prm)
63610f726efSStephen Hemminger {
63710f726efSStephen Hemminger 	int ret;
63899a2dd95SBruce Richardson 
63999a2dd95SBruce Richardson 	ret = pdump_validate_ring_mp(ring, mp);
64099a2dd95SBruce Richardson 	if (ret < 0)
64199a2dd95SBruce Richardson 		return ret;
64299a2dd95SBruce Richardson 	ret = pdump_validate_flags(flags);
64399a2dd95SBruce Richardson 	if (ret < 0)
64499a2dd95SBruce Richardson 		return ret;
64599a2dd95SBruce Richardson 
646b2be63b5SStephen Hemminger 	if (snaplen == 0)
647b2be63b5SStephen Hemminger 		snaplen = UINT32_MAX;
648b2be63b5SStephen Hemminger 
64910f726efSStephen Hemminger 	return pdump_prepare_client_request(device_id, queue, flags, snaplen,
65010f726efSStephen Hemminger 					    ENABLE, ring, mp, prm);
65110f726efSStephen Hemminger }
65299a2dd95SBruce Richardson 
65310f726efSStephen Hemminger int
rte_pdump_enable_by_deviceid(char * device_id,uint16_t queue,uint32_t flags,struct rte_ring * ring,struct rte_mempool * mp,void * filter __rte_unused)65410f726efSStephen Hemminger rte_pdump_enable_by_deviceid(char *device_id, uint16_t queue,
65510f726efSStephen Hemminger 			     uint32_t flags,
65610f726efSStephen Hemminger 			     struct rte_ring *ring,
65710f726efSStephen Hemminger 			     struct rte_mempool *mp,
65810f726efSStephen Hemminger 			     void *filter __rte_unused)
65910f726efSStephen Hemminger {
66010f726efSStephen Hemminger 	return pdump_enable_by_deviceid(device_id, queue, flags, 0,
66110f726efSStephen Hemminger 					ring, mp, NULL);
66210f726efSStephen Hemminger }
66310f726efSStephen Hemminger 
66410f726efSStephen Hemminger int
rte_pdump_enable_bpf_by_deviceid(const char * device_id,uint16_t queue,uint32_t flags,uint32_t snaplen,struct rte_ring * ring,struct rte_mempool * mp,const struct rte_bpf_prm * prm)66510f726efSStephen Hemminger rte_pdump_enable_bpf_by_deviceid(const char *device_id, uint16_t queue,
66610f726efSStephen Hemminger 				 uint32_t flags, uint32_t snaplen,
66710f726efSStephen Hemminger 				 struct rte_ring *ring,
66810f726efSStephen Hemminger 				 struct rte_mempool *mp,
66910f726efSStephen Hemminger 				 const struct rte_bpf_prm *prm)
67010f726efSStephen Hemminger {
67110f726efSStephen Hemminger 	return pdump_enable_by_deviceid(device_id, queue, flags, snaplen,
67210f726efSStephen Hemminger 					ring, mp, prm);
67399a2dd95SBruce Richardson }
67499a2dd95SBruce Richardson 
67599a2dd95SBruce Richardson int
rte_pdump_disable(uint16_t port,uint16_t queue,uint32_t flags)67699a2dd95SBruce Richardson rte_pdump_disable(uint16_t port, uint16_t queue, uint32_t flags)
67799a2dd95SBruce Richardson {
67899a2dd95SBruce Richardson 	int ret = 0;
67999a2dd95SBruce Richardson 	char name[RTE_DEV_NAME_MAX_LEN];
68099a2dd95SBruce Richardson 
68199a2dd95SBruce Richardson 	ret = pdump_validate_port(port, name);
68299a2dd95SBruce Richardson 	if (ret < 0)
68399a2dd95SBruce Richardson 		return ret;
68499a2dd95SBruce Richardson 	ret = pdump_validate_flags(flags);
68599a2dd95SBruce Richardson 	if (ret < 0)
68699a2dd95SBruce Richardson 		return ret;
68799a2dd95SBruce Richardson 
68810f726efSStephen Hemminger 	ret = pdump_prepare_client_request(name, queue, flags, 0,
68999a2dd95SBruce Richardson 					   DISABLE, NULL, NULL, NULL);
69099a2dd95SBruce Richardson 
69199a2dd95SBruce Richardson 	return ret;
69299a2dd95SBruce Richardson }
69399a2dd95SBruce Richardson 
69499a2dd95SBruce Richardson int
rte_pdump_disable_by_deviceid(char * device_id,uint16_t queue,uint32_t flags)69599a2dd95SBruce Richardson rte_pdump_disable_by_deviceid(char *device_id, uint16_t queue,
69699a2dd95SBruce Richardson 				uint32_t flags)
69799a2dd95SBruce Richardson {
69899a2dd95SBruce Richardson 	int ret = 0;
69999a2dd95SBruce Richardson 
70099a2dd95SBruce Richardson 	ret = pdump_validate_flags(flags);
70199a2dd95SBruce Richardson 	if (ret < 0)
70299a2dd95SBruce Richardson 		return ret;
70399a2dd95SBruce Richardson 
70410f726efSStephen Hemminger 	ret = pdump_prepare_client_request(device_id, queue, flags, 0,
70599a2dd95SBruce Richardson 					   DISABLE, NULL, NULL, NULL);
70699a2dd95SBruce Richardson 
70799a2dd95SBruce Richardson 	return ret;
70899a2dd95SBruce Richardson }
70910f726efSStephen Hemminger 
71010f726efSStephen Hemminger static void
pdump_sum_stats(uint16_t port,uint16_t nq,struct rte_pdump_stats stats[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],struct rte_pdump_stats * total)71110f726efSStephen Hemminger pdump_sum_stats(uint16_t port, uint16_t nq,
71210f726efSStephen Hemminger 		struct rte_pdump_stats stats[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
71310f726efSStephen Hemminger 		struct rte_pdump_stats *total)
71410f726efSStephen Hemminger {
71510f726efSStephen Hemminger 	uint64_t *sum = (uint64_t *)total;
71610f726efSStephen Hemminger 	unsigned int i;
71710f726efSStephen Hemminger 	uint64_t val;
71810f726efSStephen Hemminger 	uint16_t qid;
71910f726efSStephen Hemminger 
72010f726efSStephen Hemminger 	for (qid = 0; qid < nq; qid++) {
721938c55cbSTyler Retzlaff 		const RTE_ATOMIC(uint64_t) *perq = (const uint64_t __rte_atomic *)&stats[port][qid];
72210f726efSStephen Hemminger 
72310f726efSStephen Hemminger 		for (i = 0; i < sizeof(*total) / sizeof(uint64_t); i++) {
724938c55cbSTyler Retzlaff 			val = rte_atomic_load_explicit(&perq[i], rte_memory_order_relaxed);
72510f726efSStephen Hemminger 			sum[i] += val;
72610f726efSStephen Hemminger 		}
72710f726efSStephen Hemminger 	}
72810f726efSStephen Hemminger }
72910f726efSStephen Hemminger 
73010f726efSStephen Hemminger int
rte_pdump_stats(uint16_t port,struct rte_pdump_stats * stats)73110f726efSStephen Hemminger rte_pdump_stats(uint16_t port, struct rte_pdump_stats *stats)
73210f726efSStephen Hemminger {
73310f726efSStephen Hemminger 	struct rte_eth_dev_info dev_info;
73410f726efSStephen Hemminger 	const struct rte_memzone *mz;
73510f726efSStephen Hemminger 	int ret;
73610f726efSStephen Hemminger 
73710f726efSStephen Hemminger 	memset(stats, 0, sizeof(*stats));
73810f726efSStephen Hemminger 	ret = rte_eth_dev_info_get(port, &dev_info);
73910f726efSStephen Hemminger 	if (ret != 0) {
7400e21c7c0SDavid Marchand 		PDUMP_LOG_LINE(ERR,
7410e21c7c0SDavid Marchand 			  "Error during getting device (port %u) info: %s",
74210f726efSStephen Hemminger 			  port, strerror(-ret));
74310f726efSStephen Hemminger 		return ret;
74410f726efSStephen Hemminger 	}
74510f726efSStephen Hemminger 
74610f726efSStephen Hemminger 	if (pdump_stats == NULL) {
74710f726efSStephen Hemminger 		if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
74810f726efSStephen Hemminger 			/* rte_pdump_init was not called */
7490e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR, "pdump stats not initialized");
75010f726efSStephen Hemminger 			rte_errno = EINVAL;
75110f726efSStephen Hemminger 			return -1;
75210f726efSStephen Hemminger 		}
75310f726efSStephen Hemminger 
75410f726efSStephen Hemminger 		/* secondary process looks up the memzone */
75510f726efSStephen Hemminger 		mz = rte_memzone_lookup(MZ_RTE_PDUMP_STATS);
75610f726efSStephen Hemminger 		if (mz == NULL) {
75710f726efSStephen Hemminger 			/* rte_pdump_init was not called in primary process?? */
7580e21c7c0SDavid Marchand 			PDUMP_LOG_LINE(ERR, "can not find pdump stats");
75910f726efSStephen Hemminger 			rte_errno = EINVAL;
76010f726efSStephen Hemminger 			return -1;
76110f726efSStephen Hemminger 		}
76210f726efSStephen Hemminger 		pdump_stats = mz->addr;
76310f726efSStephen Hemminger 	}
76410f726efSStephen Hemminger 
76510f726efSStephen Hemminger 	pdump_sum_stats(port, dev_info.nb_rx_queues, pdump_stats->rx, stats);
76610f726efSStephen Hemminger 	pdump_sum_stats(port, dev_info.nb_tx_queues, pdump_stats->tx, stats);
76710f726efSStephen Hemminger 	return 0;
76810f726efSStephen Hemminger }
769