Add autotest for the PTP library covering:
- Transport classification (L2, VLAN, QinQ, UDP/IPv4, UDP/IPv6)
- Message type parsing and string conversion
- Inline helpers (is_event, two_step, seq_id, version, domain)
- Correction field arithmetic (add, accumulate, negative values)
- Timestamp nanosecond conversion
- Flag field extraction (TWO_STEP, UNICAST, LI_61, LI_59)

Signed-off-by: Rajesh Kumar <[email protected]>
---
 MAINTAINERS          |    1 +
 app/test/meson.build |    1 +
 app/test/test_ptp.c  | 1106 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1108 insertions(+)
 create mode 100644 app/test/test_ptp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 665e08dc90..8d509cbe8e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1668,6 +1668,7 @@ F: app/test-sad/
 PTP - EXPERIMENTAL
 M: Rajesh Kumar <[email protected]>
 F: lib/ptp/
+F: app/test/test_ptp.c
 F: doc/guides/prog_guide/ptp_lib.rst
 F: examples/ptp_tap_relay_sw/
 F: doc/guides/sample_app_ug/ptp_tap_relay_sw.rst
diff --git a/app/test/meson.build b/app/test/meson.build
index 7d458f9c07..ecaa8d0839 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -154,6 +154,7 @@ source_file_deps = {
     'test_power_kvm_vm.c': ['power', 'power_kvm_vm'],
     'test_prefetch.c': [],
     'test_ptr_compress.c': ['ptr_compress'],
+    'test_ptp.c': ['ptp'],
     'test_rand_perf.c': [],
     'test_rawdev.c': ['rawdev', 'bus_vdev', 'raw_skeleton'],
     'test_rcu_qsbr.c': ['rcu', 'hash'],
diff --git a/app/test/test_ptp.c b/app/test/test_ptp.c
new file mode 100644
index 0000000000..803951b1fa
--- /dev/null
+++ b/app/test/test_ptp.c
@@ -0,0 +1,1106 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Intel Corporation
+ */
+
+#include "test.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <rte_mbuf.h>
+#include <rte_mempool.h>
+#include <rte_memory.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_byteorder.h>
+#include <rte_ptp.h>
+
+#define PTP_TEST_MP_NAME   "test_ptp_pool"
+#define PTP_TEST_MP_SIZE   63
+#define PTP_TEST_BUF_SIZE  RTE_MBUF_DEFAULT_BUF_SIZE
+
+static struct rte_mempool *ptp_mp;
+
+/* Helper: fill a minimal PTP header */
+static void
+fill_ptp_hdr(struct rte_ptp_hdr *ptp, uint8_t msg_type, uint16_t flags_host,
+            int64_t correction_scaled_ns, uint16_t seq_id)
+{
+       memset(ptp, 0, sizeof(*ptp));
+       ptp->msg_type = msg_type;
+       ptp->version = 0x02;
+       ptp->msg_length = rte_cpu_to_be_16(34);
+       ptp->flags = rte_cpu_to_be_16(flags_host);
+       ptp->correction = rte_cpu_to_be_64(correction_scaled_ns);
+       ptp->sequence_id = rte_cpu_to_be_16(seq_id);
+}
+
+/* ================================================================
+ *  Packet builders
+ * ================================================================
+ */
+
+static struct rte_mbuf *
+build_l2_ptp(uint8_t msg_type)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)
+               rte_pktmbuf_append(m, sizeof(*eth) + sizeof(struct 
rte_ptp_hdr));
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(0x88F7);
+
+       struct rte_ptp_hdr *ptp = (struct rte_ptp_hdr *)((uint8_t *)eth + 
sizeof(*eth));
+       fill_ptp_hdr(ptp, msg_type, RTE_PTP_FLAG_TWO_STEP, 0, 100);
+       return m;
+}
+
+/* Build L2 PTP with no TWO_STEP flag */
+static struct rte_mbuf *
+build_l2_ptp_noflags(uint8_t msg_type)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)
+               rte_pktmbuf_append(m, sizeof(*eth) + sizeof(struct 
rte_ptp_hdr));
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(0x88F7);
+
+       struct rte_ptp_hdr *ptp = (struct rte_ptp_hdr *)((uint8_t *)eth + 
sizeof(*eth));
+       fill_ptp_hdr(ptp, msg_type, 0, 0, 200);
+       return m;
+}
+
+static struct rte_mbuf *
+build_vlan_l2_ptp(uint8_t msg_type, uint16_t tpid)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_vlan_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(tpid);
+
+       struct rte_vlan_hdr *vlan = (struct rte_vlan_hdr *)(data + 
sizeof(*eth));
+       vlan->vlan_tci = rte_cpu_to_be_16(100);
+       vlan->eth_proto = rte_cpu_to_be_16(0x88F7);
+
+       struct rte_ptp_hdr *ptp = (struct rte_ptp_hdr *)
+               (data + sizeof(*eth) + sizeof(*vlan));
+       fill_ptp_hdr(ptp, msg_type, 0, 0, 200);
+       return m;
+}
+
+static struct rte_mbuf *
+build_qinq_l2_ptp(uint8_t msg_type, uint16_t outer_tpid, uint16_t inner_tpid)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          2 * sizeof(struct rte_vlan_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(outer_tpid);
+
+       uint32_t off = sizeof(*eth);
+       struct rte_vlan_hdr *vo = (struct rte_vlan_hdr *)(data + off);
+       vo->vlan_tci = rte_cpu_to_be_16(200);
+       vo->eth_proto = rte_cpu_to_be_16(inner_tpid);
+       off += sizeof(*vo);
+
+       struct rte_vlan_hdr *vi = (struct rte_vlan_hdr *)(data + off);
+       vi->vlan_tci = rte_cpu_to_be_16(300);
+       vi->eth_proto = rte_cpu_to_be_16(0x88F7);
+       off += sizeof(*vi);
+
+       struct rte_ptp_hdr *ptp = (struct rte_ptp_hdr *)(data + off);
+       fill_ptp_hdr(ptp, msg_type, 0, 0, 300);
+       return m;
+}
+
+/* Helper: append IPv4 + UDP + PTP after offset */
+static void
+fill_ipv4_udp_ptp(uint8_t *data, uint32_t off, uint8_t msg_type,
+                 uint16_t dst_port, uint16_t seq_id)
+{
+       struct rte_ipv4_hdr *iph = (struct rte_ipv4_hdr *)(data + off);
+       memset(iph, 0, sizeof(*iph));
+       iph->version_ihl = 0x45;
+       iph->next_proto_id = IPPROTO_UDP;
+       iph->total_length = rte_cpu_to_be_16(
+               sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr) +
+               sizeof(struct rte_ptp_hdr));
+       iph->src_addr = rte_cpu_to_be_32(0x0A000001);
+       iph->dst_addr = rte_cpu_to_be_32(0xE0000181);
+       off += sizeof(*iph);
+
+       struct rte_udp_hdr *udp = (struct rte_udp_hdr *)(data + off);
+       memset(udp, 0, sizeof(*udp));
+       udp->src_port = rte_cpu_to_be_16(12345);
+       udp->dst_port = rte_cpu_to_be_16(dst_port);
+       udp->dgram_len = rte_cpu_to_be_16(sizeof(*udp) +
+               sizeof(struct rte_ptp_hdr));
+       off += sizeof(*udp);
+
+       struct rte_ptp_hdr *ptp = (struct rte_ptp_hdr *)(data + off);
+       fill_ptp_hdr(ptp, msg_type, 0, 0, seq_id);
+}
+
+static struct rte_mbuf *
+build_ipv4_udp_ptp(uint8_t msg_type, uint16_t dst_port)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_ipv4_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+       fill_ipv4_udp_ptp(data, sizeof(*eth), msg_type, dst_port, 400);
+       return m;
+}
+
+static struct rte_mbuf *
+build_vlan_ipv4_udp_ptp(uint8_t msg_type, uint16_t dst_port)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_vlan_hdr) +
+                          sizeof(struct rte_ipv4_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+
+       uint32_t off = sizeof(*eth);
+       struct rte_vlan_hdr *vlan = (struct rte_vlan_hdr *)(data + off);
+       vlan->vlan_tci = rte_cpu_to_be_16(100);
+       vlan->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+       off += sizeof(*vlan);
+
+       fill_ipv4_udp_ptp(data, off, msg_type, dst_port, 500);
+       return m;
+}
+
+static struct rte_mbuf *
+build_qinq_ipv4_udp_ptp(uint8_t msg_type, uint16_t dst_port)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          2 * sizeof(struct rte_vlan_hdr) +
+                          sizeof(struct rte_ipv4_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ);
+
+       uint32_t off = sizeof(*eth);
+       struct rte_vlan_hdr *vo = (struct rte_vlan_hdr *)(data + off);
+       vo->vlan_tci = rte_cpu_to_be_16(200);
+       vo->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+       off += sizeof(*vo);
+
+       struct rte_vlan_hdr *vi = (struct rte_vlan_hdr *)(data + off);
+       vi->vlan_tci = rte_cpu_to_be_16(300);
+       vi->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+       off += sizeof(*vi);
+
+       fill_ipv4_udp_ptp(data, off, msg_type, dst_port, 600);
+       return m;
+}
+
+/* Helper: append IPv6 + UDP + PTP */
+static void
+fill_ipv6_udp_ptp(uint8_t *data, uint32_t off, uint8_t msg_type,
+                 uint16_t dst_port, uint16_t seq_id)
+{
+       struct rte_ipv6_hdr *ip6 = (struct rte_ipv6_hdr *)(data + off);
+       memset(ip6, 0, sizeof(*ip6));
+       ip6->vtc_flow = rte_cpu_to_be_32(0x60000000);
+       ip6->payload_len = rte_cpu_to_be_16(
+               sizeof(struct rte_udp_hdr) + sizeof(struct rte_ptp_hdr));
+       ip6->proto = IPPROTO_UDP;
+       ip6->hop_limits = 64;
+       off += sizeof(*ip6);
+
+       struct rte_udp_hdr *udp = (struct rte_udp_hdr *)(data + off);
+       memset(udp, 0, sizeof(*udp));
+       udp->src_port = rte_cpu_to_be_16(12345);
+       udp->dst_port = rte_cpu_to_be_16(dst_port);
+       udp->dgram_len = rte_cpu_to_be_16(sizeof(*udp) +
+               sizeof(struct rte_ptp_hdr));
+       off += sizeof(*udp);
+
+       struct rte_ptp_hdr *ptp = (struct rte_ptp_hdr *)(data + off);
+       fill_ptp_hdr(ptp, msg_type, 0, 0, seq_id);
+}
+
+static struct rte_mbuf *
+build_ipv6_udp_ptp(uint8_t msg_type, uint16_t dst_port)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_ipv6_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+
+       fill_ipv6_udp_ptp(data, sizeof(*eth), msg_type, dst_port, 700);
+       return m;
+}
+
+static struct rte_mbuf *
+build_vlan_ipv6_udp_ptp(uint8_t msg_type, uint16_t dst_port)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_vlan_hdr) +
+                          sizeof(struct rte_ipv6_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+
+       uint32_t off = sizeof(*eth);
+       struct rte_vlan_hdr *vlan = (struct rte_vlan_hdr *)(data + off);
+       vlan->vlan_tci = rte_cpu_to_be_16(100);
+       vlan->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+       off += sizeof(*vlan);
+
+       fill_ipv6_udp_ptp(data, off, msg_type, dst_port, 800);
+       return m;
+}
+
+static struct rte_mbuf *
+build_qinq_ipv6_udp_ptp(uint8_t msg_type, uint16_t dst_port)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          2 * sizeof(struct rte_vlan_hdr) +
+                          sizeof(struct rte_ipv6_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ);
+
+       uint32_t off = sizeof(*eth);
+       struct rte_vlan_hdr *vo = (struct rte_vlan_hdr *)(data + off);
+       vo->vlan_tci = rte_cpu_to_be_16(200);
+       vo->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+       off += sizeof(*vo);
+
+       struct rte_vlan_hdr *vi = (struct rte_vlan_hdr *)(data + off);
+       vi->vlan_tci = rte_cpu_to_be_16(300);
+       vi->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+       off += sizeof(*vi);
+
+       fill_ipv6_udp_ptp(data, off, msg_type, dst_port, 900);
+       return m;
+}
+
+static struct rte_mbuf *
+build_non_ptp(void)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) + 28;
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(data, 0, pkt_len);
+       eth->ether_type = rte_cpu_to_be_16(0x0806);
+       return m;
+}
+
+static struct rte_mbuf *
+build_ipv4_udp_non_ptp(void)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       if (!m)
+               return NULL;
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_ipv4_hdr) +
+                          sizeof(struct rte_udp_hdr) + 20;
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(data, 0, pkt_len);
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+       struct rte_ipv4_hdr *iph = (struct rte_ipv4_hdr *)(data + sizeof(*eth));
+       iph->version_ihl = 0x45;
+       iph->next_proto_id = IPPROTO_UDP;
+       iph->total_length = rte_cpu_to_be_16(
+               sizeof(*iph) + sizeof(struct rte_udp_hdr) + 20);
+
+       struct rte_udp_hdr *udp = (struct rte_udp_hdr *)
+               (data + sizeof(*eth) + sizeof(*iph));
+       udp->dst_port = rte_cpu_to_be_16(53);
+       return m;
+}
+
+/* ================================================================
+ *  Individual test cases
+ * ================================================================
+ */
+
+/* Helper: classify + hdr_get for a given mbuf */
+static int
+check_classify_and_hdr_get(struct rte_mbuf *m, int expected_type)
+{
+       int ret;
+
+       TEST_ASSERT_NOT_NULL(m, "mbuf allocation failed");
+
+       ret = rte_ptp_classify(m);
+       TEST_ASSERT_EQUAL(ret, expected_type,
+               "classify: expected %d, got %d", expected_type, ret);
+
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       if (expected_type == RTE_PTP_MSGTYPE_INVALID) {
+               TEST_ASSERT_NULL(hdr,
+                       "hdr_get: expected NULL for non-PTP packet");
+       } else {
+               TEST_ASSERT_NOT_NULL(hdr,
+                       "hdr_get: expected non-NULL for PTP packet");
+               TEST_ASSERT_EQUAL(rte_ptp_msg_type(hdr),
+                       (uint8_t)expected_type,
+                       "hdr_get: msg_type mismatch: expected %d, got %d",
+                       expected_type, rte_ptp_msg_type(hdr));
+       }
+
+       rte_pktmbuf_free(m);
+       return TEST_SUCCESS;
+}
+
+/* Section 1: Transport classification */
+static int
+test_ptp_classify_l2(void)
+{
+       return check_classify_and_hdr_get(
+               build_l2_ptp(RTE_PTP_MSGTYPE_SYNC), RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_l2_delay_req(void)
+{
+       return check_classify_and_hdr_get(
+               build_l2_ptp(RTE_PTP_MSGTYPE_DELAY_REQ),
+               RTE_PTP_MSGTYPE_DELAY_REQ);
+}
+
+static int
+test_ptp_classify_vlan_8100(void)
+{
+       return check_classify_and_hdr_get(
+               build_vlan_l2_ptp(RTE_PTP_MSGTYPE_SYNC, RTE_ETHER_TYPE_VLAN),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_vlan_88a8(void)
+{
+       return check_classify_and_hdr_get(
+               build_vlan_l2_ptp(RTE_PTP_MSGTYPE_SYNC, RTE_ETHER_TYPE_QINQ),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_qinq(void)
+{
+       return check_classify_and_hdr_get(
+               build_qinq_l2_ptp(RTE_PTP_MSGTYPE_SYNC,
+                       RTE_ETHER_TYPE_QINQ, RTE_ETHER_TYPE_VLAN),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_double_8100(void)
+{
+       return check_classify_and_hdr_get(
+               build_qinq_l2_ptp(RTE_PTP_MSGTYPE_SYNC,
+                       RTE_ETHER_TYPE_VLAN, RTE_ETHER_TYPE_VLAN),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_ipv4_udp_319(void)
+{
+       return check_classify_and_hdr_get(
+               build_ipv4_udp_ptp(RTE_PTP_MSGTYPE_SYNC, 319),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_ipv4_udp_320(void)
+{
+       return check_classify_and_hdr_get(
+               build_ipv4_udp_ptp(RTE_PTP_MSGTYPE_FOLLOW_UP, 320),
+               RTE_PTP_MSGTYPE_FOLLOW_UP);
+}
+
+static int
+test_ptp_classify_vlan_ipv4_udp(void)
+{
+       return check_classify_and_hdr_get(
+               build_vlan_ipv4_udp_ptp(RTE_PTP_MSGTYPE_SYNC, 319),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_qinq_ipv4_udp(void)
+{
+       return check_classify_and_hdr_get(
+               build_qinq_ipv4_udp_ptp(RTE_PTP_MSGTYPE_SYNC, 319),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_ipv6_udp_319(void)
+{
+       return check_classify_and_hdr_get(
+               build_ipv6_udp_ptp(RTE_PTP_MSGTYPE_SYNC, 319),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_ipv6_udp_320(void)
+{
+       return check_classify_and_hdr_get(
+               build_ipv6_udp_ptp(RTE_PTP_MSGTYPE_FOLLOW_UP, 320),
+               RTE_PTP_MSGTYPE_FOLLOW_UP);
+}
+
+static int
+test_ptp_classify_vlan_ipv6_udp(void)
+{
+       return check_classify_and_hdr_get(
+               build_vlan_ipv6_udp_ptp(RTE_PTP_MSGTYPE_SYNC, 319),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_qinq_ipv6_udp(void)
+{
+       return check_classify_and_hdr_get(
+               build_qinq_ipv6_udp_ptp(RTE_PTP_MSGTYPE_SYNC, 319),
+               RTE_PTP_MSGTYPE_SYNC);
+}
+
+static int
+test_ptp_classify_non_ptp_arp(void)
+{
+       return check_classify_and_hdr_get(
+               build_non_ptp(), RTE_PTP_MSGTYPE_INVALID);
+}
+
+static int
+test_ptp_classify_non_ptp_udp(void)
+{
+       return check_classify_and_hdr_get(
+               build_ipv4_udp_non_ptp(), RTE_PTP_MSGTYPE_INVALID);
+}
+
+/* IPv4 with invalid IHL (< 5) should be rejected */
+static int
+test_ptp_classify_ipv4_bad_ihl(void)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+
+       uint32_t pkt_len = sizeof(struct rte_ether_hdr) +
+                          sizeof(struct rte_ipv4_hdr) +
+                          sizeof(struct rte_udp_hdr) +
+                          sizeof(struct rte_ptp_hdr);
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+       fill_ipv4_udp_ptp(data, sizeof(*eth), RTE_PTP_MSGTYPE_SYNC, 319, 999);
+
+       /* Corrupt the IHL to 3 (< minimum 5) */
+       struct rte_ipv4_hdr *iph = (struct rte_ipv4_hdr *)
+               (data + sizeof(*eth));
+       iph->version_ihl = 0x43;
+
+       return check_classify_and_hdr_get(m, RTE_PTP_MSGTYPE_INVALID);
+}
+
+/* IPv4 with options (IHL > 5) should still be parsed correctly */
+static int
+test_ptp_classify_ipv4_options(void)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+       uint32_t pkt_len;
+       uint32_t off;
+       uint8_t *data;
+       struct rte_ether_hdr *eth;
+       struct rte_ipv4_hdr *iph;
+       struct rte_udp_hdr *udp;
+       struct rte_ptp_hdr *ptp;
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+
+       pkt_len = sizeof(struct rte_ether_hdr) +
+                       sizeof(struct rte_ipv4_hdr) + 4 +
+                       sizeof(struct rte_udp_hdr) +
+                       sizeof(struct rte_ptp_hdr);
+       data = (uint8_t *)rte_pktmbuf_append(m, pkt_len);
+       TEST_ASSERT_NOT_NULL(data, "append failed");
+
+       eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+       off = sizeof(*eth);
+       iph = (struct rte_ipv4_hdr *)(data + off);
+       memset(iph, 0, sizeof(*iph));
+       iph->version_ihl = 0x46; /* IHL = 6 words = 24 bytes */
+       iph->next_proto_id = IPPROTO_UDP;
+       iph->total_length = rte_cpu_to_be_16(sizeof(struct rte_ipv4_hdr) + 4 +
+                       sizeof(struct rte_udp_hdr) + sizeof(struct 
rte_ptp_hdr));
+       iph->src_addr = rte_cpu_to_be_32(0x0A000001);
+       iph->dst_addr = rte_cpu_to_be_32(0xE0000181);
+       off += sizeof(*iph);
+
+       memset(data + off, 0, 4); /* IPv4 options bytes */
+       off += 4;
+
+       udp = (struct rte_udp_hdr *)(data + off);
+       memset(udp, 0, sizeof(*udp));
+       udp->src_port = rte_cpu_to_be_16(12345);
+       udp->dst_port = rte_cpu_to_be_16(RTE_PTP_EVENT_PORT);
+       udp->dgram_len = rte_cpu_to_be_16(sizeof(*udp) + sizeof(struct 
rte_ptp_hdr));
+       off += sizeof(*udp);
+
+       ptp = (struct rte_ptp_hdr *)(data + off);
+       fill_ptp_hdr(ptp, RTE_PTP_MSGTYPE_SYNC, 0, 0, 1001);
+
+       return check_classify_and_hdr_get(m, RTE_PTP_MSGTYPE_SYNC);
+}
+
+/* Truncated packet: Ethernet header only, no payload */
+static int
+test_ptp_classify_truncated(void)
+{
+       struct rte_mbuf *m = rte_pktmbuf_alloc(ptp_mp);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+
+       uint8_t *data = (uint8_t *)rte_pktmbuf_append(m,
+               sizeof(struct rte_ether_hdr));
+       struct rte_ether_hdr *eth = (struct rte_ether_hdr *)data;
+       memset(eth, 0, sizeof(*eth));
+       eth->ether_type = rte_cpu_to_be_16(0x88F7);
+
+       return check_classify_and_hdr_get(m, RTE_PTP_MSGTYPE_INVALID);
+}
+
+/* Section 2: All 10 message types via L2 */
+static int
+test_ptp_all_msg_types(void)
+{
+       static const uint8_t types[] = {
+               RTE_PTP_MSGTYPE_SYNC,
+               RTE_PTP_MSGTYPE_DELAY_REQ,
+               RTE_PTP_MSGTYPE_PDELAY_REQ,
+               RTE_PTP_MSGTYPE_PDELAY_RESP,
+               RTE_PTP_MSGTYPE_FOLLOW_UP,
+               RTE_PTP_MSGTYPE_DELAY_RESP,
+               RTE_PTP_MSGTYPE_PDELAY_RESP_FU,
+               RTE_PTP_MSGTYPE_ANNOUNCE,
+               RTE_PTP_MSGTYPE_SIGNALING,
+               RTE_PTP_MSGTYPE_MANAGEMENT,
+       };
+       unsigned int i;
+
+       for (i = 0; i < RTE_DIM(types); i++) {
+               int ret = check_classify_and_hdr_get(
+                       build_l2_ptp(types[i]), types[i]);
+               if (ret != TEST_SUCCESS)
+                       return ret;
+       }
+
+       return TEST_SUCCESS;
+}
+
+/* Section 3: Inline helpers */
+static int
+test_ptp_is_event(void)
+{
+       TEST_ASSERT(rte_ptp_is_event(RTE_PTP_MSGTYPE_SYNC),
+               "Sync should be event");
+       TEST_ASSERT(rte_ptp_is_event(RTE_PTP_MSGTYPE_DELAY_REQ),
+               "Delay_Req should be event");
+       TEST_ASSERT(rte_ptp_is_event(RTE_PTP_MSGTYPE_PDELAY_REQ),
+               "Pdelay_Req should be event");
+       TEST_ASSERT(rte_ptp_is_event(RTE_PTP_MSGTYPE_PDELAY_RESP),
+               "Pdelay_Resp should be event");
+       TEST_ASSERT(!rte_ptp_is_event(RTE_PTP_MSGTYPE_FOLLOW_UP),
+               "Follow_Up should not be event");
+       TEST_ASSERT(!rte_ptp_is_event(RTE_PTP_MSGTYPE_ANNOUNCE),
+               "Announce should not be event");
+       TEST_ASSERT(!rte_ptp_is_event(RTE_PTP_MSGTYPE_INVALID),
+               "INVALID (-1) should not be event");
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_two_step(void)
+{
+       struct rte_mbuf *m;
+       struct rte_ptp_hdr *hdr;
+
+       m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+       TEST_ASSERT(rte_ptp_is_two_step(hdr),
+               "TWO_STEP flag should be set");
+       rte_pktmbuf_free(m);
+
+       m = build_l2_ptp_noflags(RTE_PTP_MSGTYPE_SYNC);
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+       TEST_ASSERT(!rte_ptp_is_two_step(hdr),
+               "TWO_STEP flag should not be set");
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_seq_id(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+       TEST_ASSERT_EQUAL(rte_ptp_seq_id(hdr), 100,
+               "seq_id: expected 100, got %u", rte_ptp_seq_id(hdr));
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_version(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+       TEST_ASSERT_EQUAL(rte_ptp_version(hdr), 2,
+               "version: expected 2, got %u", rte_ptp_version(hdr));
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_domain(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+       TEST_ASSERT_EQUAL(rte_ptp_domain(hdr), 0,
+               "domain: expected 0, got %u", rte_ptp_domain(hdr));
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+/* Section 4: correctionField */
+static int
+test_ptp_correction_zero(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+       int64_t ns = rte_ptp_correction_ns(hdr);
+       TEST_ASSERT_EQUAL(ns, 0,
+               "correction_ns: expected 0, got %" PRId64, ns);
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_correction_known(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *ptp = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(ptp, "hdr_get failed");
+       int64_t scaled_1000 = (int64_t)1000 << 16;
+       fill_ptp_hdr(ptp, RTE_PTP_MSGTYPE_SYNC, 0, scaled_1000, 0);
+
+       int64_t ns = rte_ptp_correction_ns(ptp);
+       TEST_ASSERT_EQUAL(ns, 1000,
+               "correction_ns: expected 1000, got %" PRId64, ns);
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_add_correction(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+
+       rte_ptp_add_correction(hdr, 500);
+       int64_t ns = rte_ptp_correction_ns(hdr);
+       TEST_ASSERT_EQUAL(ns, 500,
+               "add 500: expected 500, got %" PRId64, ns);
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_add_correction_accumulate(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+
+       rte_ptp_add_correction(hdr, 300);
+       rte_ptp_add_correction(hdr, 700);
+       int64_t ns = rte_ptp_correction_ns(hdr);
+       TEST_ASSERT_EQUAL(ns, 1000,
+               "accumulate: expected 1000, got %" PRId64, ns);
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_add_correction_large(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+
+       rte_ptp_add_correction(hdr, 1000000000LL);
+       int64_t ns = rte_ptp_correction_ns(hdr);
+       TEST_ASSERT_EQUAL(ns, 1000000000LL,
+               "1s: expected 1000000000, got %" PRId64, ns);
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+static int
+test_ptp_add_correction_negative(void)
+{
+       struct rte_mbuf *m = build_l2_ptp(RTE_PTP_MSGTYPE_SYNC);
+
+       TEST_ASSERT_NOT_NULL(m, "alloc failed");
+       struct rte_ptp_hdr *hdr = rte_ptp_hdr_get(m);
+       TEST_ASSERT_NOT_NULL(hdr, "hdr_get failed");
+
+       rte_ptp_add_correction(hdr, -100LL);
+       int64_t ns = rte_ptp_correction_ns(hdr);
+       TEST_ASSERT_EQUAL(ns, -100LL,
+               "negative: expected -100, got %" PRId64, ns);
+       rte_pktmbuf_free(m);
+
+       return TEST_SUCCESS;
+}
+
+/* Section 5: Timestamp conversion */
+static int
+test_ptp_timestamp_to_ns(void)
+{
+       struct rte_ptp_timestamp ts;
+       uint64_t ns;
+
+       /* Zero */
+       memset(&ts, 0, sizeof(ts));
+       ns = rte_ptp_timestamp_to_ns(&ts);
+       TEST_ASSERT_EQUAL(ns, 0ULL,
+               "zero: expected 0, got %" PRIu64, ns);
+
+       /* 1 second */
+       ts.seconds_hi = 0;
+       ts.seconds_lo = rte_cpu_to_be_32(1);
+       ts.nanoseconds = 0;
+       ns = rte_ptp_timestamp_to_ns(&ts);
+       TEST_ASSERT_EQUAL(ns, 1000000000ULL,
+               "1s: expected 1000000000, got %" PRIu64, ns);
+
+       /* 1.5 seconds */
+       ts.seconds_lo = rte_cpu_to_be_32(1);
+       ts.nanoseconds = rte_cpu_to_be_32(500000000);
+       ns = rte_ptp_timestamp_to_ns(&ts);
+       TEST_ASSERT_EQUAL(ns, 1500000000ULL,
+               "1.5s: expected 1500000000, got %" PRIu64, ns);
+
+       /* Large value with seconds_hi */
+       ts.seconds_hi = rte_cpu_to_be_16(1);
+       ts.seconds_lo = 0;
+       ts.nanoseconds = 0;
+       ns = rte_ptp_timestamp_to_ns(&ts);
+       uint64_t expected = ((uint64_t)1 << 32) * 1000000000ULL;
+       TEST_ASSERT_EQUAL(ns, expected,
+               "2^32s: expected %" PRIu64 ", got %" PRIu64, expected, ns);
+
+       return TEST_SUCCESS;
+}
+
+/* Section 6: msg_type_str */
+static int
+test_ptp_msg_type_str(void)
+{
+       static const struct {
+               int type;
+               const char *expected;
+       } cases[] = {
+               { RTE_PTP_MSGTYPE_SYNC,           "Sync" },
+               { RTE_PTP_MSGTYPE_DELAY_REQ,      "Delay_Req" },
+               { RTE_PTP_MSGTYPE_PDELAY_REQ,     "PDelay_Req" },
+               { RTE_PTP_MSGTYPE_PDELAY_RESP,    "PDelay_Resp" },
+               { RTE_PTP_MSGTYPE_FOLLOW_UP,      "Follow_Up" },
+               { RTE_PTP_MSGTYPE_DELAY_RESP,     "Delay_Resp" },
+               { RTE_PTP_MSGTYPE_PDELAY_RESP_FU, "PDelay_Resp_Follow_Up" },
+               { RTE_PTP_MSGTYPE_ANNOUNCE,       "Announce" },
+               { RTE_PTP_MSGTYPE_SIGNALING,      "Signaling" },
+               { RTE_PTP_MSGTYPE_MANAGEMENT,     "Management" },
+       };
+       unsigned int i;
+
+       for (i = 0; i < RTE_DIM(cases); i++) {
+               const char *str = rte_ptp_msg_type_str(cases[i].type);
+               TEST_ASSERT_NOT_NULL(str,
+                       "msg_type_str(%d) returned NULL", cases[i].type);
+               TEST_ASSERT(strcmp(str, cases[i].expected) == 0,
+                       "msg_type_str(%d): expected \"%s\", got \"%s\"",
+                       cases[i].type, cases[i].expected, str);
+       }
+
+       /* Invalid type should still return non-NULL */
+       const char *inv = rte_ptp_msg_type_str(RTE_PTP_MSGTYPE_INVALID);
+       TEST_ASSERT_NOT_NULL(inv,
+               "msg_type_str(INVALID) returned NULL");
+
+       return TEST_SUCCESS;
+}
+
+/* Section 7: Flag bit positions */
+static int
+test_ptp_flags(void)
+{
+       struct rte_ptp_hdr hdr;
+       uint16_t f;
+
+       /* TWO_STEP */
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.flags = rte_cpu_to_be_16(RTE_PTP_FLAG_TWO_STEP);
+       f = rte_be_to_cpu_16(hdr.flags);
+       TEST_ASSERT(f & RTE_PTP_FLAG_TWO_STEP,
+               "TWO_STEP bit not set: 0x%04x", f);
+       TEST_ASSERT(rte_ptp_is_two_step(&hdr),
+               "is_two_step() should return true");
+
+       /* UNICAST */
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.flags = rte_cpu_to_be_16(RTE_PTP_FLAG_UNICAST);
+       f = rte_be_to_cpu_16(hdr.flags);
+       TEST_ASSERT(f & RTE_PTP_FLAG_UNICAST,
+               "UNICAST bit not set: 0x%04x", f);
+
+       /* LI_61 */
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.flags = rte_cpu_to_be_16(RTE_PTP_FLAG_LI_61);
+       f = rte_be_to_cpu_16(hdr.flags);
+       TEST_ASSERT(f & RTE_PTP_FLAG_LI_61,
+               "LI_61 bit not set: 0x%04x", f);
+
+       /* LI_59 */
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.flags = rte_cpu_to_be_16(RTE_PTP_FLAG_LI_59);
+       f = rte_be_to_cpu_16(hdr.flags);
+       TEST_ASSERT(f & RTE_PTP_FLAG_LI_59,
+               "LI_59 bit not set: 0x%04x", f);
+
+       /* Combined TWO_STEP + UNICAST */
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.flags = rte_cpu_to_be_16(
+               RTE_PTP_FLAG_TWO_STEP | RTE_PTP_FLAG_UNICAST);
+       f = rte_be_to_cpu_16(hdr.flags);
+       TEST_ASSERT((f & RTE_PTP_FLAG_TWO_STEP) &&
+                   (f & RTE_PTP_FLAG_UNICAST) &&
+                   !(f & RTE_PTP_FLAG_LI_61) &&
+                   !(f & RTE_PTP_FLAG_LI_59),
+               "combined flags incorrect: 0x%04x", f);
+
+       return TEST_SUCCESS;
+}
+
+/* ================================================================
+ *  Suite setup / teardown
+ * ================================================================
+ */
+
+static int
+test_ptp_setup(void)
+{
+       ptp_mp = rte_pktmbuf_pool_create(PTP_TEST_MP_NAME, PTP_TEST_MP_SIZE,
+               0, 0, PTP_TEST_BUF_SIZE, SOCKET_ID_ANY);
+       if (ptp_mp == NULL) {
+               printf("Cannot create ptp test mempool\n");
+               return TEST_FAILED;
+       }
+       return TEST_SUCCESS;
+}
+
+static void
+test_ptp_teardown(void)
+{
+       rte_mempool_free(ptp_mp);
+       ptp_mp = NULL;
+}
+
+static struct unit_test_suite ptp_test_suite = {
+       .suite_name = "PTP Library Unit Tests",
+       .setup = test_ptp_setup,
+       .teardown = test_ptp_teardown,
+       .unit_test_cases = {
+               /* Transport classification */
+               TEST_CASE(test_ptp_classify_l2),
+               TEST_CASE(test_ptp_classify_l2_delay_req),
+               TEST_CASE(test_ptp_classify_vlan_8100),
+               TEST_CASE(test_ptp_classify_vlan_88a8),
+               TEST_CASE(test_ptp_classify_qinq),
+               TEST_CASE(test_ptp_classify_double_8100),
+               TEST_CASE(test_ptp_classify_ipv4_udp_319),
+               TEST_CASE(test_ptp_classify_ipv4_udp_320),
+               TEST_CASE(test_ptp_classify_vlan_ipv4_udp),
+               TEST_CASE(test_ptp_classify_qinq_ipv4_udp),
+               TEST_CASE(test_ptp_classify_ipv6_udp_319),
+               TEST_CASE(test_ptp_classify_ipv6_udp_320),
+               TEST_CASE(test_ptp_classify_vlan_ipv6_udp),
+               TEST_CASE(test_ptp_classify_qinq_ipv6_udp),
+               TEST_CASE(test_ptp_classify_non_ptp_arp),
+               TEST_CASE(test_ptp_classify_non_ptp_udp),
+               TEST_CASE(test_ptp_classify_ipv4_bad_ihl),
+               TEST_CASE(test_ptp_classify_ipv4_options),
+               TEST_CASE(test_ptp_classify_truncated),
+
+               /* All message types */
+               TEST_CASE(test_ptp_all_msg_types),
+
+               /* Inline helpers */
+               TEST_CASE(test_ptp_is_event),
+               TEST_CASE(test_ptp_two_step),
+               TEST_CASE(test_ptp_seq_id),
+               TEST_CASE(test_ptp_version),
+               TEST_CASE(test_ptp_domain),
+
+               /* correctionField */
+               TEST_CASE(test_ptp_correction_zero),
+               TEST_CASE(test_ptp_correction_known),
+               TEST_CASE(test_ptp_add_correction),
+               TEST_CASE(test_ptp_add_correction_accumulate),
+               TEST_CASE(test_ptp_add_correction_large),
+               TEST_CASE(test_ptp_add_correction_negative),
+
+               /* Timestamp conversion */
+               TEST_CASE(test_ptp_timestamp_to_ns),
+
+               /* msg_type_str */
+               TEST_CASE(test_ptp_msg_type_str),
+
+               /* Flag field bit positions */
+               TEST_CASE(test_ptp_flags),
+
+               TEST_CASES_END()
+       },
+};
+
+static int
+test_ptp(void)
+{
+       return unit_test_suite_runner(&ptp_test_suite);
+}
+
+REGISTER_FAST_TEST(ptp_autotest, NOHUGE_SKIP, ASAN_OK, test_ptp);
-- 
2.53.0

Reply via email to