summaryrefslogtreecommitdiff
path: root/tools/tcpdump
diff options
context:
space:
mode:
authorsongyanchao <[email protected]>2023-12-04 06:39:05 +0000
committersongyanchao <[email protected]>2023-12-05 08:50:17 +0000
commitbafd3791592b14e635bb8e770d617b5b8fe7a2e0 (patch)
treef71f04b9c6858270ad647ce3867b441f282a8d61 /tools/tcpdump
parente0db337fa6b45820eda3401d958e4a00a116069d (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.c140
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, &current_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);