All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] graph: add support for pcap trace for graph
@ 2022-12-23 12:02 Amit Prakash Shukla
  2022-12-23 16:47 ` Stephen Hemminger
  2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  0 siblings, 2 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2022-12-23 12:02 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Packets are captured at each graph node with the node and mbuf metadata
as part of the pcap.

This is inspired from VPP.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
 doc/guides/sample_app_ug/l3_forward_graph.rst |   3 +
 examples/l3fwd-graph/main.c                   |  12 +
 lib/graph/graph_pcap_trace.c                  | 337 ++++++++++++++++++
 lib/graph/graph_populate.c                    |   6 +-
 lib/graph/meson.build                         |   5 +-
 lib/graph/rte_graph_pcap_trace.h              | 149 ++++++++
 lib/graph/rte_graph_worker.h                  |   6 +
 7 files changed, 515 insertions(+), 3 deletions(-)
 create mode 100644 lib/graph/graph_pcap_trace.c
 create mode 100644 lib/graph/rte_graph_pcap_trace.h

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..cf199bcf81 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,7 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
 
 Where,
 
@@ -69,6 +70,8 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..b6408310aa 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -404,6 +404,7 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +417,7 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +426,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
 	{NULL, 0, 0, 0},
 };
 
@@ -498,6 +501,11 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			set_pcap_trace(1);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -831,6 +839,7 @@ main(int argc, char **argv)
 			local_port_conf.txmode.offloads |=
 				RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
 
+		local_port_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
 		local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
 			dev_info.flow_type_rss_offloads;
 		if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
@@ -1116,6 +1125,9 @@ main(int argc, char **argv)
 	}
 	/* >8 End of adding route to ip4 graph infa. */
 
+	if (is_pcap_trace_enable())
+		rte_graph_pcap_trace_init();
+
 	/* Launch per-lcore init on every worker lcore */
 	rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MAIN);
 
diff --git a/lib/graph/graph_pcap_trace.c b/lib/graph/graph_pcap_trace.c
new file mode 100644
index 0000000000..c5be07de6d
--- /dev/null
+++ b/lib/graph/graph_pcap_trace.c
@@ -0,0 +1,337 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#include <unistd.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_net.h>
+#include <rte_flow.h>
+
+#include "rte_graph_worker.h"
+
+#define RTE_PCAP_MAJOR_VERSION 1
+#define RTE_PCAP_MINOR_VERSION 0
+#define MAX_PKT_TO_CAPTURE 200
+#define MAX_PCAP_BUF_SZ 2048
+
+#define PCAP_DUMP_STR(buf, buf_size, cur_len, ...)                           \
+do {                                                                         \
+	if (cur_len >= buf_size)                                             \
+		break;                                                       \
+	cur_len += snprintf(buf + cur_len, buf_size - cur_len, __VA_ARGS__); \
+} while (0)
+
+#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)                   \
+do {                                                                         \
+	if ((cur_len + len) >= buf_size)                                     \
+		break;                                                       \
+	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
+	cur_len += len;                                                      \
+} while (0)
+
+static int pcap_trace_enable;
+static pcap_trace_t pcap_trace;
+
+static uint16_t pkt_metadata_dump(struct rte_mbuf *mbuf, char *buffer,
+				  size_t buf_size, uint16_t cur_len);
+static int pcap_trace_close(void);
+static int pcap_trace_write(void);
+
+void
+rte_graph_pcap_trace_init(void)
+{
+	memset(&pcap_trace, 0, sizeof(pcap_trace_t));
+	rte_spinlock_init(&pcap_trace.lock);
+	pcap_trace.packet_type = PCAP_PACKET_TYPE_USER13;
+	pcap_trace.n_packets_to_capture = MAX_PKT_TO_CAPTURE;
+	pcap_trace.file_name = "/tmp/dpdk.pcap";
+	pcap_trace.pcap_data = NULL;
+}
+
+void
+set_pcap_trace(int val)
+{
+	pcap_trace_enable = val;
+}
+
+int
+is_pcap_trace_enable(void)
+{
+	return pcap_trace_enable;
+}
+
+static int
+pcap_trace_close(void)
+{
+	close(pcap_trace.file_descriptor);
+	pcap_trace.file_descriptor = -1;
+	return 0;
+}
+
+static int
+pcap_trace_write(void)
+{
+	pcap_file_header_t file_hdr;
+	int ret = 0;
+	int n;
+
+	if (!pcap_trace.file_name)
+		pcap_trace.file_name = "/tmp/dpdk.pcap";
+
+	pcap_trace.file_descriptor = open(pcap_trace.file_name,
+					  O_CREAT | O_TRUNC | O_WRONLY, 0664);
+	if (pcap_trace.file_descriptor < 0) {
+		ret = 1;
+		goto done;
+	}
+	pcap_trace.n_pcap_data_written = 0;
+
+	/* Write file header. */
+	memset(&file_hdr, 0, sizeof(file_hdr));
+	file_hdr.magic = 0xa1b2c3d4;
+	file_hdr.major_version = 2;
+	file_hdr.minor_version = 4;
+	file_hdr.time_zone = 0;
+	file_hdr.max_packet_size_in_bytes = ((1 << 16) - 1);
+	file_hdr.packet_type = pcap_trace.packet_type;
+	n = write(pcap_trace.file_descriptor, &file_hdr, sizeof(file_hdr));
+	if (n != sizeof(file_hdr)) {
+		ret = 1;
+		goto done;
+	}
+
+	while (pcap_trace.n_bytes > pcap_trace.n_pcap_data_written) {
+		int n = pcap_trace.n_bytes - pcap_trace.n_pcap_data_written;
+
+		n = write(pcap_trace.file_descriptor,
+			  (pcap_trace.pcap_data +
+			   pcap_trace.n_pcap_data_written), n);
+
+		if (n < 0 && errno != 0) {
+			ret = 1;
+			goto done;
+		}
+
+		pcap_trace.n_pcap_data_written += n;
+	}
+
+	if (pcap_trace.n_pcap_data_written >= pcap_trace.n_bytes)	{
+		rte_free(pcap_trace.pcap_data);
+		pcap_trace.pcap_data = NULL;
+		pcap_trace.n_pcap_data_written = 0;
+	}
+
+	if (pcap_trace.n_packets_captured >=
+	    pcap_trace.n_packets_to_capture)
+		pcap_trace_close();
+
+done:
+	if (ret) {
+		if (pcap_trace.file_descriptor >= 0)
+			pcap_trace_close();
+	}
+
+	return ret;
+}
+
+static uint16_t
+pkt_metadata_dump(struct rte_mbuf *mbuf, char *buffer, size_t buf_size,
+		  uint16_t cur_len)
+{
+	struct rte_flow_restore_info info = { 0, };
+	struct rte_net_hdr_lens hdr_lens;
+	struct rte_flow_error error;
+	uint32_t sw_packet_type;
+	uint64_t ol_flags;
+	char buf[256];
+	int ret;
+
+	ret = rte_flow_get_restore_info(mbuf->port, mbuf, &info, &error);
+	if (!ret) {
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "restore info:");
+
+		if (info.flags & RTE_FLOW_RESTORE_INFO_ENCAPSULATED)
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "outer header present. ");
+		else
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "no outer header. ");
+		if (info.flags & RTE_FLOW_RESTORE_INFO_GROUP_ID)
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "miss group %u", info.group_id);
+		else
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "no miss group");
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "\n");
+	}
+
+	PCAP_DUMP_STR(buffer, buf_size, cur_len,
+		      "pool=%s  length=%u  nb_segs=%d\n", mbuf->pool->name,
+		      (unsigned int) mbuf->pkt_len, (int)mbuf->nb_segs);
+
+	ol_flags = mbuf->ol_flags;
+	if (ol_flags & RTE_MBUF_F_RX_RSS_HASH) {
+		PCAP_DUMP_STR(buffer, buf_size, cur_len,
+			      "RSS hash=0x%x\n",
+			      (unsigned int) mbuf->hash.rss);
+	}
+
+	if (ol_flags & RTE_MBUF_F_RX_FDIR) {
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "FDIR matched ");
+		if (ol_flags & RTE_MBUF_F_RX_FDIR_ID)
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "ID=0x%x\n", mbuf->hash.fdir.hi);
+		else if (ol_flags & RTE_MBUF_F_RX_FDIR_FLX)
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "flex bytes=0x%08x %08x\n",
+				      mbuf->hash.fdir.hi, mbuf->hash.fdir.lo);
+		else
+			PCAP_DUMP_STR(buffer, buf_size, cur_len,
+				      "hash=0x%x ID=0x%x\n",
+				      mbuf->hash.fdir.hash, mbuf->hash.fdir.id);
+	}
+
+	if (ol_flags & RTE_MBUF_F_RX_QINQ)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len,
+			      "QinQ VLAN tci=0x%x, VLAN tci outer=0x%x\n",
+			      mbuf->vlan_tci, mbuf->vlan_tci_outer);
+	else if (ol_flags & RTE_MBUF_F_RX_VLAN)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "VLAN tci=0x%x\n",
+			      mbuf->vlan_tci);
+
+	if (mbuf->packet_type) {
+		rte_get_ptype_name(mbuf->packet_type, buf, sizeof(buf));
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "hw ptype: %s\n",
+			      buf);
+	}
+
+	sw_packet_type = rte_net_get_ptype(mbuf, &hdr_lens, RTE_PTYPE_ALL_MASK);
+	rte_get_ptype_name(sw_packet_type, buf, sizeof(buf));
+	PCAP_DUMP_STR(buffer, buf_size, cur_len, "sw ptype: %s\n", buf);
+
+	if (sw_packet_type & RTE_PTYPE_L2_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "l2_len=%d  ",
+			      hdr_lens.l2_len);
+	if (sw_packet_type & RTE_PTYPE_L3_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "l3_len=%d  ",
+			      hdr_lens.l3_len);
+	if (sw_packet_type & RTE_PTYPE_L4_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len, "l4_len=%d  ",
+			      hdr_lens.l4_len);
+	if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len,
+			      "tunnel_len=%d  ", hdr_lens.tunnel_len);
+	if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len,
+			      "inner_l2_len=%d  ", hdr_lens.inner_l2_len);
+	if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len,
+			      "inner_l3_len=%d  ", hdr_lens.inner_l3_len);
+	if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK)
+		PCAP_DUMP_STR(buffer, buf_size, cur_len,
+			      "inner_l4_len=%d  ", hdr_lens.inner_l4_len);
+
+	PCAP_DUMP_STR(buffer, buf_size, cur_len, "\n");
+
+	rte_get_rx_ol_flag_list(mbuf->ol_flags, buf, sizeof(buf));
+	PCAP_DUMP_STR(buffer, buf_size, cur_len, "Rx ol_flags: %s\n", buf);
+
+	rte_get_tx_ol_flag_list(mbuf->ol_flags, buf, sizeof(buf));
+	PCAP_DUMP_STR(buffer, buf_size, cur_len, "Tx ol_flags: %s\n", buf);
+
+	/* Keep it last. */
+	buffer[cur_len++] = '\0';
+	return cur_len;
+}
+
+uint16_t
+rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	struct rte_mbuf *mbuf;
+	pcap_packet_header_t *phdr;
+	pcap_version_hdr_t vhdr = {0};
+	struct timeval ts = {0};
+	char buffer[MAX_PCAP_BUF_SZ] = {0};
+	uint16_t total_len, n_bytes, cb_len;
+	uint8_t *pkt_data;
+	uint8_t *data;
+	int i;
+
+	gettimeofday(&ts, NULL);
+
+	for (i = 0; i < nb_objs; i++) {
+		if (pcap_trace.n_packets_captured >=
+		    pcap_trace.n_packets_to_capture)
+			break;
+
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		memset(buffer, 0, sizeof(buffer));
+		cb_len = 0;
+		total_len = 0;
+		n_bytes = 0;
+
+		vhdr.pcap_major_version = (uint8_t)RTE_PCAP_MAJOR_VERSION;
+		vhdr.pcap_minor_version = (uint8_t)RTE_PCAP_MINOR_VERSION;
+		PCAP_DUMP_DATA(buffer, MAX_PCAP_BUF_SZ, cb_len, &vhdr,
+			       sizeof(pcap_version_hdr_t));
+
+		PCAP_DUMP_DATA(buffer, MAX_PCAP_BUF_SZ, cb_len, node->name,
+			       (strlen(node->name) + 1));
+
+		PCAP_DUMP_DATA(buffer, MAX_PCAP_BUF_SZ, cb_len, node->ctx,
+			       RTE_NODE_CTX_SZ);
+
+		cb_len = pkt_metadata_dump(mbuf, buffer, sizeof(buffer),
+					   cb_len);
+
+		total_len = cb_len + mbuf->pkt_len +
+				sizeof(pcap_packet_header_t);
+		n_bytes = RTE_MIN((int)total_len, 16384);
+
+		rte_spinlock_lock(&pcap_trace.lock);
+
+		if (pcap_trace.pcap_data == NULL) {
+			pcap_trace.pcap_data = rte_malloc(NULL, n_bytes, 0);
+			phdr = (pcap_packet_header_t *)pcap_trace.pcap_data;
+		} else {
+			pcap_trace.pcap_data = rte_realloc(
+					pcap_trace.pcap_data,
+					(pcap_trace.n_bytes + n_bytes), 0);
+
+			phdr = (pcap_packet_header_t *)(pcap_trace.pcap_data +
+					pcap_trace.n_bytes);
+		}
+
+		phdr->time_in_sec = (uint32_t)ts.tv_sec;
+		phdr->time_in_usec = (uint32_t)ts.tv_usec;
+		phdr->n_packet_bytes_stored_in_file =
+				(n_bytes - sizeof(pcap_packet_header_t));
+		phdr->n_bytes_in_packet =
+				(total_len - sizeof(pcap_packet_header_t));
+		data = phdr->data;
+
+		rte_memcpy(data, buffer, cb_len);
+		data += cb_len;
+
+		pkt_data = rte_pktmbuf_mtod(mbuf, uint8_t *);
+		rte_memcpy(data, pkt_data, (RTE_MIN((n_bytes - cb_len),
+			   mbuf->data_len)));
+
+		pcap_trace.n_bytes += n_bytes;
+		pcap_trace.n_packets_captured++;
+
+		if (pcap_trace.n_packets_captured == MAX_PKT_TO_CAPTURE)
+			pcap_trace_write();
+
+		rte_spinlock_unlock(&pcap_trace.lock);
+	}
+
+	return node->p_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..36f81505df 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -75,7 +75,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (is_pcap_trace_enable()) {
+			node->process = rte_graph_pcap_trace_dispatch;
+			node->p_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..6cd9d836d9 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap_trace.c',
 )
-headers = files('rte_graph.h', 'rte_graph_worker.h')
+headers = files('rte_graph.h', 'rte_graph_worker.h', 'rte_graph_pcap_trace.h')
 
-deps += ['eal']
+deps += ['eal', 'mbuf', 'mempool', 'net', 'ethdev']
diff --git a/lib/graph/rte_graph_pcap_trace.h b/lib/graph/rte_graph_pcap_trace.h
new file mode 100644
index 0000000000..e2faf6205f
--- /dev/null
+++ b/lib/graph/rte_graph_pcap_trace.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#ifndef _DPDK_GRAPH_PCAP_TRACE_H_
+#define _DPDK_GRAPH_PCAP_TRACE_H_
+
+/**
+ * @file rte_graph_pcap_trace.h
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
+ * This API enables to capture packet at each node with mbuf and node metadata.
+ *
+ */
+
+#include <rte_spinlock.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * User packet type used in pcap file is used by wireshark to lookup into the
+ * DLT table to know which protocol(s) to use for each DLT.
+ */
+typedef enum {
+	PCAP_PACKET_TYPE_USER0 = 147,
+	PCAP_PACKET_TYPE_USER1,
+	PCAP_PACKET_TYPE_USER2,
+	PCAP_PACKET_TYPE_USER3,
+	PCAP_PACKET_TYPE_USER4,
+	PCAP_PACKET_TYPE_USER5,
+	PCAP_PACKET_TYPE_USER6,
+	PCAP_PACKET_TYPE_USER7,
+	PCAP_PACKET_TYPE_USER8,
+	PCAP_PACKET_TYPE_USER9,
+	PCAP_PACKET_TYPE_USER10,
+	PCAP_PACKET_TYPE_USER11,
+	PCAP_PACKET_TYPE_USER12,
+	PCAP_PACKET_TYPE_USER13,
+	PCAP_PACKET_TYPE_USER14,
+	PCAP_PACKET_TYPE_USER15,
+} pcap_packet_type_t;
+
+/**
+ * Pcap file shall contain a header at the start of the file. Parameters are
+ * dissected by the wireshark to display the data.
+ */
+typedef struct pcap_file_header {
+	uint32_t magic;
+	uint16_t major_version;
+	uint16_t minor_version;
+	uint32_t time_zone;
+	uint32_t sigfigs;
+	uint32_t max_packet_size_in_bytes;
+	uint32_t packet_type;
+} pcap_file_header_t;
+
+/**
+ * Each packet shall be prepended by the packet header.
+ */
+typedef struct pcap_packet_header_t {
+	uint32_t time_in_sec;
+	uint32_t time_in_usec;
+	uint32_t n_packet_bytes_stored_in_file;
+	uint32_t n_bytes_in_packet;
+	/** Packet data follows. */
+	uint8_t data[0];
+} pcap_packet_header_t;
+
+/**
+ * Pcap version header.
+ */
+typedef struct pcap_version_hdr {
+	uint8_t pcap_major_version;
+	uint8_t pcap_minor_version;
+} pcap_version_hdr_t;
+
+/**
+ * Book-keeping of the packets captured.
+ */
+typedef struct pcap_trace {
+	rte_spinlock_t lock;
+	const char *file_name;
+	uint32_t n_packets_to_capture;
+	uint32_t n_bytes;
+	pcap_packet_type_t packet_type;
+	uint32_t n_packets_captured;
+	int file_descriptor;
+	uint32_t n_pcap_data_written;
+	uint8_t *pcap_data;
+} pcap_trace_t;
+
+/**
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+void set_pcap_trace(int val);
+
+/**
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+int is_pcap_trace_enable(void);
+
+/**
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled from the
+ * application.
+ *
+ */
+void rte_graph_pcap_trace_init(void);
+
+/**
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+				       struct rte_node *node, void **objs,
+				       uint16_t nb_objs);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DPDK_GRAPH_PCAP_TRACE_H_ */
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..64c18421d5 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -24,6 +24,7 @@
 #include <rte_memory.h>
 
 #include "rte_graph.h"
+#include "rte_graph_pcap_trace.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,6 +65,11 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	union {
+		rte_node_process_t p_process; /**< Process function. */
+		uint64_t p_process_u64;
+	};
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [RFC PATCH] graph: add support for pcap trace for graph
  2022-12-23 12:02 [RFC PATCH] graph: add support for pcap trace for graph Amit Prakash Shukla
@ 2022-12-23 16:47 ` Stephen Hemminger
  2023-01-06 10:40   ` [EXT] " Amit Prakash Shukla
  2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  1 sibling, 1 reply; 47+ messages in thread
From: Stephen Hemminger @ 2022-12-23 16:47 UTC (permalink / raw)
  To: Amit Prakash Shukla; +Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, dev

On Fri, 23 Dec 2022 17:32:35 +0530
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> +
> +	pcap_trace.file_descriptor = open(pcap_trace.file_name,
> +					  O_CREAT | O_TRUNC | O_WRONLY, 0664);
> +	if (pcap_trace.file_descriptor < 0) {
> +		ret = 1;
> +		goto done;
> +	}
> +	pcap_trace.n_pcap_data_written = 0;
> +
> +	/* Write file header. */
> +	memset(&file_hdr, 0, sizeof(file_hdr));
> +	file_hdr.magic = 0xa1b2c3d4;
> +	file_hdr.major_version = 2;
> +	file_hdr.minor_version = 4;
> +	file_hdr.time_zone = 0;
> +	file_hdr.max_packet_size_in_bytes = ((1 << 16) - 1);
> +	file_hdr.packet_type = pcap_trace.packet_type;
> +	n = write(pcap_trace.file_descriptor, &file_hdr, sizeof(file_hdr));
> +	if (n != sizeof(file_hdr)) {
> +		ret = 1;
> +		goto done;
> +	}
> +
> +	while (pcap_trace.n_bytes > pcap_trace.n_pcap_data_written) {
> +		int n = pcap_trace.n_bytes - pcap_trace.n_pcap_data_written;
> +
> +		n = write(pcap_trace.file_descriptor,

NAK please use lib/pcapng rather than rolling your own pcap format code

^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for graph
  2022-12-23 16:47 ` Stephen Hemminger
@ 2023-01-06 10:40   ` Amit Prakash Shukla
  2023-01-06 16:41     ` Stephen Hemminger
  2023-01-06 18:56     ` Stephen Hemminger
  0 siblings, 2 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-06 10:40 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

Thanks Stephen for the review. Sure, will use lib/pcapng.

I see dpdk libpcapng adds most of the debugging data, however I would like to add a node name to the packets which I am thinking of adding using 'comment' option under 'Enhanced Packet Block' .

Please let me know if that's fine.

Thanks,
Amit Shukla

> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Friday, December 23, 2022 10:17 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; dev@dpdk.org
> Subject: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for graph
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Fri, 23 Dec 2022 17:32:35 +0530
> Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> 
> > +
> > +	pcap_trace.file_descriptor = open(pcap_trace.file_name,
> > +					  O_CREAT | O_TRUNC | O_WRONLY,
> 0664);
> > +	if (pcap_trace.file_descriptor < 0) {
> > +		ret = 1;
> > +		goto done;
> > +	}
> > +	pcap_trace.n_pcap_data_written = 0;
> > +
> > +	/* Write file header. */
> > +	memset(&file_hdr, 0, sizeof(file_hdr));
> > +	file_hdr.magic = 0xa1b2c3d4;
> > +	file_hdr.major_version = 2;
> > +	file_hdr.minor_version = 4;
> > +	file_hdr.time_zone = 0;
> > +	file_hdr.max_packet_size_in_bytes = ((1 << 16) - 1);
> > +	file_hdr.packet_type = pcap_trace.packet_type;
> > +	n = write(pcap_trace.file_descriptor, &file_hdr, sizeof(file_hdr));
> > +	if (n != sizeof(file_hdr)) {
> > +		ret = 1;
> > +		goto done;
> > +	}
> > +
> > +	while (pcap_trace.n_bytes > pcap_trace.n_pcap_data_written) {
> > +		int n = pcap_trace.n_bytes -
> pcap_trace.n_pcap_data_written;
> > +
> > +		n = write(pcap_trace.file_descriptor,
> 
> NAK please use lib/pcapng rather than rolling your own pcap format code

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for graph
  2023-01-06 10:40   ` [EXT] " Amit Prakash Shukla
@ 2023-01-06 16:41     ` Stephen Hemminger
  2023-01-06 18:56     ` Stephen Hemminger
  1 sibling, 0 replies; 47+ messages in thread
From: Stephen Hemminger @ 2023-01-06 16:41 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

On Fri, 6 Jan 2023 10:40:30 +0000
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> Thanks Stephen for the review. Sure, will use lib/pcapng.
> 
> I see dpdk libpcapng adds most of the debugging data, however I would like to add a node name to the packets which I am thinking of adding using 'comment' option under 'Enhanced Packet Block' .
> 
> Please let me know if that's fine.
> 
> Thanks,
> Amit Shukla

The pcapng supports comment on file, and the revised version has more interface info.
If you want comment on a per-packet basis that should not be a major change.

Rather than node name, maybe packet id would be better (epb_packetid)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for graph
  2023-01-06 10:40   ` [EXT] " Amit Prakash Shukla
  2023-01-06 16:41     ` Stephen Hemminger
@ 2023-01-06 18:56     ` Stephen Hemminger
  2023-01-10 11:26       ` Amit Prakash Shukla
  1 sibling, 1 reply; 47+ messages in thread
From: Stephen Hemminger @ 2023-01-06 18:56 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

On Fri, 6 Jan 2023 10:40:30 +0000
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> Thanks Stephen for the review. Sure, will use lib/pcapng.
> 
> I see dpdk libpcapng adds most of the debugging data, however I would like to add a node name to the packets which I am thinking of adding using 'comment' option under 'Enhanced Packet Block' .
> 
> Please let me know if that's fine.
> 
> Thanks,
> Amit Shukla
> 
> > -----Original Message-----
> > From: Stephen Hemminger <stephen@networkplumber.org>
> > Sent: Friday, December 23, 2022 10:17 PM
> > To: Amit Prakash Shukla <amitprakashs@marvell.com>
> > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> > Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> > <ndabilpuram@marvell.com>; dev@dpdk.org
> > Subject: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for graph
> > 
> > External Email
> > 
> > ----------------------------------------------------------------------
> > On Fri, 23 Dec 2022 17:32:35 +0530
> > Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> >   
> > > +
> > > +	pcap_trace.file_descriptor = open(pcap_trace.file_name,
> > > +					  O_CREAT | O_TRUNC | O_WRONLY,  
> > 0664);  
> > > +	if (pcap_trace.file_descriptor < 0) {
> > > +		ret = 1;
> > > +		goto done;
> > > +	}
> > > +	pcap_trace.n_pcap_data_written = 0;
> > > +
> > > +	/* Write file header. */
> > > +	memset(&file_hdr, 0, sizeof(file_hdr));
> > > +	file_hdr.magic = 0xa1b2c3d4;
> > > +	file_hdr.major_version = 2;
> > > +	file_hdr.minor_version = 4;
> > > +	file_hdr.time_zone = 0;
> > > +	file_hdr.max_packet_size_in_bytes = ((1 << 16) - 1);
> > > +	file_hdr.packet_type = pcap_trace.packet_type;
> > > +	n = write(pcap_trace.file_descriptor, &file_hdr, sizeof(file_hdr));
> > > +	if (n != sizeof(file_hdr)) {
> > > +		ret = 1;
> > > +		goto done;
> > > +	}
> > > +
> > > +	while (pcap_trace.n_bytes > pcap_trace.n_pcap_data_written) {
> > > +		int n = pcap_trace.n_bytes -  
> > pcap_trace.n_pcap_data_written;  
> > > +
> > > +		n = write(pcap_trace.file_descriptor,  
> > 
> > NAK please use lib/pcapng rather than rolling your own pcap format code  

Something like this:

diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index cb590ea0096c..216ad80f7ed6 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -492,7 +492,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -552,6 +553,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	optlen += pcapng_optlen(sizeof(queue));
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));

 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
@@ -590,6 +593,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}

