[v3] app/testpmd: fix testpmd packets dump overlapping

Message ID 1605893733-84486-1-git-send-email-jiaweiw@nvidia.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series [v3] app/testpmd: fix testpmd packets dump overlapping |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/travis-robot success Travis build: passed

Commit Message

Jiawei Wang Nov. 20, 2020, 5:35 p.m. UTC
  When testpmd enabled the verbosity for the received packets, if two packets
were received at the same time, for example, sampling packet and normal
packet, the dump output of these packets may be overlapping due to multiple
core handling the multiple queues simultaneously.

The patch uses one string buffer that collects all the packet dump output
into this buffer and then printouts it at last, that guarantees to printout
separately the dump output per packet.

Fixes: d862c45 ("app/testpmd: move dumping packets to a separate function")

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
---
v3:
* Use the marco instead of function calls to simplfy code.
* Use the shorter chars '...' append into the dump to notify the truncation.
* Update the commit message.
* Rebase.

v2:
* Print dump output of per packet instead of per burst.
* Add the checking for return value of 'snprintf' and exit if required size exceed the print buffer size.
* Update the log messages.
---
 app/test-pmd/util.c | 177 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 117 insertions(+), 60 deletions(-)
  

Comments

Ferruh Yigit Nov. 20, 2020, 5:50 p.m. UTC | #1
On 11/20/2020 5:35 PM, Jiawei Wang wrote:
> When testpmd enabled the verbosity for the received packets, if two packets
> were received at the same time, for example, sampling packet and normal
> packet, the dump output of these packets may be overlapping due to multiple
> core handling the multiple queues simultaneously.
> 
> The patch uses one string buffer that collects all the packet dump output
> into this buffer and then printouts it at last, that guarantees to printout
> separately the dump output per packet.
> 
> Fixes: d862c45 ("app/testpmd: move dumping packets to a separate function")
> 
> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>

<...>

> @@ -74,13 +85,16 @@
>   	uint32_t vx_vni;
>   	const char *reason;
>   	int dynf_index;
> +	int buf_size = MAX_STRING_LEN;
> +	char print_buf[buf_size];
> +	int cur_len = 0;
>   
> +	memset(print_buf, 0, sizeof(print_buf));

Should 'print_buf' cleaned per each packet below, if not can we drop 'memset' 
completely?

<...>

