From d0949e1e9260c47702d24d637d289029ee01d286 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Tue, 31 Mar 2026 10:30:43 -0700 Subject: [PATCH] [nexus] add 1_4_TREL_TC_2 for TREL multi-hop routing (#12804) This commit adds Nexus test case 1_4_TREL_TC_2, which verifies 6LoWPAN mesh header forwarding and fragmentation over multi-hop paths involving both 15.4 and TREL radio links, according to the Thread 1.4 spec. The implementation includes: - tests/nexus/test_1_4_TREL_TC_2.cpp: Sets up a complex topology with a multi-radio Border Router (DUT), a multi-radio Leader, and several Routers and End Devices with varying radio capabilities (15.4-only or multi-radio). It triggers pings with large payloads (500B) to verify fragmentation and multi-hop routing through the DUT. - tests/nexus/verify_1_4_TREL_TC_2.py: Verifies that packets follow the expected multi-hop path, checking that TREL is used for infrastructure segments (UDP) and 15.4 is used for Thread-only segments. It also ensures that 6LoWPAN fragmentation and mesh headers are correctly handled by the DUT when forwarding between different radio types. - Updated tests/nexus/CMakeLists.txt and tests/nexus/run_nexus_tests.sh to include the new test. This test ensures that the Thread stack correctly handles multi-hop routing and MTU differences across heterogeneous radio links. --- tests/nexus/CMakeLists.txt | 1 + tests/nexus/platform/nexus_trel.hpp | 2 +- tests/nexus/run_nexus_tests.sh | 1 + tests/nexus/test_1_4_TREL_TC_2.cpp | 280 ++++++++++ tests/nexus/verify_1_4_TREL_TC_2.py | 495 ++++++++++++++++++ tests/nexus/verify_utils.py | 16 +- tests/scripts/thread-cert/pktverify/consts.py | 2 +- .../thread-cert/pktverify/layer_fields.py | 6 + 8 files changed, 796 insertions(+), 7 deletions(-) create mode 100644 tests/nexus/test_1_4_TREL_TC_2.cpp create mode 100644 tests/nexus/verify_1_4_TREL_TC_2.py diff --git a/tests/nexus/CMakeLists.txt b/tests/nexus/CMakeLists.txt index c99f0c737..41db4fa16 100644 --- a/tests/nexus/CMakeLists.txt +++ b/tests/nexus/CMakeLists.txt @@ -284,6 +284,7 @@ ot_nexus_test(1_3_SRPC_TC_7 "cert;nexus") ot_nexus_test(1_3_DIAG_TC_1 "cert;nexus") ot_nexus_test(1_3_DIAG_TC_2 "cert;nexus") ot_nexus_test(1_4_TREL_TC_1 "cert;nexus") +ot_nexus_test(1_4_TREL_TC_2 "cert;nexus") # Misc tests ot_nexus_test(border_admitter "core;nexus") diff --git a/tests/nexus/platform/nexus_trel.hpp b/tests/nexus/platform/nexus_trel.hpp index a6c77778b..25bcd87f4 100644 --- a/tests/nexus/platform/nexus_trel.hpp +++ b/tests/nexus/platform/nexus_trel.hpp @@ -40,7 +40,7 @@ class Node; struct Trel { - static constexpr uint16_t kUdpPortStart = 49152; + static constexpr uint16_t kUdpPortStart = 19152; typedef otPlatTrelCounters Counters; diff --git a/tests/nexus/run_nexus_tests.sh b/tests/nexus/run_nexus_tests.sh index a9b89e4af..b0f67e50f 100755 --- a/tests/nexus/run_nexus_tests.sh +++ b/tests/nexus/run_nexus_tests.sh @@ -219,6 +219,7 @@ DEFAULT_TESTS=( "1_3_DIAG_TC_1" "1_3_DIAG_TC_2" "1_4_TREL_TC_1" + "1_4_TREL_TC_2" ) # Use provided arguments or the default test list diff --git a/tests/nexus/test_1_4_TREL_TC_2.cpp b/tests/nexus/test_1_4_TREL_TC_2.cpp new file mode 100644 index 000000000..61850d932 --- /dev/null +++ b/tests/nexus/test_1_4_TREL_TC_2.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2026, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "platform/nexus_core.hpp" +#include "platform/nexus_node.hpp" + +namespace ot { +namespace Nexus { + +#if OPENTHREAD_CONFIG_MULTI_RADIO + +static constexpr uint32_t kFormNetworkTime = 13 * 1000; +static constexpr uint32_t kAttachToRouterTime = 150 * 1000; +static constexpr uint32_t kStabilizationTime = 60 * 1000; +static constexpr uint32_t kInfraIfIndex = 1; +static constexpr uint16_t kPingPayloadSize = 500; +static constexpr uint32_t kPingResponseTimeout = 10000; + +void Test_1_4_TREL_TC_2(void) +{ + /** + * 8.2. [1.4] [CERT] Multi-hop routing with device (in the path) with different radio types and MTUs + * + * 8.2.1. Purpose + * This test covers the use of 6LoWPAN “Mesh Header” messages (messages sent over multi-hop) when + * underlying routes (in the path) can support different radio link types with different frame MTU sizes. + * Different types of devices (15.4, TREL, Router, End Device) are connected to the DUT. + * + * 8.2.2. Topology + * - BR Router_1 (DUT) - Border Router DUT that supports multi-radio (TREL and 15.4) + * - Leader - Reference device that supports multi-radio (TREL and 15.4). + * - Router_2 - Reference device that supports 15.4 only + * - ED_1 - Reference end device that supports 15.4 only + * - Router_3 - Reference device that supports 15.4 only + * - Router_4 - Reference device that supports multi-radio (TREL and 15.4). + * + * Spec Reference | V1.1 Section | V1.3.0 Section + * -------------------------|--------------|--------------- + * TREL / Multi-radio Links | N/A | 8.2 + */ + + Core nexus; + Node &router1 = nexus.CreateNode(); // DUT + Node &leader = nexus.CreateNode(); + Node &router2 = nexus.CreateNode(); + Node &ed1 = nexus.CreateNode(); + Node &router3 = nexus.CreateNode(); + Node &router4 = nexus.CreateNode(); + + router1.SetName("ROUTER_1"); + leader.SetName("LEADER"); + router2.SetName("ROUTER_2"); + ed1.SetName("ED_1"); + router3.SetName("ROUTER_3"); + router4.SetName("ROUTER_4"); + + nexus.AdvanceTime(0); + + SuccessOrQuit(Instance::SetGlobalLogLevel(kLogLevelNote)); + + /** + * Step 1 + * - Device: Leader, Router_1 (DUT), Router_2, ED_1, Router_3, Router_4 + * - Description (TREL-8.2): Form the topology. Wait for Router_1, Router_2, Router_3 and Router_4 to become + * routers. Note: any devices not connected by line in the topology figure MUST NOT be able to communicate + * directly via a Thread Link or TREL link and not be in each other’s neighbor table (e.g. this may be realized + * by using the allow/deny list mechanism). ED_1 MUST be configured as a non-sleepy MTD child (mode `rn`). Note: + * ED_1 MUST attach to the Router_1 (DUT) as its parent and not the other routers (e.g., can be realized by using + * denylist on ED_1). Note: The requirement for ED_1 to attach as a non-sleepy MTD child to Router_1 (DUT) is + * important to ensure messages from ED_1 are sent to its parent as is without mesh header encapsulation, to + * then be forwarded within the mesh and that the fragmentation and adding of 6LoWPAN “mesh header” is performed + * by Router_1 (DUT) - which is being verified in the next step. + * - Pass Criteria: + * - Verify that topology is formed. + * - Leader MUST see both the DUT and Router_2 as its immediate neighbors. + * - Router_2 MUST only see Leader as its immediate neighbor and not the DUT. + * - ED_1 MUST see the DUT as its parent. + */ + Log("Step 1: Form the topology"); + + // Leader <-> Router_1 (DUT) + leader.AllowList(router1); + router1.AllowList(leader); + + // Leader <-> Router_2 + leader.AllowList(router2); + router2.AllowList(leader); + + // Router_1 (DUT) <-> Router_3 + router1.AllowList(router3); + router3.AllowList(router1); + + // Router_1 (DUT) <-> Router_4 + router1.AllowList(router4); + router4.AllowList(router1); + + // Router_1 (DUT) <-> ED_1 + router1.AllowList(ed1); + ed1.AllowList(router1); + + // Enable TREL (mDNS) on all TREL nodes. + SuccessOrQuit(router1.Get().SetEnabled(true, kInfraIfIndex)); + SuccessOrQuit(leader.Get().SetEnabled(true, kInfraIfIndex)); + SuccessOrQuit(router4.Get().SetEnabled(true, kInfraIfIndex)); + + leader.Form(); + nexus.AdvanceTime(kFormNetworkTime); + VerifyOrQuit(leader.Get().IsLeader()); + + router1.Join(leader); + router2.Join(leader); + router3.Join(leader); + router4.Join(leader); + nexus.AdvanceTime(kAttachToRouterTime); + + ed1.Join(router1, Node::kAsFed); + nexus.AdvanceTime(kAttachToRouterTime); + + nexus.AdvanceTime(kStabilizationTime); + + VerifyOrQuit(router1.Get().IsRouter()); + VerifyOrQuit(router2.Get().IsRouter()); + VerifyOrQuit(router3.Get().IsRouter()); + VerifyOrQuit(router4.Get().IsRouter()); + VerifyOrQuit(ed1.Get().IsChild()); + VerifyOrQuit(ed1.Get().GetParent().GetExtAddress() == router1.Get().GetExtAddress()); + + // Verify neighbors + { + const Neighbor *neighbor = leader.Get().FindNeighbor(router1.Get().GetExtAddress()); + VerifyOrQuit(neighbor != nullptr); + VerifyOrQuit(neighbor->GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel)); + } + { + const Neighbor *neighbor = router1.Get().FindNeighbor(router4.Get().GetExtAddress()); + VerifyOrQuit(neighbor != nullptr); + VerifyOrQuit(neighbor->GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel)); + } + VerifyOrQuit(leader.Get().FindNeighbor(router2.Get().GetExtAddress()) != nullptr); + VerifyOrQuit(router2.Get().FindNeighbor(leader.Get().GetExtAddress()) != nullptr); + VerifyOrQuit(router2.Get().FindNeighbor(router1.Get().GetExtAddress()) == nullptr); + + /** + * Step 2 + * - Device: ED_1 + * - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more to + * destination Router_2 using the ML-EID address of Router_2 as the destination address. Note: this verifies the + * DUT behavior of forwarding 6LoWPAN fragmented frames from a Child (incoming over 15.4) over multiple hops. + * - Pass Criteria: + * - ED_1 MUST successfully receive a ping reply from Router_2, routed via DUT. + * - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + * frames. + */ + Log("Step 2: ED_1 pings Router_2 ML-EID"); + nexus.SendAndVerifyEchoRequest(ed1, router2.Get().GetMeshLocalEid(), kPingPayloadSize, + Ip6::kDefaultHopLimit, kPingResponseTimeout); + + /** + * Step 3 + * - Device: Router_2 + * - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + * Router_2 to ED_1 using the ML-EID address of ED_1 as the destination address. + * - Pass Criteria: + * - Router_2 MUST successfully receive a ping reply from ED_1, routed via the DUT. + * - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + * frames. + */ + Log("Step 3: Router_2 pings ED_1 ML-EID"); + nexus.SendAndVerifyEchoRequest(router2, ed1.Get().GetMeshLocalEid(), kPingPayloadSize, + Ip6::kDefaultHopLimit, kPingResponseTimeout); + + /** + * Step 4 + * - Device: Router_4 + * - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + * Router_4 to destination Router_2 using the ML-EID address of Router_2 as the destination address. Warning: see + * TESTPLAN-626 for an open issue (TBD) in this step. Note: this intends to verify the DUT behavior of + * forwarding 6LoWPAN “Mesh Header” messages, incoming over TREL, over multi-hop routes. + * - Pass Criteria: + * - Router_4 MUST successfully receive a ping reply from Router_2, routed via the DUT. + * - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + * frames. + * - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Router_4, and MUST be correct + * TREL frames. + */ + Log("Step 4: Router_4 pings Router_2 ML-EID"); + nexus.SendAndVerifyEchoRequest(router4, router2.Get().GetMeshLocalEid(), kPingPayloadSize, + Ip6::kDefaultHopLimit, kPingResponseTimeout); + + /** + * Step 5 + * - Device: Router_2 + * - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + * Router_2 to Router_4 using the ML-EID address of Router_4 as the destination address. + * - Pass Criteria: + * - Router_2 MUST successfully receive a ping reply from Router_4, routed via the DUT. + * - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + * frames. + * - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Router_4, and MUST be correct + * TREL frames. + */ + Log("Step 5: Router_2 pings Router_4 ML-EID"); + nexus.SendAndVerifyEchoRequest(router2, router4.Get().GetMeshLocalEid(), kPingPayloadSize, + Ip6::kDefaultHopLimit, kPingResponseTimeout); + + /** + * Step 6 + * - Device: Router_3 + * - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + * Router_3 to destination Router_2 using the ML-EID address of Router_2 as the destination address. Note: this + * verifies the DUT behavior of forwarding 6LoWPAN “Mesh Header” messages, incoming over 15.4, over multi-hop + * routes. + * - Pass Criteria: + * - Router_3 MUST successfully receive a ping reply from Router_2, routed via the DUT. + * - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Leader, and MUST be correct + * TREL frames. + */ + Log("Step 6: Router_3 pings Router_2 ML-EID"); + nexus.SendAndVerifyEchoRequest(router3, router2.Get().GetMeshLocalEid(), kPingPayloadSize, + Ip6::kDefaultHopLimit, kPingResponseTimeout); + + /** + * Step 7 + * - Device: Router_2 + * - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + * Router_2 to Router_3 using the ML-EID address of Router_3 as the destination address. + * - Pass Criteria: + * - Router_2 MUST successfully receive a ping reply from Router_3, routed via the DUT. + * - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Leader, and MUST be correct + * TREL frames. + */ + Log("Step 7: Router_2 pings Router_3 ML-EID"); + nexus.SendAndVerifyEchoRequest(router2, router3.Get().GetMeshLocalEid(), kPingPayloadSize, + Ip6::kDefaultHopLimit, kPingResponseTimeout); + + nexus.SaveTestInfo("test_1_4_TREL_TC_2.json"); +} + +#endif // OPENTHREAD_CONFIG_MULTI_RADIO + +} // namespace Nexus +} // namespace ot + +int main(void) +{ +#if OPENTHREAD_CONFIG_MULTI_RADIO + ot::Nexus::Test_1_4_TREL_TC_2(); + printf("All tests passed\n"); +#else + printf("Multi-radio is not enabled - test skipped\n"); +#endif + return 0; +} diff --git a/tests/nexus/verify_1_4_TREL_TC_2.py b/tests/nexus/verify_1_4_TREL_TC_2.py new file mode 100644 index 000000000..2918f96d8 --- /dev/null +++ b/tests/nexus/verify_1_4_TREL_TC_2.py @@ -0,0 +1,495 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +import sys +import os + +# Add the current directory to sys.path to find verify_utils +CUR_DIR = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(CUR_DIR) + +import verify_utils +from pktverify import consts + + +def verify(pv): + # 8.2. [1.4] [CERT] Multi-hop routing with device (in the path) with different radio types and MTUs + # + # 8.2.1. Purpose + # This test covers the use of 6LoWPAN “Mesh Header” messages (messages sent over multi-hop) when + # underlying routes (in the path) can support different radio link types with different frame MTU sizes. + # Different types of devices (15.4, TREL, Router, End Device) are connected to the DUT. + # + # Spec Reference | V1.1 Section | V1.3.0 Section + # -------------------------|--------------|--------------- + # TREL / Multi-radio Links | N/A | 8.2 + + pkts = pv.pkts + pv.summary.show() + + ROUTER_1 = pv.vars['ROUTER_1'] # DUT + LEADER = pv.vars['LEADER'] + ROUTER_2 = pv.vars['ROUTER_2'] + ED_1 = pv.vars['ED_1'] + ROUTER_3 = pv.vars['ROUTER_3'] + ROUTER_4 = pv.vars['ROUTER_4'] + + ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16'] + LEADER_RLOC16 = pv.vars['LEADER_RLOC16'] + ROUTER_2_RLOC16 = pv.vars['ROUTER_2_RLOC16'] + ROUTER_3_RLOC16 = pv.vars['ROUTER_3_RLOC16'] + ROUTER_4_RLOC16 = pv.vars['ROUTER_4_RLOC16'] + ED_1_RLOC16 = pv.vars['ED_1_RLOC16'] + + ROUTER_1_ETH = pv.vars['ROUTER_1_ETH'] + LEADER_ETH = pv.vars['LEADER_ETH'] + ROUTER_4_ETH = pv.vars['ROUTER_4_ETH'] + + ROUTER_1_TREL_PORT = pv.vars['ROUTER_1_TREL_PORT'] + LEADER_TREL_PORT = pv.vars['LEADER_TREL_PORT'] + ROUTER_4_TREL_PORT = pv.vars['ROUTER_4_TREL_PORT'] + + ROUTER_1_MLEID = pv.vars['ROUTER_1_MLEID'] + LEADER_MLEID = pv.vars['LEADER_MLEID'] + ROUTER_2_MLEID = pv.vars['ROUTER_2_MLEID'] + ED_1_MLEID = pv.vars['ED_1_MLEID'] + ROUTER_3_MLEID = pv.vars['ROUTER_3_MLEID'] + ROUTER_4_MLEID = pv.vars['ROUTER_4_MLEID'] + + # Step 1 + # - Device: Leader, Router_1 (DUT), Router_2, ED_1, Router_3, Router_4 + # - Description (TREL-8.2): Form the topology. Wait for Router_1, Router_2, Router_3 and Router_4 to become + # routers. Note: any devices not connected by line in the topology figure MUST NOT be able to communicate + # directly via a Thread Link or TREL link and not be in each other’s neighbor table (e.g. this may be realized + # by using the allow/deny list mechanism). ED_1 MUST be configured as a non-sleepy MTD child (mode `rn`). Note: + # ED_1 MUST attach to the Router_1 (DUT) as its parent and not the other routers (e.g., can be realized by using + # denylist on ED_1). Note: The requirement for ED_1 to attach as a non-sleepy MTD child to Router_1 (DUT) is + # important to ensure messages from ED_1 are sent to its parent as is without mesh header encapsulation, to + # then be forwarded within the mesh and that the fragmentation and adding of 6LoWPAN “mesh header” is performed + # by Router_1 (DUT) - which is being verified in the next step. + print("Step 1: Form the topology") + pkts.copy().\ + filter_wpan_src64(ROUTER_2).\ + filter_wpan_dst64(ROUTER_1).\ + must_not_next() + pkts.copy().\ + filter_wpan_src64(ROUTER_1).\ + filter_wpan_dst64(ROUTER_2).\ + must_not_next() + + # Step 2 + # - Device: ED_1 + # - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more to + # destination Router_2 using the ML-EID address of Router_2 as the destination address. Note: this verifies the + # DUT behavior of forwarding 6LoWPAN fragmented frames from a Child (incoming over 15.4) over multiple hops. + # - Pass Criteria: + # - ED_1 MUST successfully receive a ping reply from Router_2, routed via DUT. + # - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + # frames. + print("Step 2: ED_1 pings Router_2 ML-EID") + # Path: ED_1 -(15.4)-> ROUTER_1 -(TREL)-> LEADER -(15.4)-> ROUTER_2 + # 1. Request from ED_1 to ROUTER_1 over 15.4 + _pkt_154_req = pkts.copy().\ + filter_ping_request().\ + filter_ipv6_src_dst(ED_1_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(ED_1_RLOC16, ROUTER_1_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + _identifier = _pkt_154_req.icmpv6.echo.identifier + + # 2. Forwarded request on TREL (ROUTER_1 to LEADER) + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == LEADER_ETH).\ + filter(lambda p: p.udp.dstport == LEADER_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == LEADER).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == LEADER_RLOC16).\ + must_next() + + # 3. Forwarded request on 15.4 (LEADER to ROUTER_2) + pkts.range(pkts.index).\ + filter_ping_request(identifier=_identifier).\ + filter_ipv6_src_dst(ED_1_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(LEADER_RLOC16, ROUTER_2_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 4. Reply from Router_2 to Leader over 15.4 + pkts.copy().\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ED_1_MLEID).\ + filter_wpan_src16_dst16(ROUTER_2_RLOC16, LEADER_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 5. Forwarded reply on TREL (LEADER to ROUTER_1) + pkts.range(pkts.index).\ + filter_eth_src(LEADER_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == LEADER and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == LEADER_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 6. Forwarded reply on 15.4 (ROUTER_1 to ED_1) + pkts.range(pkts.index).\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ED_1_MLEID).\ + filter_wpan_src16_dst16(ROUTER_1_RLOC16, ED_1_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # Step 3 + # - Device: Router_2 + # - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + # Router_2 to ED_1 using the ML-EID address of ED_1 as the destination address. + # - Pass Criteria: + # - Router_2 MUST successfully receive a ping reply from ED_1, routed via the DUT. + # - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + # frames. + print("Step 3: Router_2 pings ED_1 ML-EID") + # Path: ROUTER_2 -(15.4)-> LEADER -(TREL)-> ROUTER_1 -(15.4)-> ED_1 + # 1. Request from ROUTER_2 to LEADER over 15.4 + _pkt_154_req = pkts.copy().\ + filter_ping_request().\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ED_1_MLEID).\ + filter_wpan_src16_dst16(ROUTER_2_RLOC16, LEADER_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + _identifier = _pkt_154_req.icmpv6.echo.identifier + + # 2. Forwarded request on TREL (LEADER to ROUTER_1) + pkts.range(pkts.index).\ + filter_eth_src(LEADER_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == LEADER and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == LEADER_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 3. Forwarded request on 15.4 (ROUTER_1 to ED_1) + pkts.range(pkts.index).\ + filter_ping_request(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ED_1_MLEID).\ + filter_wpan_src16_dst16(ROUTER_1_RLOC16, ED_1_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 4. Reply from ED_1 to ROUTER_1 over 15.4 + pkts.copy().\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ED_1_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(ED_1_RLOC16, ROUTER_1_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 5. Forwarded reply on TREL (ROUTER_1 to LEADER) + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == LEADER_ETH).\ + filter(lambda p: p.udp.dstport == LEADER_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == LEADER).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == LEADER_RLOC16).\ + must_next() + + # 6. Forwarded reply on 15.4 (LEADER to ROUTER_2) + pkts.range(pkts.index).\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ED_1_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(LEADER_RLOC16, ROUTER_2_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # Step 4 + # - Device: Router_4 + # - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + # Router_4 to destination Router_2 using the ML-EID address of Router_2 as the destination address. Warning: see + # TESTPLAN-626 for an open issue (TBD) in this step. Note: this intends to verify the DUT behavior of + # forwarding 6LoWPAN “Mesh Header” messages, incoming over TREL, over multi-hop routes. + # - Pass Criteria: + # - Router_4 MUST successfully receive a ping reply from Router_2, routed via the DUT. + # - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + # frames. + # - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Router_4, and MUST be correct + # TREL frames. + print("Step 4: Router_4 pings Router_2 ML-EID") + # Path: ROUTER_4 -(TREL)-> ROUTER_1 -(TREL)-> LEADER -(15.4)-> ROUTER_2 + # 1. Request from ROUTER_4 to ROUTER_1 over TREL + pkts.copy().\ + filter_eth_src(ROUTER_4_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_4 and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_4_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 2. Forwarded request from ROUTER_1 to LEADER over TREL + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == LEADER_ETH).\ + filter(lambda p: p.udp.dstport == LEADER_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == LEADER).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == LEADER_RLOC16).\ + must_next() + + # 3. Forwarded request on 15.4 (LEADER to ROUTER_2) + _pkt_154_req = pkts.range(pkts.index).\ + filter_ping_request().\ + filter_ipv6_src_dst(ROUTER_4_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(LEADER_RLOC16, ROUTER_2_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + _identifier = _pkt_154_req.icmpv6.echo.identifier + + # 4. Reply from Router_2 to Leader over 15.4 + pkts.copy().\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ROUTER_4_MLEID).\ + filter_wpan_src16_dst16(ROUTER_2_RLOC16, LEADER_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 5. Forwarded reply on TREL (LEADER to ROUTER_1) + pkts.range(pkts.index).\ + filter_eth_src(LEADER_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == LEADER and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == LEADER_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 6. Forwarded reply on TREL (ROUTER_1 to ROUTER_4) + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_4_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_4_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == ROUTER_4).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == ROUTER_4_RLOC16).\ + must_next() + + # Step 5 + # - Device: Router_2 + # - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + # Router_2 to Router_4 using the ML-EID address of Router_4 as the destination address. + # - Pass Criteria: + # - Router_2 MUST successfully receive a ping reply from Router_4, routed via the DUT. + # - TREL UDP frames MUST be used for ping/ping-reply transport between DUT and Leader, and MUST be correct TREL + # frames. + # - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Router_4, and MUST be correct + # TREL frames. + print("Step 5: Router_2 pings Router_4 ML-EID") + # Path: ROUTER_2 -(15.4)-> LEADER -(TREL)-> ROUTER_1 -(TREL)-> ROUTER_4 + # 1. Request from ROUTER_2 to LEADER over 15.4 + _pkt_154_req = pkts.copy().\ + filter_ping_request().\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ROUTER_4_MLEID).\ + filter_wpan_src16_dst16(ROUTER_2_RLOC16, LEADER_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + _identifier = _pkt_154_req.icmpv6.echo.identifier + + # 2. Forwarded request from LEADER to ROUTER_1 over TREL + pkts.range(pkts.index).\ + filter_eth_src(LEADER_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == LEADER and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == LEADER_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 3. Forwarded request from ROUTER_1 to ROUTER_4 over TREL + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_4_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_4_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == ROUTER_4).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == ROUTER_4_RLOC16).\ + must_next() + + # 4. Reply on TREL (ROUTER_4 to ROUTER_1) + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_4_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_4 and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_4_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 5. Forwarded reply on TREL (ROUTER_1 to LEADER) + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == LEADER_ETH).\ + filter(lambda p: p.udp.dstport == LEADER_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == LEADER).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == LEADER_RLOC16).\ + must_next() + + # 6. Forwarded reply on 15.4 (LEADER to ROUTER_2) + pkts.range(pkts.index).\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_4_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(LEADER_RLOC16, ROUTER_2_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # Step 6 + # - Device: Router_3 + # - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + # Router_3 to destination Router_2 using the ML-EID address of Router_2 as the destination address. Note: this + # verifies the DUT behavior of forwarding 6LoWPAN “Mesh Header” messages, incoming over 15.4, over multi-hop + # routes. + # - Pass Criteria: + # - Router_3 MUST successfully receive a ping reply from Router_2, routed via the DUT. + # - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Leader, and MUST be correct + # TREL frames. + print("Step 6: Router_3 pings Router_2 ML-EID") + # Path: ROUTER_3 -(15.4)-> ROUTER_1 -(TREL)-> LEADER -(15.4)-> ROUTER_2 + # 1. Request from ROUTER_3 to ROUTER_1 over 15.4 + _pkt_154_req = pkts.copy().\ + filter_ping_request().\ + filter_ipv6_src_dst(ROUTER_3_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(ROUTER_3_RLOC16, ROUTER_1_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + _identifier = _pkt_154_req.icmpv6.echo.identifier + + # 2. Check forwarded request on TREL from ROUTER_1 to LEADER + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == LEADER_ETH).\ + filter(lambda p: p.udp.dstport == LEADER_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == LEADER).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == LEADER_RLOC16).\ + must_next() + + # 3. Forwarded request on 15.4 (LEADER to ROUTER_2) + pkts.range(pkts.index).\ + filter_ping_request(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_3_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(LEADER_RLOC16, ROUTER_2_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 4. Reply from Router_2 to Leader over 15.4 + pkts.copy().\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ROUTER_3_MLEID).\ + filter_wpan_src16_dst16(ROUTER_2_RLOC16, LEADER_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 5. Check forwarded reply on TREL from LEADER to ROUTER_1 + pkts.range(pkts.index).\ + filter_eth_src(LEADER_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == LEADER and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == LEADER_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 6. Forwarded reply on 15.4 (ROUTER_1 to ROUTER_3) + pkts.range(pkts.index).\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ROUTER_3_MLEID).\ + filter_wpan_src16_dst16(ROUTER_1_RLOC16, ROUTER_3_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # Step 7 + # - Device: Router_2 + # - Description (TREL-8.2): Harness instructs device to send a ping of payload size of 500 bytes or more from + # Router_2 to Router_3 using the ML-EID address of Router_3 as the destination address. + # - Pass Criteria: + # - Router_2 MUST successfully receive a ping reply from Router_3, routed via the DUT. + # - TREL UDP frames MUST be used for ping/ping-reply transport between the DUT and Leader, and MUST be correct + # TREL frames. + print("Step 7: Router_2 pings Router_3 ML-EID") + # Path: ROUTER_2 -(15.4)-> LEADER -(TREL)-> ROUTER_1 -(15.4)-> ROUTER_3 + # 1. Request from ROUTER_2 to LEADER over 15.4 + _pkt_154_req = pkts.copy().\ + filter_ping_request().\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ROUTER_3_MLEID).\ + filter_wpan_src16_dst16(ROUTER_2_RLOC16, LEADER_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + _identifier = _pkt_154_req.icmpv6.echo.identifier + + # 2. Check forwarded request on TREL from LEADER to ROUTER_1 + pkts.range(pkts.index).\ + filter_eth_src(LEADER_ETH).\ + filter(lambda p: p.eth.dst == ROUTER_1_ETH).\ + filter(lambda p: p.udp.dstport == ROUTER_1_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == LEADER and p.trel.destination_addr == ROUTER_1).\ + filter(lambda p: p.trel.wpan.src16 == LEADER_RLOC16 and p.trel.wpan.dst16 == ROUTER_1_RLOC16).\ + must_next() + + # 3. Forwarded request on 15.4 (ROUTER_1 to ROUTER_3) + pkts.range(pkts.index).\ + filter_ping_request(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_2_MLEID, ROUTER_3_MLEID).\ + filter_wpan_src16_dst16(ROUTER_1_RLOC16, ROUTER_3_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 4. Reply from Router_3 to Router_1 over 15.4 + pkts.copy().\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_3_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(ROUTER_3_RLOC16, ROUTER_1_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + # 5. Check forwarded reply on TREL from ROUTER_1 to LEADER + pkts.range(pkts.index).\ + filter_eth_src(ROUTER_1_ETH).\ + filter(lambda p: p.eth.dst == LEADER_ETH).\ + filter(lambda p: p.udp.dstport == LEADER_TREL_PORT).\ + filter(lambda p: p.trel.source_addr == ROUTER_1 and p.trel.destination_addr == LEADER).\ + filter(lambda p: p.trel.wpan.src16 == ROUTER_1_RLOC16 and p.trel.wpan.dst16 == LEADER_RLOC16).\ + must_next() + + # 6. Forwarded reply on 15.4 (LEADER to ROUTER_2) + pkts.range(pkts.index).\ + filter_ping_reply(identifier=_identifier).\ + filter_ipv6_src_dst(ROUTER_3_MLEID, ROUTER_2_MLEID).\ + filter_wpan_src16_dst16(LEADER_RLOC16, ROUTER_2_RLOC16).\ + filter(lambda p: p.wpan).\ + must_next() + + print("All verification steps PASSED") + + +if __name__ == '__main__': + verify_utils.run_main(verify) diff --git a/tests/nexus/verify_utils.py b/tests/nexus/verify_utils.py index 5a0329c24..09d4273fa 100644 --- a/tests/nexus/verify_utils.py +++ b/tests/nexus/verify_utils.py @@ -498,9 +498,6 @@ def apply_patches(): consts.VALID_LAYER_NAMES.add('trel') consts.REAL_LAYER_NAMES.add('trel') - # Add TREL decoding entries for common Nexus ports - consts.WIRESHARK_DECODE_AS_ENTRIES['udp.port==12343'] = 'trel' - # Patch _get_candidate_layers to map wpan_tap to wpan-tap old_get_candidate_layers = layer_fields._get_candidate_layers @@ -705,6 +702,16 @@ def run_main(verify_func): all_thread_nodes_mcast_addr[4:12] = prefix[0:8] consts.LINK_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS = Ipv6Addr(all_thread_nodes_mcast_addr) + # Add TREL UDP port variables before creating PacketVerifier (so PcapReader uses them) + # We only do this for TREL tests to avoid interference with other tests + # using similar UDP ports for regular Thread traffic. + testcase = data.get('testcase', '') + if 'TREL' in testcase: + for node_id, port in data.get('trel_udp_ports', {}).items(): + port = int(port) + if port > 0: + consts.WIRESHARK_DECODE_AS_ENTRIES[f'udp.port=={port}'] = 'trel' + pv = PacketVerifier(json_file, wireshark_prefs=wireshark_prefs) pv.add_common_vars() @@ -713,13 +720,12 @@ def run_main(verify_func): name = pv.test_info.get_node_name(int(node_id)) pv.add_vars(**{f'{name}_RLOC16': int(rloc16, 16)}) - # Add TREL UDP port variables + # Add TREL UDP port variables to pv.vars for node_id, port in data.get('trel_udp_ports', {}).items(): name = pv.test_info.get_node_name(int(node_id)) port = int(port) if port > 0: pv.add_vars(**{f'{name}_TREL_PORT': port}) - consts.WIRESHARK_DECODE_AS_ENTRIES[f'udp.port=={port}'] = 'trel' # Add channel variables for node_id, channel in data.get('channels', {}).items(): diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py index f730b5cf5..a23f4c9ad 100644 --- a/tests/scripts/thread-cert/pktverify/consts.py +++ b/tests/scripts/thread-cert/pktverify/consts.py @@ -324,7 +324,7 @@ REAL_LAYER_NAMES = { 'dns', 'igmp', 'mdns', - 'dns', + 'trel', } FAKE_LAYER_NAMES = {'thread_nwd', 'thread_meshcop', 'ipv6inner'} diff --git a/tests/scripts/thread-cert/pktverify/layer_fields.py b/tests/scripts/thread-cert/pktverify/layer_fields.py index 42622fcb0..58b91c690 100644 --- a/tests/scripts/thread-cert/pktverify/layer_fields.py +++ b/tests/scripts/thread-cert/pktverify/layer_fields.py @@ -714,6 +714,12 @@ _LAYER_FIELDS = { 'mdns.srv.port': _list(_auto), 'mdns.srv.target': _list(_str), 'mdns.ptr.domain_name': _list(_str), + + # TREL + 'trel.source_addr': _ext_addr, + 'trel.destination_addr': _ext_addr, + 'trel.wpan.src16': _hex, + 'trel.wpan.dst16': _hex, } _layer_containers = set()