[v6,4/4] test-pmd: add more packet verbose decode options

Message ID 20240802180838.862858-5-stephen@networkplumber.org (mailing list archive)
State Superseded
Delegated to: Ferruh Yigit
Headers
Series Add network packet dissector |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/github-robot: build success github build: passed
ci/intel-Functional success Functional PASS

Commit Message

Stephen Hemminger Aug. 2, 2024, 6:07 p.m. UTC
The existing verbose levels 1..3 provide a messy multi-line
output per packet. I found this unhelpful when diagnosing many
types of problems like packet flow.

This patch keeps the previous levels and adds two new levels:
4: one line per packet is printed in a format resembling
   tshark output. With addresses and protocol info.

5: dump packet in hex.
   Useful if the driver is messing up the data.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test-pmd/cmdline_flow.c                 |  3 +-
 app/test-pmd/config.c                       | 33 ++++++---
 app/test-pmd/testpmd.h                      | 11 +++
 app/test-pmd/util.c                         | 77 +++++++++++++++++++--
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  5 +-
 5 files changed, 111 insertions(+), 18 deletions(-)
  

Patch

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index d04280eb3e..a010fcf61a 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -14143,7 +14143,8 @@  cmd_set_raw_parsed(const struct buffer *in)
 			upper_layer = proto;
 		}
 	}
-	if (verbose_level & 0x1)
+
+	if (verbose_level > 0)
 		printf("total data size is %zu\n", (*total_size));
 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
 	memmove(data, (data_tail - (*total_size)), *total_size);
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 6f0beafa27..b5b5f3b464 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -6246,26 +6246,37 @@  configure_rxtx_dump_callbacks(uint16_t verbose)
 		return;
 #endif
 
-	RTE_ETH_FOREACH_DEV(portid)
-	{
-		if (verbose == 1 || verbose > 2)
+	RTE_ETH_FOREACH_DEV(portid) {
+		switch (verbose) {
+		case VERBOSE_OFF:
+			remove_rx_dump_callbacks(portid);
+			remove_tx_dump_callbacks(portid);
+			break;
+		case VERBOSE_RX:
 			add_rx_dump_callbacks(portid);
-		else
+			remove_tx_dump_callbacks(portid);
+			break;
+		case VERBOSE_TX:
+			add_tx_dump_callbacks(portid);
 			remove_rx_dump_callbacks(portid);
-		if (verbose >= 2)
+			break;
+		default:
+			add_rx_dump_callbacks(portid);
 			add_tx_dump_callbacks(portid);
-		else
-			remove_tx_dump_callbacks(portid);
+		}
 	}
 }
 
 void
 set_verbose_level(uint16_t vb_level)
 {
-	printf("Change verbose level from %u to %u\n",
-	       (unsigned int) verbose_level, (unsigned int) vb_level);
-	verbose_level = vb_level;
-	configure_rxtx_dump_callbacks(verbose_level);
+	if (vb_level < VERBOSE_MAX) {
+		printf("Change verbose level from %u to %u\n", verbose_level, vb_level);
+		verbose_level = vb_level;
+		configure_rxtx_dump_callbacks(verbose_level);
+	} else {
+		fprintf(stderr, "Verbose level %u is out of range\n", vb_level);
+	}
 }
 
 void
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9facd7f281..3d7a2b6dac 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -489,6 +489,17 @@  enum dcb_mode_enable
 
 extern uint8_t xstats_hide_zero; /**< Hide zero values for xstats display */
 
+enum verbose_mode {
+	VERBOSE_OFF = 0,
+	VERBOSE_RX,
+	VERBOSE_TX,
+	VERBOSE_BOTH,
+	VERBOSE_DISSECT,
+	VERBOSE_HEX,
+	VERBOSE_MAX
+};
+
+
 /* globals used for configuration */
 extern uint8_t record_core_cycles; /**< Enables measurement of CPU cycles */
 extern uint8_t record_burst_stats; /**< Enables display of RX and TX bursts */
diff --git a/app/test-pmd/util.c b/app/test-pmd/util.c
index bf9b639d95..f277e7f035 100644
--- a/app/test-pmd/util.c
+++ b/app/test-pmd/util.c
@@ -5,9 +5,11 @@ 
 
 #include <stdio.h>
 