> +		if (cur_len >= buf_size) {
> +			printf("%s ...\n", print_buf);
> +			break;

Why break here? Wouldn't just append some chars to indicate trancation and 
continue be OK?
  
Jiawei Wang Nov. 23, 2020, 6:13 a.m. UTC | #2
Hi Ferruh,

> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@intel.com>
> Sent: Saturday, November 21, 2020 1:50 AM
> To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>; wenzhuo.lu@intel.com;
> beilei.xing@intel.com; bernard.iremonger@intel.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-
> Contact-Thomas Monjalon <thomas@monjalon.net>; Raslan Darawsheh
> <rasland@nvidia.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3] app/testpmd: fix testpmd packets dump overlapping
> 
> On 11/20/2020 5:35 PM, Jiawei Wang wrote:
> > When testpmd enabled the verbosity for the received packets, if two
> > packets were received at the same time, for example, sampling packet
> > and normal packet, the dump output of these packets may be overlapping
> > due to multiple core handling the multiple queues simultaneously.
> >
> > The patch uses one string buffer that collects all the packet dump
> > output into this buffer and then printouts it at last, that guarantees
> > to printout separately the dump output per packet.
> >
> > Fixes: d862c45 ("app/testpmd: move dumping packets to a separate
> > function")
> >
> > Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> 
> <...>
> 
> > @@ -74,13 +85,16 @@
> >   	uint32_t vx_vni;
> >   	const char *reason;
> >   	int dynf_index;
> > +	int buf_size = MAX_STRING_LEN;
> > +	char print_buf[buf_size];
> > +	int cur_len = 0;
> >
> > +	memset(print_buf, 0, sizeof(print_buf));
> 
> Should 'print_buf' cleaned per each packet below, if not can we drop 'memset'
> completely?
> 
Since the 'snprintf' always append the a terminating null character('\0') after the written string,
and in the code the following character be appended start from previous null character, so only one 
'\0' will be appended in the last 'snprintf' calls, 
	snprintf(buf + cur_len, buf_size - cur_len ..
At the last 'printf("%s") will print the string buffer up to a terminating null character ('\0').
so it's ok even not 'memset' calls to clean 'print_buf' per each packets. 
> <...>
> 
> > +		if (cur_len >= buf_size) {
> > +			printf("%s ...\n", print_buf);
> > +			break;
> 
> Why break here? Wouldn't just append some chars to indicate trancation and
> continue be OK?
> 
> 
Yes, doesn't  need 'break'  here.
  
Ferruh Yigit Nov. 23, 2020, 10:22 a.m. UTC | #3
On 11/23/2020 6:13 AM, Jiawei(Jonny) Wang wrote:
> Hi Ferruh,
> 
>> -----Original Message-----
>> From: Ferruh Yigit <ferruh.yigit@intel.com>
>> Sent: Saturday, November 21, 2020 1:50 AM
>> To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>; wenzhuo.lu@intel.com;
>> beilei.xing@intel.com; bernard.iremonger@intel.com; Ori Kam
>> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-
>> Contact-Thomas Monjalon <thomas@monjalon.net>; Raslan Darawsheh
>> <rasland@nvidia.com>
>> Cc: dev@dpdk.org
>> Subject: Re: [PATCH v3] app/testpmd: fix testpmd packets dump overlapping
>>
>> On 11/20/2020 5:35 PM, Jiawei Wang wrote:
>>> When testpmd enabled the verbosity for the received packets, if two
>>> packets were received at the same time, for example, sampling packet
>>> and normal packet, the dump output of these packets may be overlapping
>>> due to multiple core handling the multiple queues simultaneously.
>>>
>>> The patch uses one string buffer that collects all the packet dump
>>> output into this buffer and then printouts it at last, that guarantees
>>> to printout separately the dump output per packet.
>>>
>>> Fixes: d862c45 ("app/testpmd: move dumping packets to a separate
>>> function")
>>>
>>> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
>>
>> <...>
>>
>>> @@ -74,13 +85,16 @@
>>>    	uint32_t vx_vni;
>>>    	const char *reason;
>>>    	int dynf_index;
>>> +	int buf_size = MAX_STRING_LEN;
>>> +	char print_buf[buf_size];
>>> +	int cur_len = 0;
>>>
>>> +	memset(print_buf, 0, sizeof(print_buf));
>>
>> Should 'print_buf' cleaned per each packet below, if not can we drop 'memset'
>> completely?
>>
> Since the 'snprintf' always append the a terminating null character('\0') after the written string,
> and in the code the following character be appended start from previous null character, so only one
> '\0' will be appended in the last 'snprintf' calls,
> 	snprintf(buf + cur_len, buf_size - cur_len ..
> At the last 'printf("%s") will print the string buffer up to a terminating null character ('\0').
> so it's ok even not 'memset' calls to clean 'print_buf' per each packets.

agree, so why not drop the memset completely?
  
Jiawei Wang Nov. 23, 2020, 11:03 a.m. UTC | #4
Hi Ferruh,

> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@intel.com>
> Sent: Monday, November 23, 2020 6:23 PM
> To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>; wenzhuo.lu@intel.com;
> beilei.xing@intel.com; bernard.iremonger@intel.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-
> Contact-Thomas Monjalon <thomas@monjalon.net>; Raslan Darawsheh
> <rasland@nvidia.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3] app/testpmd: fix testpmd packets dump overlapping
> 
> On 11/23/2020 6:13 AM, Jiawei(Jonny) Wang wrote:
> > Hi Ferruh,
> >
> >> -----Original Message-----
> >> From: Ferruh Yigit <ferruh.yigit@intel.com>
> >> Sent: Saturday, November 21, 2020 1:50 AM
> >> To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>; wenzhuo.lu@intel.com;
> >> beilei.xing@intel.com; bernard.iremonger@intel.com; Ori Kam
> >> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-
> >> Contact-Thomas Monjalon <thomas@monjalon.net>; Raslan Darawsheh
> >> <rasland@nvidia.com>
> >> Cc: dev@dpdk.org
> >> Subject: Re: [PATCH v3] app/testpmd: fix testpmd packets dump
> >> overlapping
> >>
> >> On 11/20/2020 5:35 PM, Jiawei Wang wrote:
> >>> When testpmd enabled the verbosity for the received packets, if two
> >>> packets were received at the same time, for example, sampling packet
> >>> and normal packet, the dump output of these packets may be
> >>> overlapping due to multiple core handling the multiple queues
> simultaneously.
> >>>
> >>> The patch uses one string buffer that collects all the packet dump
> >>> output into this buffer and then printouts it at last, that
> >>> guarantees to printout separately the dump output per packet.
> >>>
> >>> Fixes: d862c45 ("app/testpmd: move dumping packets to a separate
> >>> function")
> >>>
> >>> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> >>
> >> <...>
> >>
> >>> @@ -74,13 +85,16 @@
> >>>    	uint32_t vx_vni;
> >>>    	const char *reason;
> >>>    	int dynf_index;
> >>> +	int buf_size = MAX_STRING_LEN;
> >>> +	char print_buf[buf_size];
> >>> +	int cur_len = 0;
> >>>
> >>> +	memset(print_buf, 0, sizeof(print_buf));
> >>
> >> Should 'print_buf' cleaned per each packet below, if not can we drop
> 'memset'
> >> completely?
> >>
> > Since the 'snprintf' always append the a terminating null
> > character('\0') after the written string, and in the code the
> > following character be appended start from previous null character, so only
> one '\0' will be appended in the last 'snprintf' calls,
> > 	snprintf(buf + cur_len, buf_size - cur_len ..
> > At the last 'printf("%s") will print the string buffer up to a terminating null
> character ('\0').
> > so it's ok even not 'memset' calls to clean 'print_buf' per each packets.
> 
> agree, so why not drop the memset completely?
Yes, don't need memset before 'snprintf' calls, removed it in the latest patch: https://patchwork.dpdk.org/patch/84465/
Thanks.
  

Patch

diff --git a/app/test-pmd/util.c b/app/test-pmd/util.c
index 649bf8f..c92811f 100644
--- a/app/test-pmd/util.c
+++ b/app/test-pmd/util.c
@@ -15,12 +15,23 @@ 
 
 #include "testpmd.h"
 
+#define MAX_STRING_LEN 8192
+
+#define MKDUMPSTR(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)
+
 static inline void
-print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr)
+print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr,
+		 char print_buf[], int buf_size, int *cur_len)
 {
 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
+
 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
-	printf("%s%s", what, buf);
+	MKDUMPSTR(print_buf, buf_size, *cur_len, "%s%s", what, buf);
 }
 
 static inline bool
@@ -74,13 +85,16 @@ 
 	uint32_t vx_vni;
 	const char *reason;
 	int dynf_index;
+	int buf_size = MAX_STRING_LEN;
+	char print_buf[buf_size];
+	int cur_len = 0;
 
+	memset(print_buf, 0, sizeof(print_buf));
 	if (!nb_pkts)
 		return;
-	printf("port %u/queue %u: %s %u packets\n",
-		port_id, queue,
-	       is_rx ? "received" : "sent",
-	       (unsigned int) nb_pkts);
+	MKDUMPSTR(print_buf, buf_size, cur_len,
+		  "port %u/queue %u: %s %u packets\n", port_id, queue,
+		  is_rx ? "received" : "sent", (unsigned int) nb_pkts);
 	for (i = 0; i < nb_pkts; i++) {
 		int ret;
 		struct rte_flow_error error;
@@ -93,95 +107,128 @@ 
 		is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
 		ret = rte_flow_get_restore_info(port_id, mb, &info, &error);
 		if (!ret) {
-			printf("restore info:");
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  "restore info:");
 			if (info.flags & RTE_FLOW_RESTORE_INFO_TUNNEL) {
 				struct port_flow_tunnel *port_tunnel;
 
 				port_tunnel = port_flow_locate_tunnel
 					      (port_id, &info.tunnel);
-				printf(" - tunnel");
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - tunnel");
 				if (port_tunnel)
-					printf(" #%u", port_tunnel->id);
+					MKDUMPSTR(print_buf, buf_size, cur_len,
+						  " #%u", port_tunnel->id);
 				else
-					printf(" %s", "-none-");
-				printf(" type %s",
-					port_flow_tunnel_type(&info.tunnel));
+					MKDUMPSTR(print_buf, buf_size, cur_len,
+						  " %s", "-none-");
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " type %s", port_flow_tunnel_type
+					  (&info.tunnel));
 			} else {
-				printf(" - no tunnel info");
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - no tunnel info");
 			}
 			if (info.flags & RTE_FLOW_RESTORE_INFO_ENCAPSULATED)
-				printf(" - outer header present");
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - outer header present");
 			else
-				printf(" - no outer header");
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - no outer header");
 			if (info.flags & RTE_FLOW_RESTORE_INFO_GROUP_ID)
-				printf(" - miss group %u", info.group_id);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - miss group %u", info.group_id);
 			else
-				printf(" - no miss group");
-			printf("\n");
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - no miss group");
+			MKDUMPSTR(print_buf, buf_size, cur_len, "\n");
 		}
-		print_ether_addr("  src=", &eth_hdr->s_addr);
-		print_ether_addr(" - dst=", &eth_hdr->d_addr);
-		printf(" - type=0x%04x - length=%u - nb_segs=%d",
-		       eth_type, (unsigned int) mb->pkt_len,
-		       (int)mb->nb_segs);
+		print_ether_addr("  src=", &eth_hdr->s_addr,
+				 print_buf, buf_size, &cur_len);
+		print_ether_addr(" - dst=", &eth_hdr->d_addr,
+				 print_buf, buf_size, &cur_len);
+		MKDUMPSTR(print_buf, buf_size, cur_len,
+			  " - type=0x%04x - length=%u - nb_segs=%d",
+			  eth_type, (unsigned int) mb->pkt_len,
+			  (int)mb->nb_segs);
 		ol_flags = mb->ol_flags;
 		if (ol_flags & PKT_RX_RSS_HASH) {
-			printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss);
-			printf(" - RSS queue=0x%x", (unsigned int) queue);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - RSS hash=0x%x",
+				  (unsigned int) mb->hash.rss);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - RSS queue=0x%x", (unsigned int) queue);
 		}
 		if (ol_flags & PKT_RX_FDIR) {
-			printf(" - FDIR matched ");
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - FDIR matched ");
 			if (ol_flags & PKT_RX_FDIR_ID)
-				printf("ID=0x%x",
-				       mb->hash.fdir.hi);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  "ID=0x%x", mb->hash.fdir.hi);
 			else if (ol_flags & PKT_RX_FDIR_FLX)
-				printf("flex bytes=0x%08x %08x",
-				       mb->hash.fdir.hi, mb->hash.fdir.lo);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  "flex bytes=0x%08x %08x",
+					  mb->hash.fdir.hi, mb->hash.fdir.lo);
 			else
