Expand pcapng test coverage to exercise comment handling and
additional code paths:

* Add packet comments of varying lengths, including strings longer than
  256 bytes, to verify option block encoding.

* Vary packet sizes randomly to test different capture lengths

* Calculate inter-packet delays to ensure timestamp values wrap
  around 32 bits at least twice during the test.

* Add a statistics block write before packet capture.

* Use RFC 864 chargen pattern for predictable fill data.

Increase total packets from 4096 to 10000 and refactor mbuf
preparation for more flexible packet construction.

Signed-off-by: Stephen Hemminger <[email protected]>
---
 app/test/test_pcapng.c | 147 ++++++++++++++++++++++++++++++-----------
 1 file changed, 109 insertions(+), 38 deletions(-)

diff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c
index 5d362ec70e..e1f722791c 100644
--- a/app/test/test_pcapng.c
+++ b/app/test/test_pcapng.c
@@ -25,13 +25,11 @@
 
 #define PCAPNG_TEST_DEBUG 0
 
-#define TOTAL_PACKETS  4096
+#define TOTAL_PACKETS  10000
 #define MAX_BURST      64
-#define MAX_GAP_US     100000
-#define DUMMY_MBUF_NUM 3
+#define DUMMY_MBUF_NUM 2
 
 static struct rte_mempool *mp;
-static const uint32_t pkt_len = 200;
 static uint16_t port_id;
 static const char null_dev[] = "net_null0";
 
@@ -41,13 +39,36 @@ struct dummy_mbuf {
        uint8_t buf[DUMMY_MBUF_NUM][RTE_MBUF_DEFAULT_BUF_SIZE];
 };
 
+#define MAX_DATA_SIZE (RTE_MBUF_DEFAULT_BUF_SIZE - RTE_PKTMBUF_HEADROOM)
+
+/* RFC 864 chargen pattern used for comment testing */
+#define FILL_LINE_LENGTH 72
+#define FILL_START     0x21 /* ! */
+#define FILL_END       0x7e /* ~ */
+#define FILL_RANGE     (FILL_END - FILL_START)
+
 static void
-dummy_mbuf_prep(struct rte_mbuf *mb, uint8_t buf[], uint32_t buf_len,
-       uint32_t data_len)
+fill_mbuf(struct rte_mbuf *mb)
 {
-       uint32_t i;
-       uint8_t *db;
+       unsigned int len = rte_pktmbuf_tailroom(mb);
+       char *buf = rte_pktmbuf_append(mb, len);
+       unsigned int n = 0;
+
+       while (n < len - 1) {
+               char ch = FILL_START + (n % FILL_LINE_LENGTH) % FILL_RANGE;
+               for (unsigned int i = 0; i < FILL_LINE_LENGTH && n < len - 1; 
i++) {
+                       buf[n++] = ch;
+                       if (++ch == FILL_END)
+                               ch = FILL_START;
+               }
+               if (n < len - 1)
+                       buf[n++] = '\n';
+       }
+}
 
