diff options
| author | songyanchao <[email protected]> | 2023-12-04 06:39:05 +0000 |
|---|---|---|
| committer | songyanchao <[email protected]> | 2023-12-05 08:50:17 +0000 |
| commit | bafd3791592b14e635bb8e770d617b5b8fe7a2e0 (patch) | |
| tree | f71f04b9c6858270ad647ce3867b441f282a8d61 /tools/tcpdump | |
| parent | e0db337fa6b45820eda3401d958e4a00a116069d (diff) | |
🎈 perf: Optimize mrpdump tool by utilizing the 'rte_pcapng_copy' API provided by DPDK.
Optimize mrpdump tool by utilizing the 'rte_pcapng_copy' API provided by DPDK.
Diffstat (limited to 'tools/tcpdump')
| -rw-r--r-- | tools/tcpdump/pdump.c | 140 |
1 files changed, 57 insertions, 83 deletions
diff --git a/tools/tcpdump/pdump.c b/tools/tcpdump/pdump.c index 9602d06..bb3a2a5 100644 --- a/tools/tcpdump/pdump.c +++ b/tools/tcpdump/pdump.c @@ -198,7 +198,8 @@ uint16_t interface_index = 0; static uint16_t port_index[MR_DEVICE_MAX] = {}; /* Pcapng */ -static int pcapng_fd = 0; +static int dumpfile_fd = 0; +rte_pcapng_t * pcapng = NULL; /**< display usage */ static void pdump_usage(const char * prgname) @@ -532,8 +533,16 @@ static unsigned int mbuf_burst_segs(struct rte_mbuf * pkts[], unsigned int n) return iovcnt; } -int mr_pcapng_set_opt(struct rte_mbuf * mbuf, uint16_t port_id, enum mr_dev_driver drv_type, uint32_t rx_tx_flags) +int mr_pcapng_add_opt(struct rte_mbuf * mbuf, uint16_t port_id, uint32_t rx_tx_flags) { + /* check the epb info */ + struct pcapng_enhance_packet_block * epb = rte_pktmbuf_mtod(mbuf, struct pcapng_enhance_packet_block *); + if (unlikely(epb->block_type != PCAPNG_ENHANCED_PACKET_BLOCK || epb->block_length != rte_pktmbuf_data_len(mbuf))) + { + fprintf(stderr, "received packet with incorrect EPB information error.\n"); + return RT_ERR; + } + /* pad the packet to 32 bit boundary */ uint32_t original_length = rte_pktmbuf_pkt_len(mbuf); uint32_t padding = RTE_ALIGN(original_length, sizeof(uint32_t)) - original_length; @@ -550,13 +559,13 @@ int mr_pcapng_set_opt(struct rte_mbuf * mbuf, uint16_t port_id, enum mr_dev_driv } /* reserve trailing options and block length */ + int len = 0; char str_rx_tx[METADATA_MAX_SIZE]; char str_sid[METADATA_MAX_SIZE]; char str_dir[METADATA_MAX_SIZE]; uint32_t str_maxlen = METADATA_MAX_SIZE - 1; struct mrb_metadata * mrb_metadata = mrbuf_cz_data(mbuf, MR_NODE_CTRLZONE_ID); - int len = 0; if (rx_tx_flags == RTE_PDUMP_FLAG_RX) len = snprintf(str_rx_tx, str_maxlen, "rx"); else @@ -596,36 +605,14 @@ int mr_pcapng_set_opt(struct rte_mbuf * mbuf, uint16_t port_id, enum mr_dev_driv return RT_ERR; } - /* Note: END_OPT necessary here. Wireshark doesn't do it. */ - /* Add PCAPNG packet header */ - struct pcapng_enhance_packet_block * epb = - (struct pcapng_enhance_packet_block *)rte_pktmbuf_prepend(mbuf, sizeof(*epb)); - if (unlikely(epb == NULL)) - { - fprintf(stderr, "mbuf prepend epb err.\n"); - return RT_ERR; - } - - /* Set epb info */ + /* update the epb info */ struct timespec current_time; clock_gettime(CLOCK_REALTIME, ¤t_time); uint64_t ns = (uint64_t)current_time.tv_sec * 1000000000 + current_time.tv_nsec; - epb->block_type = PCAPNG_ENHANCED_PACKET_BLOCK; - epb->block_length = rte_pktmbuf_pkt_len(mbuf); - epb->interface_id = port_index[port_id]; epb->timestamp_hi = ns >> 32; epb->timestamp_lo = (uint32_t)ns; - epb->capture_length = original_length; - - /* Set the original length based on the driver type */ - if (drv_type == MR_DEV_DRV_TYPE_SHMDEV) - { - epb->original_length = mbuf->tx_offload; - } - else - { - epb->original_length = original_length; - } + epb->block_length = rte_pktmbuf_pkt_len(mbuf); + epb->interface_id = port_index[port_id]; /* set trailer of block length */ struct pcapng_option * opt_new = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, str_rx_tx, strlen(str_rx_tx)); @@ -638,11 +625,9 @@ int mr_pcapng_set_opt(struct rte_mbuf * mbuf, uint16_t port_id, enum mr_dev_driv static inline void pdump_rxtx(struct pdump_tuples * pt, uint32_t rx_tx_flags) { - /* Write input packets of port_id to vdev for pdump */ uint64_t * rxtx_pkts = NULL; struct rte_ring * ring = NULL; struct pdump_stats * stats = &pt->stats; - if (rx_tx_flags == RTE_PDUMP_FLAG_RX) { ring = pt->rx_ring; @@ -676,22 +661,15 @@ static inline void pdump_rxtx(struct pdump_tuples * pt, uint32_t rx_tx_flags) if (nb_in_deq == 0) return; - /* Update the dumpfile_count */ - if (dumpfile_count_set) - { - dumpfile_count -= nb_in_deq; - } - - /* Update stats */ - stats->dequeue_pkts += nb_in_deq; + /* Write packets to dumpfile */ + /* Because 'shmdev name' needs to be recorded, 'rte_pcapng_write_packets' cannot be used. */ + unsigned int cnt = 0; int iovcnt = mbuf_burst_segs(rxtx_bufs, nb_in_deq); struct iovec iov[iovcnt]; - unsigned int cnt = 0; - for (int i = 0; i < nb_in_deq; i++) { struct rte_mbuf * mbuf = rxtx_bufs[i]; - int ret = mr_pcapng_set_opt(mbuf, pt->port_id, pt->drv_type, rx_tx_flags); + int ret = mr_pcapng_add_opt(mbuf, pt->port_id, rx_tx_flags); if (ret == RT_SUCCESS) { do @@ -708,17 +686,22 @@ static inline void pdump_rxtx(struct pdump_tuples * pt, uint32_t rx_tx_flags) /* Write pkt */ if (cnt > 0) { - if (writev(pcapng_fd, iov, cnt) <= 0) + if (writev(dumpfile_fd, iov, cnt) <= 0) perror("Pcapng packets write error."); } /* Pkt free */ - for (int i = 0; i < nb_in_deq; i++) + rte_pktmbuf_free_bulk(rxtx_bufs, nb_in_deq); + + /* Update the dumpfile_count */ + if (dumpfile_count_set) { - rte_pktmbuf_free(rxtx_bufs[i]); - stats->freed_pkts++; + dumpfile_count -= nb_in_deq; } + /* Update stats */ + stats->dequeue_pkts += nb_in_deq; + stats->freed_pkts += nb_in_deq; return; } @@ -830,8 +813,8 @@ static void enable_pdump(void) if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV) { /* Phydev use dpdk pdump api */ - int ret = - rte_pdump_enable_bpf(pt->port_id, pt->queue, RTE_PDUMP_FLAG_RX, snaplen, pt->rx_ring, pt->mp, prm); + int ret = rte_pdump_enable_bpf(pt->port_id, pt->queue, RTE_PDUMP_FLAG_RX | RTE_PDUMP_FLAG_PCAPNG, + snaplen, pt->rx_ring, pt->mp, prm); if (ret < 0) rte_exit(EXIT_FAILURE, "Phydev :%s, rx enable err.\n", pt->dev_symbol); } @@ -882,8 +865,8 @@ static void enable_pdump(void) if (pt->drv_type != MR_DEV_DRV_TYPE_SHMDEV) { /* Phydev use dpdk pdump api */ - int ret = - rte_pdump_enable_bpf(pt->port_id, pt->queue, RTE_PDUMP_FLAG_TX, snaplen, pt->tx_ring, pt->mp, prm); + int ret = rte_pdump_enable_bpf(pt->port_id, pt->queue, RTE_PDUMP_FLAG_TX | RTE_PDUMP_FLAG_PCAPNG, + snaplen, pt->tx_ring, pt->mp, prm); if (ret < 0) rte_exit(EXIT_FAILURE, "Phydev:%s, tx enable err.\n", pt->dev_symbol); } @@ -903,6 +886,7 @@ static int pcapng_add_interface(struct pdump_tuples * pt) len += pcapng_optlen(0); len += sizeof(uint32_t); + /* 'alloca' does not require explicit memory deallocation because it allocates memory on the stack. */ void * buf = alloca(len); if (!buf) return -1; @@ -923,7 +907,7 @@ static int pcapng_add_interface(struct pdump_tuples * pt) /* clone block_length after options */ memcpy(opt, &hdr->block_length, sizeof(uint32_t)); - return write(pcapng_fd, buf, len); + return write(dumpfile_fd, buf, len); } static void write_interface_info(void) @@ -1038,7 +1022,8 @@ static void disable_pdump(void) free(mp_reply.msgs); } } - close(pcapng_fd); + + rte_pcapng_close(pcapng); rte_free(prm); } @@ -1058,11 +1043,23 @@ static inline void dump_packets(void) } } -static inline void create_pcap_dumper() +/* Get os info */ +static char * get_os_info(void) { - struct rte_mp_msg mp_req = {}; - struct mr_pdump_request * req = (struct mr_pdump_request *)mp_req.param; + struct utsname uts; + char * os_name = NULL; + + if (uname(&uts) < 0) + return NULL; + if (asprintf(&os_name, "%s %s", uts.sysname, uts.release) == -1) + return NULL; + + return os_name; +} + +static inline void create_pcap_dumper() +{ /* Check dumpfile whether exist, if exist, delete it */ if (access(dumpfile_path, F_OK) == 0) { @@ -1072,35 +1069,12 @@ static inline void create_pcap_dumper() } } - pcapng_fd = open(dumpfile_path, O_WRONLY | O_CREAT, 0640); - - /* Fill request struct */ - memset(req, 0, sizeof(*req)); - req->op = WRITE_PCAPNG_HEADER; - - /* 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 = 1; - mp_req.fds[0] = pcapng_fd; - - /* Send request and wait reply */ - struct rte_mp_reply mp_reply = {}; - struct timespec ts = {.tv_sec = 20, .tv_nsec = 0}; - if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) != 0) - { - rte_exit(EXIT_FAILURE, "Failed to send the request to write the '%s' pcapng header.\n", dumpfile_path); - } - - /* 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_SUCCESS) + /* Create the pcapng file */ + dumpfile_fd = open(dumpfile_path, O_WRONLY | O_CREAT, 0640); + pcapng = rte_pcapng_fdopen(dumpfile_fd, get_os_info(), NULL, "mrpdump v1.0", NULL); + if (pcapng == NULL) { - /* Dump error info */ - err_value_dump(resp->err_value); - free(mp_reply.msgs); - rte_exit(EXIT_FAILURE, "The '%s' pcapng header write err.\n", dumpfile_path); + rte_exit(EXIT_FAILURE, "Cannot create pcapng file %s\n", dumpfile_path); } /* Set bpf */ @@ -1164,7 +1138,7 @@ int main(int argc, char ** argv) /* get default dumpfile path */ static char default_dir[PATH_MAX]; if (getcwd(default_dir, sizeof(default_dir)) == NULL) - rte_exit(EXIT_FAILURE, "Get dumpfile path faill\n"); + rte_exit(EXIT_FAILURE, "Get dumpfile path fail\n"); snprintf(dumpfile_path, sizeof(dumpfile_path), "%s/dumpfile.pcapng", default_dir); |
