All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
	Reshma Pattan <reshma.pattan@intel.com>
Subject: [PATCH v2 4/4] test: cleanups to pcapng test
Date: Thu,  5 Oct 2023 16:06:48 -0700	[thread overview]
Message-ID: <20231005230648.68244-5-stephen@networkplumber.org> (raw)
In-Reply-To: <20231005230648.68244-1-stephen@networkplumber.org>

Overhaul of the pcapng test:
  - promote it to be a fast test so it gets regularly run.
  - create null device and use i.
  - use UDP discard packets that are valid so that for debugging
    the resulting pcapng file can be looked at with wireshark.
  - do basic checks on resulting pcap file that lengths and
    timestamps are in range.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/meson.build   |   2 +-
 app/test/test_pcapng.c | 378 ++++++++++++++++++++++++++---------------
 2 files changed, 242 insertions(+), 138 deletions(-)

diff --git a/app/test/meson.build b/app/test/meson.build
index bf9fc906128f..81d7c41a07cb 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -124,7 +124,7 @@ source_file_deps = {
     'test_meter.c': ['meter'],
     'test_metrics.c': ['metrics'],
     'test_mp_secondary.c': ['hash', 'lpm'],
-    'test_pcapng.c': ['ethdev', 'net', 'pcapng'],
+    'test_pcapng.c': ['ethdev', 'net', 'pcapng', 'bus_vdev'],
     'test_pdcp.c': ['eventdev', 'pdcp', 'net', 'timer', 'security'],
     'test_pdump.c': ['pdump'] + sample_packet_forward_deps,
     'test_per_lcore.c': [],
diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index 55aa2cf93666..45223ef38240 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -6,25 +6,34 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <rte_bus_vdev.h>
 #include <rte_ethdev.h>
 #include <rte_ether.h>
+#include <rte_ip.h>
 #include <rte_mbuf.h>
 #include <rte_mempool.h>
 #include <rte_net.h>
 #include <rte_pcapng.h>
+#include <rte_random.h>
+#include <rte_reciprocal.h>
+#include <rte_time.h>
+#include <rte_udp.h>
 
 #include <pcap/pcap.h>
 
 #include "test.h"
 
-#define NUM_PACKETS    10
-#define DUMMY_MBUF_NUM 3
+#define PCAPNG_TEST_DEBUG 0
+
+#define TOTAL_PACKETS	4096
+#define MAX_BURST	64
+#define MAX_GAP_US	100000
+#define DUMMY_MBUF_NUM	3
 
-static rte_pcapng_t *pcapng;
 static struct rte_mempool *mp;
 static const uint32_t pkt_len = 200;
 static uint16_t port_id;
-static char file_name[] = "/tmp/pcapng_test_XXXXXX.pcapng";
+static const char null_dev[] = "net_null0";
 
 /* first mbuf in the packet, should always be at offset 0 */
 struct dummy_mbuf {
@@ -61,6 +70,7 @@ mbuf1_prepare(struct dummy_mbuf *dm, uint32_t plen)
 	struct {
 		struct rte_ether_hdr eth;
 		struct rte_ipv4_hdr ip;
+		struct rte_udp_hdr udp;
 	} pkt = {
 		.eth = {
 			.dst_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
@@ -68,149 +78,226 @@ mbuf1_prepare(struct dummy_mbuf *dm, uint32_t plen)
 		},
 		.ip = {
 			.version_ihl = RTE_IPV4_VHL_DEF,
-			.total_length = rte_cpu_to_be_16(plen),
-			.time_to_live = IPDEFTTL,
-			.next_proto_id = IPPROTO_RAW,
+			.time_to_live = 1,
+			.next_proto_id = IPPROTO_UDP,
 			.src_addr = rte_cpu_to_be_32(RTE_IPV4_LOOPBACK),
 			.dst_addr = rte_cpu_to_be_32(RTE_IPV4_BROADCAST),
-		}
+		},
+		.udp = {
+			.dst_port = rte_cpu_to_be_16(9), /* Discard port */
+		},
 	};
 
 	memset(dm, 0, sizeof(*dm));
 	dummy_mbuf_prep(&dm->mb[0], dm->buf[0], sizeof(dm->buf[0]), plen);
 
 	rte_eth_random_addr(pkt.eth.src_addr.addr_bytes);
-	memcpy(rte_pktmbuf_mtod(dm->mb, void *), &pkt, RTE_MIN(sizeof(pkt), plen));
+	plen -= sizeof(struct rte_ether_hdr);
+
+	pkt.ip.total_length = rte_cpu_to_be_16(plen);
+	pkt.ip.hdr_checksum = rte_ipv4_cksum(&pkt.ip);
+
+	plen -= sizeof(struct rte_ipv4_hdr);
+	pkt.udp.src_port = rte_rand();
+	pkt.udp.dgram_len = rte_cpu_to_be_16(plen);
+
+	memcpy(rte_pktmbuf_mtod(dm->mb, void *), &pkt, sizeof(pkt));
 }
 
