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); 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson /* Macro for printing using RTE_LOG */ 2199a2dd95SBruce Richardson #define PDUMP_LOG(level, fmt, args...) \ 2299a2dd95SBruce Richardson rte_log(RTE_LOG_ ## level, pdump_logtype, "%s(): " fmt, \ 2399a2dd95SBruce Richardson __func__, ## args) 2499a2dd95SBruce Richardson 2599a2dd95SBruce Richardson /* Used for the multi-process communication */ 2699a2dd95SBruce Richardson #define PDUMP_MP "mp_pdump" 2799a2dd95SBruce Richardson 2899a2dd95SBruce Richardson enum pdump_operation { 2999a2dd95SBruce Richardson DISABLE = 1, 3099a2dd95SBruce Richardson ENABLE = 2 3199a2dd95SBruce Richardson }; 3299a2dd95SBruce Richardson 3310f726efSStephen Hemminger /* Internal version number in request */ 3499a2dd95SBruce Richardson enum pdump_version { 3510f726efSStephen Hemminger V1 = 1, /* no filtering or snap */ 3610f726efSStephen Hemminger V2 = 2, 3799a2dd95SBruce Richardson }; 3899a2dd95SBruce Richardson 3999a2dd95SBruce Richardson struct pdump_request { 4099a2dd95SBruce Richardson uint16_t ver; 4199a2dd95SBruce Richardson uint16_t op; 4299a2dd95SBruce Richardson uint32_t flags; 4399a2dd95SBruce Richardson char device[RTE_DEV_NAME_MAX_LEN]; 4499a2dd95SBruce Richardson uint16_t queue; 4599a2dd95SBruce Richardson struct rte_ring *ring; 4699a2dd95SBruce Richardson struct rte_mempool *mp; 4710f726efSStephen Hemminger 4810f726efSStephen Hemminger const struct rte_bpf_prm *prm; 4910f726efSStephen Hemminger uint32_t snaplen; 5099a2dd95SBruce Richardson }; 5199a2dd95SBruce Richardson 5299a2dd95SBruce Richardson struct pdump_response { 5399a2dd95SBruce Richardson uint16_t ver; 5499a2dd95SBruce Richardson uint16_t res_op; 5599a2dd95SBruce Richardson int32_t err_value; 5699a2dd95SBruce Richardson }; 5799a2dd95SBruce Richardson 5899a2dd95SBruce Richardson static struct pdump_rxtx_cbs { 5999a2dd95SBruce Richardson struct rte_ring *ring; 6099a2dd95SBruce Richardson struct rte_mempool *mp; 6199a2dd95SBruce Richardson const struct rte_eth_rxtx_callback *cb; 6210f726efSStephen Hemminger const struct rte_bpf *filter; 6310f726efSStephen Hemminger enum pdump_version ver; 6410f726efSStephen Hemminger uint32_t snaplen; 6599a2dd95SBruce Richardson } rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT], 6699a2dd95SBruce Richardson tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; 6799a2dd95SBruce Richardson 6899a2dd95SBruce Richardson 6910f726efSStephen Hemminger /* 7010f726efSStephen Hemminger * The packet capture statistics keep track of packets 7110f726efSStephen Hemminger * accepted, filtered and dropped. These are per-queue 7210f726efSStephen Hemminger * and in memory between primary and secondary processes. 7310f726efSStephen Hemminger */ 7410f726efSStephen Hemminger static const char MZ_RTE_PDUMP_STATS[] = "rte_pdump_stats"; 7510f726efSStephen Hemminger static struct { 7610f726efSStephen Hemminger struct rte_pdump_stats rx[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; 7710f726efSStephen Hemminger struct rte_pdump_stats tx[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; 7853caecb8SKonstantin Ananyev const struct rte_memzone *mz; 7910f726efSStephen Hemminger } *pdump_stats; 8010f726efSStephen Hemminger 8110f726efSStephen Hemminger /* Create a clone of mbuf to be placed into ring. */ 8210f726efSStephen Hemminger static void 8310f726efSStephen Hemminger pdump_copy(uint16_t port_id, uint16_t queue, 8410f726efSStephen Hemminger enum rte_pcapng_direction direction, 8510f726efSStephen Hemminger struct rte_mbuf **pkts, uint16_t nb_pkts, 8610f726efSStephen Hemminger const struct pdump_rxtx_cbs *cbs, 8710f726efSStephen Hemminger struct rte_pdump_stats *stats) 8899a2dd95SBruce Richardson { 8999a2dd95SBruce Richardson unsigned int i; 9099a2dd95SBruce Richardson int ring_enq; 9199a2dd95SBruce Richardson uint16_t d_pkts = 0; 9299a2dd95SBruce Richardson struct rte_mbuf *dup_bufs[nb_pkts]; 9310f726efSStephen Hemminger uint64_t ts; 9499a2dd95SBruce Richardson struct rte_ring *ring; 9599a2dd95SBruce Richardson struct rte_mempool *mp; 9699a2dd95SBruce Richardson struct rte_mbuf *p; 9710f726efSStephen Hemminger uint64_t rcs[nb_pkts]; 9899a2dd95SBruce Richardson 9910f726efSStephen Hemminger if (cbs->filter) 10010f726efSStephen Hemminger rte_bpf_exec_burst(cbs->filter, (void **)pkts, rcs, nb_pkts); 10110f726efSStephen Hemminger 10210f726efSStephen Hemminger ts = rte_get_tsc_cycles(); 10399a2dd95SBruce Richardson ring = cbs->ring; 10499a2dd95SBruce Richardson mp = cbs->mp; 10599a2dd95SBruce Richardson for (i = 0; i < nb_pkts; i++) { 10610f726efSStephen Hemminger /* 10710f726efSStephen Hemminger * This uses same BPF return value convention as socket filter 10810f726efSStephen Hemminger * and pcap_offline_filter. 10910f726efSStephen Hemminger * if program returns zero 11010f726efSStephen Hemminger * then packet doesn't match the filter (will be ignored). 11110f726efSStephen Hemminger */ 11210f726efSStephen Hemminger if (cbs->filter && rcs[i] == 0) { 113*938c55cbSTyler Retzlaff rte_atomic_fetch_add_explicit(&stats->filtered, 114*938c55cbSTyler Retzlaff 1, rte_memory_order_relaxed); 11510f726efSStephen Hemminger continue; 11610f726efSStephen Hemminger } 11710f726efSStephen Hemminger 11810f726efSStephen Hemminger /* 11910f726efSStephen Hemminger * If using pcapng then want to wrap packets 12010f726efSStephen Hemminger * otherwise a simple copy. 12110f726efSStephen Hemminger */ 12210f726efSStephen Hemminger if (cbs->ver == V2) 12310f726efSStephen Hemminger p = rte_pcapng_copy(port_id, queue, 12410f726efSStephen Hemminger pkts[i], mp, cbs->snaplen, 125c1abd1e9SAmit Prakash Shukla ts, direction, NULL); 12610f726efSStephen Hemminger else 12710f726efSStephen Hemminger p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen); 12810f726efSStephen Hemminger 12910f726efSStephen Hemminger if (unlikely(p == NULL)) 130*938c55cbSTyler Retzlaff rte_atomic_fetch_add_explicit(&stats->nombuf, 1, rte_memory_order_relaxed); 13110f726efSStephen Hemminger else 13299a2dd95SBruce Richardson dup_bufs[d_pkts++] = p; 13399a2dd95SBruce Richardson } 13499a2dd95SBruce Richardson 135*938c55cbSTyler Retzlaff rte_atomic_fetch_add_explicit(&stats->accepted, d_pkts, rte_memory_order_relaxed); 13610f726efSStephen Hemminger 137b1824666SJoyce Kong ring_enq = rte_ring_enqueue_burst(ring, (void *)&dup_bufs[0], d_pkts, NULL); 13899a2dd95SBruce Richardson if (unlikely(ring_enq < d_pkts)) { 13999a2dd95SBruce Richardson unsigned int drops = d_pkts - ring_enq; 14099a2dd95SBruce Richardson 141*938c55cbSTyler Retzlaff rte_atomic_fetch_add_explicit(&stats->ringfull, drops, rte_memory_order_relaxed); 14299a2dd95SBruce Richardson rte_pktmbuf_free_bulk(&dup_bufs[ring_enq], drops); 14399a2dd95SBruce Richardson } 14499a2dd95SBruce Richardson } 14599a2dd95SBruce Richardson 14699a2dd95SBruce Richardson static uint16_t 14710f726efSStephen Hemminger pdump_rx(uint16_t port, uint16_t queue, 14899a2dd95SBruce Richardson struct rte_mbuf **pkts, uint16_t nb_pkts, 14910f726efSStephen Hemminger uint16_t max_pkts __rte_unused, void *user_params) 15099a2dd95SBruce Richardson { 15110f726efSStephen Hemminger const struct pdump_rxtx_cbs *cbs = user_params; 15210f726efSStephen Hemminger struct rte_pdump_stats *stats = &pdump_stats->rx[port][queue]; 15310f726efSStephen Hemminger 15410f726efSStephen Hemminger pdump_copy(port, queue, RTE_PCAPNG_DIRECTION_IN, 15510f726efSStephen Hemminger pkts, nb_pkts, cbs, stats); 15699a2dd95SBruce Richardson return nb_pkts; 15799a2dd95SBruce Richardson } 15899a2dd95SBruce Richardson 15999a2dd95SBruce Richardson static uint16_t 16010f726efSStephen Hemminger pdump_tx(uint16_t port, uint16_t queue, 16199a2dd95SBruce Richardson struct rte_mbuf **pkts, uint16_t nb_pkts, void *user_params) 16299a2dd95SBruce Richardson { 16310f726efSStephen Hemminger const struct pdump_rxtx_cbs *cbs = user_params; 16410f726efSStephen Hemminger struct rte_pdump_stats *stats = &pdump_stats->tx[port][queue]; 16510f726efSStephen Hemminger 16610f726efSStephen Hemminger pdump_copy(port, queue, RTE_PCAPNG_DIRECTION_OUT, 16710f726efSStephen Hemminger pkts, nb_pkts, cbs, stats); 16899a2dd95SBruce Richardson return nb_pkts; 16999a2dd95SBruce Richardson } 17099a2dd95SBruce Richardson 17199a2dd95SBruce Richardson static int 17210f726efSStephen Hemminger pdump_register_rx_callbacks(enum pdump_version ver, 17310f726efSStephen Hemminger uint16_t end_q, uint16_t port, uint16_t queue, 17499a2dd95SBruce Richardson struct rte_ring *ring, struct rte_mempool *mp, 17510f726efSStephen Hemminger struct rte_bpf *filter, 17610f726efSStephen Hemminger uint16_t operation, uint32_t snaplen) 17799a2dd95SBruce Richardson { 17899a2dd95SBruce Richardson uint16_t qid; 17999a2dd95SBruce Richardson 18099a2dd95SBruce Richardson qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue; 18199a2dd95SBruce Richardson for (; qid < end_q; qid++) { 18210f726efSStephen Hemminger struct pdump_rxtx_cbs *cbs = &rx_cbs[port][qid]; 18310f726efSStephen Hemminger 18410f726efSStephen Hemminger if (operation == ENABLE) { 18599a2dd95SBruce Richardson if (cbs->cb) { 18699a2dd95SBruce Richardson PDUMP_LOG(ERR, 18799a2dd95SBruce Richardson "rx callback for port=%d queue=%d, already exists\n", 18899a2dd95SBruce Richardson port, qid); 18999a2dd95SBruce Richardson return -EEXIST; 19099a2dd95SBruce Richardson } 19110f726efSStephen Hemminger cbs->ver = ver; 19299a2dd95SBruce Richardson cbs->ring = ring; 19399a2dd95SBruce Richardson cbs->mp = mp; 19410f726efSStephen Hemminger cbs->snaplen = snaplen; 19510f726efSStephen Hemminger cbs->filter = filter; 19610f726efSStephen Hemminger 19799a2dd95SBruce Richardson cbs->cb = rte_eth_add_first_rx_callback(port, qid, 19899a2dd95SBruce Richardson pdump_rx, cbs); 19999a2dd95SBruce Richardson if (cbs->cb == NULL) { 20099a2dd95SBruce Richardson PDUMP_LOG(ERR, 20199a2dd95SBruce Richardson "failed to add rx callback, errno=%d\n", 20299a2dd95SBruce Richardson rte_errno); 20399a2dd95SBruce Richardson return rte_errno; 20499a2dd95SBruce Richardson } 20510f726efSStephen Hemminger } else if (operation == DISABLE) { 20699a2dd95SBruce Richardson int ret; 20799a2dd95SBruce Richardson 20899a2dd95SBruce Richardson if (cbs->cb == NULL) { 20999a2dd95SBruce Richardson PDUMP_LOG(ERR, 21099a2dd95SBruce Richardson "no existing rx callback for port=%d queue=%d\n", 21199a2dd95SBruce Richardson port, qid); 21299a2dd95SBruce Richardson return -EINVAL; 21399a2dd95SBruce Richardson } 21499a2dd95SBruce Richardson ret = rte_eth_remove_rx_callback(port, qid, cbs->cb); 21599a2dd95SBruce Richardson if (ret < 0) { 21699a2dd95SBruce Richardson PDUMP_LOG(ERR, 21799a2dd95SBruce Richardson "failed to remove rx callback, errno=%d\n", 21899a2dd95SBruce Richardson -ret); 21999a2dd95SBruce Richardson return ret; 22099a2dd95SBruce Richardson } 22199a2dd95SBruce Richardson cbs->cb = NULL; 22299a2dd95SBruce Richardson } 22399a2dd95SBruce Richardson } 22499a2dd95SBruce Richardson 22599a2dd95SBruce Richardson return 0; 22699a2dd95SBruce Richardson } 22799a2dd95SBruce Richardson 22899a2dd95SBruce Richardson static int 22910f726efSStephen Hemminger pdump_register_tx_callbacks(enum pdump_version ver, 23010f726efSStephen Hemminger uint16_t end_q, uint16_t port, uint16_t queue, 23199a2dd95SBruce Richardson struct rte_ring *ring, struct rte_mempool *mp, 23210f726efSStephen Hemminger struct rte_bpf *filter, 23310f726efSStephen Hemminger uint16_t operation, uint32_t snaplen) 23499a2dd95SBruce Richardson { 23599a2dd95SBruce Richardson 23699a2dd95SBruce Richardson uint16_t qid; 23799a2dd95SBruce Richardson 23899a2dd95SBruce Richardson qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue; 23999a2dd95SBruce Richardson for (; qid < end_q; qid++) { 24010f726efSStephen Hemminger struct pdump_rxtx_cbs *cbs = &tx_cbs[port][qid]; 24110f726efSStephen Hemminger 24210f726efSStephen Hemminger if (operation == ENABLE) { 24399a2dd95SBruce Richardson if (cbs->cb) { 24499a2dd95SBruce Richardson PDUMP_LOG(ERR, 24599a2dd95SBruce Richardson "tx callback for port=%d queue=%d, already exists\n", 24699a2dd95SBruce Richardson port, qid); 24799a2dd95SBruce Richardson return -EEXIST; 24899a2dd95SBruce Richardson } 24910f726efSStephen Hemminger cbs->ver = ver; 25099a2dd95SBruce Richardson cbs->ring = ring; 25199a2dd95SBruce Richardson cbs->mp = mp; 25210f726efSStephen Hemminger cbs->snaplen = snaplen; 25310f726efSStephen Hemminger cbs->filter = filter; 25410f726efSStephen Hemminger 25599a2dd95SBruce Richardson cbs->cb = rte_eth_add_tx_callback(port, qid, pdump_tx, 25699a2dd95SBruce Richardson cbs); 25799a2dd95SBruce Richardson if (cbs->cb == NULL) { 25899a2dd95SBruce Richardson PDUMP_LOG(ERR, 25999a2dd95SBruce Richardson "failed to add tx callback, errno=%d\n", 26099a2dd95SBruce Richardson rte_errno); 26199a2dd95SBruce Richardson return rte_errno; 26299a2dd95SBruce Richardson } 26310f726efSStephen Hemminger } else if (operation == DISABLE) { 26499a2dd95SBruce Richardson int ret; 26599a2dd95SBruce Richardson 26699a2dd95SBruce Richardson if (cbs->cb == NULL) { 26799a2dd95SBruce Richardson PDUMP_LOG(ERR, 26899a2dd95SBruce Richardson "no existing tx callback for port=%d queue=%d\n", 26999a2dd95SBruce Richardson port, qid); 27099a2dd95SBruce Richardson return -EINVAL; 27199a2dd95SBruce Richardson } 27299a2dd95SBruce Richardson ret = rte_eth_remove_tx_callback(port, qid, cbs->cb); 27399a2dd95SBruce Richardson if (ret < 0) { 27499a2dd95SBruce Richardson PDUMP_LOG(ERR, 27599a2dd95SBruce Richardson "failed to remove tx callback, errno=%d\n", 27699a2dd95SBruce Richardson -ret); 27799a2dd95SBruce Richardson return ret; 27899a2dd95SBruce Richardson } 27999a2dd95SBruce Richardson cbs->cb = NULL; 28099a2dd95SBruce Richardson } 28199a2dd95SBruce Richardson } 28299a2dd95SBruce Richardson 28399a2dd95SBruce Richardson return 0; 28499a2dd95SBruce Richardson } 28599a2dd95SBruce Richardson 28699a2dd95SBruce Richardson static int 28799a2dd95SBruce Richardson set_pdump_rxtx_cbs(const struct pdump_request *p) 28899a2dd95SBruce Richardson { 28999a2dd95SBruce Richardson uint16_t nb_rx_q = 0, nb_tx_q = 0, end_q, queue; 29099a2dd95SBruce Richardson uint16_t port; 29199a2dd95SBruce Richardson int ret = 0; 29210f726efSStephen Hemminger struct rte_bpf *filter = NULL; 29399a2dd95SBruce Richardson uint32_t flags; 29499a2dd95SBruce Richardson uint16_t operation; 29599a2dd95SBruce Richardson struct rte_ring *ring; 29699a2dd95SBruce Richardson struct rte_mempool *mp; 29799a2dd95SBruce Richardson 29810f726efSStephen Hemminger /* Check for possible DPDK version mismatch */ 29910f726efSStephen Hemminger if (!(p->ver == V1 || p->ver == V2)) { 30010f726efSStephen Hemminger PDUMP_LOG(ERR, 30110f726efSStephen Hemminger "incorrect client version %u\n", p->ver); 30210f726efSStephen Hemminger return -EINVAL; 30310f726efSStephen Hemminger } 30410f726efSStephen Hemminger 30510f726efSStephen Hemminger if (p->prm) { 30610f726efSStephen Hemminger if (p->prm->prog_arg.type != RTE_BPF_ARG_PTR_MBUF) { 30710f726efSStephen Hemminger PDUMP_LOG(ERR, 30810f726efSStephen Hemminger "invalid BPF program type: %u\n", 30910f726efSStephen Hemminger p->prm->prog_arg.type); 31010f726efSStephen Hemminger return -EINVAL; 31110f726efSStephen Hemminger } 31210f726efSStephen Hemminger 31310f726efSStephen Hemminger filter = rte_bpf_load(p->prm); 31410f726efSStephen Hemminger if (filter == NULL) { 31510f726efSStephen Hemminger PDUMP_LOG(ERR, "cannot load BPF filter: %s\n", 31610f726efSStephen Hemminger rte_strerror(rte_errno)); 31710f726efSStephen Hemminger return -rte_errno; 31810f726efSStephen Hemminger } 31910f726efSStephen Hemminger } 32010f726efSStephen Hemminger 32199a2dd95SBruce Richardson flags = p->flags; 32299a2dd95SBruce Richardson operation = p->op; 32310f726efSStephen Hemminger queue = p->queue; 32410f726efSStephen Hemminger ring = p->ring; 32510f726efSStephen Hemminger mp = p->mp; 32610f726efSStephen Hemminger 32710f726efSStephen Hemminger ret = rte_eth_dev_get_port_by_name(p->device, &port); 32899a2dd95SBruce Richardson if (ret < 0) { 32999a2dd95SBruce Richardson PDUMP_LOG(ERR, 33099a2dd95SBruce Richardson "failed to get port id for device id=%s\n", 33110f726efSStephen Hemminger p->device); 33299a2dd95SBruce Richardson return -EINVAL; 33399a2dd95SBruce Richardson } 33499a2dd95SBruce Richardson 33599a2dd95SBruce Richardson /* validation if packet capture is for all queues */ 33699a2dd95SBruce Richardson if (queue == RTE_PDUMP_ALL_QUEUES) { 33799a2dd95SBruce Richardson struct rte_eth_dev_info dev_info; 33899a2dd95SBruce Richardson 33999a2dd95SBruce Richardson ret = rte_eth_dev_info_get(port, &dev_info); 34099a2dd95SBruce Richardson if (ret != 0) { 34199a2dd95SBruce Richardson PDUMP_LOG(ERR, 34299a2dd95SBruce Richardson "Error during getting device (port %u) info: %s\n", 34399a2dd95SBruce Richardson port, strerror(-ret)); 34499a2dd95SBruce Richardson return ret; 34599a2dd95SBruce Richardson } 34699a2dd95SBruce Richardson 34799a2dd95SBruce Richardson nb_rx_q = dev_info.nb_rx_queues; 34899a2dd95SBruce Richardson nb_tx_q = dev_info.nb_tx_queues; 34999a2dd95SBruce Richardson if (nb_rx_q == 0 && flags & RTE_PDUMP_FLAG_RX) { 35099a2dd95SBruce Richardson PDUMP_LOG(ERR, 35199a2dd95SBruce Richardson "number of rx queues cannot be 0\n"); 35299a2dd95SBruce Richardson return -EINVAL; 35399a2dd95SBruce Richardson } 35499a2dd95SBruce Richardson if (nb_tx_q == 0 && flags & RTE_PDUMP_FLAG_TX) { 35599a2dd95SBruce Richardson PDUMP_LOG(ERR, 35699a2dd95SBruce Richardson "number of tx queues cannot be 0\n"); 35799a2dd95SBruce Richardson return -EINVAL; 35899a2dd95SBruce Richardson } 35999a2dd95SBruce Richardson if ((nb_tx_q == 0 || nb_rx_q == 0) && 36099a2dd95SBruce Richardson flags == RTE_PDUMP_FLAG_RXTX) { 36199a2dd95SBruce Richardson PDUMP_LOG(ERR, 36299a2dd95SBruce Richardson "both tx&rx queues must be non zero\n"); 36399a2dd95SBruce Richardson return -EINVAL; 36499a2dd95SBruce Richardson } 36599a2dd95SBruce Richardson } 36699a2dd95SBruce Richardson 36799a2dd95SBruce Richardson /* register RX callback */ 36899a2dd95SBruce Richardson if (flags & RTE_PDUMP_FLAG_RX) { 36999a2dd95SBruce Richardson end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_rx_q : queue + 1; 37010f726efSStephen Hemminger ret = pdump_register_rx_callbacks(p->ver, end_q, port, queue, 37110f726efSStephen Hemminger ring, mp, filter, 37210f726efSStephen Hemminger operation, p->snaplen); 37399a2dd95SBruce Richardson if (ret < 0) 37499a2dd95SBruce Richardson return ret; 37599a2dd95SBruce Richardson } 37699a2dd95SBruce Richardson 37799a2dd95SBruce Richardson /* register TX callback */ 37899a2dd95SBruce Richardson if (flags & RTE_PDUMP_FLAG_TX) { 37999a2dd95SBruce Richardson end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_tx_q : queue + 1; 38010f726efSStephen Hemminger ret = pdump_register_tx_callbacks(p->ver, end_q, port, queue, 38110f726efSStephen Hemminger ring, mp, filter, 38210f726efSStephen Hemminger operation, p->snaplen); 38399a2dd95SBruce Richardson if (ret < 0) 38499a2dd95SBruce Richardson return ret; 38599a2dd95SBruce Richardson } 38699a2dd95SBruce Richardson 38799a2dd95SBruce Richardson return ret; 38899a2dd95SBruce Richardson } 38999a2dd95SBruce Richardson 39099a2dd95SBruce Richardson static int 39199a2dd95SBruce Richardson pdump_server(const struct rte_mp_msg *mp_msg, const void *peer) 39299a2dd95SBruce Richardson { 39399a2dd95SBruce Richardson struct rte_mp_msg mp_resp; 39499a2dd95SBruce Richardson const struct pdump_request *cli_req; 39599a2dd95SBruce Richardson struct pdump_response *resp = (struct pdump_response *)&mp_resp.param; 39699a2dd95SBruce Richardson 39799a2dd95SBruce Richardson /* recv client requests */ 39899a2dd95SBruce Richardson if (mp_msg->len_param != sizeof(*cli_req)) { 39999a2dd95SBruce Richardson PDUMP_LOG(ERR, "failed to recv from client\n"); 40099a2dd95SBruce Richardson resp->err_value = -EINVAL; 40199a2dd95SBruce Richardson } else { 40299a2dd95SBruce Richardson cli_req = (const struct pdump_request *)mp_msg->param; 40399a2dd95SBruce Richardson resp->ver = cli_req->ver; 40499a2dd95SBruce Richardson resp->res_op = cli_req->op; 40599a2dd95SBruce Richardson resp->err_value = set_pdump_rxtx_cbs(cli_req); 40699a2dd95SBruce Richardson } 40799a2dd95SBruce Richardson 40810f726efSStephen Hemminger rte_strscpy(mp_resp.name, PDUMP_MP, RTE_MP_MAX_NAME_LEN); 40999a2dd95SBruce Richardson mp_resp.len_param = sizeof(*resp); 41099a2dd95SBruce Richardson mp_resp.num_fds = 0; 41199a2dd95SBruce Richardson if (rte_mp_reply(&mp_resp, peer) < 0) { 41299a2dd95SBruce Richardson PDUMP_LOG(ERR, "failed to send to client:%s\n", 41399a2dd95SBruce Richardson strerror(rte_errno)); 41499a2dd95SBruce Richardson return -1; 41599a2dd95SBruce Richardson } 41699a2dd95SBruce Richardson 41799a2dd95SBruce Richardson return 0; 41899a2dd95SBruce Richardson } 41999a2dd95SBruce Richardson 42099a2dd95SBruce Richardson int 42199a2dd95SBruce Richardson rte_pdump_init(void) 42299a2dd95SBruce Richardson { 42310f726efSStephen Hemminger const struct rte_memzone *mz; 42499a2dd95SBruce Richardson int ret; 42599a2dd95SBruce Richardson 42610f726efSStephen Hemminger mz = rte_memzone_reserve(MZ_RTE_PDUMP_STATS, sizeof(*pdump_stats), 42710f726efSStephen Hemminger rte_socket_id(), 0); 42810f726efSStephen Hemminger if (mz == NULL) { 42910f726efSStephen Hemminger PDUMP_LOG(ERR, "cannot allocate pdump statistics\n"); 43010f726efSStephen Hemminger rte_errno = ENOMEM; 43110f726efSStephen Hemminger return -1; 43210f726efSStephen Hemminger } 43310f726efSStephen Hemminger pdump_stats = mz->addr; 43453caecb8SKonstantin Ananyev pdump_stats->mz = mz; 43510f726efSStephen Hemminger 43699a2dd95SBruce Richardson ret = rte_mp_action_register(PDUMP_MP, pdump_server); 43799a2dd95SBruce Richardson if (ret && rte_errno != ENOTSUP) 43899a2dd95SBruce Richardson return -1; 43999a2dd95SBruce Richardson return 0; 44099a2dd95SBruce Richardson } 44199a2dd95SBruce Richardson 44299a2dd95SBruce Richardson int 44399a2dd95SBruce Richardson rte_pdump_uninit(void) 44499a2dd95SBruce Richardson { 44599a2dd95SBruce Richardson rte_mp_action_unregister(PDUMP_MP); 44699a2dd95SBruce Richardson 44753caecb8SKonstantin Ananyev if (pdump_stats != NULL) { 44853caecb8SKonstantin Ananyev rte_memzone_free(pdump_stats->mz); 44953caecb8SKonstantin Ananyev pdump_stats = NULL; 45053caecb8SKonstantin Ananyev } 45153caecb8SKonstantin Ananyev 45299a2dd95SBruce Richardson return 0; 45399a2dd95SBruce Richardson } 45499a2dd95SBruce Richardson 45599a2dd95SBruce Richardson static int 45699a2dd95SBruce Richardson pdump_validate_ring_mp(struct rte_ring *ring, struct rte_mempool *mp) 45799a2dd95SBruce Richardson { 45899a2dd95SBruce Richardson if (ring == NULL || mp == NULL) { 45999a2dd95SBruce Richardson PDUMP_LOG(ERR, "NULL ring or mempool\n"); 46099a2dd95SBruce Richardson rte_errno = EINVAL; 46199a2dd95SBruce Richardson return -1; 46299a2dd95SBruce Richardson } 463c47d7b90SAndrew Rybchenko if (mp->flags & RTE_MEMPOOL_F_SP_PUT || 464c47d7b90SAndrew Rybchenko mp->flags & RTE_MEMPOOL_F_SC_GET) { 46599a2dd95SBruce Richardson PDUMP_LOG(ERR, 46699a2dd95SBruce Richardson "mempool with SP or SC set not valid for pdump," 46799a2dd95SBruce Richardson "must have MP and MC set\n"); 46899a2dd95SBruce Richardson rte_errno = EINVAL; 46999a2dd95SBruce Richardson return -1; 47099a2dd95SBruce Richardson } 47199a2dd95SBruce Richardson if (rte_ring_is_prod_single(ring) || rte_ring_is_cons_single(ring)) { 47299a2dd95SBruce Richardson PDUMP_LOG(ERR, 47399a2dd95SBruce Richardson "ring with SP or SC set is not valid for pdump," 47499a2dd95SBruce Richardson "must have MP and MC set\n"); 47599a2dd95SBruce Richardson rte_errno = EINVAL; 47699a2dd95SBruce Richardson return -1; 47799a2dd95SBruce Richardson } 47899a2dd95SBruce Richardson 47999a2dd95SBruce Richardson return 0; 48099a2dd95SBruce Richardson } 48199a2dd95SBruce Richardson 48299a2dd95SBruce Richardson static int 48399a2dd95SBruce Richardson pdump_validate_flags(uint32_t flags) 48499a2dd95SBruce Richardson { 48510f726efSStephen Hemminger if ((flags & RTE_PDUMP_FLAG_RXTX) == 0) { 48699a2dd95SBruce Richardson PDUMP_LOG(ERR, 48799a2dd95SBruce Richardson "invalid flags, should be either rx/tx/rxtx\n"); 48899a2dd95SBruce Richardson rte_errno = EINVAL; 48999a2dd95SBruce Richardson return -1; 49099a2dd95SBruce Richardson } 49199a2dd95SBruce Richardson 49210f726efSStephen Hemminger /* mask off the flags we know about */ 49310f726efSStephen Hemminger if (flags & ~(RTE_PDUMP_FLAG_RXTX | RTE_PDUMP_FLAG_PCAPNG)) { 49410f726efSStephen Hemminger PDUMP_LOG(ERR, 49510f726efSStephen Hemminger "unknown flags: %#x\n", flags); 49610f726efSStephen Hemminger rte_errno = ENOTSUP; 49710f726efSStephen Hemminger return -1; 49810f726efSStephen Hemminger } 49910f726efSStephen Hemminger 50099a2dd95SBruce Richardson return 0; 50199a2dd95SBruce Richardson } 50299a2dd95SBruce Richardson 50399a2dd95SBruce Richardson static int 50499a2dd95SBruce Richardson pdump_validate_port(uint16_t port, char *name) 50599a2dd95SBruce Richardson { 50699a2dd95SBruce Richardson int ret = 0; 50799a2dd95SBruce Richardson 50899a2dd95SBruce Richardson if (port >= RTE_MAX_ETHPORTS) { 50999a2dd95SBruce Richardson PDUMP_LOG(ERR, "Invalid port id %u\n", port); 51099a2dd95SBruce Richardson rte_errno = EINVAL; 51199a2dd95SBruce Richardson return -1; 51299a2dd95SBruce Richardson } 51399a2dd95SBruce Richardson 51499a2dd95SBruce Richardson ret = rte_eth_dev_get_name_by_port(port, name); 51599a2dd95SBruce Richardson if (ret < 0) { 51699a2dd95SBruce Richardson PDUMP_LOG(ERR, "port %u to name mapping failed\n", 51799a2dd95SBruce Richardson port); 51899a2dd95SBruce Richardson rte_errno = EINVAL; 51999a2dd95SBruce Richardson return -1; 52099a2dd95SBruce Richardson } 52199a2dd95SBruce Richardson 52299a2dd95SBruce Richardson return 0; 52399a2dd95SBruce Richardson } 52499a2dd95SBruce Richardson 52599a2dd95SBruce Richardson static int 52610f726efSStephen Hemminger pdump_prepare_client_request(const char *device, uint16_t queue, 52710f726efSStephen Hemminger uint32_t flags, uint32_t snaplen, 52899a2dd95SBruce Richardson uint16_t operation, 52999a2dd95SBruce Richardson struct rte_ring *ring, 53099a2dd95SBruce Richardson struct rte_mempool *mp, 53110f726efSStephen Hemminger const struct rte_bpf_prm *prm) 53299a2dd95SBruce Richardson { 53399a2dd95SBruce Richardson int ret = -1; 53499a2dd95SBruce Richardson struct rte_mp_msg mp_req, *mp_rep; 53599a2dd95SBruce Richardson struct rte_mp_reply mp_reply; 53699a2dd95SBruce Richardson struct timespec ts = {.tv_sec = 5, .tv_nsec = 0}; 53799a2dd95SBruce Richardson struct pdump_request *req = (struct pdump_request *)mp_req.param; 53899a2dd95SBruce Richardson struct pdump_response *resp; 53999a2dd95SBruce Richardson 5408a0cf0c4SStephen Hemminger if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 5418a0cf0c4SStephen Hemminger PDUMP_LOG(ERR, 5428a0cf0c4SStephen Hemminger "pdump enable/disable not allowed in primary process\n"); 5438a0cf0c4SStephen Hemminger return -EINVAL; 5448a0cf0c4SStephen Hemminger } 5458a0cf0c4SStephen Hemminger 54610f726efSStephen Hemminger memset(req, 0, sizeof(*req)); 54710f726efSStephen Hemminger 54810f726efSStephen Hemminger req->ver = (flags & RTE_PDUMP_FLAG_PCAPNG) ? V2 : V1; 54910f726efSStephen Hemminger req->flags = flags & RTE_PDUMP_FLAG_RXTX; 55099a2dd95SBruce Richardson req->op = operation; 55110f726efSStephen Hemminger req->queue = queue; 55210f726efSStephen Hemminger rte_strscpy(req->device, device, sizeof(req->device)); 55310f726efSStephen Hemminger 55499a2dd95SBruce Richardson if ((operation & ENABLE) != 0) { 55510f726efSStephen Hemminger req->ring = ring; 55610f726efSStephen Hemminger req->mp = mp; 55710f726efSStephen Hemminger req->prm = prm; 55810f726efSStephen Hemminger req->snaplen = snaplen; 55999a2dd95SBruce Richardson } 56099a2dd95SBruce Richardson 56110f726efSStephen Hemminger rte_strscpy(mp_req.name, PDUMP_MP, RTE_MP_MAX_NAME_LEN); 56299a2dd95SBruce Richardson mp_req.len_param = sizeof(*req); 56399a2dd95SBruce Richardson mp_req.num_fds = 0; 56499a2dd95SBruce Richardson if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0) { 56599a2dd95SBruce Richardson mp_rep = &mp_reply.msgs[0]; 56699a2dd95SBruce Richardson resp = (struct pdump_response *)mp_rep->param; 56799a2dd95SBruce Richardson rte_errno = resp->err_value; 56899a2dd95SBruce Richardson if (!resp->err_value) 56999a2dd95SBruce Richardson ret = 0; 57099a2dd95SBruce Richardson free(mp_reply.msgs); 57199a2dd95SBruce Richardson } 57299a2dd95SBruce Richardson 57399a2dd95SBruce Richardson if (ret < 0) 57499a2dd95SBruce Richardson PDUMP_LOG(ERR, 57599a2dd95SBruce Richardson "client request for pdump enable/disable failed\n"); 57699a2dd95SBruce Richardson return ret; 57799a2dd95SBruce Richardson } 57899a2dd95SBruce Richardson 57910f726efSStephen Hemminger /* 58010f726efSStephen Hemminger * There are two versions of this function, because although original API 58110f726efSStephen Hemminger * left place holder for future filter, it never checked the value. 58210f726efSStephen Hemminger * Therefore the API can't depend on application passing a non 58310f726efSStephen Hemminger * bogus value. 58410f726efSStephen Hemminger */ 58510f726efSStephen Hemminger static int 58610f726efSStephen Hemminger pdump_enable(uint16_t port, uint16_t queue, 58710f726efSStephen Hemminger uint32_t flags, uint32_t snaplen, 58810f726efSStephen Hemminger struct rte_ring *ring, struct rte_mempool *mp, 58910f726efSStephen Hemminger const struct rte_bpf_prm *prm) 59099a2dd95SBruce Richardson { 59199a2dd95SBruce Richardson int ret; 59299a2dd95SBruce Richardson char name[RTE_DEV_NAME_MAX_LEN]; 59399a2dd95SBruce Richardson 59499a2dd95SBruce Richardson ret = pdump_validate_port(port, name); 59599a2dd95SBruce Richardson if (ret < 0) 59699a2dd95SBruce Richardson return ret; 59799a2dd95SBruce Richardson ret = pdump_validate_ring_mp(ring, mp); 59899a2dd95SBruce Richardson if (ret < 0) 59999a2dd95SBruce Richardson return ret; 60099a2dd95SBruce Richardson ret = pdump_validate_flags(flags); 60199a2dd95SBruce Richardson if (ret < 0) 60299a2dd95SBruce Richardson return ret; 60399a2dd95SBruce Richardson 60410f726efSStephen Hemminger if (snaplen == 0) 60510f726efSStephen Hemminger snaplen = UINT32_MAX; 60699a2dd95SBruce Richardson 60710f726efSStephen Hemminger return pdump_prepare_client_request(name, queue, flags, snaplen, 60810f726efSStephen Hemminger ENABLE, ring, mp, prm); 60999a2dd95SBruce Richardson } 61099a2dd95SBruce Richardson 61199a2dd95SBruce Richardson int 61210f726efSStephen Hemminger rte_pdump_enable(uint16_t port, uint16_t queue, uint32_t flags, 61399a2dd95SBruce Richardson struct rte_ring *ring, 61499a2dd95SBruce Richardson struct rte_mempool *mp, 61510f726efSStephen Hemminger void *filter __rte_unused) 61699a2dd95SBruce Richardson { 61710f726efSStephen Hemminger return pdump_enable(port, queue, flags, 0, 61810f726efSStephen Hemminger ring, mp, NULL); 61910f726efSStephen Hemminger } 62010f726efSStephen Hemminger 62110f726efSStephen Hemminger int 62210f726efSStephen Hemminger rte_pdump_enable_bpf(uint16_t port, uint16_t queue, 62310f726efSStephen Hemminger uint32_t flags, uint32_t snaplen, 62410f726efSStephen Hemminger struct rte_ring *ring, 62510f726efSStephen Hemminger struct rte_mempool *mp, 62610f726efSStephen Hemminger const struct rte_bpf_prm *prm) 62710f726efSStephen Hemminger { 62810f726efSStephen Hemminger return pdump_enable(port, queue, flags, snaplen, 62910f726efSStephen Hemminger ring, mp, prm); 63010f726efSStephen Hemminger } 63110f726efSStephen Hemminger 63210f726efSStephen Hemminger static int 63310f726efSStephen Hemminger pdump_enable_by_deviceid(const char *device_id, uint16_t queue, 63410f726efSStephen Hemminger uint32_t flags, uint32_t snaplen, 63510f726efSStephen Hemminger struct rte_ring *ring, 63610f726efSStephen Hemminger struct rte_mempool *mp, 63710f726efSStephen Hemminger const struct rte_bpf_prm *prm) 63810f726efSStephen Hemminger { 63910f726efSStephen Hemminger int ret; 64099a2dd95SBruce Richardson 64199a2dd95SBruce Richardson ret = pdump_validate_ring_mp(ring, mp); 64299a2dd95SBruce Richardson if (ret < 0) 64399a2dd95SBruce Richardson return ret; 64499a2dd95SBruce Richardson ret = pdump_validate_flags(flags); 64599a2dd95SBruce Richardson if (ret < 0) 64699a2dd95SBruce Richardson return ret; 64799a2dd95SBruce Richardson 648b2be63b5SStephen Hemminger if (snaplen == 0) 649b2be63b5SStephen Hemminger snaplen = UINT32_MAX; 650b2be63b5SStephen Hemminger 65110f726efSStephen Hemminger return pdump_prepare_client_request(device_id, queue, flags, snaplen, 65210f726efSStephen Hemminger ENABLE, ring, mp, prm); 65310f726efSStephen Hemminger } 65499a2dd95SBruce Richardson 65510f726efSStephen Hemminger int 65610f726efSStephen Hemminger rte_pdump_enable_by_deviceid(char *device_id, uint16_t queue, 65710f726efSStephen Hemminger uint32_t flags, 65810f726efSStephen Hemminger struct rte_ring *ring, 65910f726efSStephen Hemminger struct rte_mempool *mp, 66010f726efSStephen Hemminger void *filter __rte_unused) 66110f726efSStephen Hemminger { 66210f726efSStephen Hemminger return pdump_enable_by_deviceid(device_id, queue, flags, 0, 66310f726efSStephen Hemminger ring, mp, NULL); 66410f726efSStephen Hemminger } 66510f726efSStephen Hemminger 66610f726efSStephen Hemminger int 66710f726efSStephen Hemminger rte_pdump_enable_bpf_by_deviceid(const char *device_id, uint16_t queue, 66810f726efSStephen Hemminger uint32_t flags, uint32_t snaplen, 66910f726efSStephen Hemminger struct rte_ring *ring, 67010f726efSStephen Hemminger struct rte_mempool *mp, 67110f726efSStephen Hemminger const struct rte_bpf_prm *prm) 67210f726efSStephen Hemminger { 67310f726efSStephen Hemminger return pdump_enable_by_deviceid(device_id, queue, flags, snaplen, 67410f726efSStephen Hemminger ring, mp, prm); 67599a2dd95SBruce Richardson } 67699a2dd95SBruce Richardson 67799a2dd95SBruce Richardson int 67899a2dd95SBruce Richardson rte_pdump_disable(uint16_t port, uint16_t queue, uint32_t flags) 67999a2dd95SBruce Richardson { 68099a2dd95SBruce Richardson int ret = 0; 68199a2dd95SBruce Richardson char name[RTE_DEV_NAME_MAX_LEN]; 68299a2dd95SBruce Richardson 68399a2dd95SBruce Richardson ret = pdump_validate_port(port, name); 68499a2dd95SBruce Richardson if (ret < 0) 68599a2dd95SBruce Richardson return ret; 68699a2dd95SBruce Richardson ret = pdump_validate_flags(flags); 68799a2dd95SBruce Richardson if (ret < 0) 68899a2dd95SBruce Richardson return ret; 68999a2dd95SBruce Richardson 69010f726efSStephen Hemminger ret = pdump_prepare_client_request(name, queue, flags, 0, 69199a2dd95SBruce Richardson DISABLE, NULL, NULL, NULL); 69299a2dd95SBruce Richardson 69399a2dd95SBruce Richardson return ret; 69499a2dd95SBruce Richardson } 69599a2dd95SBruce Richardson 69699a2dd95SBruce Richardson int 69799a2dd95SBruce Richardson rte_pdump_disable_by_deviceid(char *device_id, uint16_t queue, 69899a2dd95SBruce Richardson uint32_t flags) 69999a2dd95SBruce Richardson { 70099a2dd95SBruce Richardson int ret = 0; 70199a2dd95SBruce Richardson 70299a2dd95SBruce Richardson ret = pdump_validate_flags(flags); 70399a2dd95SBruce Richardson if (ret < 0) 70499a2dd95SBruce Richardson return ret; 70599a2dd95SBruce Richardson 70610f726efSStephen Hemminger ret = pdump_prepare_client_request(device_id, queue, flags, 0, 70799a2dd95SBruce Richardson DISABLE, NULL, NULL, NULL); 70899a2dd95SBruce Richardson 70999a2dd95SBruce Richardson return ret; 71099a2dd95SBruce Richardson } 71110f726efSStephen Hemminger 71210f726efSStephen Hemminger static void 71310f726efSStephen Hemminger pdump_sum_stats(uint16_t port, uint16_t nq, 71410f726efSStephen Hemminger struct rte_pdump_stats stats[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT], 71510f726efSStephen Hemminger struct rte_pdump_stats *total) 71610f726efSStephen Hemminger { 71710f726efSStephen Hemminger uint64_t *sum = (uint64_t *)total; 71810f726efSStephen Hemminger unsigned int i; 71910f726efSStephen Hemminger uint64_t val; 72010f726efSStephen Hemminger uint16_t qid; 72110f726efSStephen Hemminger 72210f726efSStephen Hemminger for (qid = 0; qid < nq; qid++) { 723*938c55cbSTyler Retzlaff const RTE_ATOMIC(uint64_t) *perq = (const uint64_t __rte_atomic *)&stats[port][qid]; 72410f726efSStephen Hemminger 72510f726efSStephen Hemminger for (i = 0; i < sizeof(*total) / sizeof(uint64_t); i++) { 726*938c55cbSTyler Retzlaff val = rte_atomic_load_explicit(&perq[i], rte_memory_order_relaxed); 72710f726efSStephen Hemminger sum[i] += val; 72810f726efSStephen Hemminger } 72910f726efSStephen Hemminger } 73010f726efSStephen Hemminger } 73110f726efSStephen Hemminger 73210f726efSStephen Hemminger int 73310f726efSStephen Hemminger rte_pdump_stats(uint16_t port, struct rte_pdump_stats *stats) 73410f726efSStephen Hemminger { 73510f726efSStephen Hemminger struct rte_eth_dev_info dev_info; 73610f726efSStephen Hemminger const struct rte_memzone *mz; 73710f726efSStephen Hemminger int ret; 73810f726efSStephen Hemminger 73910f726efSStephen Hemminger memset(stats, 0, sizeof(*stats)); 74010f726efSStephen Hemminger ret = rte_eth_dev_info_get(port, &dev_info); 74110f726efSStephen Hemminger if (ret != 0) { 74210f726efSStephen Hemminger PDUMP_LOG(ERR, 74310f726efSStephen Hemminger "Error during getting device (port %u) info: %s\n", 74410f726efSStephen Hemminger port, strerror(-ret)); 74510f726efSStephen Hemminger return ret; 74610f726efSStephen Hemminger } 74710f726efSStephen Hemminger 74810f726efSStephen Hemminger if (pdump_stats == NULL) { 74910f726efSStephen Hemminger if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 75010f726efSStephen Hemminger /* rte_pdump_init was not called */ 75110f726efSStephen Hemminger PDUMP_LOG(ERR, "pdump stats not initialized\n"); 75210f726efSStephen Hemminger rte_errno = EINVAL; 75310f726efSStephen Hemminger return -1; 75410f726efSStephen Hemminger } 75510f726efSStephen Hemminger 75610f726efSStephen Hemminger /* secondary process looks up the memzone */ 75710f726efSStephen Hemminger mz = rte_memzone_lookup(MZ_RTE_PDUMP_STATS); 75810f726efSStephen Hemminger if (mz == NULL) { 75910f726efSStephen Hemminger /* rte_pdump_init was not called in primary process?? */ 76010f726efSStephen Hemminger PDUMP_LOG(ERR, "can not find pdump stats\n"); 76110f726efSStephen Hemminger rte_errno = EINVAL; 76210f726efSStephen Hemminger return -1; 76310f726efSStephen Hemminger } 76410f726efSStephen Hemminger pdump_stats = mz->addr; 76510f726efSStephen Hemminger } 76610f726efSStephen Hemminger 76710f726efSStephen Hemminger pdump_sum_stats(port, dev_info.nb_rx_queues, pdump_stats->rx, stats); 76810f726efSStephen Hemminger pdump_sum_stats(port, dev_info.nb_tx_queues, pdump_stats->tx, stats); 76910f726efSStephen Hemminger return 0; 77010f726efSStephen Hemminger } 771