-				printf("hash=0x%x ID=0x%x ",
-				       mb->hash.fdir.hash, mb->hash.fdir.id);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  "hash=0x%x ID=0x%x ",
+					  mb->hash.fdir.hash, mb->hash.fdir.id);
 		}
 		if (is_timestamp_enabled(mb))
-			printf(" - timestamp %"PRIu64" ", get_timestamp(mb));
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - timestamp %"PRIu64" ", get_timestamp(mb));
 		if (ol_flags & PKT_RX_QINQ)
-			printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
-			       mb->vlan_tci, mb->vlan_tci_outer);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
+				  mb->vlan_tci, mb->vlan_tci_outer);
 		else if (ol_flags & PKT_RX_VLAN)
-			printf(" - VLAN tci=0x%x", mb->vlan_tci);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - VLAN tci=0x%x", mb->vlan_tci);
 		if (!is_rx && (ol_flags & PKT_TX_DYNF_METADATA))
-			printf(" - Tx metadata: 0x%x",
-			       *RTE_FLOW_DYNF_METADATA(mb));
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - Tx metadata: 0x%x",
+				  *RTE_FLOW_DYNF_METADATA(mb));
 		if (is_rx && (ol_flags & PKT_RX_DYNF_METADATA))
-			printf(" - Rx metadata: 0x%x",
-			       *RTE_FLOW_DYNF_METADATA(mb));
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - Rx metadata: 0x%x",
+				  *RTE_FLOW_DYNF_METADATA(mb));
 		for (dynf_index = 0; dynf_index < 64; dynf_index++) {
 			if (dynf_names[dynf_index][0] != '\0')
-				printf(" - dynf %s: %d",
-				       dynf_names[dynf_index],
-				       !!(ol_flags & (1UL << dynf_index)));
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - dynf %s: %d",
+					  dynf_names[dynf_index],
+					  !!(ol_flags & (1UL << dynf_index)));
 		}
 		if (mb->packet_type) {
 			rte_get_ptype_name(mb->packet_type, buf, sizeof(buf));
-			printf(" - hw ptype: %s", buf);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - hw ptype: %s", buf);
 		}
 		sw_packet_type = rte_net_get_ptype(mb, &hdr_lens,
 					RTE_PTYPE_ALL_MASK);
 		rte_get_ptype_name(sw_packet_type, buf, sizeof(buf));
