There is no test coverage for rte_net_get_ptype. Add a test suite that
exercises plain Ethernet, single VLAN, QinQ, double VLAN, IPv4 with
options, IPv6, TCP and UDP combinations.

Signed-off-by: Robin Jarry <[email protected]>
---
 app/test/meson.build      |   1 +
 app/test/test_net_ptype.c | 231 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)
 create mode 100644 app/test/test_net_ptype.c

diff --git a/app/test/meson.build b/app/test/meson.build
index 7d458f9c079a..9f4afb040a46 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -135,6 +135,7 @@ source_file_deps = {
     'test_mp_secondary.c': ['hash'],
     'test_net_ether.c': ['net'],
     'test_net_ip6.c': ['net'],
+    'test_net_ptype.c': ['net'],
     'test_pcapng.c': ['net_null', 'net', 'ethdev', 'pcapng', 'bus_vdev'],
     'test_pdcp.c': ['eventdev', 'pdcp', 'net', 'timer', 'security'],
     'test_pdump.c': ['pdump'] + sample_packet_forward_deps,
diff --git a/app/test/test_net_ptype.c b/app/test/test_net_ptype.c
new file mode 100644
index 000000000000..bfe85da13543
--- /dev/null
+++ b/app/test/test_net_ptype.c
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2026 Red Hat, Inc.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <rte_mbuf.h>
+#include <rte_net.h>
+
+#include <rte_test.h>
+#include "test.h"
+
+#define MEMPOOL_CACHE_SIZE 0
+#define MBUF_DATA_SIZE 256
+#define NB_MBUF 128
+
+/* Ether()/IP()/UDP()/Raw('x') */
+static const uint8_t pkt_ether_ipv4_udp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
+       0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09,
+       0x89, 0x6f, 0x78,
+};
+
+/* Ether()/IP()/TCP() */
+static const uint8_t pkt_ether_ipv4_tcp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
+       0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
+       0x20, 0x00, 0x91, 0x7c, 0x00, 0x00,
+};
+
+/* Ether()/IPv6()/UDP()/Raw('x') */
+static const uint8_t pkt_ether_ipv6_udp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00,
+       0x00, 0x00, 0x00, 0x09, 0x11, 0x40, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35,
+       0x00, 0x35, 0x00, 0x09, 0x87, 0x70, 0x78,
+};
+
+/* Ether()/IPv6()/TCP() */
+static const uint8_t pkt_ether_ipv6_tcp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00,
+       0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14,
+       0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x8f, 0x7d,
+       0x00, 0x00,
+};
+
+/* Ether()/IP(options='\x00')/UDP()/Raw('x') -- ihl=6 */
+static const uint8_t pkt_ether_ipv4_opts_udp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x00,
+       0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
+       0x7b, 0xc9, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35,
+       0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78,
+};
+
+/* Ether()/Dot1Q(vlan=42)/IP()/UDP()/Raw('x') */
+static const uint8_t pkt_vlan_ipv4_udp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x2a,
+       0x08, 0x00, 0x45, 0x00, 0x00, 0x1d, 0x00, 0x01,
+       0x00, 0x00, 0x40, 0x11, 0x7c, 0xcd, 0x7f, 0x00,
+       0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x35,
+       0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78,
+};
+
+/* Ether()/Dot1Q(vlan=42)/IPv6()/TCP() */
+static const uint8_t pkt_vlan_ipv6_tcp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x2a,
+       0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x14,
+       0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
+       0x20, 0x00, 0x8f, 0x7d, 0x00, 0x00,
+};
+
+/* Ether()/Dot1AD(vlan=42)/Dot1Q(vlan=43)/IP()/UDP()/Raw('x') */
+static const uint8_t pkt_qinq_ipv4_udp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x88, 0xa8, 0x00, 0x2a,
+       0x81, 0x00, 0x00, 0x2b, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
+       0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09,
+       0x89, 0x6f, 0x78,
+};
+
+/* Ether()/Dot1Q(vlan=42)/Dot1Q(vlan=43)/IP()/UDP()/Raw('x') */
+static const uint8_t pkt_vlan_vlan_ipv4_udp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x2a,
+       0x81, 0x00, 0x00, 0x2b, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
+       0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09,
+       0x89, 0x6f, 0x78,
+};
+
+/* Ether()/Dot1AD(vlan=42)/Dot1Q(vlan=43)/IPv6()/TCP() */
+static const uint8_t pkt_qinq_ipv6_tcp[] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x88, 0xa8, 0x00, 0x2a,
+       0x81, 0x00, 0x00, 0x2b, 0x86, 0xdd, 0x60, 0x00,
+       0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14,
+       0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x8f, 0x7d,
+       0x00, 0x00,
+};
+
+static int
+test_get_ptype(struct rte_mempool *pool, const char *name,
+              const uint8_t *pktdata, size_t len, uint32_t expected_ptype,
+              uint8_t expected_l2_len, uint16_t expected_l3_len,
+              uint8_t expected_l4_len)
+{
+       struct rte_net_hdr_lens hdr_lens;
+       struct rte_mbuf *m;
+       uint32_t ptype;
+       char *data;
+
+       RTE_LOG(INFO, EAL, "%s: %s\n", __func__, name);
+
+       m = rte_pktmbuf_alloc(pool);
+       RTE_TEST_ASSERT_NOT_NULL(m, "cannot allocate mbuf");
+
+       data = rte_pktmbuf_append(m, len);
+       if (data == NULL) {
+               rte_pktmbuf_free(m);
+               RTE_TEST_ASSERT_NOT_NULL(data, "cannot append data");
+       }
+
+       memcpy(data, pktdata, len);
+
+       memset(&hdr_lens, 0, sizeof(hdr_lens));
+       ptype = rte_net_get_ptype(m, &hdr_lens, RTE_PTYPE_ALL_MASK);
+
+       rte_pktmbuf_free(m);
+
+       RTE_TEST_ASSERT_EQUAL(ptype, expected_ptype,
+               "unexpected ptype: got 0x%x, expected 0x%x",
+               ptype, expected_ptype);
+       RTE_TEST_ASSERT_EQUAL(hdr_lens.l2_len, expected_l2_len,
+               "unexpected l2_len: got %u, expected %u",
+               hdr_lens.l2_len, expected_l2_len);
+       RTE_TEST_ASSERT_EQUAL(hdr_lens.l3_len, expected_l3_len,
+               "unexpected l3_len: got %u, expected %u",
+               hdr_lens.l3_len, expected_l3_len);
+       RTE_TEST_ASSERT_EQUAL(hdr_lens.l4_len, expected_l4_len,
+               "unexpected l4_len: got %u, expected %u",
+               hdr_lens.l4_len, expected_l4_len);
+
+       return 0;
+}
+
+#define test_case(pool, pkt, expected_ptype, l2, l3, l4) \
+       test_get_ptype(pool, #pkt, pkt, sizeof(pkt), expected_ptype, l2, l3, l4)
+
+static int
+test_net_ptype(void)
+{
+       struct rte_mempool *pool;
+       int ret = 0;
+
+       pool = rte_pktmbuf_pool_create("test_ptype_mbuf_pool",
+                       NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
+                       SOCKET_ID_ANY);
+       RTE_TEST_ASSERT_NOT_NULL(pool, "cannot allocate mbuf pool");
+
+       ret |= test_case(pool, pkt_ether_ipv4_udp,
+                        RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | 
RTE_PTYPE_L4_UDP,
+                        14, 20, 8);
+       ret |= test_case(pool, pkt_ether_ipv4_tcp,
+                        RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | 
RTE_PTYPE_L4_TCP,
+                        14, 20, 20);
+       ret |= test_case(pool, pkt_ether_ipv6_udp,
+                        RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | 
RTE_PTYPE_L4_UDP,
+                        14, 40, 8);
+       ret |= test_case(pool, pkt_ether_ipv6_tcp,
+                        RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | 
RTE_PTYPE_L4_TCP,
+                        14, 40, 20);
+       ret |= test_case(pool, pkt_ether_ipv4_opts_udp,
+                        RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT | 
RTE_PTYPE_L4_UDP,
+                        14, 24, 8);
+       ret |= test_case(pool, pkt_vlan_ipv4_udp,
+                        RTE_PTYPE_L2_ETHER_VLAN | RTE_PTYPE_L3_IPV4 | 
RTE_PTYPE_L4_UDP,
+                        18, 20, 8);
+       ret |= test_case(pool, pkt_vlan_ipv6_tcp,
+                        RTE_PTYPE_L2_ETHER_VLAN | RTE_PTYPE_L3_IPV6 | 
RTE_PTYPE_L4_TCP,
+                        18, 40, 20);
+       ret |= test_case(pool, pkt_qinq_ipv4_udp,
+                        RTE_PTYPE_L2_ETHER_QINQ | RTE_PTYPE_L3_IPV4 | 
RTE_PTYPE_L4_UDP,
+                        22, 20, 8);
+       ret |= test_case(pool, pkt_vlan_vlan_ipv4_udp,
+                        RTE_PTYPE_L2_ETHER_VLAN | RTE_PTYPE_L3_IPV4 | 
RTE_PTYPE_L4_UDP,
+                        22, 20, 8);
+       ret |= test_case(pool, pkt_qinq_ipv6_tcp,
+                        RTE_PTYPE_L2_ETHER_QINQ | RTE_PTYPE_L3_IPV6 | 
RTE_PTYPE_L4_TCP,
+                        22, 40, 20);
+
+       rte_mempool_free(pool);
+
+       return ret;
+}
+
+REGISTER_FAST_TEST(net_ptype_autotest, NOHUGE_OK, ASAN_OK, test_net_ptype);
-- 
2.54.0

Reply via email to