+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,
+					comment, strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */

 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 6b8aaffc6e0f..98f35e8ea177 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -126,6 +126,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *  Optional: comment on packet
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -137,7 +139,8 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction,
+		const char *comment);


 /**

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for graph
  2023-01-06 18:56     ` Stephen Hemminger
@ 2023-01-10 11:26       ` Amit Prakash Shukla
  0 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-10 11:26 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

Thanks Stephen for the pointers. I will post next version of the patch with the change.


> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Saturday, January 7, 2023 12:27 AM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; dev@dpdk.org
> Subject: Re: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for
> graph
> 
> On Fri, 6 Jan 2023 10:40:30 +0000
> Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> 
> > Thanks Stephen for the review. Sure, will use lib/pcapng.
> >
> > I see dpdk libpcapng adds most of the debugging data, however I would
> like to add a node name to the packets which I am thinking of adding using
> 'comment' option under 'Enhanced Packet Block' .
> >
> > Please let me know if that's fine.
> >
> > Thanks,
> > Amit Shukla
> >
> > > -----Original Message-----
> > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > Sent: Friday, December 23, 2022 10:17 PM
> > > To: Amit Prakash Shukla <amitprakashs@marvell.com>
> > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> > > Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> > > <ndabilpuram@marvell.com>; dev@dpdk.org
> > > Subject: [EXT] Re: [RFC PATCH] graph: add support for pcap trace for
> > > graph
> > >
> > > External Email
> > >
> > > --------------------------------------------------------------------
> > > --
> > > On Fri, 23 Dec 2022 17:32:35 +0530
> > > Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> > >
> > > > +
> > > > +	pcap_trace.file_descriptor = open(pcap_trace.file_name,
> > > > +					  O_CREAT | O_TRUNC | O_WRONLY,
> > > 0664);
> > > > +	if (pcap_trace.file_descriptor < 0) {
> > > > +		ret = 1;
> > > > +		goto done;
> > > > +	}
> > > > +	pcap_trace.n_pcap_data_written = 0;
> > > > +
> > > > +	/* Write file header. */
> > > > +	memset(&file_hdr, 0, sizeof(file_hdr));
> > > > +	file_hdr.magic = 0xa1b2c3d4;
> > > > +	file_hdr.major_version = 2;
> > > > +	file_hdr.minor_version = 4;
> > > > +	file_hdr.time_zone = 0;
> > > > +	file_hdr.max_packet_size_in_bytes = ((1 << 16) - 1);
> > > > +	file_hdr.packet_type = pcap_trace.packet_type;
> > > > +	n = write(pcap_trace.file_descriptor, &file_hdr, sizeof(file_hdr));
> > > > +	if (n != sizeof(file_hdr)) {
> > > > +		ret = 1;
> > > > +		goto done;
> > > > +	}
> > > > +
> > > > +	while (pcap_trace.n_bytes > pcap_trace.n_pcap_data_written) {
> > > > +		int n = pcap_trace.n_bytes -
> > > pcap_trace.n_pcap_data_written;
> > > > +
> > > > +		n = write(pcap_trace.file_descriptor,
> > >
> > > NAK please use lib/pcapng rather than rolling your own pcap format
> > > code
> 
> Something like this:
> 
> diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c index
> cb590ea0096c..216ad80f7ed6 100644
> --- a/lib/pcapng/rte_pcapng.c
> +++ b/lib/pcapng/rte_pcapng.c
> @@ -492,7 +492,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  		const struct rte_mbuf *md,
>  		struct rte_mempool *mp,
>  		uint32_t length, uint64_t cycles,
> -		enum rte_pcapng_direction direction)
> +		enum rte_pcapng_direction direction,
> +		const char *comment)
>  {
>  	struct pcapng_enhance_packet_block *epb;
>  	uint32_t orig_len, data_len, padding, flags; @@ -552,6 +553,8 @@
> rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  	optlen += pcapng_optlen(sizeof(queue));
>  	if (rss_hash)
>  		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
> +	if (comment)
> +		optlen += pcapng_optlen(strlen(comment));
> 
>  	/* reserve trailing options and block length */
>  	opt = (struct pcapng_option *)
> @@ -590,6 +593,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  					&hash_opt, sizeof(hash_opt));
>  	}
> 
> +	if (comment)
> +		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,
> +					comment, strlen(comment));
> +
>  	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
> 
>  	/* Add PCAPNG packet header */
> diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h index
> 6b8aaffc6e0f..98f35e8ea177 100644
> --- a/lib/pcapng/rte_pcapng.h
> +++ b/lib/pcapng/rte_pcapng.h
> @@ -126,6 +126,8 @@ enum rte_pcapng_direction {
>   *   The timestamp in TSC cycles.
>   * @param direction
>   *   The direction of the packer: receive, transmit or unknown.
> + * @param comment
> + *  Optional: comment on packet
>   *
>   * @return
>   *   - The pointer to the new mbuf formatted for pcapng_write
> @@ -137,7 +139,8 @@ struct rte_mbuf *
>  rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  		const struct rte_mbuf *m, struct rte_mempool *mp,
>  		uint32_t length, uint64_t timestamp,
> -		enum rte_pcapng_direction direction);
> +		enum rte_pcapng_direction direction,
> +		const char *comment);
> 
> 
>  /**

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v1 1/3] pcapng: comment option support for epb
  2022-12-23 12:02 [RFC PATCH] graph: add support for pcap trace for graph Amit Prakash Shukla
  2022-12-23 16:47 ` Stephen Hemminger
@ 2023-01-10 11:58 ` Amit Prakash Shukla
  2023-01-10 11:58   ` [PATCH v1 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
                     ` (3 more replies)
  1 sibling, 4 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-10 11:58 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger; +Cc: dev, jerinj, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
 app/test/test_pcapng.c  |  4 ++--
 lib/pcapng/rte_pcapng.c | 11 ++++++++++-
 lib/pcapng/rte_pcapng.h |  4 +++-
 lib/pdump/rte_pdump.c   |  2 +-
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index a7acbdc058..303d3d66f9 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -139,7 +139,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -255,7 +255,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index 80d08e1a3b..b7f67c00c2 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -450,7 +450,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -511,6 +512,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -548,6 +552,11 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment) {
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+	}
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 7d2697c647..6d286cda41 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -100,6 +100,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -111,7 +113,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v1 2/3] graph: pcap capture for graph nodes
  2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
@ 2023-01-10 11:58   ` Amit Prakash Shukla
  2023-01-10 11:58   ` [PATCH v1 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-10 11:58 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
 lib/graph/graph_pcap_trace.c     | 166 +++++++++++++++++++++++++++++++
 lib/graph/graph_populate.c       |   6 +-
 lib/graph/graph_private.h        |  21 ++++
 lib/graph/meson.build            |   5 +-
 lib/graph/rte_graph_pcap_trace.h |  90 +++++++++++++++++
 lib/graph/rte_graph_worker.h     |   3 +
 lib/graph/version.map            |   7 ++
 7 files changed, 295 insertions(+), 3 deletions(-)
 create mode 100644 lib/graph/graph_pcap_trace.c
 create mode 100644 lib/graph/rte_graph_pcap_trace.h

diff --git a/lib/graph/graph_pcap_trace.c b/lib/graph/graph_pcap_trace.c
new file mode 100644
index 0000000000..3a143b3fcf
--- /dev/null
+++ b/lib/graph/graph_pcap_trace.c
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+#include "graph_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_FILE_NAME_SZ	128
+#define GRAPH_PCAP_FILE_NAME	"/tmp/graph_pcap_capture.pcapng"
+
+#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)                   \
+do {                                                                         \
+	if ((cur_len + len) >= buf_size)                                     \
+		break;                                                       \
+	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
+	cur_len += len;                                                      \
+} while (0)
+
+static char file_name[GRAPH_PCAP_FILE_NAME_SZ];
+static uint32_t pkt_buf_sz = RTE_MBUF_DEFAULT_BUF_SIZE;
+static uint64_t packet_to_capture = GRAPH_PCAP_NUM_PACKETS;
+static rte_pcapng_t *pcapng_fd;
+static struct rte_mempool *mp;
+static uint16_t port_id;
+static uint64_t packet_captured[RTE_MAX_LCORE];
+static int pcap_trace_enable;
+
+void
+rte_num_pkt_to_capture(uint64_t val)
+{
+	packet_to_capture = val;
+}
+
+void
+rte_pcap_trace_enable(int val)
+{
+	pcap_trace_enable = val;
+}
+
+int
+rte_pcap_trace_is_enable(void)
+{
+	return pcap_trace_enable;
+}
+
+void
+rte_filename_to_capture_pkt(const char *filename)
+{
+	if (filename[0] == '\0') {
+		rte_strscpy(file_name, GRAPH_PCAP_FILE_NAME,
+		       GRAPH_PCAP_FILE_NAME_SZ);
+	}
+	else
+		rte_strscpy(file_name, filename, GRAPH_PCAP_FILE_NAME_SZ);
+}
+
+void
+rte_graph_pcap_trace_exit(void)
+{
+	rte_pcapng_close(pcapng_fd);
+}
+
+void
+rte_graph_pcap_trace_init(void)
+{
+	int fd;
+
+	port_id = rte_eth_find_next(0);
+	if (port_id >= RTE_MAX_ETHPORTS) {
+		fprintf(stderr, "No valid Ether port\n");
+		return;
+	}
+
+	if (file_name[0] == '\0')
+		rte_strscpy(file_name, GRAPH_PCAP_FILE_NAME,
+			    GRAPH_PCAP_FILE_NAME_SZ);
+
+	fd = open(file_name, O_CREAT | O_TRUNC | O_WRONLY, 0664);
+	if (fd < 0) {
+		perror("pcap file open failure");
+		return;
+	}
+
+	fprintf(stdout, "pcapng: output file %s\n", file_name);
+
+	/* open a test capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer", NULL);
+	if (pcapng_fd == NULL) {
+		fprintf(stderr, "Graph rte_pcapng_fdopen failed\n");
+		close(fd);
+		return;
+	}
+
+	/* Make a pool for cloned packets */
+	mp = rte_pktmbuf_pool_create_by_ops("pcapng_graph_pool",
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,
+			0, 0, rte_pcapng_mbuf_size(pkt_buf_sz),
+			SOCKET_ID_ANY, "ring_mp_sc");
+	if (mp == NULL) {
+		fprintf(stderr, "Cannot create mempool for graph pcap capture\n");
+		rte_pcapng_close(pcapng_fd);
+		return;
+	}
+
+	return;
+}
+
+uint16_t
+rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE] = { };
+	char buffer[GRAPH_PCAP_BUF_SZ] = {0};
+	struct rte_mbuf *mbuf;
+	uint16_t cb_len = 0;
+	ssize_t len;
+	uint16_t gid = graph->id;
+
+	if (!nb_objs || (packet_captured[gid] >= packet_to_capture))
+		goto done;
+
+	num_packets = packet_to_capture - packet_captured[gid];
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	PCAP_DUMP_DATA(buffer, GRAPH_PCAP_BUF_SZ, cb_len, node->name,
+		       (strlen(node->name) + 1));
+
+	for(i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(port_id, 0, mbuf, mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			goto done;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	packet_captured[gid] += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..aa26b1c51d 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -75,7 +75,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (rte_pcap_trace_is_enable()) {
+			node->process = rte_graph_pcap_trace_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..3edbb42692 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -319,6 +319,27 @@ struct rte_node *graph_node_id_to_ptr(const struct rte_graph *graph,
 struct rte_node *graph_node_name_to_ptr(const struct rte_graph *graph,
 					const char *node_name);
 
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+				       struct rte_node *node, void **objs,
+				       uint16_t nb_objs);
+
 /* Debug functions */
 /**
  * @internal
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..955c051a20 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap_trace.c',
 )
-headers = files('rte_graph.h', 'rte_graph_worker.h')
+headers = files('rte_graph.h', 'rte_graph_worker.h', 'rte_graph_pcap_trace.h')
 
-deps += ['eal']
+deps += ['eal', 'mbuf', 'ethdev', 'pcapng']
diff --git a/lib/graph/rte_graph_pcap_trace.h b/lib/graph/rte_graph_pcap_trace.h
new file mode 100644
index 0000000000..0583b6abf0
--- /dev/null
+++ b/lib/graph/rte_graph_pcap_trace.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_TRACE_H_
+#define _RTE_GRAPH_PCAP_TRACE_H_
+
+/**
+ * @file rte_graph_pcap_trace.h
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
+ * This API enables to capture packet at each node with mbuf and node metadata.
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+__rte_experimental
+void rte_pcap_trace_enable(int val);
+
+/**
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+__rte_experimental
+int rte_pcap_trace_is_enable(void);
+
+/**
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled from the
+ * application.
+ *
+ */
+__rte_experimental
+void rte_graph_pcap_trace_init(void);
+
+/**
+ * Pcap trace set number of packets to capture.
+ *
+ * The function is called to configure total number of packets to be captured.
+ *
+ * @param val
+ *   Number of packets to capture.
+ */
+__rte_experimental
+void rte_num_pkt_to_capture(uint64_t val);
+
+/**
+ * Pcap trace file name to capture packets.
+ *
+ * The function is called to configure file name to capture packets in.
+ *
+ * @param filename
+ *   Number of packets to capture.
+ */
+__rte_experimental
+void rte_filename_to_capture_pkt(const char *filename);
+
+/**
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's.
+ */
+__rte_experimental
+void rte_graph_pcap_trace_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_GRAPH_PCAP_TRACE_H_ */
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..fcaedbdb12 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -24,6 +24,7 @@
 #include <rte_memory.h>
 
 #include "rte_graph.h"
+#include "rte_graph_pcap_trace.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,6 +65,8 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	rte_node_process_t original_process; /**< Pcap enabled node callback */
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
diff --git a/lib/graph/version.map b/lib/graph/version.map
index 13b838752d..36153a75b2 100644
--- a/lib/graph/version.map
+++ b/lib/graph/version.map
@@ -43,5 +43,12 @@ EXPERIMENTAL {
 	rte_node_next_stream_put;
 	rte_node_next_stream_move;
 
+	rte_pcap_trace_is_enable;
+	rte_pcap_trace_enable;
+	rte_graph_pcap_trace_init;
+	rte_num_pkt_to_capture;
+	rte_filename_to_capture_pkt;
+	rte_graph_pcap_trace_exit;
+
 	local: *;
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v1 3/3] l3fwd-graph: changes to configure pcap capture
  2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-01-10 11:58   ` [PATCH v1 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-10 11:58   ` Amit Prakash Shukla
  2023-01-10 17:05   ` [PATCH v1 1/3] pcapng: comment option support for epb Stephen Hemminger
  2023-01-11  8:53   ` [PATCH v2 " Amit Prakash Shukla
  3 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-10 11:58 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
 doc/guides/sample_app_ug/l3_forward_graph.rst |  9 +++
 examples/l3fwd-graph/main.c                   | 56 ++++++++++++++++++-
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..e0935eaae3 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--num-pkt-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--num-pkt-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..a4cb58c539 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -261,7 +261,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +271,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --num-pkt-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +425,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "num-pkt-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +440,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +451,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -448,6 +478,7 @@ parse_args(int argc, char **argv)
 	int option_index;
 	char **argvopt;
 	int opt, ret;
+	uint64_t num_pkt;
 
 	argvopt = argv;
 
@@ -498,6 +529,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			rte_pcap_trace_enable(1);
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			num_pkt = parse_num_pkt_cap(optarg);
+			rte_num_pkt_to_capture(num_pkt);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       num_pkt);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_filename_to_capture_pkt(optarg);
+			printf("Pcap file name: %s\n", optarg);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -635,6 +683,7 @@ signal_handler(int signum)
 	if (signum == SIGINT || signum == SIGTERM) {
 		printf("\n\nSignal %d received, preparing to exit...\n",
 		       signum);
+		rte_graph_pcap_trace_exit();
 		force_quit = true;
 	}
 }
@@ -1116,6 +1165,9 @@ main(int argc, char **argv)
 	}
 	/* >8 End of adding route to ip4 graph infa. */
 
+	if (rte_pcap_trace_is_enable())
+		rte_graph_pcap_trace_init();
+
 	/* Launch per-lcore init on every worker lcore */
 	rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MAIN);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v1 1/3] pcapng: comment option support for epb
  2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-01-10 11:58   ` [PATCH v1 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-01-10 11:58   ` [PATCH v1 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-01-10 17:05   ` Stephen Hemminger
  2023-01-11  8:53   ` [PATCH v2 " Amit Prakash Shukla
  3 siblings, 0 replies; 47+ messages in thread
From: Stephen Hemminger @ 2023-01-10 17:05 UTC (permalink / raw)
  To: Amit Prakash Shukla; +Cc: Reshma Pattan, dev, jerinj

On Tue, 10 Jan 2023 17:28:45 +0530
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> @@ -548,6 +552,11 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  					&hash_opt, sizeof(hash_opt));
>  	}
>  
> +	if (comment) {
> +		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
> +					strlen(comment));
> +	}
> +

Minor style nit. Do not add bracket on single statement if clause

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 1/3] pcapng: comment option support for epb
  2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
                     ` (2 preceding siblings ...)
  2023-01-10 17:05   ` [PATCH v1 1/3] pcapng: comment option support for epb Stephen Hemminger