-		printf(" - sw ptype: %s", buf);
+		MKDUMPSTR(print_buf, buf_size, cur_len, " - sw ptype: %s", buf);
 		if (sw_packet_type & RTE_PTYPE_L2_MASK)
-			printf(" - l2_len=%d", hdr_lens.l2_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len, " - l2_len=%d",
+				  hdr_lens.l2_len);
 		if (sw_packet_type & RTE_PTYPE_L3_MASK)
-			printf(" - l3_len=%d", hdr_lens.l3_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len, " - l3_len=%d",
+				  hdr_lens.l3_len);
 		if (sw_packet_type & RTE_PTYPE_L4_MASK)
-			printf(" - l4_len=%d", hdr_lens.l4_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len, " - l4_len=%d",
+				  hdr_lens.l4_len);
 		if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK)
-			printf(" - tunnel_len=%d", hdr_lens.tunnel_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - tunnel_len=%d", hdr_lens.tunnel_len);
 		if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK)
-			printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - inner_l2_len=%d", hdr_lens.inner_l2_len);
 		if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK)
-			printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - inner_l3_len=%d", hdr_lens.inner_l3_len);
 		if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK)
-			printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - inner_l4_len=%d", hdr_lens.inner_l4_len);
 		if (is_encapsulation) {
 			struct rte_ipv4_hdr *ipv4_hdr;
 			struct rte_ipv6_hdr *ipv6_hdr;
@@ -218,18 +265,28 @@ 
 				l2_len + l3_len + l4_len);
 				udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port);
 				vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni);
-				printf(" - VXLAN packet: packet type =%d, "
-				       "Destination UDP port =%d, VNI = %d",
-				       packet_type, udp_port, vx_vni >> 8);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - VXLAN packet: packet type =%d, "
+					  "Destination UDP port =%d, VNI = %d",
+					  packet_type, udp_port, vx_vni >> 8);
 			}
 		}
-		printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send",
-			(unsigned int) queue);
-		printf("\n");
+		MKDUMPSTR(print_buf, buf_size, cur_len,
+			  " - %s queue=0x%x", is_rx ? "Receive" : "Send",
+			  (unsigned int) queue);
+		MKDUMPSTR(print_buf, buf_size, cur_len, "\n");
 		rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf));
-		printf("  ol_flags: %s\n", buf);
+		MKDUMPSTR(print_buf, buf_size, cur_len,
+			  "  ol_flags: %s\n", buf);
 		if (rte_mbuf_check(mb, 1, &reason) < 0)
-			printf("INVALID mbuf: %s\n", reason);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  "INVALID mbuf: %s\n", reason);
+		if (cur_len >= buf_size) {
+			printf("%s ...\n", print_buf);
+			break;
+		}
+		printf("%s", print_buf);
+		cur_len = 0;
 	}
 }