[2/2] app/pdump: add filter argument

Message ID 20220307203041.33765-1-laitianli@tom.com (mailing list archive)
State Rejected, archived
Delegated to: Thomas Monjalon
Headers
Series [1/2] net/pcap: add snaplen argument |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/iol-broadcom-Functional fail Functional Testing issues
ci/intel-Testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/github-robot: build success github build: passed
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS
ci/iol-aarch64-compile-testing success Testing PASS
ci/iol-abi-testing success Testing PASS

Commit Message

Tianli Lai March 7, 2022, 8:30 p.m. UTC
  filter argument contain size and snaplen argument.
size argument set the pcap file size, if the total packet
length over this value, pdump process will exist.
snaplen argument set each packet length to save pcap file.

Signed-off-by: Tianli Lai <laitianli@tom.com>
---
 app/pdump/main.c | 213 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 190 insertions(+), 23 deletions(-)
  

Comments

Stephen Hemminger March 7, 2022, 4:04 p.m. UTC | #1
On Tue,  8 Mar 2022 04:30:41 +0800
Tianli Lai <laitianli@tom.com> wrote:

> filter argument contain size and snaplen argument.
> size argument set the pcap file size, if the total packet
> length over this value, pdump process will exist.
> snaplen argument set each packet length to save pcap file.
> 
> Signed-off-by: Tianli Lai <laitianli@tom.com>



Why not use the the new dpdk-dumpcap?

The issue is that adding more to pdump means it now gets a dependency
on BPF.
  

Patch

diff --git a/app/pdump/main.c b/app/pdump/main.c
index 04a38e8911..664a336098 100644
--- a/app/pdump/main.c
+++ b/app/pdump/main.c
@@ -32,6 +32,8 @@ 
 #define CMD_LINE_OPT_PDUMP_NUM 256
 #define CMD_LINE_OPT_MULTI "multi"
 #define CMD_LINE_OPT_MULTI_NUM 257
+#define CMD_LINE_OPT_FILTER "filter"
+#define CMD_LINE_OPT_FILTER_NUM 258
 #define PDUMP_PORT_ARG "port"
 #define PDUMP_PCI_ARG "device_id"
 #define PDUMP_QUEUE_ARG "queue"
@@ -42,10 +44,16 @@ 
 #define PDUMP_MSIZE_ARG "mbuf-size"
 #define PDUMP_NUM_MBUFS_ARG "total-num-mbufs"
 
+#define FILTER_PCAP_FILE_SIZE_ARG "size"
+#define FILTER_PCAP_FILE_SIZE_FLAGS   (1 << 0)
+#define FILTER_SNAPLEN_ARG "snaplen"
+#define FILTER_SNAPLEN_FLAGS   (1 << 1)
+
 #define VDEV_NAME_FMT "net_pcap_%s_%d"
 #define VDEV_PCAP_ARGS_FMT "tx_pcap=%s"
 #define VDEV_IFACE_ARGS_FMT "tx_iface=%s"
 #define TX_STREAM_SIZE 64
+#define PCAP_MIN_SNAPLEN 64
 
 #define MP_NAME "pdump_pool_%d"
 
@@ -64,6 +72,7 @@ 
 #define MAX_LONG_OPT_SZ 64
 #define RING_SIZE 16384
 #define SIZE 256
+#define VDEV_ARGS_SIZE 1024
 #define BURST_SIZE 32
 #define NUM_VDEVS 2
 /* Maximum delay for exiting after primary process. */
@@ -100,6 +109,12 @@  static const char * const valid_pdump_arguments[] = {
 	NULL
 };
 
+static const char * const valid_filter_arguments[] = {
+	FILTER_PCAP_FILE_SIZE_ARG,
+	FILTER_SNAPLEN_ARG,
+	NULL
+};
+
 struct pdump_stats {
 	uint64_t dequeue_pkts;
 	uint64_t tx_pkts;
@@ -136,6 +151,14 @@  struct pdump_tuples {
 } __rte_cache_aligned;
 static struct pdump_tuples pdump_t[APP_ARG_TCPDUMP_MAX_TUPLES];
 
+struct pdump_filter {
+	uint64_t filter_flags;
+	uint32_t pcap_file_size;
+	uint16_t snaplen;
+} __rte_cache_aligned;
+static struct pdump_filter filter_t;
+
+static uint32_t pcap_data_size;
 struct parse_val {
 	uint64_t min;
 	uint64_t max;
@@ -160,7 +183,9 @@  pdump_usage(const char *prgname)
 			" 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",
+			"[total-num-mbufs=<number of mbufs>default:65535]'"
+			" --"CMD_LINE_OPT_FILTER" "
+			"'[size=<pcap size[K/k/M/m/G/g]>],[snaplen=<pkglen>]'\n",
 			prgname);
 }
 