-static int
-test_setup(void)
+/*
+ * Make a timestamp value as used by PCAPNG file format
+ * The library uses nanosecond time resolution so this is
+ * time elapsed since 1970-01-01 00:00:00 UTC.
+ *
+ * Use the same way of calculating as in pdump library.
+ */
+static struct {
+	uint64_t offset_ns;	/* ns since 1/1/1970 when initialized */
+	uint64_t tsc_base;	/* TSC when initialized */
+	uint64_t tsc_hz;	/* copy of rte_tsc_hz() */
+	struct rte_reciprocal_u64 tsc_hz_inverse; /* inverse of tsc_hz */
+} time_base;
+
+static void timestamp_init(void)
 {
-	int tmp_fd;
+	struct timespec ts;
+	uint64_t cycles;
 
-	port_id = rte_eth_find_next(0);
-	if (port_id >= RTE_MAX_ETHPORTS) {
-		fprintf(stderr, "No valid Ether port\n");
-		return -1;
-	}
+	/* Compute time base offsets */
+	cycles = rte_get_tsc_cycles();
+	clock_gettime(CLOCK_REALTIME, &ts);
 
-	tmp_fd = mkstemps(file_name, strlen(".pcapng"));
-	if (tmp_fd == -1) {
-		perror("mkstemps() failure");
-		return -1;
-	}
-	printf("pcapng: output file %s\n", file_name);
+	/* put initial TSC value in middle of clock_gettime() call */
+	time_base.tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
+	time_base.offset_ns = rte_timespec_to_ns(&ts);
 
-	/* open a test capture file */
-	pcapng = rte_pcapng_fdopen(tmp_fd, NULL, NULL, "pcapng_test", NULL);
-	if (pcapng == NULL) {
-		fprintf(stderr, "rte_pcapng_fdopen failed\n");
-		close(tmp_fd);
-		return -1;
-	}
+	time_base.tsc_hz = rte_get_tsc_hz();
+	time_base.tsc_hz_inverse = rte_reciprocal_value_u64(time_base.tsc_hz);
+}
 