@ 2023-01-11  8:53   ` Amit Prakash Shukla
  2023-01-11  8:53     ` [PATCH v2 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
                       ` (2 more replies)
  3 siblings, 3 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-11  8:53 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger; +Cc: dev, jerinj, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

 app/test/test_pcapng.c  |  4 ++--
 lib/pcapng/rte_pcapng.c | 10 +++++++++-
 lib/pcapng/rte_pcapng.h |  4 +++-
 lib/pdump/rte_pdump.c   |  2 +-
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index a7acbdc058..303d3d66f9 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -139,7 +139,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -255,7 +255,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index 80d08e1a3b..acb31a9d93 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -450,7 +450,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -511,6 +512,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -548,6 +552,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 7d2697c647..6d286cda41 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -100,6 +100,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -111,7 +113,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v2 2/3] graph: pcap capture for graph nodes
  2023-01-11  8:53   ` [PATCH v2 " Amit Prakash Shukla
@ 2023-01-11  8:53     ` Amit Prakash Shukla
  2023-01-11 16:07       ` Stephen Hemminger
  2023-01-11  8:53     ` [PATCH v2 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
  2023-01-12 10:01     ` [PATCH v3 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-11  8:53 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

 lib/graph/graph_pcap_trace.c     | 165 +++++++++++++++++++++++++++++++
 lib/graph/graph_populate.c       |   6 +-
 lib/graph/graph_private.h        |  21 ++++
 lib/graph/meson.build            |   5 +-
 lib/graph/rte_graph_pcap_trace.h |  96 ++++++++++++++++++
 lib/graph/rte_graph_worker.h     |   3 +
 lib/graph/version.map            |   7 ++
 7 files changed, 300 insertions(+), 3 deletions(-)
 create mode 100644 lib/graph/graph_pcap_trace.c
 create mode 100644 lib/graph/rte_graph_pcap_trace.h

diff --git a/lib/graph/graph_pcap_trace.c b/lib/graph/graph_pcap_trace.c
new file mode 100644
index 0000000000..7f29043fcd
--- /dev/null
+++ b/lib/graph/graph_pcap_trace.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+#include "graph_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_FILE_NAME_SZ	128
+#define GRAPH_PCAP_FILE_NAME	"/tmp/graph_pcap_capture.pcapng"
+
+#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)                   \
+do {                                                                         \
+	if ((cur_len + len) >= buf_size)                                     \
+		break;                                                       \
+	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
+	cur_len += len;                                                      \
+} while (0)
+
+static char file_name[GRAPH_PCAP_FILE_NAME_SZ];
+static uint32_t pkt_buf_sz = RTE_MBUF_DEFAULT_BUF_SIZE;
+static uint64_t packet_to_capture = GRAPH_PCAP_NUM_PACKETS;
+static rte_pcapng_t *pcapng_fd;
+static struct rte_mempool *mp;
+static uint16_t port_id;
+static uint64_t packet_captured[RTE_MAX_LCORE];
+static int pcap_trace_enable;
+
+void
+rte_num_pkt_to_capture(uint64_t val)
+{
+	packet_to_capture = val;
+}
+
+void
+rte_pcap_trace_enable(int val)
+{
+	pcap_trace_enable = val;
+}
+
+int
+rte_pcap_trace_is_enable(void)
+{
+	return pcap_trace_enable;
+}
+
+void
+rte_filename_to_capture_pkt(const char *filename)
+{
+	if (filename[0] == '\0')
+		rte_strscpy(file_name, GRAPH_PCAP_FILE_NAME,
+			    GRAPH_PCAP_FILE_NAME_SZ);
+	else
+		rte_strscpy(file_name, filename, GRAPH_PCAP_FILE_NAME_SZ);
+}
+
+void
+rte_graph_pcap_trace_exit(void)
+{
+	rte_pcapng_close(pcapng_fd);
+}
+
+int
+rte_graph_pcap_trace_init(void)
+{
+	int fd;
+
+	port_id = rte_eth_find_next(0);
+	if (port_id >= RTE_MAX_ETHPORTS) {
+		fprintf(stderr, "No valid Ether port\n");
+		return -1;
+	}
+
+	if (file_name[0] == '\0')
+		rte_strscpy(file_name, GRAPH_PCAP_FILE_NAME,
+			    GRAPH_PCAP_FILE_NAME_SZ);
+
+	fd = open(file_name, O_CREAT | O_TRUNC | O_WRONLY, 0664);
+	if (fd < 0) {
+		perror("pcap file open failure");
+		return -1;
+	}
+
+	fprintf(stdout, "pcapng: output file %s\n", file_name);
+
+	/* open a test capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer", NULL);
+	if (pcapng_fd == NULL) {
+		fprintf(stderr, "Graph rte_pcapng_fdopen failed\n");
+		close(fd);
+		return -1;
+	}
+
+	/* Make a pool for cloned packets */
+	mp = rte_pktmbuf_pool_create_by_ops("pcapng_graph_pool",
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,
+			0, 0, rte_pcapng_mbuf_size(pkt_buf_sz),
+			SOCKET_ID_ANY, "ring_mp_sc");
+	if (mp == NULL) {
+		fprintf(stderr, "Cannot create mempool for graph pcap capture\n");
+		rte_pcapng_close(pcapng_fd);
+		return -1;
+	}
+
+	return 0;
+}
+
+uint16_t
+rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE] = { };
+	char buffer[GRAPH_PCAP_BUF_SZ] = {0};
+	struct rte_mbuf *mbuf;
+	uint16_t cb_len = 0;
+	ssize_t len;
+	uint16_t gid = graph->id;
+
+	if (!nb_objs || (packet_captured[gid] >= packet_to_capture))
+		goto done;
+
+	num_packets = packet_to_capture - packet_captured[gid];
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	PCAP_DUMP_DATA(buffer, GRAPH_PCAP_BUF_SZ, cb_len, node->name,
+		       (strlen(node->name) + 1));
+
+	for (i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(port_id, 0, mbuf, mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			goto done;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	packet_captured[gid] += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..aa26b1c51d 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -75,7 +75,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (rte_pcap_trace_is_enable()) {
+			node->process = rte_graph_pcap_trace_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..3edbb42692 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -319,6 +319,27 @@ struct rte_node *graph_node_id_to_ptr(const struct rte_graph *graph,
 struct rte_node *graph_node_name_to_ptr(const struct rte_graph *graph,
 					const char *node_name);
 
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+				       struct rte_node *node, void **objs,
+				       uint16_t nb_objs);
+
 /* Debug functions */
 /**
  * @internal
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..955c051a20 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap_trace.c',
 )
-headers = files('rte_graph.h', 'rte_graph_worker.h')
+headers = files('rte_graph.h', 'rte_graph_worker.h', 'rte_graph_pcap_trace.h')
 
-deps += ['eal']
+deps += ['eal', 'mbuf', 'ethdev', 'pcapng']
diff --git a/lib/graph/rte_graph_pcap_trace.h b/lib/graph/rte_graph_pcap_trace.h
new file mode 100644
index 0000000000..2af807c95b
--- /dev/null
+++ b/lib/graph/rte_graph_pcap_trace.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_TRACE_H_
+#define _RTE_GRAPH_PCAP_TRACE_H_
+
+/**
+ * @file rte_graph_pcap_trace.h
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
+ * This API enables to capture packet at each node with mbuf and node metadata.
+ *
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+__rte_experimental
+void rte_pcap_trace_enable(int val);
+
+/**
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+__rte_experimental
+int rte_pcap_trace_is_enable(void);
+
+/**
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled from the
+ * application.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+__rte_experimental
+int rte_graph_pcap_trace_init(void);
+
+/**
+ * Pcap trace set number of packets to capture.
+ *
+ * The function is called to configure total number of packets to be captured.
+ *
+ * @param val
+ *   Number of packets to capture.
+ */
+__rte_experimental
+void rte_num_pkt_to_capture(uint64_t val);
+
+/**
+ * Pcap trace file name to capture packets.
+ *
+ * The function is called to configure file name to capture packets in.
+ *
+ * @param filename
+ *   Number of packets to capture.
+ */
+__rte_experimental
+void rte_filename_to_capture_pkt(const char *filename);
+
+/**
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's.
+ */
+__rte_experimental
+void rte_graph_pcap_trace_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_GRAPH_PCAP_TRACE_H_ */
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..fcaedbdb12 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -24,6 +24,7 @@
 #include <rte_memory.h>
 
 #include "rte_graph.h"
+#include "rte_graph_pcap_trace.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,6 +65,8 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	rte_node_process_t original_process; /**< Pcap enabled node callback */
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
diff --git a/lib/graph/version.map b/lib/graph/version.map
index 13b838752d..36153a75b2 100644
--- a/lib/graph/version.map
+++ b/lib/graph/version.map
@@ -43,5 +43,12 @@ EXPERIMENTAL {
 	rte_node_next_stream_put;
 	rte_node_next_stream_move;
 
+	rte_pcap_trace_is_enable;
+	rte_pcap_trace_enable;
+	rte_graph_pcap_trace_init;
+	rte_num_pkt_to_capture;
+	rte_filename_to_capture_pkt;
+	rte_graph_pcap_trace_exit;
+
 	local: *;
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v2 3/3] l3fwd-graph: changes to configure pcap capture
  2023-01-11  8:53   ` [PATCH v2 " Amit Prakash Shukla
  2023-01-11  8:53     ` [PATCH v2 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-11  8:53     ` Amit Prakash Shukla
  2023-01-12 10:01     ` [PATCH v3 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-11  8:53 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

 doc/guides/sample_app_ug/l3_forward_graph.rst |  9 +++
 examples/l3fwd-graph/main.c                   | 58 ++++++++++++++++++-
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..e0935eaae3 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--num-pkt-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--num-pkt-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..0b30ebbd83 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -261,7 +261,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +271,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --num-pkt-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +425,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "num-pkt-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +440,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +451,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -448,6 +478,7 @@ parse_args(int argc, char **argv)
 	int option_index;
 	char **argvopt;
 	int opt, ret;
+	uint64_t num_pkt;
 
 	argvopt = argv;
 
@@ -498,6 +529,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			rte_pcap_trace_enable(1);
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			num_pkt = parse_num_pkt_cap(optarg);
+			rte_num_pkt_to_capture(num_pkt);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       num_pkt);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_filename_to_capture_pkt(optarg);
+			printf("Pcap file name: %s\n", optarg);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -635,6 +683,7 @@ signal_handler(int signum)
 	if (signum == SIGINT || signum == SIGTERM) {
 		printf("\n\nSignal %d received, preparing to exit...\n",
 		       signum);
+		rte_graph_pcap_trace_exit();
 		force_quit = true;
 	}
 }
@@ -1015,6 +1064,11 @@ main(int argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
+	if (rte_pcap_trace_is_enable()) {
+		if (rte_graph_pcap_trace_init() < 0)
+			rte_pcap_trace_enable(0);
+	}
+
 	/* Graph Initialization */
 	nb_patterns = RTE_DIM(default_patterns);
 	node_patterns = malloc((MAX_RX_QUEUE_PER_LCORE + nb_patterns) *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
  2023-01-11  8:53     ` [PATCH v2 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-11 16:07       ` Stephen Hemminger
  2023-01-12  9:57         ` [EXT] " Amit Prakash Shukla
  0 siblings, 1 reply; 47+ messages in thread
From: Stephen Hemminger @ 2023-01-11 16:07 UTC (permalink / raw)
  To: Amit Prakash Shukla; +Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, dev

On Wed, 11 Jan 2023 14:23:41 +0530
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> +
> +#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)                   \
> +do {                                                                         \
> +	if ((cur_len + len) >= buf_size)                                     \
> +		break;                                                       \
> +	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
> +	cur_len += len;                                                      \
> +} while (0)
> +

Why do you need this to be a macro.
Macro's are evil, have side effects and hide code.

> +uint16_t
> +rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
> +			      struct rte_node *node, void **objs,
> +			      uint16_t nb_objs)
> +{
> +	uint64_t i, num_packets;
> +	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE] = { };
> +	char buffer[GRAPH_PCAP_BUF_SZ] = {0};

The initialization probably is not needed here.

Couldn't you just do:
	rte_strlcpy(buffer, node->name, GRAPH_PCAP_BUF_SZ);

> +	for (i = 0; i < num_packets; i++) {
> +		struct rte_mbuf *mc;
> +		mbuf = (struct rte_mbuf *)objs[i];
> +
> +		mc = rte_pcapng_copy(port_id, 0, mbuf, mp, mbuf->pkt_len,
> +				     rte_get_tsc_cycles(), 0, buffer);
> +		if (mc == NULL)
> +			goto done;

The code will leak mbuf's if pcapng_copy() fails.
Suppose packet #2 caused the pool to get exhausted.
That copy would fail, but the mbuf for packets 0 and 1 would already
be sitting in mbuf_clones.
> +
> +		mbuf_clones[i] = mc;
> +	}

^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
  2023-01-11 16:07       ` Stephen Hemminger
@ 2023-01-12  9:57         ` Amit Prakash Shukla
  2023-01-12 16:30           ` Stephen Hemminger
  0 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-12  9:57 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

Hi Stephen,

> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Wednesday, January 11, 2023 9:37 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; dev@dpdk.org
> Subject: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Wed, 11 Jan 2023 14:23:41 +0530
> Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> 
> > +
> > +#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)                   \
> > +do {                                                                         \
> > +	if ((cur_len + len) >= buf_size)                                     \
> > +		break;                                                       \
> > +	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
> > +	cur_len += len;                                                      \
> > +} while (0)
> > +
> 
> Why do you need this to be a macro.
> Macro's are evil, have side effects and hide code.

I had added macro for future, if lot of custom data is to be added to pcapng. Anyways I will remove it
in next version of patch.

> 
> > +uint16_t
> > +rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
> > +			      struct rte_node *node, void **objs,
> > +			      uint16_t nb_objs)
> > +{
> > +	uint64_t i, num_packets;
> > +	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE] = { };
> > +	char buffer[GRAPH_PCAP_BUF_SZ] = {0};
> 
> The initialization probably is not needed here.
> 
> Couldn't you just do:
> 	rte_strlcpy(buffer, node->name, GRAPH_PCAP_BUF_SZ);
> 
> > +	for (i = 0; i < num_packets; i++) {
> > +		struct rte_mbuf *mc;
> > +		mbuf = (struct rte_mbuf *)objs[i];
> > +
> > +		mc = rte_pcapng_copy(port_id, 0, mbuf, mp, mbuf->pkt_len,
> > +				     rte_get_tsc_cycles(), 0, buffer);
> > +		if (mc == NULL)
> > +			goto done;
> 
> The code will leak mbuf's if pcapng_copy() fails.
> Suppose packet #2 caused the pool to get exhausted.
> That copy would fail, but the mbuf for packets 0 and 1 would already be
> sitting in mbuf_clones.

My bad. Thanks for catching the issue. I will correct it in next version of the patch.

> > +
> > +		mbuf_clones[i] = mc;
> > +	}

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v3 1/3] pcapng: comment option support for epb
  2023-01-11  8:53   ` [PATCH v2 " Amit Prakash Shukla
  2023-01-11  8:53     ` [PATCH v2 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-01-11  8:53     ` [PATCH v2 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-01-12 10:01     ` Amit Prakash Shukla
  2023-01-12 10:01       ` [PATCH v3 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
                         ` (2 more replies)
  2 siblings, 3 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-12 10:01 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger; +Cc: dev, jerinj, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
 app/test/test_pcapng.c  |  4 ++--
 lib/pcapng/rte_pcapng.c | 10 +++++++++-
 lib/pcapng/rte_pcapng.h |  4 +++-
 lib/pdump/rte_pdump.c   |  2 +-
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index a7acbdc058..303d3d66f9 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -139,7 +139,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -255,7 +255,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index 80d08e1a3b..acb31a9d93 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -450,7 +450,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -511,6 +512,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -548,6 +552,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 7d2697c647..6d286cda41 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -100,6 +100,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -111,7 +113,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v3 2/3] graph: pcap capture for graph nodes
  2023-01-12 10:01     ` [PATCH v3 1/3] pcapng: comment option support for epb Amit Prakash Shukla
@ 2023-01-12 10:01       ` Amit Prakash Shukla
  2023-01-12 12:18         ` Jerin Jacob
  2023-01-12 10:01       ` [PATCH v3 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
  2023-01-24 11:21       ` [PATCH v4 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-12 10:01 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak

 lib/graph/graph_pcap_trace.c     | 155 +++++++++++++++++++++++++++++++
 lib/graph/graph_populate.c       |   6 +-
 lib/graph/graph_private.h        |  21 +++++
 lib/graph/meson.build            |   5 +-
 lib/graph/rte_graph_pcap_trace.h |  96 +++++++++++++++++++
 lib/graph/rte_graph_worker.h     |   3 +
 lib/graph/version.map            |   7 ++
 7 files changed, 290 insertions(+), 3 deletions(-)
 create mode 100644 lib/graph/graph_pcap_trace.c
 create mode 100644 lib/graph/rte_graph_pcap_trace.h

diff --git a/lib/graph/graph_pcap_trace.c b/lib/graph/graph_pcap_trace.c
new file mode 100644
index 0000000000..f7b81a7ad1
--- /dev/null
+++ b/lib/graph/graph_pcap_trace.c
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+#include "graph_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_FILE_NAME_SZ	128
+#define GRAPH_PCAP_FILE_NAME	"/tmp/graph_pcap_capture.pcapng"
+
+static char file_name[GRAPH_PCAP_FILE_NAME_SZ];
+static uint32_t pkt_buf_sz = RTE_MBUF_DEFAULT_BUF_SIZE;
+static uint64_t packet_to_capture = GRAPH_PCAP_NUM_PACKETS;
+static rte_pcapng_t *pcapng_fd;
+static struct rte_mempool *mp;
+static uint16_t port_id;
+static uint64_t packet_captured[RTE_MAX_LCORE];
+static int pcap_trace_enable;
+
+void
+rte_num_pkt_to_capture(uint64_t val)
+{
+	packet_to_capture = val;
+}
+
+void
+rte_pcap_trace_enable(int val)
+{
+	pcap_trace_enable = val;
+}
+
+int
+rte_pcap_trace_is_enable(void)
+{
+	return pcap_trace_enable;
+}
+
+void
+rte_filename_to_capture_pkt(const char *filename)
+{
+	if (filename[0] == '\0')
+		rte_strscpy(file_name, GRAPH_PCAP_FILE_NAME,
+			    GRAPH_PCAP_FILE_NAME_SZ);
+	else
+		rte_strscpy(file_name, filename, GRAPH_PCAP_FILE_NAME_SZ);
+}
+
+void
+rte_graph_pcap_trace_exit(void)
+{
+	rte_pcapng_close(pcapng_fd);
+}
+
+int
+rte_graph_pcap_trace_init(void)
+{
+	int fd;
+
+	port_id = rte_eth_find_next(0);
+	if (port_id >= RTE_MAX_ETHPORTS) {
+		fprintf(stderr, "No valid Ether port\n");
+		return -1;
+	}
+
+	if (file_name[0] == '\0')
+		rte_strscpy(file_name, GRAPH_PCAP_FILE_NAME,
+			    GRAPH_PCAP_FILE_NAME_SZ);
+
+	fd = open(file_name, O_CREAT | O_TRUNC | O_WRONLY, 0664);
+	if (fd < 0) {
+		perror("pcap file open failure");
+		return -1;
+	}
+
+	fprintf(stdout, "pcapng: output file %s\n", file_name);
+
+	/* open a test capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer", NULL);
+	if (pcapng_fd == NULL) {
+		fprintf(stderr, "Graph rte_pcapng_fdopen failed\n");
+		close(fd);
+		return -1;
+	}
+
+	/* Make a pool for cloned packets */
+	mp = rte_pktmbuf_pool_create_by_ops("pcapng_graph_pool",
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,
+			0, 0, rte_pcapng_mbuf_size(pkt_buf_sz),
+			SOCKET_ID_ANY, "ring_mp_sc");
+	if (mp == NULL) {
+		fprintf(stderr, "Cannot create mempool for graph pcap capture\n");
+		rte_pcapng_close(pcapng_fd);
+		return -1;
+	}
+
+	return 0;
+}
+
+uint16_t
+rte_graph_pcap_trace_dispatch(struct rte_graph *graph,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
+	char buffer[GRAPH_PCAP_BUF_SZ];
+	struct rte_mbuf *mbuf;
+	ssize_t len;
+	uint16_t gid = graph->id;
+
+	if (!nb_objs || (packet_captured[gid] >= packet_to_capture))
+		goto done;
+
+	num_packets = packet_to_capture - packet_captured[gid];
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	rte_strlcpy(buffer, node->name, GRAPH_PCAP_BUF_SZ);
+
+	for (i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(port_id, 0, mbuf, mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			break;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	packet_captured[gid] += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..aa26b1c51d 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -75,7 +75,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (rte_pcap_trace_is_enable()) {
+			node->process = rte_graph_pcap_trace_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..3edbb42692 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -319,6 +319,27 @@ struct rte_node *graph_node_id_to_ptr(const struct rte_graph *graph,
 struct rte_node *graph_node_name_to_ptr(const struct rte_graph *graph,
 					const char *node_name);
 
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t rte_graph_pcap_trace_dispatch(struct rte_graph *graph __rte_unused,
+				       struct rte_node *node, void **objs,
+				       uint16_t nb_objs);
+
 /* Debug functions */
 /**
  * @internal
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..955c051a20 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap_trace.c',
 )
-headers = files('rte_graph.h', 'rte_graph_worker.h')
+headers = files('rte_graph.h', 'rte_graph_worker.h', 'rte_graph_pcap_trace.h')
 
-deps += ['eal']
+deps += ['eal', 'mbuf', 'ethdev', 'pcapng']
diff --git a/lib/graph/rte_graph_pcap_trace.h b/lib/graph/rte_graph_pcap_trace.h
new file mode 100644
index 0000000000..2af807c95b
--- /dev/null
+++ b/lib/graph/rte_graph_pcap_trace.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_TRACE_H_
+#define _RTE_GRAPH_PCAP_TRACE_H_
+
+/**
+ * @file rte_graph_pcap_trace.h
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
+ * This API enables to capture packet at each node with mbuf and node metadata.
+ *
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+__rte_experimental
+void rte_pcap_trace_enable(int val);
+
+/**
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+__rte_experimental
+int rte_pcap_trace_is_enable(void);
+
+/**
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled from the
+ * application.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+__rte_experimental
+int rte_graph_pcap_trace_init(void);
+
+/**
+ * Pcap trace set number of packets to capture.
+ *
+ * The function is called to configure total number of packets to be captured.
+ *
+ * @param val
+ *   Number of packets to capture.
+ */
+__rte_experimental
+void rte_num_pkt_to_capture(uint64_t val);
+
+/**
+ * Pcap trace file name to capture packets.
+ *
+ * The function is called to configure file name to capture packets in.
+ *
+ * @param filename
+ *   Number of packets to capture.
+ */
+__rte_experimental
+void rte_filename_to_capture_pkt(const char *filename);
+
+/**
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's.
+ */
+__rte_experimental
+void rte_graph_pcap_trace_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_GRAPH_PCAP_TRACE_H_ */
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..fcaedbdb12 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -24,6 +24,7 @@
 #include <rte_memory.h>
 
 #include "rte_graph.h"
+#include "rte_graph_pcap_trace.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,6 +65,8 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	rte_node_process_t original_process; /**< Pcap enabled node callback */
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
diff --git a/lib/graph/version.map b/lib/graph/version.map
index 13b838752d..36153a75b2 100644
--- a/lib/graph/version.map
+++ b/lib/graph/version.map
@@ -43,5 +43,12 @@ EXPERIMENTAL {
 	rte_node_next_stream_put;
 	rte_node_next_stream_move;
 
+	rte_pcap_trace_is_enable;
+	rte_pcap_trace_enable;
+	rte_graph_pcap_trace_init;
+	rte_num_pkt_to_capture;
+	rte_filename_to_capture_pkt;
+	rte_graph_pcap_trace_exit;
+
 	local: *;
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v3 3/3] l3fwd-graph: changes to configure pcap capture
  2023-01-12 10:01     ` [PATCH v3 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-01-12 10:01       ` [PATCH v3 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-12 10:01       ` Amit Prakash Shukla
  2023-01-24 11:21       ` [PATCH v4 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-12 10:01 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak

 doc/guides/sample_app_ug/l3_forward_graph.rst |  9 +++
 examples/l3fwd-graph/main.c                   | 58 ++++++++++++++++++-
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..e0935eaae3 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--num-pkt-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--num-pkt-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..0b30ebbd83 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -261,7 +261,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +271,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --num-pkt-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +425,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "num-pkt-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +440,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +451,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -448,6 +478,7 @@ parse_args(int argc, char **argv)
 	int option_index;
 	char **argvopt;
 	int opt, ret;
+	uint64_t num_pkt;
 
 	argvopt = argv;
 
@@ -498,6 +529,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			rte_pcap_trace_enable(1);
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			num_pkt = parse_num_pkt_cap(optarg);
+			rte_num_pkt_to_capture(num_pkt);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       num_pkt);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_filename_to_capture_pkt(optarg);
+			printf("Pcap file name: %s\n", optarg);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -635,6 +683,7 @@ signal_handler(int signum)
 	if (signum == SIGINT || signum == SIGTERM) {
 		printf("\n\nSignal %d received, preparing to exit...\n",
 		       signum);
+		rte_graph_pcap_trace_exit();
 		force_quit = true;
 	}
 }
@@ -1015,6 +1064,11 @@ main(int argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
+	if (rte_pcap_trace_is_enable()) {
+		if (rte_graph_pcap_trace_init() < 0)
+			rte_pcap_trace_enable(0);
+	}
+
 	/* Graph Initialization */
 	nb_patterns = RTE_DIM(default_patterns);
 	node_patterns = malloc((MAX_RX_QUEUE_PER_LCORE + nb_patterns) *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v3 2/3] graph: pcap capture for graph nodes
  2023-01-12 10:01       ` [PATCH v3 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-12 12:18         ` Jerin Jacob
  2023-01-19 14:21           ` [EXT] " Amit Prakash Shukla
  0 siblings, 1 reply; 47+ messages in thread
From: Jerin Jacob @ 2023-01-12 12:18 UTC (permalink / raw)
  To: Amit Prakash Shukla; +Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, dev

On Thu, Jan 12, 2023 at 3:31 PM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
>
> Implementation adds support to capture packets at each node with
> packet metadata and node name.
>
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> ---
> v2:
>  - Fixed code style issue
>  - Fixed CI compilation issue on github-robot
>
>
> diff --git a/lib/graph/graph_pcap_trace.c b/lib/graph/graph_pcap_trace.c
> new file mode 100644
> index 0000000000..f7b81a7ad1
> --- /dev/null
> +++ b/lib/graph/graph_pcap_trace.c
> @@ -0,0 +1,155 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell International Ltd.

2023

> +
> +#define GRAPH_PCAP_BUF_SZ      128
> +#define GRAPH_PCAP_NUM_PACKETS 1024
> +#define GRAPH_PCAP_FILE_NAME_SZ        128
> +#define GRAPH_PCAP_FILE_NAME   "/tmp/graph_pcap_capture.pcapng"

Expecting the filename from application. So no need to define here.

> +
> +static char file_name[GRAPH_PCAP_FILE_NAME_SZ];
> +static uint32_t pkt_buf_sz = RTE_MBUF_DEFAULT_BUF_SIZE;
> +static uint64_t packet_to_capture = GRAPH_PCAP_NUM_PACKETS;
> +static rte_pcapng_t *pcapng_fd;
> +static struct rte_mempool *mp;
> +static uint16_t port_id;
> +static uint64_t packet_captured[RTE_MAX_LCORE];
> +static int pcap_trace_enable;

See what it takes for multiprocess. If anything needs to be available
in graph walk(which runs on secondary process) needs to be part of
huge page. i.e part of rte_graph structure.

>
> +       rte_node_process_t original_process; /**< Pcap enabled node callback */

Add comment like, "Used to store the original process when pcap is
enabled"  or so

> +
>         /* Fast path area  */
>  #define RTE_NODE_CTX_SZ 16
>         uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
> diff --git a/lib/graph/version.map b/lib/graph/version.map
> index 13b838752d..36153a75b2 100644
> --- a/lib/graph/version.map
> +++ b/lib/graph/version.map
> @@ -43,5 +43,12 @@ EXPERIMENTAL {
>         rte_node_next_stream_put;
>         rte_node_next_stream_move;
>
> +       rte_pcap_trace_is_enable;
> +       rte_pcap_trace_enable;
> +       rte_graph_pcap_trace_init;
> +       rte_num_pkt_to_capture;
> +       rte_filename_to_capture_pkt;
> +       rte_graph_pcap_trace_exit;

All of these public APIs are not needed. Since rte_graph is still
experimental to make it clean, please add file name and number of
packet to capture
in  struct rte_graph_param and update doc/guides/rel_notes/release_23_03.rst.

See following example in doc/guides/rel_notes/release_22_07.rst

API Changes
-----------

* Experimental structures ``struct rte_mtr_params``
  and ``struct rte_mtr_capabilities`` were updated to support
  protocol based input color for meter.

> +
>         local: *;
>  };
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
  2023-01-12  9:57         ` [EXT] " Amit Prakash Shukla
@ 2023-01-12 16:30           ` Stephen Hemminger
  2023-01-19 14:37             ` Amit Prakash Shukla
  0 siblings, 1 reply; 47+ messages in thread
From: Stephen Hemminger @ 2023-01-12 16:30 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

On Thu, 12 Jan 2023 09:57:50 +0000
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> Hi Stephen,
> 
> > -----Original Message-----
> > From: Stephen Hemminger <stephen@networkplumber.org>
> > Sent: Wednesday, January 11, 2023 9:37 PM
> > To: Amit Prakash Shukla <amitprakashs@marvell.com>
> > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> > Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> > <ndabilpuram@marvell.com>; dev@dpdk.org
> > Subject: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
> > 
> > External Email
> > 
> > ----------------------------------------------------------------------
> > On Wed, 11 Jan 2023 14:23:41 +0530
> > Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> >   
> > > +
> > > +#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)                   \
> > > +do {                                                                         \
> > > +	if ((cur_len + len) >= buf_size)                                     \
> > > +		break;                                                       \
> > > +	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
> > > +	cur_len += len;                                                      \
> > > +} while (0)
> > > +  
> > 
> > Why do you need this to be a macro.
> > Macro's are evil, have side effects and hide code.  
> 
> I had added macro for future, if lot of custom data is to be added to pcapng. Anyways I will remove it
> in next version of patch.

One other option is to add a new custom block type or options in pcapng.
Keep comment as a string, since that is what wireshark etc no how to handle.
Also, packet id data might be useful for graph.


https://pcapng.github.io/pcapng/draft-tuexen-opsawg-pcapng.html

^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [PATCH v3 2/3] graph: pcap capture for graph nodes
  2023-01-12 12:18         ` Jerin Jacob
@ 2023-01-19 14:21           ` Amit Prakash Shukla
  0 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-19 14:21 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

Thanks Jerin for the code review and feedback. I will make the suggested changes in next version of the patch.

> -----Original Message-----
> From: Jerin Jacob <jerinjacobk@gmail.com>
> Sent: Thursday, January 12, 2023 5:48 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; dev@dpdk.org
> Subject: [EXT] Re: [PATCH v3 2/3] graph: pcap capture for graph nodes
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Thu, Jan 12, 2023 at 3:31 PM Amit Prakash Shukla
> <amitprakashs@marvell.com> wrote:
> >
> > Implementation adds support to capture packets at each node with
> > packet metadata and node name.
> >
> > Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> > ---
> > v2:
> >  - Fixed code style issue
> >  - Fixed CI compilation issue on github-robot
> >
> >
> > diff --git a/lib/graph/graph_pcap_trace.c
> > b/lib/graph/graph_pcap_trace.c new file mode 100644 index
> > 0000000000..f7b81a7ad1
> > --- /dev/null
> > +++ b/lib/graph/graph_pcap_trace.c
> > @@ -0,0 +1,155 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(C) 2022 Marvell International Ltd.
> 
> 2023
> 
> > +
> > +#define GRAPH_PCAP_BUF_SZ      128
> > +#define GRAPH_PCAP_NUM_PACKETS 1024
> > +#define GRAPH_PCAP_FILE_NAME_SZ        128
> > +#define GRAPH_PCAP_FILE_NAME   "/tmp/graph_pcap_capture.pcapng"
> 
> Expecting the filename from application. So no need to define here.
> 
> > +
> > +static char file_name[GRAPH_PCAP_FILE_NAME_SZ];
> > +static uint32_t pkt_buf_sz = RTE_MBUF_DEFAULT_BUF_SIZE; static
> > +uint64_t packet_to_capture = GRAPH_PCAP_NUM_PACKETS; static
> > +rte_pcapng_t *pcapng_fd; static struct rte_mempool *mp; static
> > +uint16_t port_id; static uint64_t packet_captured[RTE_MAX_LCORE];
> > +static int pcap_trace_enable;
> 
> See what it takes for multiprocess. If anything needs to be available in graph
> walk(which runs on secondary process) needs to be part of huge page. i.e
> part of rte_graph structure.
> 
> >
> > +       rte_node_process_t original_process; /**< Pcap enabled node
> > + callback */
> 
> Add comment like, "Used to store the original process when pcap is enabled"
> or so
> 
> > +
> >         /* Fast path area  */
> >  #define RTE_NODE_CTX_SZ 16
> >         uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node
> > Context. */ diff --git a/lib/graph/version.map b/lib/graph/version.map
> > index 13b838752d..36153a75b2 100644
> > --- a/lib/graph/version.map
> > +++ b/lib/graph/version.map
> > @@ -43,5 +43,12 @@ EXPERIMENTAL {
> >         rte_node_next_stream_put;
> >         rte_node_next_stream_move;
> >
> > +       rte_pcap_trace_is_enable;
> > +       rte_pcap_trace_enable;
> > +       rte_graph_pcap_trace_init;
> > +       rte_num_pkt_to_capture;
> > +       rte_filename_to_capture_pkt;
> > +       rte_graph_pcap_trace_exit;
> 
> All of these public APIs are not needed. Since rte_graph is still experimental
> to make it clean, please add file name and number of packet to capture in
> struct rte_graph_param and update
> doc/guides/rel_notes/release_23_03.rst.
> 
> See following example in doc/guides/rel_notes/release_22_07.rst
> 
> API Changes
> -----------
> 
> * Experimental structures ``struct rte_mtr_params``
>   and ``struct rte_mtr_capabilities`` were updated to support
>   protocol based input color for meter.
> 
> > +
> >         local: *;
> >  };
> > --
> > 2.25.1
> >

^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
  2023-01-12 16:30           ` Stephen Hemminger
@ 2023-01-19 14:37             ` Amit Prakash Shukla
  2023-01-19 16:48               ` Stephen Hemminger
  0 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-19 14:37 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

Hi Stephen,

Thanks for the reply. Please find my reply in-line.

> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Thursday, January 12, 2023 10:00 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; dev@dpdk.org
> Subject: Re: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
> 
> On Thu, 12 Jan 2023 09:57:50 +0000
> Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> 
> > Hi Stephen,
> >
> > > -----Original Message-----
> > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > Sent: Wednesday, January 11, 2023 9:37 PM
> > > To: Amit Prakash Shukla <amitprakashs@marvell.com>
> > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> > > Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> > > <ndabilpuram@marvell.com>; dev@dpdk.org
> > > Subject: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph
> > > nodes
> > >
> > > External Email
> > >
> > > --------------------------------------------------------------------
> > > --
> > > On Wed, 11 Jan 2023 14:23:41 +0530
> > > Amit Prakash Shukla <amitprakashs@marvell.com> wrote:
> > >
> > > > +
> > > > +#define PCAP_DUMP_DATA(dbuf, buf_size, cur_len, sbuf, len)
> \
> > > > +do {                                                                         \
> > > > +	if ((cur_len + len) >= buf_size)                                     \
> > > > +		break;                                                       \
> > > > +	rte_memcpy(dbuf + cur_len, sbuf, len);                               \
> > > > +	cur_len += len;                                                      \
> > > > +} while (0)
> > > > +
> > >
> > > Why do you need this to be a macro.
> > > Macro's are evil, have side effects and hide code.
> >
> > I had added macro for future, if lot of custom data is to be added to
> > pcapng. Anyways I will remove it in next version of patch.
> 
> One other option is to add a new custom block type or options in pcapng.
> Keep comment as a string, since that is what wireshark etc no how to handle.
> Also, packet id data might be useful for graph.

I gave a try by adding a support for custom options in libpcapng, but it seems wireshark does not support PEN in custom options as of now. 
Wireshark was not dissecting dummy PEN that was passed in custom option.

> 
> 
> https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__pcapng.github.io_pcapng_draft-2Dtuexen-2Dopsawg-
> 2Dpcapng.html&d=DwICAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=ALGdXl3fZgFG
> R69VnJLdSnADun7zLaXG1p5Rs7pXihE&m=L7hbHExlVJ9DVyJLvofg2oChAcRcF
> GBypawp8vQkR5nAGLbwS2NdSNepsq8v5Zx7&s=1tIiV96rTBAhzcLS_JiJ5FRbL
> PUja4HyT3rhQA4RIsg&e=

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [EXT] Re: [PATCH v2 2/3] graph: pcap capture for graph nodes
  2023-01-19 14:37             ` Amit Prakash Shukla
@ 2023-01-19 16:48               ` Stephen Hemminger
  0 siblings, 0 replies; 47+ messages in thread
From: Stephen Hemminger @ 2023-01-19 16:48 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

On Thu, 19 Jan 2023 14:37:49 +0000
Amit Prakash Shukla <amitprakashs@marvell.com> wrote:

> > 
> > One other option is to add a new custom block type or options in pcapng.
> > Keep comment as a string, since that is what wireshark etc no how to handle.
> > Also, packet id data might be useful for graph.  
> 
> I gave a try by adding a support for custom options in libpcapng, but it seems wireshark does not support PEN in custom options as of now. 
> Wireshark was not dissecting dummy PEN that was passed in custom option.


Wireshark is not too difficult to add new types to.
I added support for RSS hash option to wireshark.

You might get good feedback on this from others.
Maybe discuss on the wireshark or pcapng mailing list.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v4 1/3] pcapng: comment option support for epb
  2023-01-12 10:01     ` [PATCH v3 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-01-12 10:01       ` [PATCH v3 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-01-12 10:01       ` [PATCH v3 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-01-24 11:21       ` Amit Prakash Shukla
  2023-01-24 11:21         ` [PATCH v4 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
                           ` (2 more replies)
  2 siblings, 3 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-24 11:21 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger; +Cc: dev, jerinj, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

 app/test/test_pcapng.c                 |  4 ++--
 doc/guides/rel_notes/release_23_03.rst |  2 ++
 lib/pcapng/rte_pcapng.c                | 10 +++++++++-
 lib/pcapng/rte_pcapng.h                |  4 +++-
 lib/pdump/rte_pdump.c                  |  2 +-
 5 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index a7acbdc058..303d3d66f9 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -139,7 +139,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -255,7 +255,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index c15f6fbb9f..8c360b89e4 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -98,6 +98,8 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* Experimental function ``rte_pcapng_copy`` was updated to support comment
+  section in enhanced packet block in pcapng library.
 
 ABI Changes
 -----------
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index 80d08e1a3b..acb31a9d93 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -450,7 +450,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -511,6 +512,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -548,6 +552,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 7d2697c647..6d286cda41 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -100,6 +100,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -111,7 +113,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 2/3] graph: pcap capture for graph nodes
  2023-01-24 11:21       ` [PATCH v4 1/3] pcapng: comment option support for epb Amit Prakash Shukla
@ 2023-01-24 11:21         ` Amit Prakash Shukla
  2023-01-31  8:06           ` Jerin Jacob
  2023-01-24 11:21         ` [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
  2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-24 11:21 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Anatoly Burakov
  Cc: dev, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

 app/test/test_graph_perf.c             |   2 +-
 doc/guides/rel_notes/release_23_03.rst |   7 +
 lib/graph/graph.c                      |  17 +-
 lib/graph/graph_pcap.c                 | 217 +++++++++++++++++++++++++
 lib/graph/graph_pcap_private.h         | 124 ++++++++++++++
 lib/graph/graph_populate.c             |  12 +-
 lib/graph/graph_private.h              |   5 +
 lib/graph/meson.build                  |   3 +-
 lib/graph/rte_graph.h                  |   5 +
 lib/graph/rte_graph_worker.h           |   9 +
 10 files changed, 397 insertions(+), 4 deletions(-)
 create mode 100644 lib/graph/graph_pcap.c
 create mode 100644 lib/graph/graph_pcap_private.h

diff --git a/app/test/test_graph_perf.c b/app/test/test_graph_perf.c
index 1d065438a6..c5b463f700 100644
--- a/app/test/test_graph_perf.c
+++ b/app/test/test_graph_perf.c
@@ -324,7 +324,7 @@ graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks,
 	char nname[RTE_NODE_NAMESIZE / 2];
 	struct test_node_data *node_data;
 	char *ename[nodes_per_stage];
-	struct rte_graph_param gconf;
+	struct rte_graph_param gconf = {0};
 	const struct rte_memzone *mz;
 	uint8_t total_percent = 0;
 	rte_node_t *src_nodes;
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index 8c360b89e4..9ba392fb58 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -69,6 +69,10 @@ New Features
     ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
     required for eth_rx, eth_tx, crypto and timer eventdev adapters.
 
+* **Added pcap trace support in graph library.**
+
+  * Added support to capture packets at each graph node with packet metadata and
+    node name.
 
 Removed Items
 -------------
@@ -101,6 +105,9 @@ API Changes
 * Experimental function ``rte_pcapng_copy`` was updated to support comment
   section in enhanced packet block in pcapng library.
 
+* Experimental structures ``struct rte_graph_param``, ``struct rte_graph`` and
+  ``struct graph`` were updated to support pcap trace in graph library.
+
 ABI Changes
 -----------
 
diff --git a/lib/graph/graph.c b/lib/graph/graph.c
index 3a617cc369..a839a2803b 100644
--- a/lib/graph/graph.c
+++ b/lib/graph/graph.c
@@ -15,6 +15,7 @@
 #include <rte_string_fns.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static struct graph_head graph_list = STAILQ_HEAD_INITIALIZER(graph_list);
 static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER;
@@ -228,7 +229,12 @@ graph_mem_fixup_node_ctx(struct rte_graph *graph)
 		node_db = node_from_name(name);
 		if (node_db == NULL)
 			SET_ERR_JMP(ENOLINK, fail, "Node %s not found", name);
-		node->process = node_db->process;
+
+		if (graph->pcap_enable) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = node_db->process;
+		} else
+			node->process = node_db->process;
 	}
 
 	return graph;
@@ -242,6 +248,9 @@ graph_mem_fixup_secondary(struct rte_graph *graph)
 	if (graph == NULL || rte_eal_process_type() == RTE_PROC_PRIMARY)
 		return graph;
 
+	if (graph_pcap_file_open(graph->pcap_filename) || graph_pcap_mp_init())
+		graph_pcap_exit(graph);
+
 	return graph_mem_fixup_node_ctx(graph);
 }
 
@@ -323,11 +332,17 @@ rte_graph_create(const char *name, struct rte_graph_param *prm)
 	if (graph_has_isolated_node(graph))
 		goto graph_cleanup;
 
+	/* Initialize pcap config. */
+	graph_pcap_enable(prm->pcap_enable);
+
 	/* Initialize graph object */
 	graph->socket = prm->socket_id;
 	graph->src_node_count = src_node_count;
 	graph->node_count = graph_nodes_count(graph);
 	graph->id = graph_id;
+	graph->num_pkt_to_capture = prm->num_pkt_to_capture;
+	if (prm->pcap_filename)
+		rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
 
 	/* Allocate the Graph fast path memory and populate the data */
 	if (graph_fp_mem_create(graph))
diff --git a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c
new file mode 100644
index 0000000000..7bd13ed61e
--- /dev/null
+++ b/lib/graph/graph_pcap.c
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pwd.h>
+
+#include <rte_mbuf.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+
+#include "graph_pcap_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_PKT_POOL	"graph_pcap_pkt_pool"
+#define GRAPH_PCAP_FILE_NAME	"dpdk_graph_pcap_capture_XXXXXX.pcapng"
+
+/* For multi-process, packets are captured in separate files. */
+static rte_pcapng_t *pcapng_fd;
+static bool pcap_enable;
+struct rte_mempool *pkt_mp;
+
+void
+graph_pcap_enable(bool val)
+{
+	pcap_enable = val;
+}
+
+int
+graph_pcap_is_enable(void)
+{
+	return pcap_enable;
+}
+
+void
+graph_pcap_exit(struct rte_graph *graph)
+{
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		if (pkt_mp)
+			rte_mempool_free(pkt_mp);
+
+	if (pcapng_fd) {
+		rte_pcapng_close(pcapng_fd);
+		pcapng_fd = NULL;
+	}
+
+	/* Disable pcap. */
+	graph->pcap_enable = 0;
+	graph_pcap_enable(0);
+}
+
+static int
+graph_pcap_default_path_get(char **dir_path)
+{
+	struct passwd *pwd;
+	char *home_dir;
+
+	/* First check for shell environment variable */
+	home_dir = getenv("HOME");
+	if (home_dir == NULL) {
+		graph_warn("Home env not preset.");
+		/* Fallback to password file entry */
+		pwd = getpwuid(getuid());
+		if (pwd == NULL)
+			return -EINVAL;
+
+		home_dir = pwd->pw_dir;
+	}
+
+	/* Append default pcap file to directory */
+	if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME) == -1)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int
+graph_pcap_file_open(const char *filename)
+{
+	int fd;
+	char file_name[RTE_GRAPH_PCAP_FILE_SZ];
+	char *pcap_dir;
+
+	if (pcapng_fd)
+		goto done;
+
+	if (!filename || filename[0] == '\0') {
+		if (graph_pcap_default_path_get(&pcap_dir) < 0)
+			return -1;
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
+		free(pcap_dir);
+	} else {
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s_XXXXXX.pcapng",
+			 filename);
+	}
+
+	fd = mkstemps(file_name, strlen(".pcapng"));
+	if (fd < 0) {
+		graph_err("mkstemps() failure");
+		return -1;
+	}
+
+	graph_info("pcap filename: %s", file_name);
+
+	/* Open a capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
+				      NULL);
+	if (pcapng_fd == NULL) {
+		graph_err("Graph rte_pcapng_fdopen failed.");
+		close(fd);
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_mp_init(void)
+{
+	pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
+	if (pkt_mp)
+		goto done;
+
+	/* Make a pool for cloned packets */
+	pkt_mp = rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,	0, 0,
+			rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
+			SOCKET_ID_ANY, "ring_mp_mc");
+	if (pkt_mp == NULL) {
+		graph_err("Cannot create mempool for graph pcap capture.");
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_init(struct graph *graph)
+{
+	struct rte_graph *graph_data = graph->graph;
+
+	if (graph_pcap_file_open(graph->pcap_filename) < 0)
+		goto error;
+
+	if (graph_pcap_mp_init() < 0)
+		goto error;
+
+	/* User configured number of packets to capture. */
+	if (graph->num_pkt_to_capture)
+		graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
+	else
+		graph_data->nb_pkt_to_capture = GRAPH_PCAP_NUM_PACKETS;
+
+	/* All good. Now populate data for secondary process. */
+
+	rte_strscpy(graph_data->pcap_filename, graph->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
+	graph_data->pcap_enable = 1;
+
+	return 0;
+
+error:
+	graph_pcap_exit(graph_data);
+	graph_pcap_enable(0);
+	graph_err("Graph pcap initialization failed. Disabling pcap trace.");
+	return -1;
+}
+
+uint16_t
+graph_pcap_dispatch(struct rte_graph *graph,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
+	char buffer[GRAPH_PCAP_BUF_SZ];
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf;
+	ssize_t len;
+
+	if (!nb_objs || (graph->nb_pkt_captured >= graph->nb_pkt_to_capture))
+		goto done;
+
+	num_packets = graph->nb_pkt_to_capture - graph->nb_pkt_captured;
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	snprintf(buffer, GRAPH_PCAP_BUF_SZ, "%s: %s", graph->name, node->name);
+
+	for (i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			break;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	graph->nb_pkt_captured += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_pcap_private.h b/lib/graph/graph_pcap_private.h
new file mode 100644
index 0000000000..198add67e2
--- /dev/null
+++ b/lib/graph/graph_pcap_private.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_PRIVATE_H_
+#define _RTE_GRAPH_PCAP_PRIVATE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "graph_private.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @internal
+ *
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+void graph_pcap_enable(bool val);
+
+/**
+ * @internal
+ *
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+int graph_pcap_is_enable(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to allocate mempool.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_mp_init(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to open pcap file.
+ *
+ * @param filename
+ *   Pcap filename.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_file_open(const char *filename);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled. This function
+ * open's pcap file and allocates mempool. Information needed for secondary
+ * process is populated.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_init(struct graph *graph);
+
+/**
+ * @internal
+ *
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's and
+ * free up memory. Pcap trace is also disabled.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ */
+void graph_pcap_exit(struct rte_graph *graph);
+
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t graph_pcap_dispatch(struct rte_graph *graph,
+				   struct rte_node *node, void **objs,
+				   uint16_t nb_objs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_GRAPH_PCAP_PRIVATE_H_ */
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..2c0844ce92 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -9,6 +9,7 @@
 #include <rte_memzone.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static size_t
 graph_fp_mem_calc_size(struct graph *graph)
@@ -75,7 +76,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (graph_pcap_is_enable()) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
@@ -183,6 +188,8 @@ graph_fp_mem_populate(struct graph *graph)
 	int rc;
 
 	graph_header_popluate(graph);
+	if (graph_pcap_is_enable())
+		graph_pcap_init(graph);
 	graph_nodes_populate(graph);
 	rc = graph_node_nexts_populate(graph);
 	rc |= graph_src_nodes_populate(graph);
@@ -227,6 +234,9 @@ graph_nodes_mem_destroy(struct rte_graph *graph)
 int
 graph_fp_mem_destroy(struct graph *graph)
 {
+	if (graph_pcap_is_enable())
+		graph_pcap_exit(graph->graph);
+
 	graph_nodes_mem_destroy(graph->graph);
 	return rte_memzone_free(graph->mz);
 }
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..7d1b30b8ac 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -22,6 +22,7 @@ extern int rte_graph_logtype;
 			__func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__, )))
 
 #define graph_err(...) GRAPH_LOG(ERR, __VA_ARGS__)
+#define graph_warn(...) GRAPH_LOG(WARNING, __VA_ARGS__)
 #define graph_info(...) GRAPH_LOG(INFO, __VA_ARGS__)
 #define graph_dbg(...) GRAPH_LOG(DEBUG, __VA_ARGS__)
 
@@ -100,6 +101,10 @@ struct graph {
 	/**< Memory size of the graph. */
 	int socket;
 	/**< Socket identifier where memory is allocated. */
+	uint64_t num_pkt_to_capture;
+	/**< Number of packets to be captured per core. */
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+	/**< pcap file name/path. */
 	STAILQ_HEAD(gnode_list, graph_node) node_list;
 	/**< Nodes in a graph. */
 };
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..3526d1b5d4 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap.c',
 )
 headers = files('rte_graph.h', 'rte_graph_worker.h')
 
-deps += ['eal']
+deps += ['eal', 'pcapng']
diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h
index b32c4bc217..c9a77297fc 100644
--- a/lib/graph/rte_graph.h
+++ b/lib/graph/rte_graph.h
@@ -35,6 +35,7 @@ extern "C" {
 
 #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
 #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
+#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */
 #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
 #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
 #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
@@ -164,6 +165,10 @@ struct rte_graph_param {
 	uint16_t nb_node_patterns;  /**< Number of node patterns. */
 	const char **node_patterns;
 	/**< Array of node patterns based on shell pattern. */
+
+	bool pcap_enable; /**< Pcap enable. */
+	uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
+	char *pcap_filename; /**< Filename in which packets to be captured.*/
 };
 
 /**
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..438595b15c 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -44,6 +44,12 @@ struct rte_graph {
 	rte_graph_t id;	/**< Graph identifier. */
 	int socket;	/**< Socket ID where memory is allocated. */
 	char name[RTE_GRAPH_NAMESIZE];	/**< Name of the graph. */
+	bool pcap_enable;	        /**< Pcap trace enabled. */
+	/** Number of packets captured per core. */
+	uint64_t nb_pkt_captured;
+	/** Number of packets to capture per core. */
+	uint64_t nb_pkt_to_capture;
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];  /**< Pcap filename. */
 	uint64_t fence;			/**< Fence. */
 } __rte_cache_aligned;
 
@@ -64,6 +70,9 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	/** Original process function when pcap is enabled. */
+	rte_node_process_t original_process;
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture
  2023-01-24 11:21       ` [PATCH v4 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-01-24 11:21         ` [PATCH v4 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-24 11:21         ` Amit Prakash Shukla
  2023-01-31  8:14           ` Jerin Jacob
  2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-01-24 11:21 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

 doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
 examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..3043dba8e2 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--pcap-num-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--pcap-num-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
@@ -99,6 +108,20 @@ In this command:
 |          |           |           |                                     |
 +----------+-----------+-----------+-------------------------------------+
 
+To enable pcap trace on each graph, use following command:
+
+.. code-block:: console
+
+    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets> --pcap-file-name "</filepath/filename>"
+
+In this command:
+
+*   The --pcap-enable option enables pcap trace on graph nodes.
+
+*   The --pcap-num-cap option enables user to configure number packets to be captured per graph. Default 1024 packets per graph are captured.
+
+*   The --pcap-file-name option enables user to give filename in which packets are to be captured.
+
 Refer to the *DPDK Getting Started Guide* for general information on running applications and
 the Environment Abstraction Layer (EAL) options.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..5feeab4f0f 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -76,6 +76,12 @@ xmm_t val_eth[RTE_MAX_ETHPORTS];
 /* Mask of enabled ports */
 static uint32_t enabled_port_mask;
 
+/* Pcap trace */
+static char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+static uint64_t packet_to_capture;
+static int pcap_trace_enable;
+
+
 struct lcore_rx_queue {
 	uint16_t port_id;
 	uint8_t queue_id;
@@ -261,7 +267,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +277,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --pcap-num-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +431,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "pcap-num-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +446,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +457,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -498,6 +534,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			pcap_trace_enable = 1;
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			packet_to_capture = parse_num_pkt_cap(optarg);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       packet_to_capture);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_strlcpy(pcap_filename, optarg,
+				    sizeof(pcap_filename));
+			printf("Pcap file name: %s\n", pcap_filename);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -1027,6 +1080,11 @@ main(int argc, char **argv)
 	memset(&graph_conf, 0, sizeof(graph_conf));
 	graph_conf.node_patterns = node_patterns;
 
+	/* Pcap config */
+	graph_conf.pcap_enable = pcap_trace_enable;
+	graph_conf.num_pkt_to_capture = packet_to_capture;
+	graph_conf.pcap_filename = pcap_filename;
+
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 		rte_graph_t graph_id;
 		rte_edge_t i;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 2/3] graph: pcap capture for graph nodes
  2023-01-24 11:21         ` [PATCH v4 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-01-31  8:06           ` Jerin Jacob
  2023-02-03  8:15             ` [EXT] " Amit Prakash Shukla
  0 siblings, 1 reply; 47+ messages in thread
From: Jerin Jacob @ 2023-01-31  8:06 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Anatoly Burakov, dev

On Tue, Jan 24, 2023 at 4:52 PM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
>
> Implementation adds support to capture packets at each node with
> packet metadata and node name.
>
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> ---
> v2:
>  - Fixed code style issue
>  - Fixed CI compilation issue on github-robot
>
> v3:
>  - Code review suggestion from Stephen
>  - Fixed potential memory leak
>
> v4:
>  - Code review suggestion from Jerin
>
>  app/test/test_graph_perf.c             |   2 +-
>  doc/guides/rel_notes/release_23_03.rst |   7 +
>  lib/graph/graph.c                      |  17 +-
>  lib/graph/graph_pcap.c                 | 217 +++++++++++++++++++++++++
>  lib/graph/graph_pcap_private.h         | 124 ++++++++++++++
>  lib/graph/graph_populate.c             |  12 +-
>  lib/graph/graph_private.h              |   5 +
>  lib/graph/meson.build                  |   3 +-
>  lib/graph/rte_graph.h                  |   5 +
>  lib/graph/rte_graph_worker.h           |   9 +
>  10 files changed, 397 insertions(+), 4 deletions(-)
>  create mode 100644 lib/graph/graph_pcap.c
>  create mode 100644 lib/graph/graph_pcap_private.h
>
> diff --git a/app/test/test_graph_perf.c b/app/test/test_graph_perf.c
> index 1d065438a6..c5b463f700 100644
> --- a/app/test/test_graph_perf.c
> +++ b/app/test/test_graph_perf.c
> @@ -324,7 +324,7 @@ graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks,
>         char nname[RTE_NODE_NAMESIZE / 2];
>         struct test_node_data *node_data;
>         char *ename[nodes_per_stage];
> -       struct rte_graph_param gconf;
> +       struct rte_graph_param gconf = {0};

If it is Fix move to seperate patch out this series.


>         const struct rte_memzone *mz;
>         uint8_t total_percent = 0;
>         rte_node_t *src_nodes;
> diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
> index 8c360b89e4..9ba392fb58 100644
> --- a/doc/guides/rel_notes/release_23_03.rst
> +++ b/doc/guides/rel_notes/release_23_03.rst
> @@ -69,6 +69,10 @@ New Features
>      ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
>      required for eth_rx, eth_tx, crypto and timer eventdev adapters.
>
> +* **Added pcap trace support in graph library.**
> +
> +  * Added support to capture packets at each graph node with packet metadata and
> +    node name.
>
>  Removed Items
>  -------------
> @@ -101,6 +105,9 @@ API Changes
>  * Experimental function ``rte_pcapng_copy`` was updated to support comment
>    section in enhanced packet block in pcapng library.
>
> +* Experimental structures ``struct rte_graph_param``, ``struct rte_graph`` and
> +  ``struct graph`` were updated to support pcap trace in graph library.
> +
>  ABI Changes
>  -----------
>
> diff --git a/lib/graph/graph.c b/lib/graph/graph.c
> index 3a617cc369..a839a2803b 100644
> --- a/lib/graph/graph.c
> +++ b/lib/graph/graph.c
> @@ -15,6 +15,7 @@
>  #include <rte_string_fns.h>
>
>  #include "graph_private.h"
> +#include "graph_pcap_private.h"
>
>  static struct graph_head graph_list = STAILQ_HEAD_INITIALIZER(graph_list);
>  static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER;
> @@ -228,7 +229,12 @@ graph_mem_fixup_node_ctx(struct rte_graph *graph)
>                 node_db = node_from_name(name);
>                 if (node_db == NULL)
>                         SET_ERR_JMP(ENOLINK, fail, "Node %s not found", name);
> -               node->process = node_db->process;
> +
> +               if (graph->pcap_enable) {
> +                       node->process = graph_pcap_dispatch;
> +                       node->original_process = node_db->process;
> +               } else
> +                       node->process = node_db->process;
>         }
>
>         return graph;
> @@ -242,6 +248,9 @@ graph_mem_fixup_secondary(struct rte_graph *graph)
>         if (graph == NULL || rte_eal_process_type() == RTE_PROC_PRIMARY)
>                 return graph;
>
> +       if (graph_pcap_file_open(graph->pcap_filename) || graph_pcap_mp_init())
> +               graph_pcap_exit(graph);
> +
>         return graph_mem_fixup_node_ctx(graph);
>  }
>
> @@ -323,11 +332,17 @@ rte_graph_create(const char *name, struct rte_graph_param *prm)
>         if (graph_has_isolated_node(graph))
>                 goto graph_cleanup;
>
> +       /* Initialize pcap config. */
> +       graph_pcap_enable(prm->pcap_enable);
> +
>         /* Initialize graph object */
>         graph->socket = prm->socket_id;
>         graph->src_node_count = src_node_count;
>         graph->node_count = graph_nodes_count(graph);
>         graph->id = graph_id;
> +       graph->num_pkt_to_capture = prm->num_pkt_to_capture;
> +       if (prm->pcap_filename)
> +               rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
>
>         /* Allocate the Graph fast path memory and populate the data */
>         if (graph_fp_mem_create(graph))
> diff --git a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c
> new file mode 100644
> index 0000000000..7bd13ed61e
> --- /dev/null
> +++ b/lib/graph/graph_pcap.c
> @@ -0,0 +1,217 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2023 Marvell International Ltd.
> + */
> +
> +#include <errno.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <pwd.h>

Sort in alphabetical order.


> +
> +#include <rte_mbuf.h>
> +#include <rte_pcapng.h>
> +
> +#include "rte_graph_worker.h"
> +
> +#include "graph_pcap_private.h"
> +
> +#define GRAPH_PCAP_BUF_SZ      128
> +#define GRAPH_PCAP_NUM_PACKETS 1024
> +#define GRAPH_PCAP_PKT_POOL    "graph_pcap_pkt_pool"
> +#define GRAPH_PCAP_FILE_NAME   "dpdk_graph_pcap_capture_XXXXXX.pcapng"
> +
> +/* For multi-process, packets are captured in separate files. */
> +static rte_pcapng_t *pcapng_fd;
> +static bool pcap_enable;
> +struct rte_mempool *pkt_mp;
> +
> +void
> +graph_pcap_enable(bool val)
> +{
> +       pcap_enable = val;
> +}
> +
> +int
> +graph_pcap_is_enable(void)
> +{
> +       return pcap_enable;
> +}
> +
> +void
> +graph_pcap_exit(struct rte_graph *graph)
> +{
> +       if (rte_eal_process_type() == RTE_PROC_PRIMARY)
> +               if (pkt_mp)
> +                       rte_mempool_free(pkt_mp);
> +
> +       if (pcapng_fd) {
> +               rte_pcapng_close(pcapng_fd);
> +               pcapng_fd = NULL;
> +       }
> +
> +       /* Disable pcap. */
> +       graph->pcap_enable = 0;
> +       graph_pcap_enable(0);
> +}
> +
> +static int
> +graph_pcap_default_path_get(char **dir_path)
> +{
> +       struct passwd *pwd;
> +       char *home_dir;
> +
> +       /* First check for shell environment variable */
> +       home_dir = getenv("HOME");
> +       if (home_dir == NULL) {
> +               graph_warn("Home env not preset.");
> +               /* Fallback to password file entry */
> +               pwd = getpwuid(getuid());
> +               if (pwd == NULL)
> +                       return -EINVAL;
> +
> +               home_dir = pwd->pw_dir;
> +       }
> +
> +       /* Append default pcap file to directory */
> +       if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME) == -1)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +int
> +graph_pcap_file_open(const char *filename)
> +{
> +       int fd;
> +       char file_name[RTE_GRAPH_PCAP_FILE_SZ];
> +       char *pcap_dir;
> +
> +       if (pcapng_fd)
> +               goto done;
> +
> +       if (!filename || filename[0] == '\0') {
> +               if (graph_pcap_default_path_get(&pcap_dir) < 0)
> +                       return -1;
> +               snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
> +               free(pcap_dir);
> +       } else {
> +               snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s_XXXXXX.pcapng",
> +                        filename);
> +       }
> +
> +       fd = mkstemps(file_name, strlen(".pcapng"));
> +       if (fd < 0) {
> +               graph_err("mkstemps() failure");
> +               return -1;
> +       }
> +
> +       graph_info("pcap filename: %s", file_name);
> +
> +       /* Open a capture file */
> +       pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
> +                                     NULL);
> +       if (pcapng_fd == NULL) {
> +               graph_err("Graph rte_pcapng_fdopen failed.");
> +               close(fd);
> +               return -1;
> +       }
> +
> +done:
> +       return 0;
> +}
> +
> +int
> +graph_pcap_mp_init(void)
> +{
> +       pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
> +       if (pkt_mp)
> +               goto done;
> +
> +       /* Make a pool for cloned packets */
> +       pkt_mp = rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
> +                       IOV_MAX + RTE_GRAPH_BURST_SIZE, 0, 0,
> +                       rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
> +                       SOCKET_ID_ANY, "ring_mp_mc");
> +       if (pkt_mp == NULL) {
> +               graph_err("Cannot create mempool for graph pcap capture.");
> +               return -1;
> +       }
> +
> +done:
> +       return 0;
> +}
> +
> +int
> +graph_pcap_init(struct graph *graph)
> +{
> +       struct rte_graph *graph_data = graph->graph;
> +
> +       if (graph_pcap_file_open(graph->pcap_filename) < 0)
> +               goto error;
> +
> +       if (graph_pcap_mp_init() < 0)
> +               goto error;
> +
> +       /* User configured number of packets to capture. */
> +       if (graph->num_pkt_to_capture)
> +               graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
> +       else
> +               graph_data->nb_pkt_to_capture = GRAPH_PCAP_NUM_PACKETS;
> +
> +       /* All good. Now populate data for secondary process. */

No need new line.

> +
> +       rte_strscpy(graph_data->pcap_filename, graph->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
> +       graph_data->pcap_enable = 1;
> +
> +       return 0;
> +
> +error:
> +       graph_pcap_exit(graph_data);
> +       graph_pcap_enable(0);
> +       graph_err("Graph pcap initialization failed. Disabling pcap trace.");
> +       return -1;
> +}
> +
> +uint16_t
> +graph_pcap_dispatch(struct rte_graph *graph,
> +                             struct rte_node *node, void **objs,
> +                             uint16_t nb_objs)
> +{
> +       struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
> +       char buffer[GRAPH_PCAP_BUF_SZ];
> +       uint64_t i, num_packets;
> +       struct rte_mbuf *mbuf;
> +       ssize_t len;
> +
> +       if (!nb_objs || (graph->nb_pkt_captured >= graph->nb_pkt_to_capture))
> +               goto done;
> +
> +       num_packets = graph->nb_pkt_to_capture - graph->nb_pkt_captured;
> +       /* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
> +       if (num_packets > nb_objs)
> +               num_packets = nb_objs;
> +
> +       snprintf(buffer, GRAPH_PCAP_BUF_SZ, "%s: %s", graph->name, node->name);
> +
> +       for (i = 0; i < num_packets; i++) {
> +               struct rte_mbuf *mc;
> +               mbuf = (struct rte_mbuf *)objs[i];
> +
> +               mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len,
> +                                    rte_get_tsc_cycles(), 0, buffer);
> +               if (mc == NULL)
> +                       break;
> +
> +               mbuf_clones[i] = mc;
> +       }
> +
> +       /* write it to capture file */
> +       len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
> +       rte_pktmbuf_free_bulk(mbuf_clones, i);
> +       if (len <= 0)
> +               goto done;
> +
> +       graph->nb_pkt_captured += i;
> +
> +done:
> +       return node->original_process(graph, node, objs, nb_objs);
> +}
> diff --git a/lib/graph/graph_pcap_private.h b/lib/graph/graph_pcap_private.h
> new file mode 100644
> index 0000000000..198add67e2
> --- /dev/null
> +++ b/lib/graph/graph_pcap_private.h
> @@ -0,0 +1,124 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2023 Marvell International Ltd.
> + */
> +
> +#ifndef _RTE_GRAPH_PCAP_PRIVATE_H_
> +#define _RTE_GRAPH_PCAP_PRIVATE_H_
> +
> +#include <stdint.h>
> +#include <sys/types.h>
> +
> +#include "graph_private.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif

No need this for internal header files


> +
> +/**
> + * @internal
> + *
> + * Pcap trace enable/disable function.
> + *
> + * The function is called to enable/disable graph pcap trace functionality.
> + *
> + * @param val
> + *   Value to be set to enable/disable graph pcap trace.
> + */
> +void graph_pcap_enable(bool val);
> +
> +/**
> + * @internal
> + *
> + * Check graph pcap trace is enable/disable.
> + *
> + * The function is called to check if the graph pcap trace is enabled/disabled.
> + *
> + * @return
> + *   - 1: Enable
> + *   - 0: Disable
> + */
> +int graph_pcap_is_enable(void);
> +
> +/**
> + * @internal
> + *
> + * Initialise graph pcap trace functionality.
> + *
> + * The function invoked to allocate mempool.
> + *
> + * @return
> + *   0 on success and -1 on failure.
> + */
> +int graph_pcap_mp_init(void);
> +
> +/**
> + * @internal
> + *
> + * Initialise graph pcap trace functionality.
> + *
> + * The function invoked to open pcap file.
> + *
> + * @param filename
> + *   Pcap filename.
> + *
> + * @return
> + *   0 on success and -1 on failure.
> + */
> +int graph_pcap_file_open(const char *filename);
> +
> +/**
> + * @internal
> + *
> + * Initialise graph pcap trace functionality.
> + *
> + * The function invoked when the graph pcap trace is enabled. This function
> + * open's pcap file and allocates mempool. Information needed for secondary
> + * process is populated.
> + *
> + * @param graph
> + *   Pointer to graph structure.
> + *
> + * @return
> + *   0 on success and -1 on failure.
> + */
> +int graph_pcap_init(struct graph *graph);
> +
> +/**
> + * @internal
> + *
> + * Exit graph pcap trace functionality.
> + *
> + * The function is called to exit graph pcap trace and close open fd's and
> + * free up memory. Pcap trace is also disabled.
> + *
> + * @param graph
> + *   Pointer to graph structure.
> + */
> +void graph_pcap_exit(struct rte_graph *graph);
> +
> +/**
> + * @internal
> + *
> + * Capture mbuf metadata and node metadata to a pcap file.
> + *
> + * When graph pcap trace enabled, this function is invoked prior to each node
> + * and mbuf, node metadata is parsed and captured in a pcap file.
> + *
> + * @param graph
> + *   Pointer to the graph object.
> + * @param node
> + *   Pointer to the node object.
> + * @param objs
> + *   Pointer to an array of objects to be processed.
> + * @param nb_objs
> + *   Number of objects in the array.
> + */
> +uint16_t graph_pcap_dispatch(struct rte_graph *graph,
> +                                  struct rte_node *node, void **objs,
> +                                  uint16_t nb_objs);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_GRAPH_PCAP_PRIVATE_H_ */
> diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
> index 102fd6c29b..2c0844ce92 100644
> --- a/lib/graph/graph_populate.c
> +++ b/lib/graph/graph_populate.c
> @@ -9,6 +9,7 @@
>  #include <rte_memzone.h>
>
>  #include "graph_private.h"
> +#include "graph_pcap_private.h"
>
>  static size_t
>  graph_fp_mem_calc_size(struct graph *graph)
> @@ -75,7 +76,11 @@ graph_nodes_populate(struct graph *_graph)
>                 memset(node, 0, sizeof(*node));
>                 node->fence = RTE_GRAPH_FENCE;
>                 node->off = off;
> -               node->process = graph_node->node->process;
> +               if (graph_pcap_is_enable()) {
> +                       node->process = graph_pcap_dispatch;
> +                       node->original_process = graph_node->node->process;
> +               } else
> +                       node->process = graph_node->node->process;
>                 memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
>                 pid = graph_node->node->parent_id;
>                 if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
> @@ -183,6 +188,8 @@ graph_fp_mem_populate(struct graph *graph)
>         int rc;
>
>         graph_header_popluate(graph);
> +       if (graph_pcap_is_enable())
> +               graph_pcap_init(graph);
>         graph_nodes_populate(graph);
>         rc = graph_node_nexts_populate(graph);
>         rc |= graph_src_nodes_populate(graph);
> @@ -227,6 +234,9 @@ graph_nodes_mem_destroy(struct rte_graph *graph)
>  int
>  graph_fp_mem_destroy(struct graph *graph)
>  {
> +       if (graph_pcap_is_enable())
> +               graph_pcap_exit(graph->graph);
> +
>         graph_nodes_mem_destroy(graph->graph);
>         return rte_memzone_free(graph->mz);
>  }
> diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
> index f9a85c8926..7d1b30b8ac 100644
> --- a/lib/graph/graph_private.h
> +++ b/lib/graph/graph_private.h
> @@ -22,6 +22,7 @@ extern int rte_graph_logtype;
>                         __func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__, )))
>
>  #define graph_err(...) GRAPH_LOG(ERR, __VA_ARGS__)
> +#define graph_warn(...) GRAPH_LOG(WARNING, __VA_ARGS__)
>  #define graph_info(...) GRAPH_LOG(INFO, __VA_ARGS__)
>  #define graph_dbg(...) GRAPH_LOG(DEBUG, __VA_ARGS__)
>
> @@ -100,6 +101,10 @@ struct graph {
>         /**< Memory size of the graph. */
>         int socket;
>         /**< Socket identifier where memory is allocated. */
> +       uint64_t num_pkt_to_capture;
> +       /**< Number of packets to be captured per core. */
> +       char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
> +       /**< pcap file name/path. */
>         STAILQ_HEAD(gnode_list, graph_node) node_list;
>         /**< Nodes in a graph. */
>  };
> diff --git a/lib/graph/meson.build b/lib/graph/meson.build
> index c7327549e8..3526d1b5d4 100644
> --- a/lib/graph/meson.build
> +++ b/lib/graph/meson.build
> @@ -14,7 +14,8 @@ sources = files(
>          'graph_debug.c',
>          'graph_stats.c',
>          'graph_populate.c',
> +        'graph_pcap.c',
>  )
>  headers = files('rte_graph.h', 'rte_graph_worker.h')
>
> -deps += ['eal']
> +deps += ['eal', 'pcapng']
> diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h
> index b32c4bc217..c9a77297fc 100644
> --- a/lib/graph/rte_graph.h
> +++ b/lib/graph/rte_graph.h
> @@ -35,6 +35,7 @@ extern "C" {
>
>  #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
>  #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
> +#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */
>  #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
>  #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
>  #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
> @@ -164,6 +165,10 @@ struct rte_graph_param {
>         uint16_t nb_node_patterns;  /**< Number of node patterns. */
>         const char **node_patterns;
>         /**< Array of node patterns based on shell pattern. */
> +
> +       bool pcap_enable; /**< Pcap enable. */
> +       uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
> +       char *pcap_filename; /**< Filename in which packets to be captured.*/
>  };
>
>  /**
> diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
> index fc6fee48c8..438595b15c 100644
> --- a/lib/graph/rte_graph_worker.h
> +++ b/lib/graph/rte_graph_worker.h
> @@ -44,6 +44,12 @@ struct rte_graph {
>         rte_graph_t id; /**< Graph identifier. */
>         int socket;     /**< Socket ID where memory is allocated. */
>         char name[RTE_GRAPH_NAMESIZE];  /**< Name of the graph. */
> +       bool pcap_enable;               /**< Pcap trace enabled. */
> +       /** Number of packets captured per core. */
> +       uint64_t nb_pkt_captured;
> +       /** Number of packets to capture per core. */
> +       uint64_t nb_pkt_to_capture;
> +       char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];  /**< Pcap filename. */
>         uint64_t fence;                 /**< Fence. */
>  } __rte_cache_aligned;
>
> @@ -64,6 +70,9 @@ struct rte_node {
>         char parent[RTE_NODE_NAMESIZE]; /**< Parent node name. */
>         char name[RTE_NODE_NAMESIZE];   /**< Name of the node. */
>
> +       /** Original process function when pcap is enabled. */
> +       rte_node_process_t original_process;
> +
>         /* Fast path area  */
>  #define RTE_NODE_CTX_SZ 16
>         uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture
  2023-01-24 11:21         ` [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-01-31  8:14           ` Jerin Jacob
  2023-02-03  8:16             ` [EXT] " Amit Prakash Shukla
  0 siblings, 1 reply; 47+ messages in thread
From: Jerin Jacob @ 2023-01-31  8:14 UTC (permalink / raw)
  To: Amit Prakash Shukla; +Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, dev

On Tue, Jan 24, 2023 at 4:53 PM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
>
> Added support to configure pcap capture.
>
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>


Change the subject as examples/l3fwd-graph:

> ---
> v2:
>  - Fixed code style issue
>  - Fixed CI compilation issue on github-robot
>
> v3:
>  - Code review suggestion from Stephen
>  - Fixed potential memory leak
>
> v4:
>  - Code review suggestion from Jerin
>
>  doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
>  examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
>  2 files changed, 83 insertions(+), 2 deletions(-)
>
> diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
> index 0a3e0d44ec..3043dba8e2 100644
> --- a/doc/guides/sample_app_ug/l3_forward_graph.rst
> +++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
> @@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
>                                     [--max-pkt-len PKTLEN]
>                                     [--no-numa]
>                                     [--per-port-pool]
> +                                   [--pcap-enable]
> +                                   [--pcap-num-cap]
> +                                   [--pcap-file-name]
>
>  Where,
>
> @@ -69,6 +72,12 @@ Where,
>
>  * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
>
> +* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
> +
> +* ``--pcap-num-cap:`` Optional, Number of packets to be captured per core.
> +
> +* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
> +
>  For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
>  while cores 8-15 and 24-31 appear on socket 1.
>
> @@ -99,6 +108,20 @@ In this command:
>  |          |           |           |                                     |
>  +----------+-----------+-----------+-------------------------------------+
>
> +To enable pcap trace on each graph, use following command:
> +
> +.. code-block:: console
> +
> +    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets> --pcap-file-name "</filepath/filename>"

</filepath/filename> can be changes as  "/path/to/file"

^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [PATCH v4 2/3] graph: pcap capture for graph nodes
  2023-01-31  8:06           ` Jerin Jacob
@ 2023-02-03  8:15             ` Amit Prakash Shukla
  0 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-03  8:15 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, Anatoly Burakov, dev

Thanks Jerin for the feedback. I will make the changes in next version of the patch.

> -----Original Message-----
> From: Jerin Jacob <jerinjacobk@gmail.com>
> Sent: Tuesday, January 31, 2023 1:37 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; Anatoly Burakov
> <anatoly.burakov@intel.com>; dev@dpdk.org
> Subject: [EXT] Re: [PATCH v4 2/3] graph: pcap capture for graph nodes
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Tue, Jan 24, 2023 at 4:52 PM Amit Prakash Shukla
> <amitprakashs@marvell.com> wrote:
> >
> > Implementation adds support to capture packets at each node with
> > packet metadata and node name.
> >
> > Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> > ---
> > v2:
> >  - Fixed code style issue
> >  - Fixed CI compilation issue on github-robot
> >
> > v3:
> >  - Code review suggestion from Stephen
> >  - Fixed potential memory leak
> >
> > v4:
> >  - Code review suggestion from Jerin
> >
> >  app/test/test_graph_perf.c             |   2 +-
> >  doc/guides/rel_notes/release_23_03.rst |   7 +
> >  lib/graph/graph.c                      |  17 +-
> >  lib/graph/graph_pcap.c                 | 217 +++++++++++++++++++++++++
> >  lib/graph/graph_pcap_private.h         | 124 ++++++++++++++
> >  lib/graph/graph_populate.c             |  12 +-
> >  lib/graph/graph_private.h              |   5 +
> >  lib/graph/meson.build                  |   3 +-
> >  lib/graph/rte_graph.h                  |   5 +
> >  lib/graph/rte_graph_worker.h           |   9 +
> >  10 files changed, 397 insertions(+), 4 deletions(-)  create mode
> > 100644 lib/graph/graph_pcap.c  create mode 100644
> > lib/graph/graph_pcap_private.h
> >
> > diff --git a/app/test/test_graph_perf.c b/app/test/test_graph_perf.c
> > index 1d065438a6..c5b463f700 100644
> > --- a/app/test/test_graph_perf.c
> > +++ b/app/test/test_graph_perf.c
> > @@ -324,7 +324,7 @@ graph_init(const char *gname, uint8_t nb_srcs,
> uint8_t nb_sinks,
> >         char nname[RTE_NODE_NAMESIZE / 2];
> >         struct test_node_data *node_data;
> >         char *ename[nodes_per_stage];
> > -       struct rte_graph_param gconf;
> > +       struct rte_graph_param gconf = {0};
> 
> If it is Fix move to seperate patch out this series.
> 
> 
> >         const struct rte_memzone *mz;
> >         uint8_t total_percent = 0;
> >         rte_node_t *src_nodes;
> > diff --git a/doc/guides/rel_notes/release_23_03.rst
> > b/doc/guides/rel_notes/release_23_03.rst
> > index 8c360b89e4..9ba392fb58 100644
> > --- a/doc/guides/rel_notes/release_23_03.rst
> > +++ b/doc/guides/rel_notes/release_23_03.rst
> > @@ -69,6 +69,10 @@ New Features
> >      ``rte_event_dev_config::nb_single_link_event_port_queues``
> parameter
> >      required for eth_rx, eth_tx, crypto and timer eventdev adapters.
> >
> > +* **Added pcap trace support in graph library.**
> > +
> > +  * Added support to capture packets at each graph node with packet
> metadata and
> > +    node name.
> >
> >  Removed Items
> >  -------------
> > @@ -101,6 +105,9 @@ API Changes
> >  * Experimental function ``rte_pcapng_copy`` was updated to support
> comment
> >    section in enhanced packet block in pcapng library.
> >
> > +* Experimental structures ``struct rte_graph_param``, ``struct
> > +rte_graph`` and
> > +  ``struct graph`` were updated to support pcap trace in graph library.
> > +
> >  ABI Changes
> >  -----------
> >
> > diff --git a/lib/graph/graph.c b/lib/graph/graph.c index
> > 3a617cc369..a839a2803b 100644
> > --- a/lib/graph/graph.c
> > +++ b/lib/graph/graph.c
> > @@ -15,6 +15,7 @@
> >  #include <rte_string_fns.h>
> >
> >  #include "graph_private.h"
> > +#include "graph_pcap_private.h"
> >
> >  static struct graph_head graph_list =
> > STAILQ_HEAD_INITIALIZER(graph_list);
> >  static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER; @@
> > -228,7 +229,12 @@ graph_mem_fixup_node_ctx(struct rte_graph *graph)
> >                 node_db = node_from_name(name);
> >                 if (node_db == NULL)
> >                         SET_ERR_JMP(ENOLINK, fail, "Node %s not found", name);
> > -               node->process = node_db->process;
> > +
> > +               if (graph->pcap_enable) {
> > +                       node->process = graph_pcap_dispatch;
> > +                       node->original_process = node_db->process;
> > +               } else
> > +                       node->process = node_db->process;
> >         }
> >
> >         return graph;
> > @@ -242,6 +248,9 @@ graph_mem_fixup_secondary(struct rte_graph
> *graph)
> >         if (graph == NULL || rte_eal_process_type() == RTE_PROC_PRIMARY)
> >                 return graph;
> >
> > +       if (graph_pcap_file_open(graph->pcap_filename) ||
> graph_pcap_mp_init())
> > +               graph_pcap_exit(graph);
> > +
> >         return graph_mem_fixup_node_ctx(graph);  }
> >
> > @@ -323,11 +332,17 @@ rte_graph_create(const char *name, struct
> rte_graph_param *prm)
> >         if (graph_has_isolated_node(graph))
> >                 goto graph_cleanup;
> >
> > +       /* Initialize pcap config. */
> > +       graph_pcap_enable(prm->pcap_enable);
> > +
> >         /* Initialize graph object */
> >         graph->socket = prm->socket_id;
> >         graph->src_node_count = src_node_count;
> >         graph->node_count = graph_nodes_count(graph);
> >         graph->id = graph_id;
> > +       graph->num_pkt_to_capture = prm->num_pkt_to_capture;
> > +       if (prm->pcap_filename)
> > +               rte_strscpy(graph->pcap_filename, prm->pcap_filename,
> > + RTE_GRAPH_PCAP_FILE_SZ);
> >
> >         /* Allocate the Graph fast path memory and populate the data */
> >         if (graph_fp_mem_create(graph)) diff --git
> > a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c new file mode 100644
> > index 0000000000..7bd13ed61e
> > --- /dev/null
> > +++ b/lib/graph/graph_pcap.c
> > @@ -0,0 +1,217 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(C) 2023 Marvell International Ltd.
> > + */
> > +
> > +#include <errno.h>
> > +#include <unistd.h>
> > +#include <stdlib.h>
> > +#include <pwd.h>
> 
> Sort in alphabetical order.
> 
> 
> > +
> > +#include <rte_mbuf.h>
> > +#include <rte_pcapng.h>
> > +
> > +#include "rte_graph_worker.h"
> > +
> > +#include "graph_pcap_private.h"
> > +
> > +#define GRAPH_PCAP_BUF_SZ      128
> > +#define GRAPH_PCAP_NUM_PACKETS 1024
> > +#define GRAPH_PCAP_PKT_POOL    "graph_pcap_pkt_pool"
> > +#define GRAPH_PCAP_FILE_NAME
> "dpdk_graph_pcap_capture_XXXXXX.pcapng"
> > +
> > +/* For multi-process, packets are captured in separate files. */
> > +static rte_pcapng_t *pcapng_fd; static bool pcap_enable; struct
> > +rte_mempool *pkt_mp;
> > +
> > +void
> > +graph_pcap_enable(bool val)
> > +{
> > +       pcap_enable = val;
> > +}
> > +
> > +int
> > +graph_pcap_is_enable(void)
> > +{
> > +       return pcap_enable;
> > +}
> > +
> > +void
> > +graph_pcap_exit(struct rte_graph *graph) {
> > +       if (rte_eal_process_type() == RTE_PROC_PRIMARY)
> > +               if (pkt_mp)
> > +                       rte_mempool_free(pkt_mp);
> > +
> > +       if (pcapng_fd) {
> > +               rte_pcapng_close(pcapng_fd);
> > +               pcapng_fd = NULL;
> > +       }
> > +
> > +       /* Disable pcap. */
> > +       graph->pcap_enable = 0;
> > +       graph_pcap_enable(0);
> > +}
> > +
> > +static int
> > +graph_pcap_default_path_get(char **dir_path) {
> > +       struct passwd *pwd;
> > +       char *home_dir;
> > +
> > +       /* First check for shell environment variable */
> > +       home_dir = getenv("HOME");
> > +       if (home_dir == NULL) {
> > +               graph_warn("Home env not preset.");
> > +               /* Fallback to password file entry */
> > +               pwd = getpwuid(getuid());
> > +               if (pwd == NULL)
> > +                       return -EINVAL;
> > +
> > +               home_dir = pwd->pw_dir;
> > +       }
> > +
> > +       /* Append default pcap file to directory */
> > +       if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME)
> == -1)
> > +               return -ENOMEM;
> > +
> > +       return 0;
> > +}
> > +
> > +int
> > +graph_pcap_file_open(const char *filename) {
> > +       int fd;
> > +       char file_name[RTE_GRAPH_PCAP_FILE_SZ];
> > +       char *pcap_dir;
> > +
> > +       if (pcapng_fd)
> > +               goto done;
> > +
> > +       if (!filename || filename[0] == '\0') {
> > +               if (graph_pcap_default_path_get(&pcap_dir) < 0)
> > +                       return -1;
> > +               snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
> > +               free(pcap_dir);
> > +       } else {
> > +               snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ,
> "%s_XXXXXX.pcapng",
> > +                        filename);
> > +       }
> > +
> > +       fd = mkstemps(file_name, strlen(".pcapng"));
> > +       if (fd < 0) {
> > +               graph_err("mkstemps() failure");
> > +               return -1;
> > +       }
> > +
> > +       graph_info("pcap filename: %s", file_name);
> > +
> > +       /* Open a capture file */
> > +       pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
> > +                                     NULL);
> > +       if (pcapng_fd == NULL) {
> > +               graph_err("Graph rte_pcapng_fdopen failed.");
> > +               close(fd);
> > +               return -1;
> > +       }
> > +
> > +done:
> > +       return 0;
> > +}
> > +
> > +int
> > +graph_pcap_mp_init(void)
> > +{
> > +       pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
> > +       if (pkt_mp)
> > +               goto done;
> > +
> > +       /* Make a pool for cloned packets */
> > +       pkt_mp =
> rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
> > +                       IOV_MAX + RTE_GRAPH_BURST_SIZE, 0, 0,
> > +                       rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
> > +                       SOCKET_ID_ANY, "ring_mp_mc");
> > +       if (pkt_mp == NULL) {
> > +               graph_err("Cannot create mempool for graph pcap capture.");
> > +               return -1;
> > +       }
> > +
> > +done:
> > +       return 0;
> > +}
> > +
> > +int
> > +graph_pcap_init(struct graph *graph)
> > +{
> > +       struct rte_graph *graph_data = graph->graph;
> > +
> > +       if (graph_pcap_file_open(graph->pcap_filename) < 0)
> > +               goto error;
> > +
> > +       if (graph_pcap_mp_init() < 0)
> > +               goto error;
> > +
> > +       /* User configured number of packets to capture. */
> > +       if (graph->num_pkt_to_capture)
> > +               graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
> > +       else
> > +               graph_data->nb_pkt_to_capture =
> > + GRAPH_PCAP_NUM_PACKETS;
> > +
> > +       /* All good. Now populate data for secondary process. */
> 
> No need new line.
> 
> > +
> > +       rte_strscpy(graph_data->pcap_filename, graph->pcap_filename,
> RTE_GRAPH_PCAP_FILE_SZ);
> > +       graph_data->pcap_enable = 1;
> > +
> > +       return 0;
> > +
> > +error:
> > +       graph_pcap_exit(graph_data);
> > +       graph_pcap_enable(0);
> > +       graph_err("Graph pcap initialization failed. Disabling pcap trace.");
> > +       return -1;
> > +}
> > +
> > +uint16_t
> > +graph_pcap_dispatch(struct rte_graph *graph,
> > +                             struct rte_node *node, void **objs,
> > +                             uint16_t nb_objs) {
> > +       struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
> > +       char buffer[GRAPH_PCAP_BUF_SZ];
> > +       uint64_t i, num_packets;
> > +       struct rte_mbuf *mbuf;
> > +       ssize_t len;
> > +
> > +       if (!nb_objs || (graph->nb_pkt_captured >= graph-
> >nb_pkt_to_capture))
> > +               goto done;
> > +
> > +       num_packets = graph->nb_pkt_to_capture - graph-
> >nb_pkt_captured;
> > +       /* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
> > +       if (num_packets > nb_objs)
> > +               num_packets = nb_objs;
> > +
> > +       snprintf(buffer, GRAPH_PCAP_BUF_SZ, "%s: %s", graph->name,
> > + node->name);
> > +
> > +       for (i = 0; i < num_packets; i++) {
> > +               struct rte_mbuf *mc;
> > +               mbuf = (struct rte_mbuf *)objs[i];
> > +
> > +               mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf-
> >pkt_len,
> > +                                    rte_get_tsc_cycles(), 0, buffer);
> > +               if (mc == NULL)
> > +                       break;
> > +
> > +               mbuf_clones[i] = mc;
> > +       }
> > +
> > +       /* write it to capture file */
> > +       len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
> > +       rte_pktmbuf_free_bulk(mbuf_clones, i);
> > +       if (len <= 0)
> > +               goto done;
> > +
> > +       graph->nb_pkt_captured += i;
> > +
> > +done:
> > +       return node->original_process(graph, node, objs, nb_objs); }
> > diff --git a/lib/graph/graph_pcap_private.h
> > b/lib/graph/graph_pcap_private.h new file mode 100644 index
> > 0000000000..198add67e2
> > --- /dev/null
> > +++ b/lib/graph/graph_pcap_private.h
> > @@ -0,0 +1,124 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(C) 2023 Marvell International Ltd.
> > + */
> > +
> > +#ifndef _RTE_GRAPH_PCAP_PRIVATE_H_
> > +#define _RTE_GRAPH_PCAP_PRIVATE_H_
> > +
> > +#include <stdint.h>
> > +#include <sys/types.h>
> > +
> > +#include "graph_private.h"
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif
> 
> No need this for internal header files
> 
> 
> > +
> > +/**
> > + * @internal
> > + *
> > + * Pcap trace enable/disable function.
> > + *
> > + * The function is called to enable/disable graph pcap trace functionality.
> > + *
> > + * @param val
> > + *   Value to be set to enable/disable graph pcap trace.
> > + */
> > +void graph_pcap_enable(bool val);
> > +
> > +/**
> > + * @internal
> > + *
> > + * Check graph pcap trace is enable/disable.
> > + *
> > + * The function is called to check if the graph pcap trace is
> enabled/disabled.
> > + *
> > + * @return
> > + *   - 1: Enable
> > + *   - 0: Disable
> > + */
> > +int graph_pcap_is_enable(void);
> > +
> > +/**
> > + * @internal
> > + *
> > + * Initialise graph pcap trace functionality.
> > + *
> > + * The function invoked to allocate mempool.
> > + *
> > + * @return
> > + *   0 on success and -1 on failure.
> > + */
> > +int graph_pcap_mp_init(void);
> > +
> > +/**
> > + * @internal
> > + *
> > + * Initialise graph pcap trace functionality.
> > + *
> > + * The function invoked to open pcap file.
> > + *
> > + * @param filename
> > + *   Pcap filename.
> > + *
> > + * @return
> > + *   0 on success and -1 on failure.
> > + */
> > +int graph_pcap_file_open(const char *filename);
> > +
> > +/**
> > + * @internal
> > + *
> > + * Initialise graph pcap trace functionality.
> > + *
> > + * The function invoked when the graph pcap trace is enabled. This
> > +function
> > + * open's pcap file and allocates mempool. Information needed for
> > +secondary
> > + * process is populated.
> > + *
> > + * @param graph
> > + *   Pointer to graph structure.
> > + *
> > + * @return
> > + *   0 on success and -1 on failure.
> > + */
> > +int graph_pcap_init(struct graph *graph);
> > +
> > +/**
> > + * @internal
> > + *
> > + * Exit graph pcap trace functionality.
> > + *
> > + * The function is called to exit graph pcap trace and close open
> > +fd's and
> > + * free up memory. Pcap trace is also disabled.
> > + *
> > + * @param graph
> > + *   Pointer to graph structure.
> > + */
> > +void graph_pcap_exit(struct rte_graph *graph);
> > +
> > +/**
> > + * @internal
> > + *
> > + * Capture mbuf metadata and node metadata to a pcap file.
> > + *
> > + * When graph pcap trace enabled, this function is invoked prior to
> > +each node
> > + * and mbuf, node metadata is parsed and captured in a pcap file.
> > + *
> > + * @param graph
> > + *   Pointer to the graph object.
> > + * @param node
> > + *   Pointer to the node object.
> > + * @param objs
> > + *   Pointer to an array of objects to be processed.
> > + * @param nb_objs
> > + *   Number of objects in the array.
> > + */
> > +uint16_t graph_pcap_dispatch(struct rte_graph *graph,
> > +                                  struct rte_node *node, void **objs,
> > +                                  uint16_t nb_objs);
> > +
> > +#ifdef __cplusplus
> > +}
> > +#endif
> > +
> > +#endif /* _RTE_GRAPH_PCAP_PRIVATE_H_ */
> > diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
> > index 102fd6c29b..2c0844ce92 100644
> > --- a/lib/graph/graph_populate.c
> > +++ b/lib/graph/graph_populate.c
> > @@ -9,6 +9,7 @@
> >  #include <rte_memzone.h>
> >
> >  #include "graph_private.h"
> > +#include "graph_pcap_private.h"
> >
> >  static size_t
> >  graph_fp_mem_calc_size(struct graph *graph) @@ -75,7 +76,11 @@
> > graph_nodes_populate(struct graph *_graph)
> >                 memset(node, 0, sizeof(*node));
> >                 node->fence = RTE_GRAPH_FENCE;
> >                 node->off = off;
> > -               node->process = graph_node->node->process;
> > +               if (graph_pcap_is_enable()) {
> > +                       node->process = graph_pcap_dispatch;
> > +                       node->original_process = graph_node->node->process;
> > +               } else
> > +                       node->process = graph_node->node->process;
> >                 memcpy(node->name, graph_node->node->name,
> RTE_GRAPH_NAMESIZE);
> >                 pid = graph_node->node->parent_id;
> >                 if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ @@
> > -183,6 +188,8 @@ graph_fp_mem_populate(struct graph *graph)
> >         int rc;
> >
> >         graph_header_popluate(graph);
> > +       if (graph_pcap_is_enable())
> > +               graph_pcap_init(graph);
> >         graph_nodes_populate(graph);
> >         rc = graph_node_nexts_populate(graph);
> >         rc |= graph_src_nodes_populate(graph); @@ -227,6 +234,9 @@
> > graph_nodes_mem_destroy(struct rte_graph *graph)  int
> > graph_fp_mem_destroy(struct graph *graph)  {
> > +       if (graph_pcap_is_enable())
> > +               graph_pcap_exit(graph->graph);
> > +
> >         graph_nodes_mem_destroy(graph->graph);
> >         return rte_memzone_free(graph->mz);  } diff --git
> > a/lib/graph/graph_private.h b/lib/graph/graph_private.h index
> > f9a85c8926..7d1b30b8ac 100644
> > --- a/lib/graph/graph_private.h
> > +++ b/lib/graph/graph_private.h
> > @@ -22,6 +22,7 @@ extern int rte_graph_logtype;
> >                         __func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__,
> > )))
> >
> >  #define graph_err(...) GRAPH_LOG(ERR, __VA_ARGS__)
> > +#define graph_warn(...) GRAPH_LOG(WARNING, __VA_ARGS__)
> >  #define graph_info(...) GRAPH_LOG(INFO, __VA_ARGS__)  #define
> > graph_dbg(...) GRAPH_LOG(DEBUG, __VA_ARGS__)
> >
> > @@ -100,6 +101,10 @@ struct graph {
> >         /**< Memory size of the graph. */
> >         int socket;
> >         /**< Socket identifier where memory is allocated. */
> > +       uint64_t num_pkt_to_capture;
> > +       /**< Number of packets to be captured per core. */
> > +       char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
> > +       /**< pcap file name/path. */
> >         STAILQ_HEAD(gnode_list, graph_node) node_list;
> >         /**< Nodes in a graph. */
> >  };
> > diff --git a/lib/graph/meson.build b/lib/graph/meson.build index
> > c7327549e8..3526d1b5d4 100644
> > --- a/lib/graph/meson.build
> > +++ b/lib/graph/meson.build
> > @@ -14,7 +14,8 @@ sources = files(
> >          'graph_debug.c',
> >          'graph_stats.c',
> >          'graph_populate.c',
> > +        'graph_pcap.c',
> >  )
> >  headers = files('rte_graph.h', 'rte_graph_worker.h')
> >
> > -deps += ['eal']
> > +deps += ['eal', 'pcapng']
> > diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index
> > b32c4bc217..c9a77297fc 100644
> > --- a/lib/graph/rte_graph.h
> > +++ b/lib/graph/rte_graph.h
> > @@ -35,6 +35,7 @@ extern "C" {
> >
> >  #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
> > #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
> > +#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file
> name.
> > +*/
> >  #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph
> offset. */
> >  #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
> >  #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
> > @@ -164,6 +165,10 @@ struct rte_graph_param {
> >         uint16_t nb_node_patterns;  /**< Number of node patterns. */
> >         const char **node_patterns;
> >         /**< Array of node patterns based on shell pattern. */
> > +
> > +       bool pcap_enable; /**< Pcap enable. */
> > +       uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
> > +       char *pcap_filename; /**< Filename in which packets to be
> > + captured.*/
> >  };
> >
> >  /**
> > diff --git a/lib/graph/rte_graph_worker.h
> > b/lib/graph/rte_graph_worker.h index fc6fee48c8..438595b15c 100644
> > --- a/lib/graph/rte_graph_worker.h
> > +++ b/lib/graph/rte_graph_worker.h
> > @@ -44,6 +44,12 @@ struct rte_graph {
> >         rte_graph_t id; /**< Graph identifier. */
> >         int socket;     /**< Socket ID where memory is allocated. */
> >         char name[RTE_GRAPH_NAMESIZE];  /**< Name of the graph. */
> > +       bool pcap_enable;               /**< Pcap trace enabled. */
> > +       /** Number of packets captured per core. */
> > +       uint64_t nb_pkt_captured;
> > +       /** Number of packets to capture per core. */
> > +       uint64_t nb_pkt_to_capture;
> > +       char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];  /**< Pcap
> > + filename. */
> >         uint64_t fence;                 /**< Fence. */
> >  } __rte_cache_aligned;
> >
> > @@ -64,6 +70,9 @@ struct rte_node {
> >         char parent[RTE_NODE_NAMESIZE]; /**< Parent node name. */
> >         char name[RTE_NODE_NAMESIZE];   /**< Name of the node. */
> >
> > +       /** Original process function when pcap is enabled. */
> > +       rte_node_process_t original_process;
> > +
> >         /* Fast path area  */
> >  #define RTE_NODE_CTX_SZ 16
> >         uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node
> > Context. */
> > --
> > 2.25.1
> >

^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture
  2023-01-31  8:14           ` Jerin Jacob
@ 2023-02-03  8:16             ` Amit Prakash Shukla
  0 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-03  8:16 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, dev

Thanks Jerin for the feedback. I will make the changes in next version of the patch.


> -----Original Message-----
> From: Jerin Jacob <jerinjacobk@gmail.com>
> Sent: Tuesday, January 31, 2023 1:45 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; dev@dpdk.org
> Subject: [EXT] Re: [PATCH v4 3/3] l3fwd-graph: changes to configure pcap
> capture
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Tue, Jan 24, 2023 at 4:53 PM Amit Prakash Shukla
> <amitprakashs@marvell.com> wrote:
> >
> > Added support to configure pcap capture.
> >
> > Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> 
> 
> Change the subject as examples/l3fwd-graph:
> 
> > ---
> > v2:
> >  - Fixed code style issue
> >  - Fixed CI compilation issue on github-robot
> >
> > v3:
> >  - Code review suggestion from Stephen
> >  - Fixed potential memory leak
> >
> > v4:
> >  - Code review suggestion from Jerin
> >
> >  doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
> >  examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
> >  2 files changed, 83 insertions(+), 2 deletions(-)
> >
> > diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst
> > b/doc/guides/sample_app_ug/l3_forward_graph.rst
> > index 0a3e0d44ec..3043dba8e2 100644
> > --- a/doc/guides/sample_app_ug/l3_forward_graph.rst
> > +++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
> > @@ -51,6 +51,9 @@ The application has a number of command line options
> similar to l3fwd::
> >                                     [--max-pkt-len PKTLEN]
> >                                     [--no-numa]
> >                                     [--per-port-pool]
> > +                                   [--pcap-enable]
> > +                                   [--pcap-num-cap]
> > +                                   [--pcap-file-name]
> >
> >  Where,
> >
> > @@ -69,6 +72,12 @@ Where,
> >
> >  * ``--per-port-pool:`` Optional, set to use independent buffer pools per
> port. Without this option, single buffer pool is used for all ports.
> >
> > +* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on
> each node with mbuf and node metadata.
> > +
> > +* ``--pcap-num-cap:`` Optional, Number of packets to be captured per
> core.
> > +
> > +* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
> > +
> >  For example, consider a dual processor socket platform with 8
> > physical cores, where cores 0-7 and 16-23 appear on socket 0,  while cores
> 8-15 and 24-31 appear on socket 1.
> >
> > @@ -99,6 +108,20 @@ In this command:
> >  |          |           |           |                                     |
> >
> > +----------+-----------+-----------+----------------------------------
> > ---+
> >
> > +To enable pcap trace on each graph, use following command:
> > +
> > +.. code-block:: console
> > +
> > +    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --
> config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets>
> --pcap-file-name "</filepath/filename>"
> 
> </filepath/filename> can be changes as  "/path/to/file"

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v5 1/3] pcapng: comment option support for epb
  2023-01-24 11:21       ` [PATCH v4 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-01-24 11:21         ` [PATCH v4 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-01-24 11:21         ` [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-02-03  8:19         ` Amit Prakash Shukla
  2023-02-03  8:19           ` [PATCH v5 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
                             ` (3 more replies)
  2 siblings, 4 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-03  8:19 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger; +Cc: dev, jerinj, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

 app/test/test_pcapng.c                 |  4 ++--
 doc/guides/rel_notes/release_23_03.rst |  2 ++
 lib/pcapng/rte_pcapng.c                | 10 +++++++++-
 lib/pcapng/rte_pcapng.h                |  4 +++-
 lib/pdump/rte_pdump.c                  |  2 +-
 5 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index a7acbdc058..303d3d66f9 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -139,7 +139,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -255,7 +255,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index 73f5d94e14..dab62508c4 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -107,6 +107,8 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* Experimental function ``rte_pcapng_copy`` was updated to support comment
+  section in enhanced packet block in pcapng library.
 
 ABI Changes
 -----------
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index 80d08e1a3b..acb31a9d93 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -450,7 +450,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -511,6 +512,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -548,6 +552,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 7d2697c647..6d286cda41 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -100,6 +100,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -111,7 +113,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v5 2/3] graph: pcap capture for graph nodes
  2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
