diff options
| author | songyanchao <[email protected]> | 2023-03-07 06:29:26 +0000 |
|---|---|---|
| committer | songyanchao <[email protected]> | 2023-03-07 06:29:26 +0000 |
| commit | 075c2cd470d19e0687823e2ee79e46c76c50f8ae (patch) | |
| tree | d506270f5fcf272b7acffeb53ee0a9330624c889 /tools/tcpdump | |
| parent | 0c6d487e64f64a19dc3ccf14afdcc6c1ecad497e (diff) | |
✨ feat(DPISDN-2): mrpdump 支持 shmdev 设备
mrpdump 支持 shmdev 设备
Diffstat (limited to 'tools/tcpdump')
| -rw-r--r-- | tools/tcpdump/pdump.c | 307 |
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(); |