+#include <rte_atomic.h>
 #include <rte_bitops.h>
 #include <rte_net.h>
 #include <rte_mbuf.h>
+#include <rte_dissect.h>
 #include <rte_ether.h>
 #include <rte_vxlan.h>
 #include <rte_ethdev.h>
@@ -16,6 +18,7 @@ 
 #include "testpmd.h"
 
 #define MAX_STRING_LEN 8192
+#define MAX_DUMP_LEN   1024
 
 #define MKDUMPSTR(buf, buf_size, cur_len, ...) \
 do { \
@@ -67,9 +70,10 @@  get_timestamp(const struct rte_mbuf *mbuf)
 			timestamp_dynfield_offset, rte_mbuf_timestamp_t *);
 }
 
-static inline void
-dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
-	      uint16_t nb_pkts, int is_rx)
+/* More verbose older style packet decode */
+static void
+dump_pkt_verbose(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+		 uint16_t nb_pkts, int is_rx)
 {
 	struct rte_mbuf  *mb;
 	const struct rte_ether_hdr *eth_hdr;
@@ -90,8 +94,6 @@  dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
 	size_t cur_len = 0;
 	uint64_t restore_info_dynflag;
 
-	if (!nb_pkts)
-		return;
 	restore_info_dynflag = rte_flow_restore_info_dynflag();
 	MKDUMPSTR(print_buf, buf_size, cur_len,
 		  "port %u/queue %u: %s %u packets\n", port_id, queue,
@@ -299,6 +301,71 @@  dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
 	}
 }
 
+/* Brief tshark style one line output which is
+ * number time_delta Source Destination Protocol len info
+ */
+static void
+dump_pkt_brief(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[], uint16_t nb_pkts, int is_rx)
+{
+	static uint64_t start_cycles;
+	static RTE_ATOMIC(uint64_t) packet_count = 1;
+	uint64_t now;
+	uint64_t count;
+	double interval;
+	uint16_t i;
+
+	now = rte_rdtsc();
+	if (start_cycles == 0) {
+		start_cycles = now;
+		printf("Seq#   Time        Port:Que R Description\n");
+	}
+
+	interval = (double)(now - start_cycles) / (double)rte_get_tsc_hz();
+
+	count = rte_atomic_fetch_add_explicit(&packet_count, nb_pkts, rte_memory_order_relaxed);
+
+	for (i = 0; i < nb_pkts; i++) {
+		const struct rte_mbuf *mb = pkts[i];
+		char str[256];
+
+		rte_dissect_mbuf(str, sizeof(str), mb, 0);
+		printf("%6"PRIu64" %11.9f %4u:%-3u %c %s\n",
+		       count + i, interval, port, queue, is_rx ? 'R' : 'T', str);
+	}
+}
+
+/* Hex dump of packet data */
+static void
+dump_pkt_hex(struct rte_mbuf *pkts[], uint16_t nb_pkts)
+{
+	uint16_t i;
+
+	for (i = 0; i < nb_pkts; i++)
+		rte_pktmbuf_dump(stdout, pkts[i], MAX_DUMP_LEN);
+
+}
+
+static uint16_t
+dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+	      uint16_t nb_pkts, int is_rx)
+{
+	if (unlikely(nb_pkts == 0))
+		return 0;
+
+	switch (verbose_level) {
+	case VERBOSE_RX ... VERBOSE_BOTH:
+		dump_pkt_verbose(port_id, queue, pkts, nb_pkts, is_rx);
+		break;
+	case VERBOSE_DISSECT:
+		dump_pkt_brief(port_id, queue, pkts, nb_pkts, is_rx);
+		break;
+	case VERBOSE_HEX:
+		dump_pkt_hex(pkts, nb_pkts);
+	}
+	fflush(stdout);
+	return nb_pkts;
+}
+
 uint16_t
 dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
 	     uint16_t nb_pkts, __rte_unused uint16_t max_pkts,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f00ab07605..b9ce7698db 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -677,7 +677,10 @@  Available levels are as following:
 * ``0`` silent except for error.
 * ``1`` fully verbose except for Tx packets.
 * ``2`` fully verbose except for Rx packets.
-* ``> 2`` fully verbose.
+* ``3`` fully verbose except for Tx and Rx packets.
+* ``4`` dissected protocol information for Tx and Rx packets.
+* ``5`` hex dump of packets
+
 
 set log
 ~~~~~~~