@ 2023-02-03  8:19           ` Amit Prakash Shukla
  2023-02-09  9:12             ` David Marchand
  2023-02-03  8:19           ` [PATCH v5 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-03  8:19 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Anatoly Burakov
  Cc: dev, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

 doc/guides/rel_notes/release_23_03.rst |   7 +
 lib/graph/graph.c                      |  17 +-
 lib/graph/graph_pcap.c                 | 216 +++++++++++++++++++++++++
 lib/graph/graph_pcap_private.h         | 116 +++++++++++++
 lib/graph/graph_populate.c             |  12 +-
 lib/graph/graph_private.h              |   5 +
 lib/graph/meson.build                  |   3 +-
 lib/graph/rte_graph.h                  |   5 +
 lib/graph/rte_graph_worker.h           |   9 ++
 9 files changed, 387 insertions(+), 3 deletions(-)
 create mode 100644 lib/graph/graph_pcap.c
 create mode 100644 lib/graph/graph_pcap_private.h

diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index dab62508c4..e709df8b53 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -78,6 +78,10 @@ New Features
     ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
     required for eth_rx, eth_tx, crypto and timer eventdev adapters.
 
+* **Added pcap trace support in graph library.**
+
+  * Added support to capture packets at each graph node with packet metadata and
+    node name.
 
 Removed Items
 -------------
@@ -110,6 +114,9 @@ API Changes
 * Experimental function ``rte_pcapng_copy`` was updated to support comment
   section in enhanced packet block in pcapng library.
 
+* Experimental structures ``struct rte_graph_param``, ``struct rte_graph`` and
+  ``struct graph`` were updated to support pcap trace in graph library.
+
 ABI Changes
 -----------
 
diff --git a/lib/graph/graph.c b/lib/graph/graph.c
index 3a617cc369..a839a2803b 100644
--- a/lib/graph/graph.c
+++ b/lib/graph/graph.c
@@ -15,6 +15,7 @@
 #include <rte_string_fns.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static struct graph_head graph_list = STAILQ_HEAD_INITIALIZER(graph_list);
 static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER;
@@ -228,7 +229,12 @@ graph_mem_fixup_node_ctx(struct rte_graph *graph)
 		node_db = node_from_name(name);
 		if (node_db == NULL)
 			SET_ERR_JMP(ENOLINK, fail, "Node %s not found", name);
-		node->process = node_db->process;
+
+		if (graph->pcap_enable) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = node_db->process;
+		} else
+			node->process = node_db->process;
 	}
 
 	return graph;
@@ -242,6 +248,9 @@ graph_mem_fixup_secondary(struct rte_graph *graph)
 	if (graph == NULL || rte_eal_process_type() == RTE_PROC_PRIMARY)
 		return graph;
 
+	if (graph_pcap_file_open(graph->pcap_filename) || graph_pcap_mp_init())
+		graph_pcap_exit(graph);
+
 	return graph_mem_fixup_node_ctx(graph);
 }
 
@@ -323,11 +332,17 @@ rte_graph_create(const char *name, struct rte_graph_param *prm)
 	if (graph_has_isolated_node(graph))
 		goto graph_cleanup;
 
+	/* Initialize pcap config. */
+	graph_pcap_enable(prm->pcap_enable);
+
 	/* Initialize graph object */
 	graph->socket = prm->socket_id;
 	graph->src_node_count = src_node_count;
 	graph->node_count = graph_nodes_count(graph);
 	graph->id = graph_id;
+	graph->num_pkt_to_capture = prm->num_pkt_to_capture;
+	if (prm->pcap_filename)
+		rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
 
 	/* Allocate the Graph fast path memory and populate the data */
 	if (graph_fp_mem_create(graph))
diff --git a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c
new file mode 100644
index 0000000000..9cbd1b8fdb
--- /dev/null
+++ b/lib/graph/graph_pcap.c
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_mbuf.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+
+#include "graph_pcap_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_PKT_POOL	"graph_pcap_pkt_pool"
+#define GRAPH_PCAP_FILE_NAME	"dpdk_graph_pcap_capture_XXXXXX.pcapng"
+
+/* For multi-process, packets are captured in separate files. */
+static rte_pcapng_t *pcapng_fd;
+static bool pcap_enable;
+struct rte_mempool *pkt_mp;
+
+void
+graph_pcap_enable(bool val)
+{
+	pcap_enable = val;
+}
+
+int
+graph_pcap_is_enable(void)
+{
+	return pcap_enable;
+}
+
+void
+graph_pcap_exit(struct rte_graph *graph)
+{
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		if (pkt_mp)
+			rte_mempool_free(pkt_mp);
+
+	if (pcapng_fd) {
+		rte_pcapng_close(pcapng_fd);
+		pcapng_fd = NULL;
+	}
+
+	/* Disable pcap. */
+	graph->pcap_enable = 0;
+	graph_pcap_enable(0);
+}
+
+static int
+graph_pcap_default_path_get(char **dir_path)
+{
+	struct passwd *pwd;
+	char *home_dir;
+
+	/* First check for shell environment variable */
+	home_dir = getenv("HOME");
+	if (home_dir == NULL) {
+		graph_warn("Home env not preset.");
+		/* Fallback to password file entry */
+		pwd = getpwuid(getuid());
+		if (pwd == NULL)
+			return -EINVAL;
+
+		home_dir = pwd->pw_dir;
+	}
+
+	/* Append default pcap file to directory */
+	if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME) == -1)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int
+graph_pcap_file_open(const char *filename)
+{
+	int fd;
+	char file_name[RTE_GRAPH_PCAP_FILE_SZ];
+	char *pcap_dir;
+
+	if (pcapng_fd)
+		goto done;
+
+	if (!filename || filename[0] == '\0') {
+		if (graph_pcap_default_path_get(&pcap_dir) < 0)
+			return -1;
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
+		free(pcap_dir);
+	} else {
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s_XXXXXX.pcapng",
+			 filename);
+	}
+
+	fd = mkstemps(file_name, strlen(".pcapng"));
+	if (fd < 0) {
+		graph_err("mkstemps() failure");
+		return -1;
+	}
+
+	graph_info("pcap filename: %s", file_name);
+
+	/* Open a capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
+				      NULL);
+	if (pcapng_fd == NULL) {
+		graph_err("Graph rte_pcapng_fdopen failed.");
+		close(fd);
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_mp_init(void)
+{
+	pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
+	if (pkt_mp)
+		goto done;
+
+	/* Make a pool for cloned packets */
+	pkt_mp = rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,	0, 0,
+			rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
+			SOCKET_ID_ANY, "ring_mp_mc");
+	if (pkt_mp == NULL) {
+		graph_err("Cannot create mempool for graph pcap capture.");
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_init(struct graph *graph)
+{
+	struct rte_graph *graph_data = graph->graph;
+
+	if (graph_pcap_file_open(graph->pcap_filename) < 0)
+		goto error;
+
+	if (graph_pcap_mp_init() < 0)
+		goto error;
+
+	/* User configured number of packets to capture. */
+	if (graph->num_pkt_to_capture)
+		graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
+	else
+		graph_data->nb_pkt_to_capture = GRAPH_PCAP_NUM_PACKETS;
+
+	/* All good. Now populate data for secondary process. */
+	rte_strscpy(graph_data->pcap_filename, graph->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
+	graph_data->pcap_enable = 1;
+
+	return 0;
+
+error:
+	graph_pcap_exit(graph_data);
+	graph_pcap_enable(0);
+	graph_err("Graph pcap initialization failed. Disabling pcap trace.");
+	return -1;
+}
+
+uint16_t
+graph_pcap_dispatch(struct rte_graph *graph,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
+	char buffer[GRAPH_PCAP_BUF_SZ];
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf;
+	ssize_t len;
+
+	if (!nb_objs || (graph->nb_pkt_captured >= graph->nb_pkt_to_capture))
+		goto done;
+
+	num_packets = graph->nb_pkt_to_capture - graph->nb_pkt_captured;
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	snprintf(buffer, GRAPH_PCAP_BUF_SZ, "%s: %s", graph->name, node->name);
+
+	for (i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			break;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	graph->nb_pkt_captured += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_pcap_private.h b/lib/graph/graph_pcap_private.h
new file mode 100644
index 0000000000..2ec772072c
--- /dev/null
+++ b/lib/graph/graph_pcap_private.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_PRIVATE_H_
+#define _RTE_GRAPH_PCAP_PRIVATE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "graph_private.h"
+
+/**
+ * @internal
+ *
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+void graph_pcap_enable(bool val);
+
+/**
+ * @internal
+ *
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+int graph_pcap_is_enable(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to allocate mempool.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_mp_init(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to open pcap file.
+ *
+ * @param filename
+ *   Pcap filename.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_file_open(const char *filename);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled. This function
+ * open's pcap file and allocates mempool. Information needed for secondary
+ * process is populated.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_init(struct graph *graph);
+
+/**
+ * @internal
+ *
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's and
+ * free up memory. Pcap trace is also disabled.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ */
+void graph_pcap_exit(struct rte_graph *graph);
+
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t graph_pcap_dispatch(struct rte_graph *graph,
+				   struct rte_node *node, void **objs,
+				   uint16_t nb_objs);
+
+#endif /* _RTE_GRAPH_PCAP_PRIVATE_H_ */
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..2c0844ce92 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -9,6 +9,7 @@
 #include <rte_memzone.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static size_t
 graph_fp_mem_calc_size(struct graph *graph)
@@ -75,7 +76,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (graph_pcap_is_enable()) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
@@ -183,6 +188,8 @@ graph_fp_mem_populate(struct graph *graph)
 	int rc;
 
 	graph_header_popluate(graph);
+	if (graph_pcap_is_enable())
+		graph_pcap_init(graph);
 	graph_nodes_populate(graph);
 	rc = graph_node_nexts_populate(graph);
 	rc |= graph_src_nodes_populate(graph);
@@ -227,6 +234,9 @@ graph_nodes_mem_destroy(struct rte_graph *graph)
 int
 graph_fp_mem_destroy(struct graph *graph)
 {
+	if (graph_pcap_is_enable())
+		graph_pcap_exit(graph->graph);
+
 	graph_nodes_mem_destroy(graph->graph);
 	return rte_memzone_free(graph->mz);
 }
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..7d1b30b8ac 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -22,6 +22,7 @@ extern int rte_graph_logtype;
 			__func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__, )))
 
 #define graph_err(...) GRAPH_LOG(ERR, __VA_ARGS__)
+#define graph_warn(...) GRAPH_LOG(WARNING, __VA_ARGS__)
 #define graph_info(...) GRAPH_LOG(INFO, __VA_ARGS__)
 #define graph_dbg(...) GRAPH_LOG(DEBUG, __VA_ARGS__)
 
@@ -100,6 +101,10 @@ struct graph {
 	/**< Memory size of the graph. */
 	int socket;
 	/**< Socket identifier where memory is allocated. */
+	uint64_t num_pkt_to_capture;
+	/**< Number of packets to be captured per core. */
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+	/**< pcap file name/path. */
 	STAILQ_HEAD(gnode_list, graph_node) node_list;
 	/**< Nodes in a graph. */
 };
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..3526d1b5d4 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap.c',
 )
 headers = files('rte_graph.h', 'rte_graph_worker.h')
 
-deps += ['eal']
+deps += ['eal', 'pcapng']
diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h
index b32c4bc217..c9a77297fc 100644
--- a/lib/graph/rte_graph.h
+++ b/lib/graph/rte_graph.h
@@ -35,6 +35,7 @@ extern "C" {
 
 #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
 #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
+#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */
 #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
 #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
 #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
@@ -164,6 +165,10 @@ struct rte_graph_param {
 	uint16_t nb_node_patterns;  /**< Number of node patterns. */
 	const char **node_patterns;
 	/**< Array of node patterns based on shell pattern. */
+
+	bool pcap_enable; /**< Pcap enable. */
+	uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
+	char *pcap_filename; /**< Filename in which packets to be captured.*/
 };
 
 /**
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..438595b15c 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -44,6 +44,12 @@ struct rte_graph {
 	rte_graph_t id;	/**< Graph identifier. */
 	int socket;	/**< Socket ID where memory is allocated. */
 	char name[RTE_GRAPH_NAMESIZE];	/**< Name of the graph. */
+	bool pcap_enable;	        /**< Pcap trace enabled. */
+	/** Number of packets captured per core. */
+	uint64_t nb_pkt_captured;
+	/** Number of packets to capture per core. */
+	uint64_t nb_pkt_to_capture;
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];  /**< Pcap filename. */
 	uint64_t fence;			/**< Fence. */
 } __rte_cache_aligned;
 
@@ -64,6 +70,9 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	/** Original process function when pcap is enabled. */
+	rte_node_process_t original_process;
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v5 3/3] examples/l3fwd-graph: changes to configure pcap capture
  2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-02-03  8:19           ` [PATCH v5 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-02-03  8:19           ` Amit Prakash Shukla
  2023-02-09  9:13           ` [PATCH v5 1/3] pcapng: comment option support for epb David Marchand
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
  3 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-03  8:19 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram; +Cc: dev, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

 doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
 examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..585ac8c898 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--pcap-num-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--pcap-num-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
@@ -99,6 +108,20 @@ In this command:
 |          |           |           |                                     |
 +----------+-----------+-----------+-------------------------------------+
 
+To enable pcap trace on each graph, use following command:
+
+.. code-block:: console
+
+    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets> --pcap-file-name "</path/to/file>"
+
+In this command:
+
+*   The --pcap-enable option enables pcap trace on graph nodes.
+
+*   The --pcap-num-cap option enables user to configure number packets to be captured per graph. Default 1024 packets per graph are captured.
+
+*   The --pcap-file-name option enables user to give filename in which packets are to be captured.
+
 Refer to the *DPDK Getting Started Guide* for general information on running applications and
 the Environment Abstraction Layer (EAL) options.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..5feeab4f0f 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -76,6 +76,12 @@ xmm_t val_eth[RTE_MAX_ETHPORTS];
 /* Mask of enabled ports */
 static uint32_t enabled_port_mask;
 
+/* Pcap trace */
+static char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+static uint64_t packet_to_capture;
+static int pcap_trace_enable;
+
+
 struct lcore_rx_queue {
 	uint16_t port_id;
 	uint8_t queue_id;
@@ -261,7 +267,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +277,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --pcap-num-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +431,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "pcap-num-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +446,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +457,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -498,6 +534,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			pcap_trace_enable = 1;
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			packet_to_capture = parse_num_pkt_cap(optarg);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       packet_to_capture);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_strlcpy(pcap_filename, optarg,
+				    sizeof(pcap_filename));
+			printf("Pcap file name: %s\n", pcap_filename);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -1027,6 +1080,11 @@ main(int argc, char **argv)
 	memset(&graph_conf, 0, sizeof(graph_conf));
 	graph_conf.node_patterns = node_patterns;
 
+	/* Pcap config */
+	graph_conf.pcap_enable = pcap_trace_enable;
+	graph_conf.num_pkt_to_capture = packet_to_capture;
+	graph_conf.pcap_filename = pcap_filename;
+
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 		rte_graph_t graph_id;
 		rte_edge_t i;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v5 2/3] graph: pcap capture for graph nodes
  2023-02-03  8:19           ` [PATCH v5 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-02-09  9:12             ` David Marchand
  2023-02-09  9:29               ` [EXT] " Amit Prakash Shukla
  0 siblings, 1 reply; 47+ messages in thread
From: David Marchand @ 2023-02-09  9:12 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Anatoly Burakov, dev

On Fri, Feb 3, 2023 at 9:19 AM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
> diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h
> index b32c4bc217..c9a77297fc 100644
> --- a/lib/graph/rte_graph.h
> +++ b/lib/graph/rte_graph.h
> @@ -35,6 +35,7 @@ extern "C" {
>
>  #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
>  #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
> +#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */
>  #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
>  #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
>  #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
> @@ -164,6 +165,10 @@ struct rte_graph_param {
>         uint16_t nb_node_patterns;  /**< Number of node patterns. */
>         const char **node_patterns;
>         /**< Array of node patterns based on shell pattern. */
> +
> +       bool pcap_enable; /**< Pcap enable. */
> +       uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
> +       char *pcap_filename; /**< Filename in which packets to be captured.*/
>  };

Repeating in this thread what I commented on a patch fixing
compilation for the unit test.

Extending this structure requires updating the graph unit test.
Please squash this fix in this series.


Thanks.

-- 
David Marchand


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v5 1/3] pcapng: comment option support for epb
  2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
  2023-02-03  8:19           ` [PATCH v5 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-02-03  8:19           ` [PATCH v5 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-02-09  9:13           ` David Marchand
  2023-02-09 16:48             ` Stephen Hemminger
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
  3 siblings, 1 reply; 47+ messages in thread
From: David Marchand @ 2023-02-09  9:13 UTC (permalink / raw)
  To: Amit Prakash Shukla, Reshma Pattan, Stephen Hemminger; +Cc: dev, jerinj

Stephen, Reshma,

On Fri, Feb 3, 2023 at 9:19 AM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
>
> This change enhances rte_pcapng_copy to have comment in enhanced
> packet block.
>
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>

Is this change ok for you?
Thanks.

-- 
David Marchand


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [EXT] Re: [PATCH v5 2/3] graph: pcap capture for graph nodes
  2023-02-09  9:12             ` David Marchand
@ 2023-02-09  9:29               ` Amit Prakash Shukla
  0 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09  9:29 UTC (permalink / raw)
  To: David Marchand
  Cc: Jerin Jacob Kollanukkaran, Kiran Kumar Kokkilagadda,
	Nithin Kumar Dabilpuram, Anatoly Burakov, dev

Hi David,

Sorry for the delayed reply. I will send the next version of the patch, in sometime,  after squashing the fix.

Thanks,
Amit Shukla

> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Thursday, February 9, 2023 2:43 PM
> To: Amit Prakash Shukla <amitprakashs@marvell.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; Anatoly Burakov
> <anatoly.burakov@intel.com>; dev@dpdk.org
> Subject: [EXT] Re: [PATCH v5 2/3] graph: pcap capture for graph nodes
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Fri, Feb 3, 2023 at 9:19 AM Amit Prakash Shukla
> <amitprakashs@marvell.com> wrote:
> > diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index
> > b32c4bc217..c9a77297fc 100644
> > --- a/lib/graph/rte_graph.h
> > +++ b/lib/graph/rte_graph.h
> > @@ -35,6 +35,7 @@ extern "C" {
> >
> >  #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
> > #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
> > +#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file
> name.
> > +*/
> >  #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph
> offset. */
> >  #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
> >  #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
> > @@ -164,6 +165,10 @@ struct rte_graph_param {
> >         uint16_t nb_node_patterns;  /**< Number of node patterns. */
> >         const char **node_patterns;
> >         /**< Array of node patterns based on shell pattern. */
> > +
> > +       bool pcap_enable; /**< Pcap enable. */
> > +       uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
> > +       char *pcap_filename; /**< Filename in which packets to be
> > + captured.*/
> >  };
> 
> Repeating in this thread what I commented on a patch fixing compilation for
> the unit test.
> 
> Extending this structure requires updating the graph unit test.
> Please squash this fix in this series.
> 
> 
> Thanks.
> 
> --
> David Marchand


^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v6 1/4] pcapng: comment option support for epb
  2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
                             ` (2 preceding siblings ...)
  2023-02-09  9:13           ` [PATCH v5 1/3] pcapng: comment option support for epb David Marchand
@ 2023-02-09  9:56           ` Amit Prakash Shukla
  2023-02-09  9:56             ` [PATCH v6 2/4] graph: pcap capture for graph nodes Amit Prakash Shukla
                               ` (4 more replies)
  3 siblings, 5 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09  9:56 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger
  Cc: dev, jerinj, david.marchand, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix

 app/test/test_pcapng.c                 |  4 ++--
 doc/guides/rel_notes/release_23_03.rst |  2 ++
 lib/pcapng/rte_pcapng.c                | 10 +++++++++-
 lib/pcapng/rte_pcapng.h                |  4 +++-
 lib/pdump/rte_pdump.c                  |  2 +-
 5 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index edba46d1fe..b8429a02f1 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -146,7 +146,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -262,7 +262,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index 1fa101c420..bb435dde32 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -116,6 +116,8 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* Experimental function ``rte_pcapng_copy`` was updated to support comment
+  section in enhanced packet block in pcapng library.
 
 ABI Changes
 -----------
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index ea004939e6..65c8c77fa4 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -466,7 +466,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -527,6 +528,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -564,6 +568,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 86b7996e29..4afdec22ef 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -125,6 +125,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -136,7 +138,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v6 2/4] graph: pcap capture for graph nodes
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
@ 2023-02-09  9:56             ` Amit Prakash Shukla
  2023-02-09  9:56             ` [PATCH v6 3/4] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
                               ` (3 subsequent siblings)
  4 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09  9:56 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Anatoly Burakov
  Cc: dev, david.marchand, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix

 doc/guides/rel_notes/release_23_03.rst |   7 +
 lib/graph/graph.c                      |  17 +-
 lib/graph/graph_pcap.c                 | 216 +++++++++++++++++++++++++
 lib/graph/graph_pcap_private.h         | 116 +++++++++++++
 lib/graph/graph_populate.c             |  12 +-
 lib/graph/graph_private.h              |   5 +
 lib/graph/meson.build                  |   3 +-
 lib/graph/rte_graph.h                  |   5 +
 lib/graph/rte_graph_worker.h           |   9 ++
 9 files changed, 387 insertions(+), 3 deletions(-)
 create mode 100644 lib/graph/graph_pcap.c
 create mode 100644 lib/graph/graph_pcap_private.h

diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index bb435dde32..328dfd3009 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -87,6 +87,10 @@ New Features
     ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
     required for eth_rx, eth_tx, crypto and timer eventdev adapters.
 
+* **Added pcap trace support in graph library.**
+
+  * Added support to capture packets at each graph node with packet metadata and
+    node name.
 
 Removed Items
 -------------
@@ -119,6 +123,9 @@ API Changes
 * Experimental function ``rte_pcapng_copy`` was updated to support comment
   section in enhanced packet block in pcapng library.
 
+* Experimental structures ``struct rte_graph_param``, ``struct rte_graph`` and
+  ``struct graph`` were updated to support pcap trace in graph library.
+
 ABI Changes
 -----------
 
diff --git a/lib/graph/graph.c b/lib/graph/graph.c
index 3a617cc369..a839a2803b 100644
--- a/lib/graph/graph.c
+++ b/lib/graph/graph.c
@@ -15,6 +15,7 @@
 #include <rte_string_fns.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static struct graph_head graph_list = STAILQ_HEAD_INITIALIZER(graph_list);
 static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER;
@@ -228,7 +229,12 @@ graph_mem_fixup_node_ctx(struct rte_graph *graph)
 		node_db = node_from_name(name);
 		if (node_db == NULL)
 			SET_ERR_JMP(ENOLINK, fail, "Node %s not found", name);
-		node->process = node_db->process;
+
+		if (graph->pcap_enable) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = node_db->process;
+		} else
+			node->process = node_db->process;
 	}
 
 	return graph;
@@ -242,6 +248,9 @@ graph_mem_fixup_secondary(struct rte_graph *graph)
 	if (graph == NULL || rte_eal_process_type() == RTE_PROC_PRIMARY)
 		return graph;
 
+	if (graph_pcap_file_open(graph->pcap_filename) || graph_pcap_mp_init())
+		graph_pcap_exit(graph);
+
 	return graph_mem_fixup_node_ctx(graph);
 }
 
@@ -323,11 +332,17 @@ rte_graph_create(const char *name, struct rte_graph_param *prm)
 	if (graph_has_isolated_node(graph))
 		goto graph_cleanup;
 
+	/* Initialize pcap config. */
+	graph_pcap_enable(prm->pcap_enable);
+
 	/* Initialize graph object */
 	graph->socket = prm->socket_id;
 	graph->src_node_count = src_node_count;
 	graph->node_count = graph_nodes_count(graph);
 	graph->id = graph_id;
+	graph->num_pkt_to_capture = prm->num_pkt_to_capture;
+	if (prm->pcap_filename)
+		rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
 
 	/* Allocate the Graph fast path memory and populate the data */
 	if (graph_fp_mem_create(graph))
diff --git a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c
new file mode 100644
index 0000000000..9cbd1b8fdb
--- /dev/null
+++ b/lib/graph/graph_pcap.c
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_mbuf.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+
+#include "graph_pcap_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_PKT_POOL	"graph_pcap_pkt_pool"
+#define GRAPH_PCAP_FILE_NAME	"dpdk_graph_pcap_capture_XXXXXX.pcapng"
+
+/* For multi-process, packets are captured in separate files. */
+static rte_pcapng_t *pcapng_fd;
+static bool pcap_enable;
+struct rte_mempool *pkt_mp;
+
+void
+graph_pcap_enable(bool val)
+{
+	pcap_enable = val;
+}
+
+int
+graph_pcap_is_enable(void)
+{
+	return pcap_enable;
+}
+
+void
+graph_pcap_exit(struct rte_graph *graph)
+{
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		if (pkt_mp)
+			rte_mempool_free(pkt_mp);
+
+	if (pcapng_fd) {
+		rte_pcapng_close(pcapng_fd);
+		pcapng_fd = NULL;
+	}
+
+	/* Disable pcap. */
+	graph->pcap_enable = 0;
+	graph_pcap_enable(0);
+}
+
+static int
+graph_pcap_default_path_get(char **dir_path)
+{
+	struct passwd *pwd;
+	char *home_dir;
+
+	/* First check for shell environment variable */
+	home_dir = getenv("HOME");
+	if (home_dir == NULL) {
+		graph_warn("Home env not preset.");
+		/* Fallback to password file entry */
+		pwd = getpwuid(getuid());
+		if (pwd == NULL)
+			return -EINVAL;
+
+		home_dir = pwd->pw_dir;
+	}
+
+	/* Append default pcap file to directory */
+	if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME) == -1)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int
+graph_pcap_file_open(const char *filename)
+{
+	int fd;
+	char file_name[RTE_GRAPH_PCAP_FILE_SZ];
+	char *pcap_dir;
+
+	if (pcapng_fd)
+		goto done;
+
+	if (!filename || filename[0] == '\0') {
+		if (graph_pcap_default_path_get(&pcap_dir) < 0)
+			return -1;
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
+		free(pcap_dir);
+	} else {
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s_XXXXXX.pcapng",
+			 filename);
+	}
+
+	fd = mkstemps(file_name, strlen(".pcapng"));
+	if (fd < 0) {
+		graph_err("mkstemps() failure");
+		return -1;
+	}
+
+	graph_info("pcap filename: %s", file_name);
+
+	/* Open a capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
+				      NULL);
+	if (pcapng_fd == NULL) {
+		graph_err("Graph rte_pcapng_fdopen failed.");
+		close(fd);
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_mp_init(void)
+{
+	pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
+	if (pkt_mp)
+		goto done;
+
+	/* Make a pool for cloned packets */
+	pkt_mp = rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,	0, 0,
+			rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
+			SOCKET_ID_ANY, "ring_mp_mc");
+	if (pkt_mp == NULL) {
+		graph_err("Cannot create mempool for graph pcap capture.");
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_init(struct graph *graph)
+{
+	struct rte_graph *graph_data = graph->graph;
+
+	if (graph_pcap_file_open(graph->pcap_filename) < 0)
+		goto error;
+
+	if (graph_pcap_mp_init() < 0)
+		goto error;
+
+	/* User configured number of packets to capture. */
+	if (graph->num_pkt_to_capture)
+		graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
+	else
+		graph_data->nb_pkt_to_capture = GRAPH_PCAP_NUM_PACKETS;
+
+	/* All good. Now populate data for secondary process. */
+	rte_strscpy(graph_data->pcap_filename, graph->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
+	graph_data->pcap_enable = 1;
+
+	return 0;
+
+error:
+	graph_pcap_exit(graph_data);
+	graph_pcap_enable(0);
+	graph_err("Graph pcap initialization failed. Disabling pcap trace.");
+	return -1;
+}
+
+uint16_t
+graph_pcap_dispatch(struct rte_graph *graph,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
+	char buffer[GRAPH_PCAP_BUF_SZ];
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf;
+	ssize_t len;
+
+	if (!nb_objs || (graph->nb_pkt_captured >= graph->nb_pkt_to_capture))
+		goto done;
+
+	num_packets = graph->nb_pkt_to_capture - graph->nb_pkt_captured;
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	snprintf(buffer, GRAPH_PCAP_BUF_SZ, "%s: %s", graph->name, node->name);
+
+	for (i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			break;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	graph->nb_pkt_captured += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_pcap_private.h b/lib/graph/graph_pcap_private.h
new file mode 100644
index 0000000000..2ec772072c
--- /dev/null
+++ b/lib/graph/graph_pcap_private.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_PRIVATE_H_
+#define _RTE_GRAPH_PCAP_PRIVATE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "graph_private.h"
+
+/**
+ * @internal
+ *
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+void graph_pcap_enable(bool val);
+
+/**
+ * @internal
+ *
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+int graph_pcap_is_enable(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to allocate mempool.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_mp_init(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to open pcap file.
+ *
+ * @param filename
+ *   Pcap filename.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_file_open(const char *filename);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled. This function
+ * open's pcap file and allocates mempool. Information needed for secondary
+ * process is populated.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_init(struct graph *graph);
+
+/**
+ * @internal
+ *
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's and
+ * free up memory. Pcap trace is also disabled.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ */
+void graph_pcap_exit(struct rte_graph *graph);
+
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t graph_pcap_dispatch(struct rte_graph *graph,
+				   struct rte_node *node, void **objs,
+				   uint16_t nb_objs);
+
+#endif /* _RTE_GRAPH_PCAP_PRIVATE_H_ */
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..2c0844ce92 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -9,6 +9,7 @@
 #include <rte_memzone.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static size_t
 graph_fp_mem_calc_size(struct graph *graph)
@@ -75,7 +76,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (graph_pcap_is_enable()) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
@@ -183,6 +188,8 @@ graph_fp_mem_populate(struct graph *graph)
 	int rc;
 
 	graph_header_popluate(graph);
+	if (graph_pcap_is_enable())
+		graph_pcap_init(graph);
 	graph_nodes_populate(graph);
 	rc = graph_node_nexts_populate(graph);
 	rc |= graph_src_nodes_populate(graph);
@@ -227,6 +234,9 @@ graph_nodes_mem_destroy(struct rte_graph *graph)
 int
 graph_fp_mem_destroy(struct graph *graph)
 {
+	if (graph_pcap_is_enable())
+		graph_pcap_exit(graph->graph);
+
 	graph_nodes_mem_destroy(graph->graph);
 	return rte_memzone_free(graph->mz);
 }
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..7d1b30b8ac 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -22,6 +22,7 @@ extern int rte_graph_logtype;
 			__func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__, )))
 
 #define graph_err(...) GRAPH_LOG(ERR, __VA_ARGS__)
+#define graph_warn(...) GRAPH_LOG(WARNING, __VA_ARGS__)
 #define graph_info(...) GRAPH_LOG(INFO, __VA_ARGS__)
 #define graph_dbg(...) GRAPH_LOG(DEBUG, __VA_ARGS__)
 
@@ -100,6 +101,10 @@ struct graph {
 	/**< Memory size of the graph. */
 	int socket;
 	/**< Socket identifier where memory is allocated. */
+	uint64_t num_pkt_to_capture;
+	/**< Number of packets to be captured per core. */
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+	/**< pcap file name/path. */
 	STAILQ_HEAD(gnode_list, graph_node) node_list;
 	/**< Nodes in a graph. */
 };
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..3526d1b5d4 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap.c',
 )
 headers = files('rte_graph.h', 'rte_graph_worker.h')
 
-deps += ['eal']
+deps += ['eal', 'pcapng']
diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h
index b32c4bc217..c9a77297fc 100644
--- a/lib/graph/rte_graph.h
+++ b/lib/graph/rte_graph.h
@@ -35,6 +35,7 @@ extern "C" {
 
 #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
 #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
+#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */
 #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
 #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
 #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
@@ -164,6 +165,10 @@ struct rte_graph_param {
 	uint16_t nb_node_patterns;  /**< Number of node patterns. */
 	const char **node_patterns;
 	/**< Array of node patterns based on shell pattern. */
+
+	bool pcap_enable; /**< Pcap enable. */
+	uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
+	char *pcap_filename; /**< Filename in which packets to be captured.*/
 };
 
 /**
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..438595b15c 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -44,6 +44,12 @@ struct rte_graph {
 	rte_graph_t id;	/**< Graph identifier. */
 	int socket;	/**< Socket ID where memory is allocated. */
 	char name[RTE_GRAPH_NAMESIZE];	/**< Name of the graph. */
+	bool pcap_enable;	        /**< Pcap trace enabled. */
+	/** Number of packets captured per core. */
+	uint64_t nb_pkt_captured;
+	/** Number of packets to capture per core. */
+	uint64_t nb_pkt_to_capture;
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];  /**< Pcap filename. */
 	uint64_t fence;			/**< Fence. */
 } __rte_cache_aligned;
 
@@ -64,6 +70,9 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	/** Original process function when pcap is enabled. */
+	rte_node_process_t original_process;
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v6 3/4] examples/l3fwd-graph: changes to configure pcap capture
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
  2023-02-09  9:56             ` [PATCH v6 2/4] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-02-09  9:56             ` Amit Prakash Shukla
  2023-02-09  9:56             ` [PATCH v6 4/4] test/graph: initialize graph param variable Amit Prakash Shukla
                               ` (2 subsequent siblings)
  4 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09  9:56 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram
  Cc: dev, david.marchand, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix

 doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
 examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..585ac8c898 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--pcap-num-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--pcap-num-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
@@ -99,6 +108,20 @@ In this command:
 |          |           |           |                                     |
 +----------+-----------+-----------+-------------------------------------+
 
+To enable pcap trace on each graph, use following command:
+
+.. code-block:: console
+
+    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets> --pcap-file-name "</path/to/file>"
+
+In this command:
+
+*   The --pcap-enable option enables pcap trace on graph nodes.
+
+*   The --pcap-num-cap option enables user to configure number packets to be captured per graph. Default 1024 packets per graph are captured.
+
+*   The --pcap-file-name option enables user to give filename in which packets are to be captured.
+
 Refer to the *DPDK Getting Started Guide* for general information on running applications and
 the Environment Abstraction Layer (EAL) options.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..5feeab4f0f 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -76,6 +76,12 @@ xmm_t val_eth[RTE_MAX_ETHPORTS];
 /* Mask of enabled ports */
 static uint32_t enabled_port_mask;
 
+/* Pcap trace */
+static char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+static uint64_t packet_to_capture;
+static int pcap_trace_enable;
+
+
 struct lcore_rx_queue {
 	uint16_t port_id;
 	uint8_t queue_id;
@@ -261,7 +267,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +277,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --pcap-num-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +431,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "pcap-num-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +446,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +457,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -498,6 +534,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			pcap_trace_enable = 1;
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			packet_to_capture = parse_num_pkt_cap(optarg);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       packet_to_capture);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_strlcpy(pcap_filename, optarg,
+				    sizeof(pcap_filename));
+			printf("Pcap file name: %s\n", pcap_filename);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -1027,6 +1080,11 @@ main(int argc, char **argv)
 	memset(&graph_conf, 0, sizeof(graph_conf));
 	graph_conf.node_patterns = node_patterns;
 
+	/* Pcap config */
+	graph_conf.pcap_enable = pcap_trace_enable;
+	graph_conf.num_pkt_to_capture = packet_to_capture;
+	graph_conf.pcap_filename = pcap_filename;
+
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 		rte_graph_t graph_id;
 		rte_edge_t i;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v6 4/4] test/graph: initialize graph param variable
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
  2023-02-09  9:56             ` [PATCH v6 2/4] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-02-09  9:56             ` [PATCH v6 3/4] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-02-09  9:56             ` Amit Prakash Shukla
  2023-02-09 10:03             ` [PATCH v6 1/4] pcapng: comment option support for epb Amit Prakash Shukla
  2023-02-09 10:24             ` [PATCH v7 1/3] " Amit Prakash Shukla
  4 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09  9:56 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram
  Cc: dev, david.marchand, Amit Prakash Shukla