+static void
+dummy_mbuf_prep(struct rte_mbuf *mb, uint8_t buf[], uint32_t buf_len)
+{
        mb->buf_addr = buf;
        rte_mbuf_iova_set(mb, (uintptr_t)buf);
        mb->buf_len = buf_len;
@@ -57,15 +78,11 @@ dummy_mbuf_prep(struct rte_mbuf *mb, uint8_t buf[], 
uint32_t buf_len,
        mb->pool = (void *)buf;
 
        rte_pktmbuf_reset(mb);
-       db = (uint8_t *)rte_pktmbuf_append(mb, data_len);
-
-       for (i = 0; i != data_len; i++)
-               db[i] = i;
 }
 
 /* Make an IP packet consisting of chain of one packets */
 static void
-mbuf1_prepare(struct dummy_mbuf *dm, uint32_t plen)
+mbuf1_prepare(struct dummy_mbuf *dm)
 {
        struct {
                struct rte_ether_hdr eth;
@@ -84,32 +101,47 @@ mbuf1_prepare(struct dummy_mbuf *dm, uint32_t plen)
                        .dst_addr = rte_cpu_to_be_32(RTE_IPV4_BROADCAST),
                },
                .udp = {
+                       .src_port = rte_cpu_to_be_16(19), /* Chargen port */
                        .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);
+       dummy_mbuf_prep(&dm->mb[0], dm->buf[0], sizeof(dm->buf[0]));
+       dummy_mbuf_prep(&dm->mb[1], dm->buf[1], sizeof(dm->buf[1]));
 
        rte_eth_random_addr(pkt.eth.src_addr.addr_bytes);
-       plen -= sizeof(struct rte_ether_hdr);
+       memcpy(rte_pktmbuf_append(&dm->mb[0], sizeof(pkt)), &pkt, sizeof(pkt));
 
-       pkt.ip.total_length = rte_cpu_to_be_16(plen);
-       pkt.ip.hdr_checksum = rte_ipv4_cksum(&pkt.ip);
+       fill_mbuf(&dm->mb[1]);
+       rte_pktmbuf_chain(&dm->mb[0], &dm->mb[1]);
 
-       plen -= sizeof(struct rte_ipv4_hdr);
-       pkt.udp.src_port = rte_rand();
-       pkt.udp.dgram_len = rte_cpu_to_be_16(plen);
+       rte_mbuf_sanity_check(&dm->mb[0], 1);
+       rte_mbuf_sanity_check(&dm->mb[1], 0);
+}
 
-       memcpy(rte_pktmbuf_mtod(dm->mb, void *), &pkt, sizeof(pkt));
+static void
+mbuf1_resize(struct dummy_mbuf *dm, uint16_t len)
+{
+       struct {
+               struct rte_ether_hdr eth;
+               struct rte_ipv4_hdr ip;
+               struct rte_udp_hdr udp;
+       } *pkt = rte_pktmbuf_mtod(&dm->mb[0], void *);
 
-       /* Idea here is to create mbuf chain big enough that after mbuf deep 
copy they won't be
-        * compressed into single mbuf to properly test store of chained mbufs
-        */
-       dummy_mbuf_prep(&dm->mb[1], dm->buf[1], sizeof(dm->buf[1]), pkt_len);
-       dummy_mbuf_prep(&dm->mb[2], dm->buf[2], sizeof(dm->buf[2]), pkt_len);
-       rte_pktmbuf_chain(&dm->mb[0], &dm->mb[1]);
-       rte_pktmbuf_chain(&dm->mb[0], &dm->mb[2]);
+       dm->mb[1].data_len = len;
+       dm->mb[0].pkt_len = dm->mb[0].data_len + dm->mb[1].data_len;
+
+       len += sizeof(struct rte_udp_hdr);
+       pkt->udp.dgram_len = rte_cpu_to_be_16(len);
+
+       len += sizeof(struct rte_ipv4_hdr);
+       pkt->ip.total_length = rte_cpu_to_be_16(len);
+       pkt->ip.hdr_checksum = 0;
+       pkt->ip.hdr_checksum = rte_ipv4_cksum(&pkt->ip);
+
+       rte_mbuf_sanity_check(&dm->mb[0], 1);
+       rte_mbuf_sanity_check(&dm->mb[1], 0);
 }
 
 static int
@@ -126,7 +158,7 @@ test_setup(void)
        /* Make a pool for cloned packets */
        mp = rte_pktmbuf_pool_create_by_ops("pcapng_test_pool",
                                            MAX_BURST * 32, 0, 0,
-                                           rte_pcapng_mbuf_size(pkt_len) + 128,
+                                           rte_pcapng_mbuf_size(MAX_DATA_SIZE),
                                            SOCKET_ID_ANY, "ring_mp_sc");
        if (mp == NULL) {
                fprintf(stderr, "Cannot create mempool\n");
@@ -142,19 +174,44 @@ test_setup(void)
 }
 
 static int
-fill_pcapng_file(rte_pcapng_t *pcapng, unsigned int num_packets)
+fill_pcapng_file(rte_pcapng_t *pcapng)
 {
        struct dummy_mbuf mbfs;
        struct rte_mbuf *orig;
        unsigned int burst_size;
        unsigned int count;
        ssize_t len;
+       /*
+        * These are some silly comments to test various lengths and alignments 
sprinkle
+        * into the file. You can see these comments by using the dumpcap 
program on the file
+        */
+       static const char * const examples[] = {
+               "Lockless and fearless - that’s how we roll in userspace.",
+               "Memory pool deep / Mbufs swim in lockless rings / Zero copy 
dreams,",
+               "Poll mode driver waits / No interrupts disturb its zen / Busy 
loop finds peace,",
+               "Memory barriers / rte_atomic_thread_fence() / Guards our 
shared state",
+               "Hugepages so vast / Two megabytes of glory / TLB misses weep",
+               "Packets flow like streams / Through the graph node pipeline / 
Iterate in place",
+
+               /* Long one to make sure we can do > 256 characters */
+               ("Dear future maintainer: I am sorry. This packet was captured 
at 3 AM while "
+                "debugging a priority flow control issue that turned out to be 
a loose cable. "
+                "The rte_eth_tx_burst() call you see here has been 
cargo-culted through four "
+                "generations of example code. The magic number 32 is not 
documented because "
+                "nobody remembers why. Trust the process."),
+       };
+       /* How many microseconds does it take TSC to wrap around 32 bits */
+       const unsigned wrap_us
+               = (US_PER_S * (uint64_t)UINT32_MAX) / rte_get_tsc_hz();
 
-       /* make a dummy packet */
-       mbuf1_prepare(&mbfs, pkt_len);
+       /* Want overall test to take to wraparound at least twice. */
+       const unsigned int avg_gap = (2 * wrap_us)
+               / (TOTAL_PACKETS / (MAX_BURST / 2));
+
+       mbuf1_prepare(&mbfs);
        orig  = &mbfs.mb[0];
 
-       for (count = 0; count < num_packets; count += burst_size) {
+       for (count = 0; count < TOTAL_PACKETS; count += burst_size) {
                struct rte_mbuf *clones[MAX_BURST];
                unsigned int i;
 
@@ -162,9 +219,17 @@ fill_pcapng_file(rte_pcapng_t *pcapng, unsigned int 
num_packets)
                burst_size = rte_rand_max(MAX_BURST) + 1;
                for (i = 0; i < burst_size; i++) {
                        struct rte_mbuf *mc;
+                       const char *comment = NULL;
+
+                       /* Put randomized comment on every 100th packet (1%) */
+                       if (count % 100 == 0)
+                               comment = 
examples[rte_rand_max(RTE_DIM(examples))];
+
+                       /* Vary the size of the packets, okay to allow 0 sized 
packet */
+                       mbuf1_resize(&mbfs, rte_rand_max(MAX_DATA_SIZE));
 
                        mc = rte_pcapng_copy(port_id, 0, orig, mp, 
rte_pktmbuf_pkt_len(orig),
-                                            RTE_PCAPNG_DIRECTION_IN, NULL);
+                                            RTE_PCAPNG_DIRECTION_IN, comment);
                        if (mc == NULL) {
                                fprintf(stderr, "Cannot copy packet\n");
                                return -1;
@@ -182,8 +247,7 @@ fill_pcapng_file(rte_pcapng_t *pcapng, unsigned int 
num_packets)
                        return -1;
                }
 
-               /* Leave a small gap between packets to test for time wrap */
-               usleep(rte_rand_max(MAX_GAP_US));
+               rte_delay_us_block(rte_rand_max(2 * avg_gap));
        }
 
        return count;
@@ -386,7 +450,7 @@ static int
 test_write_packets(void)
 {
        char file_name[] = "/tmp/pcapng_test_XXXXXX.pcapng";
-       static rte_pcapng_t *pcapng;
+       rte_pcapng_t *pcapng = NULL;
        int ret, tmp_fd, count;
        uint64_t now = current_timestamp();
 
@@ -413,7 +477,14 @@ test_write_packets(void)
                goto fail;
        }
 
-       count = fill_pcapng_file(pcapng, TOTAL_PACKETS);
+       /* write a statistics block */
+       ret = rte_pcapng_write_stats(pcapng, port_id, 0, 0, NULL);
+       if (ret <= 0) {
+               fprintf(stderr, "Write of statistics failed\n");
+               goto fail;
+       }
+
+       count = fill_pcapng_file(pcapng);
        if (count < 0)
                goto fail;
 
-- 
2.51.0

Reply via email to