@@ -243,6 +268,39 @@  parse_uint_value(const char *key, const char *value, void *extra_args)
 	return 0;
 }
 
+static int
+__parse_size(const char *key __rte_unused, const char *value,
+		void *extra_args)
+{
+	const char *str_size = NULL;
+	char *p1, *p2;
+	char *end;
+	int *val = extra_args;
+	int size = 0;
+
+	str_size = strdup(value);
+	p1 = strchr(str_size, 'K');
+	p2 = strchr(str_size, 'k');
+	if (p1 || p2)
+		size = strtoul(str_size, &end, 10) * 1024;
+	else {
+		p1 = strchr(str_size, 'M');
+		p2 = strchr(str_size, 'm');
+		if (p1 || p2)
+			size = strtoul(str_size, &end, 10) * 1024 * 1024;
+		else {
+			p1 = strchr(str_size, 'G');
+			p2 = strchr(str_size, 'g');
+			if (p1 || p2)
+				size = strtoul(str_size, &end, 10) * 1024 * 1024 * 1024;
+			else
+				size = strtoul(str_size, &end, 10);
+		}
+	}
+	*val = (uint32_t)size;
+	return 0;
+}
+
 static int
 parse_pdump(const char *optarg)
 {
@@ -377,6 +435,46 @@  parse_pdump(const char *optarg)
 	return ret;
 }
 
+static int
+parse_filter(const char *optarg)
+{
+	int ret = 0, cnt;
+	struct parse_val v = {0};
+	struct rte_kvargs *kvlist;
+	struct pdump_filter *ft = &filter_t;
+	/* initial check for invalid arguments */
+	kvlist = rte_kvargs_parse(optarg, valid_filter_arguments);
+	if (kvlist == NULL) {
+		printf("--filter=\"%s\": invalid argument passed\n", optarg);
+		return -1;
+	}
+	cnt = rte_kvargs_count(kvlist, FILTER_PCAP_FILE_SIZE_ARG);
+	if (cnt == 1) {
+		ret = rte_kvargs_process(kvlist, FILTER_PCAP_FILE_SIZE_ARG,
+						&__parse_size, &ft->pcap_file_size);
+		if (ret < 0)
+			goto free_kvlist;
+
+		ft->filter_flags |= FILTER_PCAP_FILE_SIZE_FLAGS;
+	}
+
+	cnt = rte_kvargs_count(kvlist, FILTER_SNAPLEN_ARG);
+	if (cnt == 1) {
+		v.min = PCAP_MIN_SNAPLEN;
+		v.max = 65535;
+		ret = rte_kvargs_process(kvlist, FILTER_SNAPLEN_ARG,
+						&parse_uint_value, &v);
+		if (ret < 0)
+			goto free_kvlist;
+		ft->snaplen = (uint32_t)v.val;
+		ft->filter_flags |= FILTER_SNAPLEN_FLAGS;
+	}
+free_kvlist:
+	rte_kvargs_free(kvlist);
+	return ret;
+}
+
+
 /* Parse the argument given in the command line of the application */
 static int
 launch_args_parse(int argc, char **argv, char *prgname)