Initializing rte_graph_param variable with 0 to avoid any
garbage value in structure elements which are not populated
as part of this function.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
Acked-by: Jerin Jacob <jerinj@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix

 app/test/test_graph_perf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/test/test_graph_perf.c b/app/test/test_graph_perf.c
index 1d065438a6..c5b463f700 100644
--- a/app/test/test_graph_perf.c
+++ b/app/test/test_graph_perf.c
@@ -324,7 +324,7 @@ graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks,
 	char nname[RTE_NODE_NAMESIZE / 2];
 	struct test_node_data *node_data;
 	char *ename[nodes_per_stage];
-	struct rte_graph_param gconf;
+	struct rte_graph_param gconf = {0};
 	const struct rte_memzone *mz;
 	uint8_t total_percent = 0;
 	rte_node_t *src_nodes;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* RE: [PATCH v6 1/4] pcapng: comment option support for epb
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
                               ` (2 preceding siblings ...)
  2023-02-09  9:56             ` [PATCH v6 4/4] test/graph: initialize graph param variable Amit Prakash Shukla
@ 2023-02-09 10:03             ` Amit Prakash Shukla
  2023-02-09 10:24             ` [PATCH v7 1/3] " Amit Prakash Shukla
  4 siblings, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09 10:03 UTC (permalink / raw)
  To: Amit Prakash Shukla, Reshma Pattan, Stephen Hemminger
  Cc: dev, Jerin Jacob Kollanukkaran, david.marchand