-	/* Add interface to the file */
-	if (rte_pcapng_add_interface(pcapng, port_id,
-				     NULL, NULL, NULL) != 0) {
-		fprintf(stderr, "can not add port %u\n", port_id);
-		return -1;
+static int
+test_setup(void)
+{
+	port_id = rte_eth_dev_count_avail();
+
+	/* Make a dummy null device to snoop on */
+	if (rte_vdev_init(null_dev, NULL) != 0) {
+		fprintf(stderr, "Failed to create vdev '%s'\n", null_dev);
+		goto fail;
 	}
 
 	/* Make a pool for cloned packets */
-	mp = rte_pktmbuf_pool_create_by_ops("pcapng_test_pool", IOV_MAX + NUM_PACKETS,
-					    0, 0,
-					    rte_pcapng_mbuf_size(pkt_len),
+	mp = rte_pktmbuf_pool_create_by_ops("pcapng_test_pool",
+					    MAX_BURST, 0, 0,
+					    rte_pcapng_mbuf_size(pkt_len) + 128,
 					    SOCKET_ID_ANY, "ring_mp_sc");
 	if (mp == NULL) {
 		fprintf(stderr, "Cannot create mempool\n");
-		return -1;
+		goto fail;
 	}
+
+	timestamp_init();
 	return 0;
+
+fail:
+	rte_vdev_uninit(null_dev);
+	rte_mempool_free(mp);
+	return -1;
 }
 
 static int
-test_write_packets(void)
+fill_pcapng_file(rte_pcapng_t *pcapng, unsigned int num_packets)
 {
-	struct rte_mbuf *orig;
-	struct rte_mbuf *clones[NUM_PACKETS] = { };
 	struct dummy_mbuf mbfs;
-	unsigned int i;
+	struct rte_mbuf *orig;
+	unsigned int burst_size;
+	unsigned int count;
 	ssize_t len;
 
 	/* make a dummy packet */
 	mbuf1_prepare(&mbfs, pkt_len);
-
-	/* clone them */
 	orig  = &mbfs.mb[0];
-	for (i = 0; i < NUM_PACKETS; i++) {
-		struct rte_mbuf *mc;
 
-		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0, NULL);
-		if (mc == NULL) {
-			fprintf(stderr, "Cannot copy packet\n");
+	for (count = 0; count < num_packets; count += burst_size) {
+		struct rte_mbuf *clones[MAX_BURST];
+		unsigned int i;
+
+		/* put 1 .. MAX_BURST packets in one write call */
+		burst_size = rte_rand_max(MAX_BURST) + 1;
+		for (i = 0; i < burst_size; i++) {
+			struct rte_mbuf *mc;
+
+			mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
+					     RTE_PCAPNG_DIRECTION_IN,
+					     NULL);
+			if (mc == NULL) {
+				fprintf(stderr, "Cannot copy packet\n");
+				return -1;
+			}
+			clones[i] = mc;
+		}
+
+		/* write it to capture file */
+		len = rte_pcapng_write_packets(pcapng, clones, burst_size);
+		rte_pktmbuf_free_bulk(clones, burst_size);
+
+		if (len <= 0) {
+			fprintf(stderr, "Write of packets failed: %s\n",
+				rte_strerror(rte_errno));
 			return -1;
 		}
-		clones[i] = mc;
+
+		/* Leave a small gap between packets to test for time wrap */
+		usleep(rte_rand_max(MAX_GAP_US));
 	}
 
-	/* write it to capture file */
-	len = rte_pcapng_write_packets(pcapng, clones, NUM_PACKETS);
+	return count;
+}
 
-	rte_pktmbuf_free_bulk(clones, NUM_PACKETS);
+static char *
+fmt_time(char *buf, size_t size, uint64_t ts_ns)
+{
+	time_t sec;
+	size_t len;
 
-	if (len <= 0) {
-		fprintf(stderr, "Write of packets failed\n");
-		return -1;
-	}
+	sec = ts_ns / NS_PER_S;
+	len = strftime(buf, size, "%X", localtime(&sec));
+	snprintf(buf + len, size - len, ".%09lu",
+		 (unsigned long)(ts_ns % NS_PER_S));
 
-	return 0;
+	return buf;
 }
 
-static int
-test_write_stats(void)
+/* Context for the pcap_loop callback */
+struct pkt_print_ctx {
+	pcap_t *pcap;
+	unsigned int count;
+};
+
+static void
+print_packet(uint64_t ts_ns, const struct rte_ether_hdr *eh, size_t len)
 {
-	ssize_t len;
+	char tbuf[128], src[64], dst[64];
 
-	/* write a statistics block */
-	len = rte_pcapng_write_stats(pcapng, port_id, NULL,
-				     0, 0, 0,
-				     NUM_PACKETS, 0);
-	if (len <= 0) {
-		fprintf(stderr, "Write of statistics failed\n");
-		return -1;
-	}
-	return 0;
+	fmt_time(tbuf, sizeof(tbuf), ts_ns);
+	rte_ether_format_addr(dst, sizeof(dst), &eh->dst_addr);
+	rte_ether_format_addr(src, sizeof(src), &eh->src_addr);
+	printf("%s: %s -> %s type %x length %zu\n",
+	       tbuf, src, dst, rte_be_to_cpu_16(eh->ether_type), len);
 }
 
+/* Callback from pcap_loop used to validate packets in the file */
 static void
-pkt_print(u_char *user, const struct pcap_pkthdr *h,
-	  const u_char *bytes)
+parse_pcap_packet(u_char *user, const struct pcap_pkthdr *h,
+		  const u_char *bytes)
 {
-	unsigned int *countp = (unsigned int *)user;
+	struct pkt_print_ctx *ctx = (struct pkt_print_ctx *)user;
 	const struct rte_ether_hdr *eh;
-	struct tm *tm;
-	char tbuf[128], src[64], dst[64];
+	const struct rte_ipv4_hdr *ip;
+	struct timespec ts;
+	uint64_t ns, now;
 
-	tm = localtime(&h->ts.tv_sec);
-	if (tm == NULL) {
-		perror("localtime");
-		return;
+	eh = (const struct rte_ether_hdr *)bytes;
+	ip = (const struct rte_ipv4_hdr *)(eh + 1);
+
+	ctx->count += 1;
+
+	clock_gettime(CLOCK_REALTIME, &ts);
+	now = rte_timespec_to_ns(&ts);
+
+	/* The pcap library is misleading in reporting timestamp.
+	 * packet header struct gives timestamp as a timeval (ie. usec);
+	 * but the file is open in nanonsecond mode therefore
+	 * the timestamp is really in timespec (ie. nanoseconds).
+	 */
+	ns = h->ts.tv_sec * NS_PER_S + h->ts.tv_usec;
+	if (ns < time_base.offset_ns || ns > now) {
+		char tstart[128], tend[128];
+
+		fmt_time(tstart, sizeof(tstart), time_base.offset_ns);
+		fmt_time(tend, sizeof(tend), now);
+		fprintf(stderr, "Timestamp out of range [%s .. %s]\n",
+			tstart, tend);
+		goto error;
 	}
 
-	if (strftime(tbuf, sizeof(tbuf), "%X", tm) == 0) {
-		fprintf(stderr, "strftime returned 0!\n");
-		return;
+	if (!rte_is_broadcast_ether_addr(&eh->dst_addr)) {
+		fprintf(stderr, "Destination is not broadcast\n");
+		goto error;
 	}
 
-	eh = (const struct rte_ether_hdr *)bytes;
-	rte_ether_format_addr(dst, sizeof(dst), &eh->dst_addr);
-	rte_ether_format_addr(src, sizeof(src), &eh->src_addr);
-	printf("%s.%06lu: %s -> %s type %x length %u\n",
-	       tbuf, (unsigned long)h->ts.tv_usec,
-	       src, dst, rte_be_to_cpu_16(eh->ether_type), h->len);
+	if (rte_ipv4_cksum(ip) != 0) {
+		fprintf(stderr, "Bad IPv4 checksum\n");
+		goto error;
+	}
+
+	return;		/* packet is normal */
 
-	*countp += 1;
+error:
+	print_packet(ns, eh, h->len);
+
+	/* Stop parsing at first error */
+	pcap_breakloop(ctx->pcap);
 }
 
 /*
@@ -219,78 +306,98 @@ pkt_print(u_char *user, const struct pcap_pkthdr *h,
  * but that creates an unwanted dependency.
  */
 static int
-test_validate(void)
+valid_pcapng_file(const char *file_name, unsigned int expected)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];
-	unsigned int count = 0;
-	pcap_t *pcap;
+	struct pkt_print_ctx ctx;
 	int ret;
 
-	pcap = pcap_open_offline(file_name, errbuf);
-	if (pcap == NULL) {
+	ctx.count = 0;
+	ctx.pcap = pcap_open_offline_with_tstamp_precision(file_name,
+							   PCAP_TSTAMP_PRECISION_NANO,
+							   errbuf);
+	if (ctx.pcap == NULL) {
 		fprintf(stderr, "pcap_open_offline('%s') failed: %s\n",
 			file_name, errbuf);
 		return -1;
 	}
 
-	ret = pcap_loop(pcap, 0, pkt_print, (u_char *)&count);
-	if (ret == 0)
-		printf("Saw %u packets\n", count);
-	else
+	ret = pcap_loop(ctx.pcap, 0, parse_pcap_packet, (u_char *)&ctx);
+	if (ret != 0) {
 		fprintf(stderr, "pcap_dispatch: failed: %s\n",
-			pcap_geterr(pcap));
-	pcap_close(pcap);
+			pcap_geterr(ctx.pcap));
+	} else if (ctx.count != expected) {
+		printf("Only %u packets, expected %u\n",
+		       ctx.count, expected);
+		ret = -1;
+	}
+
+	pcap_close(ctx.pcap);
 
 	return ret;
 }
 
 static int
-test_write_over_limit_iov_max(void)
+test_write_packets(void)
 {
-	struct rte_mbuf *orig;
-	struct rte_mbuf *clones[IOV_MAX + NUM_PACKETS] = { };
-	struct dummy_mbuf mbfs;
-	unsigned int i;
-	ssize_t len;
-
-	/* make a dummy packet */
-	mbuf1_prepare(&mbfs, pkt_len);
+	char file_name[] = "/tmp/pcapng_test_XXXXXX.pcapng";
+	static rte_pcapng_t *pcapng;
+	int ret, tmp_fd, count;
 
-	/* clone them */
-	orig  = &mbfs.mb[0];
-	for (i = 0; i < IOV_MAX + NUM_PACKETS; i++) {
-		struct rte_mbuf *mc;
+	tmp_fd = mkstemps(file_name, strlen(".pcapng"));
+	if (tmp_fd == -1) {
+		perror("mkstemps() failure");
+		goto fail;
+	}
+	printf("pcapng: output file %s\n", file_name);
 
-		mc = rte_pcapng_copy(port_id, 0, orig, mp, pkt_len,
-				rte_get_tsc_cycles(), 0, NULL);
-		if (mc == NULL) {
-			fprintf(stderr, "Cannot copy packet\n");
-			return -1;
-		}
-		clones[i] = mc;
+	/* open a test capture file */
+	pcapng = rte_pcapng_fdopen(tmp_fd, NULL, NULL, "pcapng_test", NULL);
+	if (pcapng == NULL) {
+		fprintf(stderr, "rte_pcapng_fdopen failed\n");
+		close(tmp_fd);
+		goto fail;
 	}
 
-	/* write it to capture file */
-	len = rte_pcapng_write_packets(pcapng, clones, IOV_MAX + NUM_PACKETS);
+	/* Add interface to the file */
+	ret = rte_pcapng_add_interface(pcapng, port_id,
+				       NULL, NULL, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "can not add port %u\n", port_id);
+		goto fail;
+	}
 
-	rte_pktmbuf_free_bulk(clones, IOV_MAX + NUM_PACKETS);
+	count = fill_pcapng_file(pcapng, TOTAL_PACKETS);
+	if (count < 0)
+		goto fail;
 
-	if (len <= 0) {
-		fprintf(stderr, "Write of packets failed\n");
-		return -1;
+	/* write a statistics block */
+	ret = rte_pcapng_write_stats(pcapng, port_id,
+				     count, 0, "end of test");
+	if (ret <= 0) {
+		fprintf(stderr, "Write of statistics failed\n");
+		goto fail;
 	}
 
-	return 0;
+	rte_pcapng_close(pcapng);
+
+	ret = valid_pcapng_file(file_name, count);
+	/* if test fails want to investigate the file */
+	if (ret == 0)
+		unlink(file_name);
+
+	return ret;
+
+fail:
+	rte_pcapng_close(pcapng);
+	return -1;
 }
 
 static void
 test_cleanup(void)
 {
 	rte_mempool_free(mp);
-
-	if (pcapng)
-		rte_pcapng_close(pcapng);
-
+	rte_vdev_uninit(null_dev);
 }
 
 static struct
@@ -300,9 +407,6 @@ unit_test_suite test_pcapng_suite  = {
 	.suite_name = "Test Pcapng Unit Test Suite",
 	.unit_test_cases = {
 		TEST_CASE(test_write_packets),
-		TEST_CASE(test_write_stats),
-		TEST_CASE(test_validate),
-		TEST_CASE(test_write_over_limit_iov_max),
 		TEST_CASES_END()
 	}
 };
@@ -313,4 +417,4 @@ test_pcapng(void)
 	return unit_test_suite_runner(&test_pcapng_suite);
 }
 
-REGISTER_TEST_COMMAND(pcapng_autotest, test_pcapng);
+REGISTER_FAST_TEST(pcapng_autotest, true, true, test_pcapng);
-- 
2.39.2


  parent reply	other threads:[~2023-10-05 23:07 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-21  4:23 [PATCH 0/4] pcapng fixes Stephen Hemminger
2023-09-21  4:23 ` [PATCH 1/4] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-09-21  4:23 ` [PATCH 2/4] dumpcap: allow multiple invocations Stephen Hemminger
2023-09-21  6:22   ` Morten Brørup
2023-09-21  7:10     ` Isaac Boukris
2023-11-07  2:34     ` Stephen Hemminger
2023-09-21  4:23 ` [PATCH 3/4] pcapng: change timestamp argument to write_stats Stephen Hemminger
2023-09-21  4:23 ` [PATCH 4/4] pcapng: move timestamp calculation into pdump Stephen Hemminger
2023-10-02  8:15   ` David Marchand
2023-10-04 17:13     ` Stephen Hemminger
2023-10-06  9:10       ` David Marchand
2023-10-06 14:59         ` Kevin Traynor
2023-10-05 23:06 ` [PATCH v2 0/4] dumpcap and pcapng fixes Stephen Hemminger
2023-10-05 23:06   ` [PATCH v2 1/4] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-10-05 23:06   ` [PATCH v2 2/4] dumpcap: allow multiple invocations Stephen Hemminger
2023-10-05 23:06   ` [PATCH v2 3/4] pcapng: modify timestamp calculation Stephen Hemminger
2023-10-05 23:06   ` Stephen Hemminger [this message]
2023-11-08 18:35 ` [PATCH v3 0/5] dumpcap and pcapng fixes Stephen Hemminger
2023-11-08 18:35   ` [PATCH v3 1/5] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-11-09  7:34     ` Morten Brørup
2023-11-08 18:35   ` [PATCH v3 2/5] dumpcap: allow multiple invocations Stephen Hemminger
2023-11-09  7:50     ` Morten Brørup
2023-11-09 15:40       ` Stephen Hemminger
2023-11-09 16:00         ` Morten Brørup
2023-11-09 17:16       ` Stephen Hemminger
2023-11-09 18:22         ` Morten Brørup
2023-11-08 18:35   ` [PATCH v3 3/5] pcapng: modify timestamp calculation Stephen Hemminger
2023-11-09  7:57     ` Morten Brørup
2023-11-08 18:35   ` [PATCH v3 4/5] pcapng: avoid using alloca() Stephen Hemminger
2023-11-09  8:21     ` Morten Brørup
2023-11-09 15:44       ` Stephen Hemminger
2023-11-09 16:25         ` Morten Brørup
2023-11-08 18:35   ` [PATCH v3 5/5] test: cleanups to pcapng test Stephen Hemminger
2023-11-09 17:34 ` [PATCH v4 0/5] dumpcap and pcapng fixes Stephen Hemminger
2023-11-09 17:34   ` [PATCH v4 1/5] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-11-09 17:34   ` [PATCH v4 2/5] dumpcap: allow multiple invocations Stephen Hemminger
2023-11-09 18:30     ` Morten Brørup
2023-11-09 17:34   ` [PATCH v4 3/5] pcapng: modify timestamp calculation Stephen Hemminger
2023-11-09 17:34   ` [PATCH v4 4/5] pcapng: avoid using alloca() Stephen Hemminger
2023-11-09 17:34   ` [PATCH v4 5/5] test: cleanups to pcapng test Stephen Hemminger
2023-11-09 19:45 ` [PATCH v5 0/5] dumpcap and pcapng fixes Stephen Hemminger
2023-11-09 19:45   ` [PATCH v5 1/5] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-11-09 19:45   ` [PATCH v5 2/5] dumpcap: allow multiple invocations Stephen Hemminger
2023-11-09 20:09     ` Morten Brørup
2023-11-09 19:45   ` [PATCH v5 3/5] pcapng: modify timestamp calculation Stephen Hemminger
2023-11-12 14:22     ` Thomas Monjalon
2023-11-09 19:45   ` [PATCH v5 4/5] pcapng: avoid using alloca() Stephen Hemminger
2023-11-09 19:45   ` [PATCH v5 5/5] test: cleanups to pcapng test Stephen Hemminger
2023-11-13 16:15 ` [PATCH v6 0/5] dumpcap and pcapng fixes Stephen Hemminger
2023-11-13 16:15   ` [PATCH v6 1/5] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-11-13 16:15   ` [PATCH v6 2/5] dumpcap: allow multiple invocations Stephen Hemminger
2023-11-13 16:15   ` [PATCH v6 3/5] pcapng: modify timestamp calculation Stephen Hemminger
2023-11-13 16:15   ` [PATCH v6 4/5] pcapng: avoid using alloca() Stephen Hemminger
2023-11-13 16:15   ` [PATCH v6 5/5] test: cleanups to pcapng test Stephen Hemminger
2023-11-17 16:35 ` [PATCH v7 0/5] dumpcap and pcapng fixes Stephen Hemminger
2023-11-17 16:35   ` [PATCH v7 1/5] pdump: fix setting rte_errno on mp error Stephen Hemminger
2023-11-17 16:35   ` [PATCH v7 2/5] dumpcap: allow multiple invocations Stephen Hemminger
2023-11-17 16:35   ` [PATCH v7 3/5] pcapng: modify timestamp calculation Stephen Hemminger
2023-11-17 16:35   ` [PATCH v7 4/5] pcapng: avoid using alloca() Stephen Hemminger
2023-11-17 16:35   ` [PATCH v7 5/5] test: cleanups to pcapng test Stephen Hemminger
2023-11-22 22:42   ` [PATCH v7 0/5] dumpcap and pcapng fixes Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231005230648.68244-5-stephen@networkplumber.org \
    --to=stephen@networkplumber.org \
    --cc=dev@dpdk.org \
    --cc=reshma.pattan@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.