@@ -386,6 +484,7 @@  launch_args_parse(int argc, char **argv, char *prgname)
 	static struct option long_option[] = {
 		{CMD_LINE_OPT_PDUMP, 1, 0, CMD_LINE_OPT_PDUMP_NUM},
 		{CMD_LINE_OPT_MULTI, 0, 0, CMD_LINE_OPT_MULTI_NUM},
+		{CMD_LINE_OPT_FILTER, 1, 0, CMD_LINE_OPT_FILTER_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -406,6 +505,13 @@  launch_args_parse(int argc, char **argv, char *prgname)
 		case CMD_LINE_OPT_MULTI_NUM:
 			multiple_core_capture = 1;
 			break;
+		case CMD_LINE_OPT_FILTER_NUM:
+			ret = parse_filter(optarg);
+			if (ret) {
+				pdump_usage(prgname);
+				return -1;
+			}
+			break;
 		default:
 			pdump_usage(prgname);
 			return -1;
@@ -458,9 +564,38 @@  disable_pdump(struct pdump_tuples *pt)
 		rte_pdump_disable(pt->port, pt->queue, pt->dir);
 }
 
+static inline int pdump_filter_pcap_size(struct rte_mbuf **pkts, uint16_t nb_in_deq)
+{
+	int ret = 1;
+	int i = 0;
+	uint32_t data_len = 0;
+
+	if (likely(!(filter_t.filter_flags & FILTER_PCAP_FILE_SIZE_FLAGS)))
+		return 1;
+
+	if (filter_t.filter_flags & FILTER_PCAP_FILE_SIZE_FLAGS) {
+		for (i = 0; i < nb_in_deq; i++) {
+			data_len = rte_pktmbuf_pkt_len(pkts[i]);
+			if (filter_t.filter_flags & FILTER_SNAPLEN_FLAGS) {
+				if (data_len > filter_t.snaplen)
+					data_len = filter_t.snaplen;
+			}
+			pcap_data_size += data_len;
+		}
+		if (pcap_data_size >= filter_t.pcap_file_size) {
+			printf("recv packet total size: %u, will exit...\n",
+				pcap_data_size);
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
+
 static inline void
 pdump_rxtx(struct rte_ring *ring, uint16_t vdev_id, struct pdump_stats *stats)
 {
+	int ret = 0;
 	/* write input packets of port to vdev for pdump */
 	struct rte_mbuf *rxtx_bufs[BURST_SIZE];
 
@@ -468,7 +603,7 @@  pdump_rxtx(struct rte_ring *ring, uint16_t vdev_id, struct pdump_stats *stats)
 	const uint16_t nb_in_deq = rte_ring_dequeue_burst(ring,
 			(void *)rxtx_bufs, BURST_SIZE, NULL);
 	stats->dequeue_pkts += nb_in_deq;
-
+	ret = pdump_filter_pcap_size(rxtx_bufs, nb_in_deq);
 	if (nb_in_deq) {
 		/* then sent on vdev */
 		uint16_t nb_in_txd = rte_eth_tx_burst(
@@ -483,6 +618,8 @@  pdump_rxtx(struct rte_ring *ring, uint16_t vdev_id, struct pdump_stats *stats)
 			stats->freed_pkts += drops;
 		}
 	}
+	if (!ret)
+		quit_signal = 1;
 }
 
 static void
@@ -622,6 +759,52 @@  configure_vdev(uint16_t port_id)
 	return 0;
 }
 
+static int
+get_vdev_rx_args(char *vdev_args, int size, struct pdump_tuples *pt)
+{
+	int args_len = 0;
+	if (!vdev_args || size < 0)
+		return -1;
+	char *str = pt->rx_dev;
+
+	if (pt->rx_vdev_stream_type == IFACE) {
+		args_len += snprintf(vdev_args + args_len, size - args_len,
+				VDEV_IFACE_ARGS_FMT, str);
+	} else {
+		args_len += snprintf(vdev_args + args_len, size - args_len,
+				VDEV_PCAP_ARGS_FMT, str);
+	}
+	if ((filter_t.filter_flags & FILTER_SNAPLEN_FLAGS) &&
+		 filter_t.snaplen >= PCAP_MIN_SNAPLEN) {
+		args_len += snprintf(vdev_args + args_len, size - args_len,
+			","FILTER_SNAPLEN_ARG"=%d", filter_t.snaplen);
+	}
+	return args_len;
+}
+
+
+static int
+get_vdev_tx_args(char *vdev_args, int size, struct pdump_tuples *pt)
+{
+	int args_len = 0;
+	if (!vdev_args || size < 0)
+		return -1;
+	char *str = pt->tx_dev;
+	if (pt->tx_vdev_stream_type == IFACE) {
+		args_len += snprintf(vdev_args + args_len, size - args_len,
+				VDEV_IFACE_ARGS_FMT, str);
+	} else {
+		args_len += snprintf(vdev_args + args_len, size	 - args_len,
+				VDEV_PCAP_ARGS_FMT, str);
+	}
+	if ((filter_t.filter_flags & FILTER_SNAPLEN_FLAGS) &&
+		filter_t.snaplen >= PCAP_MIN_SNAPLEN) {
+		args_len += snprintf(vdev_args + args_len, size	 - args_len,
+			","FILTER_SNAPLEN_ARG"=%d", filter_t.snaplen);
+	}
+	return args_len;
+}
+
 static void
 create_mp_ring_vdev(void)
 {
@@ -630,7 +813,7 @@  create_mp_ring_vdev(void)
 	struct pdump_tuples *pt = NULL;
 	struct rte_mempool *mbuf_pool = NULL;
 	char vdev_name[SIZE];
-	char vdev_args[SIZE];
+	char vdev_args[VDEV_ARGS_SIZE];
 	char ring_name[SIZE];
 	char mempool_name[SIZE];
 
@@ -681,11 +864,7 @@  create_mp_ring_vdev(void)
 			/* create vdevs */
 			snprintf(vdev_name, sizeof(vdev_name),
 				 VDEV_NAME_FMT, RX_STR, i);
-			(pt->rx_vdev_stream_type == IFACE) ?
-			snprintf(vdev_args, sizeof(vdev_args),
-				 VDEV_IFACE_ARGS_FMT, pt->rx_dev) :
-			snprintf(vdev_args, sizeof(vdev_args),
-				 VDEV_PCAP_ARGS_FMT, pt->rx_dev);
+			get_vdev_rx_args(vdev_args, sizeof(vdev_args), pt);
 			if (rte_eal_hotplug_add("vdev", vdev_name,
 						vdev_args) < 0) {
 				cleanup_rings();
@@ -711,11 +890,7 @@  create_mp_ring_vdev(void)
 			else {
 				snprintf(vdev_name, sizeof(vdev_name),
 					 VDEV_NAME_FMT, TX_STR, i);
-				(pt->rx_vdev_stream_type == IFACE) ?
-				snprintf(vdev_args, sizeof(vdev_args),
-					 VDEV_IFACE_ARGS_FMT, pt->tx_dev) :
-				snprintf(vdev_args, sizeof(vdev_args),
-					 VDEV_PCAP_ARGS_FMT, pt->tx_dev);
+				get_vdev_tx_args(vdev_args, sizeof(vdev_args), pt);
 				if (rte_eal_hotplug_add("vdev", vdev_name,
 							vdev_args) < 0) {
 					cleanup_rings();
@@ -751,11 +926,7 @@  create_mp_ring_vdev(void)
 
 			snprintf(vdev_name, sizeof(vdev_name),
 				 VDEV_NAME_FMT, RX_STR, i);
-			(pt->rx_vdev_stream_type == IFACE) ?
-			snprintf(vdev_args, sizeof(vdev_args),
-				 VDEV_IFACE_ARGS_FMT, pt->rx_dev) :
-			snprintf(vdev_args, sizeof(vdev_args),
-				 VDEV_PCAP_ARGS_FMT, pt->rx_dev);
+			get_vdev_rx_args(vdev_args, sizeof(vdev_args), pt);
 			if (rte_eal_hotplug_add("vdev", vdev_name,
 						vdev_args) < 0) {
 				cleanup_rings();
@@ -788,11 +959,7 @@  create_mp_ring_vdev(void)
 
 			snprintf(vdev_name, sizeof(vdev_name),
 				 VDEV_NAME_FMT, TX_STR, i);
-			(pt->tx_vdev_stream_type == IFACE) ?
-			snprintf(vdev_args, sizeof(vdev_args),
-				 VDEV_IFACE_ARGS_FMT, pt->tx_dev) :
-			snprintf(vdev_args, sizeof(vdev_args),
-				 VDEV_PCAP_ARGS_FMT, pt->tx_dev);
+			get_vdev_tx_args(vdev_args, sizeof(vdev_args), pt);
 			if (rte_eal_hotplug_add("vdev", vdev_name,
 						vdev_args) < 0) {
 				cleanup_rings();