Please ignore this version. I will resend the patch.

> -----Original Message-----
> From: Amit Prakash Shukla <amitprakashs@marvell.com>
> Sent: Thursday, February 9, 2023 3:26 PM
> To: Reshma Pattan <reshma.pattan@intel.com>; Stephen Hemminger
> <stephen@networkplumber.org>
> Cc: dev@dpdk.org; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> david.marchand@redhat.com; Amit Prakash Shukla
> <amitprakashs@marvell.com>
> Subject: [PATCH v6 1/4] pcapng: comment option support for epb
> 
> This change enhances rte_pcapng_copy to have comment in enhanced
> packet block.
> 
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> ---
> v2:
>  - Fixed code style issue
>  - Fixed CI compilation issue on github-robot
> 
> v3:
>  - Code review suggestion from Stephen
>  - Fixed potential memory leak
> 
> v4:
>  - Code review suggestion from Jerin
> 
> v5:
>  - Code review suggestion from Jerin
> 
> v6:
>  - Squashing test graph param initialize fix
> 
>  app/test/test_pcapng.c                 |  4 ++--
>  doc/guides/rel_notes/release_23_03.rst |  2 ++
>  lib/pcapng/rte_pcapng.c                | 10 +++++++++-
>  lib/pcapng/rte_pcapng.h                |  4 +++-
>  lib/pdump/rte_pdump.c                  |  2 +-
>  5 files changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c index
> edba46d1fe..b8429a02f1 100644
> --- a/app/test/test_pcapng.c
> +++ b/app/test/test_pcapng.c
> @@ -146,7 +146,7 @@ test_write_packets(void)
>  		struct rte_mbuf *mc;
> 
>  		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
> -				rte_get_tsc_cycles(), 0);
> +				rte_get_tsc_cycles(), 0, NULL);
>  		if (mc == NULL) {
>  			fprintf(stderr, "Cannot copy packet\n");
>  			return -1;
> @@ -262,7 +262,7 @@ test_write_over_limit_iov_max(void)
>  		struct rte_mbuf *mc;
> 
>  		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
> -				rte_get_tsc_cycles(), 0);
> +				rte_get_tsc_cycles(), 0, NULL);
>  		if (mc == NULL) {
>  			fprintf(stderr, "Cannot copy packet\n");
>  			return -1;
> diff --git a/doc/guides/rel_notes/release_23_03.rst
> b/doc/guides/rel_notes/release_23_03.rst
> index 1fa101c420..bb435dde32 100644
> --- a/doc/guides/rel_notes/release_23_03.rst
> +++ b/doc/guides/rel_notes/release_23_03.rst
> @@ -116,6 +116,8 @@ API Changes
>     Also, make sure to start the actual text at the margin.
>     =======================================================
> 
> +* Experimental function ``rte_pcapng_copy`` was updated to support
> +comment
> +  section in enhanced packet block in pcapng library.
> 
>  ABI Changes
>  -----------
> diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c index
> ea004939e6..65c8c77fa4 100644
> --- a/lib/pcapng/rte_pcapng.c
> +++ b/lib/pcapng/rte_pcapng.c
> @@ -466,7 +466,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  		const struct rte_mbuf *md,
>  		struct rte_mempool *mp,
>  		uint32_t length, uint64_t cycles,
> -		enum rte_pcapng_direction direction)
> +		enum rte_pcapng_direction direction,
> +		const char *comment)
>  {
>  	struct pcapng_enhance_packet_block *epb;
>  	uint32_t orig_len, data_len, padding, flags; @@ -527,6 +528,9 @@
> rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  	if (rss_hash)
>  		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
> 
> +	if (comment)
> +		optlen += pcapng_optlen(strlen(comment));
> +
>  	/* reserve trailing options and block length */
>  	opt = (struct pcapng_option *)
>  		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t)); @@ -
> 564,6 +568,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  					&hash_opt, sizeof(hash_opt));
>  	}
> 
> +	if (comment)
> +		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,
> comment,
> +					strlen(comment));
> +
>  	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
> 
>  	/* Add PCAPNG packet header */
> diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h index
> 86b7996e29..4afdec22ef 100644
> --- a/lib/pcapng/rte_pcapng.h
> +++ b/lib/pcapng/rte_pcapng.h
> @@ -125,6 +125,8 @@ enum rte_pcapng_direction {
>   *   The timestamp in TSC cycles.
>   * @param direction
>   *   The direction of the packer: receive, transmit or unknown.
> + * @param comment
> + *   Packet comment.
>   *
>   * @return
>   *   - The pointer to the new mbuf formatted for pcapng_write
> @@ -136,7 +138,7 @@ struct rte_mbuf *
>  rte_pcapng_copy(uint16_t port_id, uint32_t queue,
>  		const struct rte_mbuf *m, struct rte_mempool *mp,
>  		uint32_t length, uint64_t timestamp,
> -		enum rte_pcapng_direction direction);
> +		enum rte_pcapng_direction direction, const char
> *comment);
> 
> 
>  /**
> diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c index
> a81544cb57..9bc4bab4f2 100644
> --- a/lib/pdump/rte_pdump.c
> +++ b/lib/pdump/rte_pdump.c
> @@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
>  		if (cbs->ver == V2)
>  			p = rte_pcapng_copy(port_id, queue,
>  					    pkts[i], mp, cbs->snaplen,
> -					    ts, direction);
> +					    ts, direction, NULL);
>  		else
>  			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
> 
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v7 1/3] pcapng: comment option support for epb
  2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
                               ` (3 preceding siblings ...)
  2023-02-09 10:03             ` [PATCH v6 1/4] pcapng: comment option support for epb Amit Prakash Shukla
@ 2023-02-09 10:24             ` Amit Prakash Shukla
  2023-02-09 10:24               ` [PATCH v7 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
  2023-02-09 10:24               ` [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
  4 siblings, 2 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09 10:24 UTC (permalink / raw)
  To: Reshma Pattan, Stephen Hemminger
  Cc: dev, jerinj, david.marchand, Amit Prakash Shukla

This change enhances rte_pcapng_copy to have comment in enhanced
packet block.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix
 
v7:
 - Resending the patch

 app/test/test_pcapng.c                 |  4 ++--
 doc/guides/rel_notes/release_23_03.rst |  2 ++
 lib/pcapng/rte_pcapng.c                | 10 +++++++++-
 lib/pcapng/rte_pcapng.h                |  4 +++-
 lib/pdump/rte_pdump.c                  |  2 +-
 5 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index edba46d1fe..b8429a02f1 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -146,7 +146,7 @@ test_write_packets(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
@@ -262,7 +262,7 @@ test_write_over_limit_iov_max(void)
 		struct rte_mbuf *mc;
 
 		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0);
+				rte_get_tsc_cycles(), 0, NULL);
 		if (mc == NULL) {
 			fprintf(stderr, "Cannot copy packet\n");
 			return -1;
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index 1fa101c420..bb435dde32 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -116,6 +116,8 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* Experimental function ``rte_pcapng_copy`` was updated to support comment
+  section in enhanced packet block in pcapng library.
 
 ABI Changes
 -----------
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index ea004939e6..65c8c77fa4 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -466,7 +466,8 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *md,
 		struct rte_mempool *mp,
 		uint32_t length, uint64_t cycles,
-		enum rte_pcapng_direction direction)
+		enum rte_pcapng_direction direction,
+		const char *comment)
 {
 	struct pcapng_enhance_packet_block *epb;
 	uint32_t orig_len, data_len, padding, flags;
@@ -527,6 +528,9 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 	if (rss_hash)
 		optlen += pcapng_optlen(sizeof(uint8_t) + sizeof(uint32_t));
 
+	if (comment)
+		optlen += pcapng_optlen(strlen(comment));
+
 	/* reserve trailing options and block length */
 	opt = (struct pcapng_option *)
 		rte_pktmbuf_append(mc, optlen + sizeof(uint32_t));
