summaryrefslogtreecommitdiff
path: root/tools/tcpdump
diff options
context:
space:
mode:
authorsongyanchao <[email protected]>2023-03-07 06:29:26 +0000
committersongyanchao <[email protected]>2023-03-07 06:29:26 +0000
commit075c2cd470d19e0687823e2ee79e46c76c50f8ae (patch)
treed506270f5fcf272b7acffeb53ee0a9330624c889 /tools/tcpdump
parent0c6d487e64f64a19dc3ccf14afdcc6c1ecad497e (diff)
✨ feat(DPISDN-2): mrpdump 支持 shmdev 设备
mrpdump 支持 shmdev 设备
Diffstat (limited to 'tools/tcpdump')
-rw-r--r--tools/tcpdump/pdump.c307
1 files changed, 179 insertions, 128 deletions
diff --git a/tools/tcpdump/pdump.c b/tools/tcpdump/pdump.c
index 93ba601..a5c1b4b 100644
--- a/tools/tcpdump/pdump.c
+++ b/tools/tcpdump/pdump.c
@@ -44,7 +44,7 @@
#include <unistd.h>
#include "common.h"
-#include "mr_pcapng_proto.h"
+#include "pcapng_proto.h"
#include <mrb_define.h>
#include <pcap/bpf.h>
#include <pcap/pcap.h>
@@ -66,7 +66,7 @@
#include <sc_pdump.h>
#define CMD_LINE_OPT_PDUMP "pdump"
-#define PDUMP_DEV_ARG "dev"
+#define PDUMP_DEV_NAME_ARG "dev_name"
#define PDUMP_QUEUE_ARG "queue"
#define PDUMP_RX_ARG "rx"
#define PDUMP_TX_ARG "tx"
@@ -88,7 +88,6 @@
#define RX_DESC_PER_QUEUE 128
#define MBUFS_PER_POOL MR_PDUMP_MBUFS_PER_POOL
#define MAX_LONG_OPT_SZ 64
-#define RING_SIZE 16384
#define SIZE 256
#define BURST_SIZE 32
#define NUM_VDEVS 2
@@ -114,7 +113,7 @@ enum pdump_by
DEVICE_ID = 2
};
-const char * valid_pdump_arguments[] = {PDUMP_DEV_ARG, PDUMP_QUEUE_ARG, PDUMP_RX_ARG, PDUMP_TX_ARG,
+const char * valid_pdump_arguments[] = {PDUMP_DEV_NAME_ARG, PDUMP_QUEUE_ARG, PDUMP_RX_ARG, PDUMP_TX_ARG,
PDUMP_RING_SIZE_ARG, PDUMP_MSIZE_ARG, PDUMP_NUM_MBUFS_ARG, NULL};
struct pdump_stats
@@ -132,6 +131,7 @@ struct pdump_tuples
enum mr_dev_driver drv_type;
char dev_symbol[MR_SYMBOL_MAX];
char * device_id;
+ struct rte_ether_addr eth_addr;
uint16_t queue;
char rx_dev[TX_STREAM_SIZE];
char tx_dev[TX_STREAM_SIZE];
@@ -191,6 +191,9 @@ static struct bpf_program bpf_prog;
static char str_bpf_expr[4096] = {};
static bool is_str_bpf_expr_set = false; /* */
+uint16_t interface_index = 0;
+static uint16_t port_index[MR_DEVICE_MAX] = {};
+
/* Pcapng */
static int pcapng_fd = 0;
static rte_pcapng_t * _pcapng_item = NULL;
@@ -200,13 +203,10 @@ static void pdump_usage(const char * prgname)
{
fprintf(stderr,
"usage: %s [EAL options] -- --pdump "
- "'(port_id=<port_id id> | device_id=<pci id or vdev name>),"
+ "'dev_name=<phydev or shmdev name>),"
"(queue=<queue_id>),"
"(rx-dev=<iface or pcap file> |"
" tx-dev=<iface or pcap file>,"
- "[ring-size=<ring size>default:16384],"
- "[mbuf-size=<mbuf data size>default:2176],"
- "[total-num-mbufs=<number of mbufs>default:65535]'\n"
"[--server-socket-path=<server socket dir>"
"default:/var/run/.dpdk/ (or) ~/.dpdk/]\n"
"[--client-socket-path=<client socket dir>"
@@ -294,10 +294,10 @@ static int parse_pdump(const char * optarg)
}
/* port_id/device_id parsing and validation */
- cnt1 = rte_kvargs_count(kvlist, PDUMP_DEV_ARG);
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_DEV_NAME_ARG);
if (cnt1 == 1)
{
- ret = rte_kvargs_process(kvlist, PDUMP_DEV_ARG, &parse_device_name, NULL);
+ ret = rte_kvargs_process(kvlist, PDUMP_DEV_NAME_ARG, &parse_device_name, NULL);
if (ret < 0)
goto free_kvlist;
}
@@ -355,7 +355,7 @@ static int parse_pdump(const char * optarg)
pt->ring_size = (uint32_t)v.val;
}
else
- pt->ring_size = RING_SIZE;
+ pt->ring_size = MR_PDUMP_RING_SIZE;
/* mbuf_data_size parsing and validation */
cnt1 = rte_kvargs_count(kvlist, PDUMP_MSIZE_ARG);
@@ -580,7 +580,7 @@ int mr_pcapng_set_opt(struct rte_mbuf * mbuf, uint16_t port_id)
uint64_t ns = pcapng_tsc_to_ns(rte_get_tsc_cycles());
epb->block_type = PCAPNG_ENHANCED_PACKET_BLOCK;
epb->block_length = rte_pktmbuf_data_len(mbuf);
- epb->interface_id = port_id;
+ epb->interface_id = port_index[port_id];
epb->timestamp_hi = ns >> 32;
epb->timestamp_lo = (uint32_t)ns;
epb->capture_length = data_len;
@@ -595,8 +595,7 @@ int mr_pcapng_set_opt(struct rte_mbuf * mbuf, uint16_t port_id)
static inline void pdump_rxtx(uint16_t port_id, struct rte_ring * ring, struct pdump_stats * stats, uint32_t flags)
{
- /* write input packets of port_id to vdev for pdump */
- struct rte_mbuf * rxtx_bufs[BURST_SIZE];
+ /* Write input packets of port_id to vdev for pdump */
uint64_t * rxtx_pkts = NULL;
if (flags == RTE_PDUMP_FLAG_RX)
@@ -604,7 +603,8 @@ static inline void pdump_rxtx(uint16_t port_id, struct rte_ring * ring, struct p
else
rxtx_pkts = &stats->tx_pkts;
- /* first dequeue packets from ring of primary process */
+ /* First dequeue packets from ring of primary process */
+ struct rte_mbuf * rxtx_bufs[BURST_SIZE];
const uint16_t nb_in_deq = rte_ring_dequeue_burst(ring, (void *)rxtx_bufs, BURST_SIZE, NULL);
stats->dequeue_pkts += nb_in_deq;
int iovcnt = mbuf_burst_segs(rxtx_bufs, nb_in_deq);
@@ -637,10 +637,8 @@ static inline void pdump_rxtx(uint16_t port_id, struct rte_ring * ring, struct p
}
}
- if (!is_str_bpf_expr_set)
- {
- writev(pcapng_fd, iov, iovcnt);
- }
+ /* Write pkt */
+ writev(pcapng_fd, iov, iovcnt);
/* Pkt free */
for (int i = 0; i < nb_in_deq; i++)
@@ -706,6 +704,7 @@ static void err_value_dump(int32_t err_value)
static void enable_pdump(void)
{
+ /* Set all device */
for (int i = 0; i < num_tuples; i++)
{
struct pdump_tuples * pt = &pdump_t[i];
@@ -714,51 +713,49 @@ static void enable_pdump(void)
struct rte_mp_msg mp_req = {};
struct mr_pdump_request * req = (struct mr_pdump_request *)mp_req.param;
+ /* Fill request struct */
memset(req, 0, sizeof(*req));
-
req->op = ENABLE;
req->queue = pt->queue;
- req->mbuf_data_size = pt->mbuf_data_size;
- req->total_num_mbufs = pt->total_num_mbufs;
req->flags = RTE_PDUMP_FLAG_RX;
- req->ring_size = pt->ring_size;
memcpy(req->dev_symbol, pt->dev_symbol, sizeof(pt->dev_symbol));
- struct rte_mp_reply mp_reply = {};
- struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ /* Fill request name */
rte_strscpy(mp_req.name, MR_PDUMP_MP, RTE_MP_MAX_NAME_LEN);
mp_req.len_param = sizeof(*req);
mp_req.num_fds = 0;
- if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0)
+
+ /* Send request and wait reply */
+ struct rte_mp_reply mp_reply = {};
+ struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) != 0)
+ rte_exit(EXIT_FAILURE, "Device:%s, send rx enable msg timeout.\n", pt->dev_symbol);
+
+ /* Deal reply */
+ struct rte_mp_msg * mp_rep = &mp_reply.msgs[0];
+ struct mr_pdump_response * resp = (struct mr_pdump_response *)mp_rep->param;
+ if (resp->err_value != MR_PDUMP_SUCESS)
{
- struct rte_mp_msg * mp_rep = &mp_reply.msgs[0];
- struct mr_pdump_response * resp = (struct mr_pdump_response *)mp_rep->param;
- int32_t err_value = resp->err_value;
- if (err_value == MR_PDUMP_SUCESS)
- {
- pt->rx_ring = resp->rx_ring;
- pt->mp = resp->mp;
- pt->port_id = resp->port_id;
- pt->drv_type = resp->drv_type;
- free(mp_reply.msgs);
- }
- else
- {
- /* Dump error info */
- err_value_dump(resp->err_value);
- free(mp_reply.msgs);
- rte_exit(EXIT_FAILURE, "Device:%s, rx enable err.\n", pt->dev_symbol);
- }
+ /* Dump error info */
+ err_value_dump(resp->err_value);
+ free(mp_reply.msgs);
+ rte_exit(EXIT_FAILURE, "Device:%s, rx enable err.\n", pt->dev_symbol);
}
+ /* Save dump info */
+ pt->rx_ring = resp->rx_ring;
+ pt->mp = resp->mp;
+ pt->port_id = resp->port_id;
+ pt->drv_type = resp->drv_type;
+ rte_ether_addr_copy(&resp->eth_addr, &pt->eth_addr);
+ free(mp_reply.msgs);
+
if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV)
{
- /* Phydev */
+ /* Phydev use dpdk pdump api */
int ret = rte_pdump_enable(pt->port_id, pt->queue, RTE_PDUMP_FLAG_RX, pt->rx_ring, pt->mp, NULL);
if (ret < 0)
- {
rte_exit(EXIT_FAILURE, "Phydev :%s, rx enable err.\n", pt->dev_symbol);
- }
}
}
@@ -767,56 +764,100 @@ static void enable_pdump(void)
struct rte_mp_msg mp_req = {};
struct mr_pdump_request * req = (struct mr_pdump_request *)mp_req.param;
+ /* Fill request struct */
memset(req, 0, sizeof(*req));
-
req->op = ENABLE;
req->queue = pt->queue;
- req->mbuf_data_size = pt->mbuf_data_size;
- req->total_num_mbufs = pt->total_num_mbufs;
req->flags = RTE_PDUMP_FLAG_TX;
- req->ring_size = pt->ring_size;
memcpy(req->dev_symbol, pt->dev_symbol, sizeof(pt->dev_symbol));
- struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
- struct rte_mp_reply mp_reply = {};
+ /* Fill request name */
rte_strscpy(mp_req.name, MR_PDUMP_MP, RTE_MP_MAX_NAME_LEN);
mp_req.len_param = sizeof(*req);
mp_req.num_fds = 0;
- if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0)
+
+ /* Send request and wait reply */
+ struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ struct rte_mp_reply mp_reply = {};
+ if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) != 0)
+ rte_exit(EXIT_FAILURE, "Device:%s, send tx enable msg timeout.\n", pt->dev_symbol);
+
+ struct rte_mp_msg * mp_rep = &mp_reply.msgs[0];
+ struct mr_pdump_response * resp = (struct mr_pdump_response *)mp_rep->param;
+ if (resp->err_value != MR_PDUMP_SUCESS)
{
- struct rte_mp_msg * mp_rep = &mp_reply.msgs[0];
- struct mr_pdump_response * resp = (struct mr_pdump_response *)mp_rep->param;
- rte_errno = resp->err_value;
- if (resp->err_value == MR_PDUMP_SUCESS)
- {
- pt->tx_ring = resp->tx_ring;
- pt->mp = resp->mp;
- pt->port_id = resp->port_id;
- pt->drv_type = resp->drv_type;
- free(mp_reply.msgs);
- }
- else
- {
- /* Dump error info */
- err_value_dump(resp->err_value);
- free(mp_reply.msgs);
- rte_exit(EXIT_FAILURE, "Devices:%s, tx enable err.\n", pt->dev_symbol);
- }
+ /* Dump error info */
+ err_value_dump(resp->err_value);
+ free(mp_reply.msgs);
+ rte_exit(EXIT_FAILURE, "Devices:%s, tx enable err.\n", pt->dev_symbol);
}
+ pt->tx_ring = resp->tx_ring;
+ pt->mp = resp->mp;
+ pt->port_id = resp->port_id;
+ pt->drv_type = resp->drv_type;
+ rte_ether_addr_copy(&resp->eth_addr, &pt->eth_addr);
+ free(mp_reply.msgs);
+
if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV)
{
- /* Phydev */
+ /* Phydev use dpdk pdump api */
int ret = rte_pdump_enable(pt->port_id, pt->queue, RTE_PDUMP_FLAG_TX, pt->tx_ring, pt->mp, NULL);
if (ret < 0)
- {
rte_exit(EXIT_FAILURE, "Phydev:%s, tx enable err.\n", pt->dev_symbol);
- }
}
}
}
}
+static int pcapng_add_interface(struct pdump_tuples * pt)
+{
+ /* Compute length of interface block options */
+ uint32_t len = sizeof(struct pcapng_interface_block);
+
+ const uint8_t tsresol = 9;
+ len += pcapng_optlen(sizeof(tsresol)); /* timestamp */
+ len += pcapng_optlen(strlen(pt->dev_symbol)); /* ifname */
+ len += pcapng_optlen(RTE_ETHER_ADDR_LEN); /* macaddr */
+ len += pcapng_optlen(0);
+ len += sizeof(uint32_t);
+
+ void * buf = alloca(len);
+ if (!buf)
+ return -1;
+
+ struct pcapng_interface_block * hdr = (struct pcapng_interface_block *)buf;
+ *hdr = (struct pcapng_interface_block){
+ .block_type = PCAPNG_INTERFACE_BLOCK,
+ .link_type = 1, /* DLT_EN10MB - Ethernet */
+ .block_length = len,
+ };
+
+ struct pcapng_option * opt = (struct pcapng_option *)(hdr + 1);
+ opt = pcapng_add_option(opt, PCAPNG_IFB_TSRESOL, &tsresol, sizeof(tsresol));
+ opt = pcapng_add_option(opt, PCAPNG_IFB_NAME, pt->dev_symbol, strlen(pt->dev_symbol));
+ opt = pcapng_add_option(opt, PCAPNG_IFB_MACADDR, &pt->eth_addr, RTE_ETHER_ADDR_LEN);
+ opt = pcapng_add_option(opt, PCAPNG_OPT_END, NULL, 0);
+
+ /* clone block_length after options */
+ memcpy(opt, &hdr->block_length, sizeof(uint32_t));
+
+ return write(pcapng_fd, buf, len);
+}
+
+static void write_interface_info(void)
+{
+ for (int i = 0; i < num_tuples; i++)
+ {
+ struct pdump_tuples * pt = &pdump_t[i];
+ if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV)
+ continue;
+ if (pcapng_add_interface(pt) < 0)
+ rte_exit(EXIT_FAILURE, "Phydev:%s, write interface info err.\n", pt->dev_symbol);
+ port_index[pt->port_id] = interface_index++;
+ }
+}
+
static void disable_pdump(void)
{
for (int i = 0; i < num_tuples; i++)
@@ -826,94 +867,94 @@ static void disable_pdump(void)
{
if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV)
{
+ /* The Shmdev use dpdk pdump api */
int ret = rte_pdump_disable(pt->port_id, pt->queue, RTE_PDUMP_FLAG_RX);
if (ret < 0)
- {
rte_exit(EXIT_FAILURE, "Phydev:%s, rx disable err.\n", pt->dev_symbol);
- }
}
- struct rte_mp_msg mp_req, *mp_rep;
- struct rte_mp_reply mp_reply;
- struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ struct rte_mp_msg mp_req = {};
struct mr_pdump_request * req = (struct mr_pdump_request *)mp_req.param;
- struct mr_pdump_response * resp;
+ /* Fill request struct */
memset(req, 0, sizeof(*req));
-
req->op = DISABLE;
req->flags = RTE_PDUMP_FLAG_RX;
memcpy(req->dev_symbol, pt->dev_symbol, sizeof(pt->dev_symbol));
+ /* Fill request name */
rte_strscpy(mp_req.name, MR_PDUMP_MP, RTE_MP_MAX_NAME_LEN);
mp_req.len_param = sizeof(*req);
mp_req.num_fds = 0;
- if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0)
+
+ /* Send request msg and wait reply */
+ struct rte_mp_reply mp_reply = {};
+ struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) != 0)
+ rte_exit(EXIT_FAILURE, "Device:%s, send rx disable msg timeout.\n", pt->dev_symbol);
+
+ /* Deal reply */
+ struct rte_mp_msg * mp_rep = &mp_reply.msgs[0];
+ struct mr_pdump_response * resp = (struct mr_pdump_response *)mp_rep->param;
+ if (resp->err_value != MR_PDUMP_SUCESS)
{
- mp_rep = &mp_reply.msgs[0];
- resp = (struct mr_pdump_response *)mp_rep->param;
- int32_t err_value = resp->err_value;
- if (err_value == MR_PDUMP_SUCESS)
- {
- pt->rx_ring = NULL;
- pt->mp = NULL;
- free(mp_reply.msgs);
- }
- else
- {
- /* Dump error info */
- err_value_dump(resp->err_value);
- free(mp_reply.msgs);
- rte_exit(EXIT_FAILURE, "Device:%s, disable err.\n", pt->dev_symbol);
- }
+ /* Dump error info */
+ err_value_dump(resp->err_value);
+ free(mp_reply.msgs);
+ rte_exit(EXIT_FAILURE, "Device:%s, disable err.\n", pt->dev_symbol);
}
+
+ /* Clear pt info */
+ pt->rx_ring = NULL;
+ pt->mp = NULL;
+ free(mp_reply.msgs);
}
if (pt->dir & RTE_PDUMP_FLAG_TX)
{
if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV)
{
+ /* The Shmdev use dpdk pdump api */
int ret = rte_pdump_disable(pt->port_id, pt->queue, RTE_PDUMP_FLAG_TX);
if (ret < 0)
- {
rte_exit(EXIT_FAILURE, "Phydev:%s, tx disable err.\n", pt->dev_symbol);
- }
}
- struct rte_mp_msg mp_req, *mp_rep;
- struct rte_mp_reply mp_reply;
- struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ struct rte_mp_msg mp_req = {};
struct mr_pdump_request * req = (struct mr_pdump_request *)mp_req.param;
- struct mr_pdump_response * resp;
+ /* Fill request struct */
memset(req, 0, sizeof(*req));
-
req->op = DISABLE;
req->flags = RTE_PDUMP_FLAG_TX;
memcpy(req->dev_symbol, pt->dev_symbol, sizeof(pt->dev_symbol));
+ /* Fill request name */
rte_strscpy(mp_req.name, MR_PDUMP_MP, RTE_MP_MAX_NAME_LEN);
mp_req.len_param = sizeof(*req);
mp_req.num_fds = 0;
- if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0)
+
+ /* Send request msg and wait reply */
+ struct rte_mp_reply mp_reply = {};
+ struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) != 0)
+ rte_exit(EXIT_FAILURE, "Device:%s, send tx disable msg timeout.\n", pt->dev_symbol);
+
+ /* Deal reply */
+ struct rte_mp_msg * mp_rep = &mp_reply.msgs[0];
+ struct mr_pdump_response * resp = (struct mr_pdump_response *)mp_rep->param;
+ if (resp->err_value != MR_PDUMP_SUCESS)
{
- mp_rep = &mp_reply.msgs[0];
- resp = (struct mr_pdump_response *)mp_rep->param;
- rte_errno = resp->err_value;
- if (resp->err_value == MR_PDUMP_SUCESS)
- {
- pt->tx_ring = NULL;
- pt->mp = NULL;
- free(mp_reply.msgs);
- }
- else
- {
- /* Dump error info */
- err_value_dump(resp->err_value);
- free(mp_reply.msgs);
- rte_exit(EXIT_FAILURE, "Device:%s, disable err.\n", pt->dev_symbol);
- }
+ /* Dump error info */
+ err_value_dump(resp->err_value);
+ free(mp_reply.msgs);
+ rte_exit(EXIT_FAILURE, "Device:%s, disable err.\n", pt->dev_symbol);
}
+
+ /* Clear pt info */
+ pt->tx_ring = NULL;
+ pt->mp = NULL;
+ free(mp_reply.msgs);
}
}
close(pcapng_fd);
@@ -921,14 +962,11 @@ static void disable_pdump(void)
static inline void dump_packets(void)
{
- int i;
- struct pdump_tuples * pt;
-
while (!quit_signal)
{
- for (i = 0; i < num_tuples; i++)
+ for (int i = 0; i < num_tuples; i++)
{
- pt = &pdump_t[i];
+ struct pdump_tuples * pt = &pdump_t[i];
if (pt->dir & RTE_PDUMP_FLAG_RX)
pdump_rxtx(pt->port_id, pt->rx_ring, &pt->stats, RTE_PDUMP_FLAG_RX);
@@ -954,12 +992,22 @@ static char * get_os_info(void)
static inline void create_pcap_dumper()
{
+ /* Save PCI devices */
+ uint16_t port_id = 0;
+ RTE_ETH_FOREACH_DEV(port_id)
+ {
+ /* The list if ports in pcapng needs to be contiguous */
+ port_index[port_id] = interface_index++;
+ }
+
+ /* Create pcapng file */
pcapng_fd = open(dumpfile_path, O_WRONLY | O_CREAT, 0640);
char * os = get_os_info();
_pcapng_item = rte_pcapng_fdopen(pcapng_fd, os, NULL, "Mrpdump v1.0", NULL);
if (_pcapng_item == NULL)
rte_exit(EXIT_FAILURE, "Cannot open pcap dumper for %s\n", dumpfile_path);
+ /* Set bpf */
if (is_str_bpf_expr_set)
{
int ret = pcap_compile_nopcap(65535, DLT_EN10MB, &bpf_prog, str_bpf_expr, 1, PCAP_NETMASK_UNKNOWN);
@@ -1017,6 +1065,9 @@ int main(int argc, char ** argv)
/* device enable */
enable_pdump();
+ /* write interface info */
+ write_interface_info();
+
/* dump packets */
dump_packets();