@@ -564,6 +568,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 					&hash_opt, sizeof(hash_opt));
 	}
 
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strlen(comment));
+
 	/* Note: END_OPT necessary here. Wireshark doesn't do it. */
 
 	/* Add PCAPNG packet header */
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index 86b7996e29..4afdec22ef 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -125,6 +125,8 @@ enum rte_pcapng_direction {
  *   The timestamp in TSC cycles.
  * @param direction
  *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
@@ -136,7 +138,7 @@ struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
 		const struct rte_mbuf *m, struct rte_mempool *mp,
 		uint32_t length, uint64_t timestamp,
-		enum rte_pcapng_direction direction);
+		enum rte_pcapng_direction direction, const char *comment);
 
 
 /**
diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index a81544cb57..9bc4bab4f2 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -122,7 +122,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,
 		if (cbs->ver == V2)
 			p = rte_pcapng_copy(port_id, queue,
 					    pkts[i], mp, cbs->snaplen,
-					    ts, direction);
+					    ts, direction, NULL);
 		else
 			p = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v7 2/3] graph: pcap capture for graph nodes
  2023-02-09 10:24             ` [PATCH v7 1/3] " Amit Prakash Shukla
@ 2023-02-09 10:24               ` Amit Prakash Shukla
  2023-02-09 10:24               ` [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
  1 sibling, 0 replies; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09 10:24 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Anatoly Burakov
  Cc: dev, david.marchand, Amit Prakash Shukla

Implementation adds support to capture packets at each node with
packet metadata and node name.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix
 
v7:
 - Resending the patch

 app/test/test_graph_perf.c             |   2 +-
 doc/guides/rel_notes/release_23_03.rst |   7 +
 lib/graph/graph.c                      |  17 +-
 lib/graph/graph_pcap.c                 | 216 +++++++++++++++++++++++++
 lib/graph/graph_pcap_private.h         | 116 +++++++++++++
 lib/graph/graph_populate.c             |  12 +-
 lib/graph/graph_private.h              |   5 +
 lib/graph/meson.build                  |   3 +-
 lib/graph/rte_graph.h                  |   5 +
 lib/graph/rte_graph_worker.h           |   9 ++
 10 files changed, 388 insertions(+), 4 deletions(-)
 create mode 100644 lib/graph/graph_pcap.c
 create mode 100644 lib/graph/graph_pcap_private.h

diff --git a/app/test/test_graph_perf.c b/app/test/test_graph_perf.c
index 1d065438a6..c5b463f700 100644
--- a/app/test/test_graph_perf.c
+++ b/app/test/test_graph_perf.c
@@ -324,7 +324,7 @@ graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks,
 	char nname[RTE_NODE_NAMESIZE / 2];
 	struct test_node_data *node_data;
 	char *ename[nodes_per_stage];
-	struct rte_graph_param gconf;
+	struct rte_graph_param gconf = {0};
 	const struct rte_memzone *mz;
 	uint8_t total_percent = 0;
 	rte_node_t *src_nodes;
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index bb435dde32..328dfd3009 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -87,6 +87,10 @@ New Features
     ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
     required for eth_rx, eth_tx, crypto and timer eventdev adapters.
 
+* **Added pcap trace support in graph library.**
+
+  * Added support to capture packets at each graph node with packet metadata and
+    node name.
 
 Removed Items
 -------------
@@ -119,6 +123,9 @@ API Changes
 * Experimental function ``rte_pcapng_copy`` was updated to support comment
   section in enhanced packet block in pcapng library.
 
+* Experimental structures ``struct rte_graph_param``, ``struct rte_graph`` and
+  ``struct graph`` were updated to support pcap trace in graph library.
+
 ABI Changes
 -----------
 
diff --git a/lib/graph/graph.c b/lib/graph/graph.c
index 3a617cc369..a839a2803b 100644
--- a/lib/graph/graph.c
+++ b/lib/graph/graph.c
@@ -15,6 +15,7 @@
 #include <rte_string_fns.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static struct graph_head graph_list = STAILQ_HEAD_INITIALIZER(graph_list);
 static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER;
@@ -228,7 +229,12 @@ graph_mem_fixup_node_ctx(struct rte_graph *graph)
 		node_db = node_from_name(name);
 		if (node_db == NULL)
 			SET_ERR_JMP(ENOLINK, fail, "Node %s not found", name);
-		node->process = node_db->process;
+
+		if (graph->pcap_enable) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = node_db->process;
+		} else
+			node->process = node_db->process;
 	}
 
 	return graph;
@@ -242,6 +248,9 @@ graph_mem_fixup_secondary(struct rte_graph *graph)
 	if (graph == NULL || rte_eal_process_type() == RTE_PROC_PRIMARY)
 		return graph;
 
+	if (graph_pcap_file_open(graph->pcap_filename) || graph_pcap_mp_init())
+		graph_pcap_exit(graph);
+
 	return graph_mem_fixup_node_ctx(graph);
 }
 
@@ -323,11 +332,17 @@ rte_graph_create(const char *name, struct rte_graph_param *prm)
 	if (graph_has_isolated_node(graph))
 		goto graph_cleanup;
 
+	/* Initialize pcap config. */
+	graph_pcap_enable(prm->pcap_enable);
+
 	/* Initialize graph object */
 	graph->socket = prm->socket_id;
 	graph->src_node_count = src_node_count;
 	graph->node_count = graph_nodes_count(graph);
 	graph->id = graph_id;
+	graph->num_pkt_to_capture = prm->num_pkt_to_capture;
+	if (prm->pcap_filename)
+		rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
 
 	/* Allocate the Graph fast path memory and populate the data */
 	if (graph_fp_mem_create(graph))
diff --git a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c
new file mode 100644
index 0000000000..9cbd1b8fdb
--- /dev/null
+++ b/lib/graph/graph_pcap.c
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_mbuf.h>
+#include <rte_pcapng.h>
+
+#include "rte_graph_worker.h"
+
+#include "graph_pcap_private.h"
+
+#define GRAPH_PCAP_BUF_SZ	128
+#define GRAPH_PCAP_NUM_PACKETS	1024
+#define GRAPH_PCAP_PKT_POOL	"graph_pcap_pkt_pool"
+#define GRAPH_PCAP_FILE_NAME	"dpdk_graph_pcap_capture_XXXXXX.pcapng"
+
+/* For multi-process, packets are captured in separate files. */
+static rte_pcapng_t *pcapng_fd;
+static bool pcap_enable;
+struct rte_mempool *pkt_mp;
+
+void
+graph_pcap_enable(bool val)
+{
+	pcap_enable = val;
+}
+
+int
+graph_pcap_is_enable(void)
+{
+	return pcap_enable;
+}
+
+void
+graph_pcap_exit(struct rte_graph *graph)
+{
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		if (pkt_mp)
+			rte_mempool_free(pkt_mp);
+
+	if (pcapng_fd) {
+		rte_pcapng_close(pcapng_fd);
+		pcapng_fd = NULL;
+	}
+
+	/* Disable pcap. */
+	graph->pcap_enable = 0;
+	graph_pcap_enable(0);
+}
+
+static int
+graph_pcap_default_path_get(char **dir_path)
+{
+	struct passwd *pwd;
+	char *home_dir;
+
+	/* First check for shell environment variable */
+	home_dir = getenv("HOME");
+	if (home_dir == NULL) {
+		graph_warn("Home env not preset.");
+		/* Fallback to password file entry */
+		pwd = getpwuid(getuid());
+		if (pwd == NULL)
+			return -EINVAL;
+
+		home_dir = pwd->pw_dir;
+	}
+
+	/* Append default pcap file to directory */
+	if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME) == -1)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int
+graph_pcap_file_open(const char *filename)
+{
+	int fd;
+	char file_name[RTE_GRAPH_PCAP_FILE_SZ];
+	char *pcap_dir;
+
+	if (pcapng_fd)
+		goto done;
+
+	if (!filename || filename[0] == '\0') {
+		if (graph_pcap_default_path_get(&pcap_dir) < 0)
+			return -1;
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
+		free(pcap_dir);
+	} else {
+		snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s_XXXXXX.pcapng",
+			 filename);
+	}
+
+	fd = mkstemps(file_name, strlen(".pcapng"));
+	if (fd < 0) {
+		graph_err("mkstemps() failure");
+		return -1;
+	}
+
+	graph_info("pcap filename: %s", file_name);
+
+	/* Open a capture file */
+	pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
+				      NULL);
+	if (pcapng_fd == NULL) {
+		graph_err("Graph rte_pcapng_fdopen failed.");
+		close(fd);
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_mp_init(void)
+{
+	pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
+	if (pkt_mp)
+		goto done;
+
+	/* Make a pool for cloned packets */
+	pkt_mp = rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
+			IOV_MAX + RTE_GRAPH_BURST_SIZE,	0, 0,
+			rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
+			SOCKET_ID_ANY, "ring_mp_mc");
+	if (pkt_mp == NULL) {
+		graph_err("Cannot create mempool for graph pcap capture.");
+		return -1;
+	}
+
+done:
+	return 0;
+}
+
+int
+graph_pcap_init(struct graph *graph)
+{
+	struct rte_graph *graph_data = graph->graph;
+
+	if (graph_pcap_file_open(graph->pcap_filename) < 0)
+		goto error;
+
+	if (graph_pcap_mp_init() < 0)
+		goto error;
+
+	/* User configured number of packets to capture. */
+	if (graph->num_pkt_to_capture)
+		graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
+	else
+		graph_data->nb_pkt_to_capture = GRAPH_PCAP_NUM_PACKETS;
+
+	/* All good. Now populate data for secondary process. */
+	rte_strscpy(graph_data->pcap_filename, graph->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
+	graph_data->pcap_enable = 1;
+
+	return 0;
+
+error:
+	graph_pcap_exit(graph_data);
+	graph_pcap_enable(0);
+	graph_err("Graph pcap initialization failed. Disabling pcap trace.");
+	return -1;
+}
+
+uint16_t
+graph_pcap_dispatch(struct rte_graph *graph,
+			      struct rte_node *node, void **objs,
+			      uint16_t nb_objs)
+{
+	struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
+	char buffer[GRAPH_PCAP_BUF_SZ];
+	uint64_t i, num_packets;
+	struct rte_mbuf *mbuf;
+	ssize_t len;
+
+	if (!nb_objs || (graph->nb_pkt_captured >= graph->nb_pkt_to_capture))
+		goto done;
+
+	num_packets = graph->nb_pkt_to_capture - graph->nb_pkt_captured;
+	/* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
+	if (num_packets > nb_objs)
+		num_packets = nb_objs;
+
+	snprintf(buffer, GRAPH_PCAP_BUF_SZ, "%s: %s", graph->name, node->name);
+
+	for (i = 0; i < num_packets; i++) {
+		struct rte_mbuf *mc;
+		mbuf = (struct rte_mbuf *)objs[i];
+
+		mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len,
+				     rte_get_tsc_cycles(), 0, buffer);
+		if (mc == NULL)
+			break;
+
+		mbuf_clones[i] = mc;
+	}
+
+	/* write it to capture file */
+	len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
+	rte_pktmbuf_free_bulk(mbuf_clones, i);
+	if (len <= 0)
+		goto done;
+
+	graph->nb_pkt_captured += i;
+
+done:
+	return node->original_process(graph, node, objs, nb_objs);
+}
diff --git a/lib/graph/graph_pcap_private.h b/lib/graph/graph_pcap_private.h
new file mode 100644
index 0000000000..2ec772072c
--- /dev/null
+++ b/lib/graph/graph_pcap_private.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_PCAP_PRIVATE_H_
+#define _RTE_GRAPH_PCAP_PRIVATE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "graph_private.h"
+
+/**
+ * @internal
+ *
+ * Pcap trace enable/disable function.
+ *
+ * The function is called to enable/disable graph pcap trace functionality.
+ *
+ * @param val
+ *   Value to be set to enable/disable graph pcap trace.
+ */
+void graph_pcap_enable(bool val);
+
+/**
+ * @internal
+ *
+ * Check graph pcap trace is enable/disable.
+ *
+ * The function is called to check if the graph pcap trace is enabled/disabled.
+ *
+ * @return
+ *   - 1: Enable
+ *   - 0: Disable
+ */
+int graph_pcap_is_enable(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to allocate mempool.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_mp_init(void);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked to open pcap file.
+ *
+ * @param filename
+ *   Pcap filename.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_file_open(const char *filename);
+
+/**
+ * @internal
+ *
+ * Initialise graph pcap trace functionality.
+ *
+ * The function invoked when the graph pcap trace is enabled. This function
+ * open's pcap file and allocates mempool. Information needed for secondary
+ * process is populated.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ *
+ * @return
+ *   0 on success and -1 on failure.
+ */
+int graph_pcap_init(struct graph *graph);
+
+/**
+ * @internal
+ *
+ * Exit graph pcap trace functionality.
+ *
+ * The function is called to exit graph pcap trace and close open fd's and
+ * free up memory. Pcap trace is also disabled.
+ *
+ * @param graph
+ *   Pointer to graph structure.
+ */
+void graph_pcap_exit(struct rte_graph *graph);
+
+/**
+ * @internal
+ *
+ * Capture mbuf metadata and node metadata to a pcap file.
+ *
+ * When graph pcap trace enabled, this function is invoked prior to each node
+ * and mbuf, node metadata is parsed and captured in a pcap file.
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ */
+uint16_t graph_pcap_dispatch(struct rte_graph *graph,
+				   struct rte_node *node, void **objs,
+				   uint16_t nb_objs);
+
+#endif /* _RTE_GRAPH_PCAP_PRIVATE_H_ */
diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c
index 102fd6c29b..2c0844ce92 100644
--- a/lib/graph/graph_populate.c
+++ b/lib/graph/graph_populate.c
@@ -9,6 +9,7 @@
 #include <rte_memzone.h>
 
 #include "graph_private.h"
+#include "graph_pcap_private.h"
 
 static size_t
 graph_fp_mem_calc_size(struct graph *graph)
@@ -75,7 +76,11 @@ graph_nodes_populate(struct graph *_graph)
 		memset(node, 0, sizeof(*node));
 		node->fence = RTE_GRAPH_FENCE;
 		node->off = off;
-		node->process = graph_node->node->process;
+		if (graph_pcap_is_enable()) {
+			node->process = graph_pcap_dispatch;
+			node->original_process = graph_node->node->process;
+		} else
+			node->process = graph_node->node->process;
 		memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
 		pid = graph_node->node->parent_id;
 		if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
@@ -183,6 +188,8 @@ graph_fp_mem_populate(struct graph *graph)
 	int rc;
 
 	graph_header_popluate(graph);
+	if (graph_pcap_is_enable())
+		graph_pcap_init(graph);
 	graph_nodes_populate(graph);
 	rc = graph_node_nexts_populate(graph);
 	rc |= graph_src_nodes_populate(graph);
@@ -227,6 +234,9 @@ graph_nodes_mem_destroy(struct rte_graph *graph)
 int
 graph_fp_mem_destroy(struct graph *graph)
 {
+	if (graph_pcap_is_enable())
+		graph_pcap_exit(graph->graph);
+
 	graph_nodes_mem_destroy(graph->graph);
 	return rte_memzone_free(graph->mz);
 }
diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h
index f9a85c8926..7d1b30b8ac 100644
--- a/lib/graph/graph_private.h
+++ b/lib/graph/graph_private.h
@@ -22,6 +22,7 @@ extern int rte_graph_logtype;
 			__func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__, )))
 
 #define graph_err(...) GRAPH_LOG(ERR, __VA_ARGS__)
+#define graph_warn(...) GRAPH_LOG(WARNING, __VA_ARGS__)
 #define graph_info(...) GRAPH_LOG(INFO, __VA_ARGS__)
 #define graph_dbg(...) GRAPH_LOG(DEBUG, __VA_ARGS__)
 
@@ -100,6 +101,10 @@ struct graph {
 	/**< Memory size of the graph. */
 	int socket;
 	/**< Socket identifier where memory is allocated. */
+	uint64_t num_pkt_to_capture;
+	/**< Number of packets to be captured per core. */
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+	/**< pcap file name/path. */
 	STAILQ_HEAD(gnode_list, graph_node) node_list;
 	/**< Nodes in a graph. */
 };
diff --git a/lib/graph/meson.build b/lib/graph/meson.build
index c7327549e8..3526d1b5d4 100644
--- a/lib/graph/meson.build
+++ b/lib/graph/meson.build
@@ -14,7 +14,8 @@ sources = files(
         'graph_debug.c',
         'graph_stats.c',
         'graph_populate.c',
+        'graph_pcap.c',
 )
 headers = files('rte_graph.h', 'rte_graph_worker.h')
 
-deps += ['eal']
+deps += ['eal', 'pcapng']
diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h
index b32c4bc217..c9a77297fc 100644
--- a/lib/graph/rte_graph.h
+++ b/lib/graph/rte_graph.h
@@ -35,6 +35,7 @@ extern "C" {
 
 #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
 #define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
+#define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */
 #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
 #define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
 #define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
@@ -164,6 +165,10 @@ struct rte_graph_param {
 	uint16_t nb_node_patterns;  /**< Number of node patterns. */
 	const char **node_patterns;
 	/**< Array of node patterns based on shell pattern. */
+
+	bool pcap_enable; /**< Pcap enable. */
+	uint64_t num_pkt_to_capture; /**< Number of packets to capture. */
+	char *pcap_filename; /**< Filename in which packets to be captured.*/
 };
 
 /**
diff --git a/lib/graph/rte_graph_worker.h b/lib/graph/rte_graph_worker.h
index fc6fee48c8..438595b15c 100644
--- a/lib/graph/rte_graph_worker.h
+++ b/lib/graph/rte_graph_worker.h
@@ -44,6 +44,12 @@ struct rte_graph {
 	rte_graph_t id;	/**< Graph identifier. */
 	int socket;	/**< Socket ID where memory is allocated. */
 	char name[RTE_GRAPH_NAMESIZE];	/**< Name of the graph. */
+	bool pcap_enable;	        /**< Pcap trace enabled. */
+	/** Number of packets captured per core. */
+	uint64_t nb_pkt_captured;
+	/** Number of packets to capture per core. */
+	uint64_t nb_pkt_to_capture;
+	char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];  /**< Pcap filename. */
 	uint64_t fence;			/**< Fence. */
 } __rte_cache_aligned;
 
@@ -64,6 +70,9 @@ struct rte_node {
 	char parent[RTE_NODE_NAMESIZE];	/**< Parent node name. */
 	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
 
+	/** Original process function when pcap is enabled. */
+	rte_node_process_t original_process;
+
 	/* Fast path area  */
 #define RTE_NODE_CTX_SZ 16
 	uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture
  2023-02-09 10:24             ` [PATCH v7 1/3] " Amit Prakash Shukla
  2023-02-09 10:24               ` [PATCH v7 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
@ 2023-02-09 10:24               ` Amit Prakash Shukla
  2023-02-09 17:28                 ` Jerin Jacob
  1 sibling, 1 reply; 47+ messages in thread
From: Amit Prakash Shukla @ 2023-02-09 10:24 UTC (permalink / raw)
  To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram
  Cc: dev, david.marchand, Amit Prakash Shukla

Added support to configure pcap capture.

Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
 - Fixed code style issue
 - Fixed CI compilation issue on github-robot

v3:
 - Code review suggestion from Stephen
 - Fixed potential memory leak
 
v4:
 - Code review suggestion from Jerin

v5:
 - Code review suggestion from Jerin

v6:
 - Squashing test graph param initialize fix
 
v7:
 - Resending the patch

 doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
 examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 0a3e0d44ec..585ac8c898 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
                                    [--max-pkt-len PKTLEN]
                                    [--no-numa]
                                    [--per-port-pool]
+                                   [--pcap-enable]
+                                   [--pcap-num-cap]
+                                   [--pcap-file-name]
 
 Where,
 
@@ -69,6 +72,12 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
+
+* ``--pcap-num-cap:`` Optional, Number of packets to be captured per core.
+
+* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
@@ -99,6 +108,20 @@ In this command:
 |          |           |           |                                     |
 +----------+-----------+-----------+-------------------------------------+
 
+To enable pcap trace on each graph, use following command:
+
+.. code-block:: console
+
+    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets> --pcap-file-name "</path/to/file>"
+
+In this command:
+
+*   The --pcap-enable option enables pcap trace on graph nodes.
+
+*   The --pcap-num-cap option enables user to configure number packets to be captured per graph. Default 1024 packets per graph are captured.
+
+*   The --pcap-file-name option enables user to give filename in which packets are to be captured.
+
 Refer to the *DPDK Getting Started Guide* for general information on running applications and
 the Environment Abstraction Layer (EAL) options.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 6dcb6ee92b..5feeab4f0f 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -76,6 +76,12 @@ xmm_t val_eth[RTE_MAX_ETHPORTS];
 /* Mask of enabled ports */
 static uint32_t enabled_port_mask;
 
+/* Pcap trace */
+static char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
+static uint64_t packet_to_capture;
+static int pcap_trace_enable;
+
+
 struct lcore_rx_queue {
 	uint16_t port_id;
 	uint8_t queue_id;
@@ -261,7 +267,8 @@ print_usage(const char *prgname)
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--max-pkt-len PKTLEN]"
 		" [--no-numa]"
-		" [--per-port-pool]\n\n"
+		" [--per-port-pool]"
+		" [--num-pkt-cap]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -270,10 +277,30 @@ print_usage(const char *prgname)
 		"port X\n"
 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
 		"  --no-numa: Disable numa awareness\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n"
+		"  --pcap-enable: Enables pcap capture\n"
+		"  --pcap-num-cap NUMPKT: Number of packets to capture\n"
+		"  --pcap-file-name NAME: Pcap file name\n\n",
 		prgname);
 }
 
+static uint64_t
+parse_num_pkt_cap(const char *num_pkt_cap)
+{
+	uint64_t num_pkt;
+	char *end = NULL;
+
+	/* Parse decimal string */
+	num_pkt = strtoull(num_pkt_cap, &end, 10);
+	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (num_pkt == 0)
+		return 0;
+
+	return num_pkt;
+}
+
 static int
 parse_max_pkt_len(const char *pktlen)
 {
@@ -404,6 +431,9 @@ static const char short_options[] = "p:" /* portmask */
 #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
 #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
+#define CMD_LINE_OPT_NUM_PKT_CAP   "pcap-num-cap"
+#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
 enum {
 	/* Long options mapped to a short option */
 
@@ -416,6 +446,9 @@ enum {
 	CMD_LINE_OPT_NO_NUMA_NUM,
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
+	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
+	CMD_LINE_OPT_PCAP_FILENAME_CAP,
 };
 
 static const struct option lgopts[] = {
@@ -424,6 +457,9 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
+	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
+	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
 	{NULL, 0, 0, 0},
 };
 
@@ -498,6 +534,23 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
+			printf("Packet capture enabled\n");
+			pcap_trace_enable = 1;
+			break;
+
+		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
+			packet_to_capture = parse_num_pkt_cap(optarg);
+			printf("Number of packets to capture: %"PRIu64"\n",
+			       packet_to_capture);
+			break;
+
+		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
+			rte_strlcpy(pcap_filename, optarg,
+				    sizeof(pcap_filename));
+			printf("Pcap file name: %s\n", pcap_filename);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -1027,6 +1080,11 @@ main(int argc, char **argv)
 	memset(&graph_conf, 0, sizeof(graph_conf));
 	graph_conf.node_patterns = node_patterns;
 
+	/* Pcap config */
+	graph_conf.pcap_enable = pcap_trace_enable;
+	graph_conf.num_pkt_to_capture = packet_to_capture;
+	graph_conf.pcap_filename = pcap_filename;
+
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 		rte_graph_t graph_id;
 		rte_edge_t i;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v5 1/3] pcapng: comment option support for epb
  2023-02-09  9:13           ` [PATCH v5 1/3] pcapng: comment option support for epb David Marchand
@ 2023-02-09 16:48             ` Stephen Hemminger
  0 siblings, 0 replies; 47+ messages in thread
From: Stephen Hemminger @ 2023-02-09 16:48 UTC (permalink / raw)
  To: David Marchand; +Cc: Amit Prakash Shukla, Reshma Pattan, dev, jerinj

On Thu, 9 Feb 2023 10:13:41 +0100
David Marchand <david.marchand@redhat.com> wrote:

> Stephen, Reshma,
> 
> On Fri, Feb 3, 2023 at 9:19 AM Amit Prakash Shukla
> <amitprakashs@marvell.com> wrote:
> >
> > This change enhances rte_pcapng_copy to have comment in enhanced
> > packet block.
> >
> > Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>  
> 
> Is this change ok for you?
> Thanks.
> 

Yes
Acked-by: Stephen Hemminger <stephen@networkplumber.org>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture
  2023-02-09 10:24               ` [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
@ 2023-02-09 17:28                 ` Jerin Jacob
  2023-02-10 12:18                   ` David Marchand
  0 siblings, 1 reply; 47+ messages in thread
From: Jerin Jacob @ 2023-02-09 17:28 UTC (permalink / raw)
  To: Amit Prakash Shukla
  Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, dev, david.marchand

On Thu, Feb 9, 2023 at 3:54 PM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
>
> Added support to configure pcap capture.
>
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>


Acked-by: Jerin Jacob <jerinj@marvell.com>


> ---
> v2:
>  - Fixed code style issue
>  - Fixed CI compilation issue on github-robot
>
> v3:
>  - Code review suggestion from Stephen
>  - Fixed potential memory leak
>
> v4:
>  - Code review suggestion from Jerin
>
> v5:
>  - Code review suggestion from Jerin
>
> v6:
>  - Squashing test graph param initialize fix
>
> v7:
>  - Resending the patch
>
>  doc/guides/sample_app_ug/l3_forward_graph.rst | 23 +++++++
>  examples/l3fwd-graph/main.c                   | 62 ++++++++++++++++++-
>  2 files changed, 83 insertions(+), 2 deletions(-)
>
> diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
> index 0a3e0d44ec..585ac8c898 100644
> --- a/doc/guides/sample_app_ug/l3_forward_graph.rst
> +++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
> @@ -51,6 +51,9 @@ The application has a number of command line options similar to l3fwd::
>                                     [--max-pkt-len PKTLEN]
>                                     [--no-numa]
>                                     [--per-port-pool]
> +                                   [--pcap-enable]
> +                                   [--pcap-num-cap]
> +                                   [--pcap-file-name]
>
>  Where,
>
> @@ -69,6 +72,12 @@ Where,
>
>  * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
>
> +* ``--pcap-enable:`` Optional, Enables packet capture in pcap format on each node with mbuf and node metadata.
> +
> +* ``--pcap-num-cap:`` Optional, Number of packets to be captured per core.
> +
> +* ``--pcap-file-name:`` Optional, Pcap filename to capture packets in.
> +
>  For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
>  while cores 8-15 and 24-31 appear on socket 1.
>
> @@ -99,6 +108,20 @@ In this command:
>  |          |           |           |                                     |
>  +----------+-----------+-----------+-------------------------------------+
>
> +To enable pcap trace on each graph, use following command:
> +
> +.. code-block:: console
> +
> +    ./<build_dir>/examples/dpdk-l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --pcap-enable --pcap-num-cap=<number of packets> --pcap-file-name "</path/to/file>"
> +
> +In this command:
> +
> +*   The --pcap-enable option enables pcap trace on graph nodes.
> +
> +*   The --pcap-num-cap option enables user to configure number packets to be captured per graph. Default 1024 packets per graph are captured.
> +
> +*   The --pcap-file-name option enables user to give filename in which packets are to be captured.
> +
>  Refer to the *DPDK Getting Started Guide* for general information on running applications and
>  the Environment Abstraction Layer (EAL) options.
>
> diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
> index 6dcb6ee92b..5feeab4f0f 100644
> --- a/examples/l3fwd-graph/main.c
> +++ b/examples/l3fwd-graph/main.c
> @@ -76,6 +76,12 @@ xmm_t val_eth[RTE_MAX_ETHPORTS];
>  /* Mask of enabled ports */
>  static uint32_t enabled_port_mask;
>
> +/* Pcap trace */
> +static char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
> +static uint64_t packet_to_capture;
> +static int pcap_trace_enable;
> +
> +
>  struct lcore_rx_queue {
>         uint16_t port_id;
>         uint8_t queue_id;
> @@ -261,7 +267,8 @@ print_usage(const char *prgname)
>                 " [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
>                 " [--max-pkt-len PKTLEN]"
>                 " [--no-numa]"
> -               " [--per-port-pool]\n\n"
> +               " [--per-port-pool]"
> +               " [--num-pkt-cap]\n\n"
>
>                 "  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
>                 "  -P : Enable promiscuous mode\n"
> @@ -270,10 +277,30 @@ print_usage(const char *prgname)
>                 "port X\n"
>                 "  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
>                 "  --no-numa: Disable numa awareness\n"
> -               "  --per-port-pool: Use separate buffer pool per port\n\n",
> +               "  --per-port-pool: Use separate buffer pool per port\n"
> +               "  --pcap-enable: Enables pcap capture\n"
> +               "  --pcap-num-cap NUMPKT: Number of packets to capture\n"
> +               "  --pcap-file-name NAME: Pcap file name\n\n",
>                 prgname);
>  }
>
> +static uint64_t
> +parse_num_pkt_cap(const char *num_pkt_cap)
> +{
> +       uint64_t num_pkt;
> +       char *end = NULL;
> +
> +       /* Parse decimal string */
> +       num_pkt = strtoull(num_pkt_cap, &end, 10);
> +       if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
> +               return 0;
> +
> +       if (num_pkt == 0)
> +               return 0;
> +
> +       return num_pkt;
> +}
> +
>  static int
>  parse_max_pkt_len(const char *pktlen)
>  {
> @@ -404,6 +431,9 @@ static const char short_options[] = "p:" /* portmask */
>  #define CMD_LINE_OPT_NO_NUMA      "no-numa"
>  #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
>  #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
> +#define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
> +#define CMD_LINE_OPT_NUM_PKT_CAP   "pcap-num-cap"
> +#define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
>  enum {
>         /* Long options mapped to a short option */
>
> @@ -416,6 +446,9 @@ enum {
>         CMD_LINE_OPT_NO_NUMA_NUM,
>         CMD_LINE_OPT_MAX_PKT_LEN_NUM,
>         CMD_LINE_OPT_PARSE_PER_PORT_POOL,
> +       CMD_LINE_OPT_PARSE_PCAP_ENABLE,
> +       CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
> +       CMD_LINE_OPT_PCAP_FILENAME_CAP,
>  };
>
>  static const struct option lgopts[] = {
> @@ -424,6 +457,9 @@ static const struct option lgopts[] = {
>         {CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
>         {CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
>         {CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
> +       {CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
> +       {CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
> +       {CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
>         {NULL, 0, 0, 0},
>  };
>
> @@ -498,6 +534,23 @@ parse_args(int argc, char **argv)
>                         per_port_pool = 1;
>                         break;
>
> +               case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
> +                       printf("Packet capture enabled\n");
> +                       pcap_trace_enable = 1;
> +                       break;
> +
> +               case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
> +                       packet_to_capture = parse_num_pkt_cap(optarg);
> +                       printf("Number of packets to capture: %"PRIu64"\n",
> +                              packet_to_capture);
> +                       break;
> +
> +               case CMD_LINE_OPT_PCAP_FILENAME_CAP:
> +                       rte_strlcpy(pcap_filename, optarg,
> +                                   sizeof(pcap_filename));
> +                       printf("Pcap file name: %s\n", pcap_filename);
> +                       break;
> +
>                 default:
>                         print_usage(prgname);
>                         return -1;
> @@ -1027,6 +1080,11 @@ main(int argc, char **argv)
>         memset(&graph_conf, 0, sizeof(graph_conf));
>         graph_conf.node_patterns = node_patterns;
>
> +       /* Pcap config */
> +       graph_conf.pcap_enable = pcap_trace_enable;
> +       graph_conf.num_pkt_to_capture = packet_to_capture;
> +       graph_conf.pcap_filename = pcap_filename;
> +
>         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
>                 rte_graph_t graph_id;
>                 rte_edge_t i;
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture
  2023-02-09 17:28                 ` Jerin Jacob
@ 2023-02-10 12:18                   ` David Marchand
  0 siblings, 0 replies; 47+ messages in thread
From: David Marchand @ 2023-02-10 12:18 UTC (permalink / raw)
  To: Amit Prakash Shukla; +Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, dev

On Thu, Feb 9, 2023 at 6:28 PM Jerin Jacob <jerinjacobk@gmail.com> wrote:
>
> On Thu, Feb 9, 2023 at 3:54 PM Amit Prakash Shukla
> <amitprakashs@marvell.com> wrote:
> >
> > Added support to configure pcap capture.
> >
> > Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> Acked-by: Jerin Jacob <jerinj@marvell.com>

Series applied, thanks.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2023-02-10 12:18 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-23 12:02 [RFC PATCH] graph: add support for pcap trace for graph Amit Prakash Shukla
2022-12-23 16:47 ` Stephen Hemminger
2023-01-06 10:40   ` [EXT] " Amit Prakash Shukla
2023-01-06 16:41     ` Stephen Hemminger
2023-01-06 18:56     ` Stephen Hemminger
2023-01-10 11:26       ` Amit Prakash Shukla
2023-01-10 11:58 ` [PATCH v1 1/3] pcapng: comment option support for epb Amit Prakash Shukla
2023-01-10 11:58   ` [PATCH v1 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-01-10 11:58   ` [PATCH v1 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-01-10 17:05   ` [PATCH v1 1/3] pcapng: comment option support for epb Stephen Hemminger
2023-01-11  8:53   ` [PATCH v2 " Amit Prakash Shukla
2023-01-11  8:53     ` [PATCH v2 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-01-11 16:07       ` Stephen Hemminger
2023-01-12  9:57         ` [EXT] " Amit Prakash Shukla
2023-01-12 16:30           ` Stephen Hemminger
2023-01-19 14:37             ` Amit Prakash Shukla
2023-01-19 16:48               ` Stephen Hemminger
2023-01-11  8:53     ` [PATCH v2 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-01-12 10:01     ` [PATCH v3 1/3] pcapng: comment option support for epb Amit Prakash Shukla
2023-01-12 10:01       ` [PATCH v3 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-01-12 12:18         ` Jerin Jacob
2023-01-19 14:21           ` [EXT] " Amit Prakash Shukla
2023-01-12 10:01       ` [PATCH v3 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-01-24 11:21       ` [PATCH v4 1/3] pcapng: comment option support for epb Amit Prakash Shukla
2023-01-24 11:21         ` [PATCH v4 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-01-31  8:06           ` Jerin Jacob
2023-02-03  8:15             ` [EXT] " Amit Prakash Shukla
2023-01-24 11:21         ` [PATCH v4 3/3] l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-01-31  8:14           ` Jerin Jacob
2023-02-03  8:16             ` [EXT] " Amit Prakash Shukla
2023-02-03  8:19         ` [PATCH v5 1/3] pcapng: comment option support for epb Amit Prakash Shukla
2023-02-03  8:19           ` [PATCH v5 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-02-09  9:12             ` David Marchand
2023-02-09  9:29               ` [EXT] " Amit Prakash Shukla
2023-02-03  8:19           ` [PATCH v5 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-02-09  9:13           ` [PATCH v5 1/3] pcapng: comment option support for epb David Marchand
2023-02-09 16:48             ` Stephen Hemminger
2023-02-09  9:56           ` [PATCH v6 1/4] " Amit Prakash Shukla
2023-02-09  9:56             ` [PATCH v6 2/4] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-02-09  9:56             ` [PATCH v6 3/4] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-02-09  9:56             ` [PATCH v6 4/4] test/graph: initialize graph param variable Amit Prakash Shukla
2023-02-09 10:03             ` [PATCH v6 1/4] pcapng: comment option support for epb Amit Prakash Shukla
2023-02-09 10:24             ` [PATCH v7 1/3] " Amit Prakash Shukla
2023-02-09 10:24               ` [PATCH v7 2/3] graph: pcap capture for graph nodes Amit Prakash Shukla
2023-02-09 10:24               ` [PATCH v7 3/3] examples/l3fwd-graph: changes to configure pcap capture Amit Prakash Shukla
2023-02-09 17:28                 ` Jerin Jacob
2023-02-10 12:18                   ` David Marchand

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.