[nexus] add 1_4_TREL_TC_1 for Thread over Infrastructure (#12803)

This commit adds the Nexus test case 1_4_TREL_TC_1 which verifies
connectivity between multi-radio (15.4 and TREL) and single-radio
(15.4 only) devices, as per the Thread 1.4 test specification.

The implementation includes:
- tests/nexus/test_1_4_TREL_TC_1.cpp: Implements the test sequence.
  It sets up a topology with a Border Router (DUT) and two Routers.
  BR and Router_1 support both 15.4 and TREL, while Router_2 supports
  only 15.4. The test verifies that nodes can correctly detect
  neighbor radio capabilities and establishes connectivity using
  both radio types.
- tests/nexus/verify_1_4_TREL_TC_1.py: Performs automated packet
  verification. It ensures that traffic between multi-radio nodes
  preferentially uses TREL (simulated over the infrastructure link
  via UDP), while traffic involving the single-radio node uses 15.4.
  It also validates successful ping exchange across the mixed-radio
  topology.
- Integrated the new test into tests/nexus/CMakeLists.txt and
  tests/nexus/run_nexus_tests.sh.

The test validates that the Thread stack correctly manages multiple
radio links and ensures seamless connectivity across different
physical layers.
This commit is contained in:
Jonathan Hui
2026-03-31 09:39:13 -05:00
committed by GitHub
parent c3813d6253
commit 63ec21ea77
7 changed files with 469 additions and 0 deletions
+1
View File
@@ -283,6 +283,7 @@ ot_nexus_test(1_3_SRPC_TC_5 "cert;nexus")
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")
# Misc tests
ot_nexus_test(border_admitter "core;nexus")
+4
View File
@@ -49,6 +49,10 @@ case $1 in
trel=ON
fifteenfour=OFF
;;
multi-radio)
trel=ON
fifteenfour=ON
;;
*)
trel=ON
fifteenfour=ON
+12
View File
@@ -238,6 +238,18 @@ void Core::SaveTestInfo(const char *aFilename, Node *aLeaderNode)
}
fprintf(file, " },\n");
fprintf(file, " \"trel_udp_ports\": {\n");
for (Node &node : mNodes)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
fprintf(file, " \"%u\": %u%s\n", node.GetInstance().GetId(), node.mTrel.mUdpPort,
(&node == tail) ? "" : ",");
#else
fprintf(file, " \"%u\": 0%s\n", node.GetInstance().GetId(), (&node == tail) ? "" : ",");
#endif
}
fprintf(file, " },\n");
fprintf(file, " \"ipaddrs\": {\n");
for (Node &node : mNodes)
{
+1
View File
@@ -218,6 +218,7 @@ DEFAULT_TESTS=(
"1_3_SRPC_TC_7"
"1_3_DIAG_TC_1"
"1_3_DIAG_TC_2"
"1_4_TREL_TC_1"
)
# Use provided arguments or the default test list
+214
View File
@@ -0,0 +1,214 @@
/*
* 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 <stdio.h>
#include "platform/nexus_core.hpp"
#include "platform/nexus_node.hpp"
namespace ot {
namespace Nexus {
/**
* 8.1. [1.4] [CERT] Attach and connectivity (unicast/broadcast) between multi-radio and single-radio devices
*
* 8.1.1. Purpose
* To test the following:
* 1. Attaching Thread Devices with different radio links.
* 2. Verifies the detection of radio link types supported by neighbors/children.
* 3. Verifies connectivity between nodes (unicast and broadcast frame exchange with multi-radio support).
*
* 8.1.2. Topology
* - BR Leader (DUT) - Support multi-radio (15.4 and TREL).
* - Router_1 - Reference device that supports multi-radio (15.4 and TREL).
* - Router_2 - Reference device that supports 15.4 radio only.
*
* Spec Reference | V1.1 Section | V1.3.0 Section
* -------------------------|--------------|---------------
* TREL / Multi-radio Links | N/A | 8.1
*/
#if OPENTHREAD_CONFIG_MULTI_RADIO
static constexpr uint32_t kFormNetworkTime = 13 * 1000;
static constexpr uint32_t kAttachToRouterTime = 200 * 1000;
static constexpr uint32_t kStabilizationTime = 30 * 1000;
static constexpr uint32_t kInfraIfIndex = 1;
static constexpr uint16_t kPingPayloadSize = 500;
static constexpr uint32_t kPingResponseTimeout = 10000;
void Test1_4_Trel_Tc_1(void)
{
Core nexus;
Node &br = nexus.CreateNode();
Node &router1 = nexus.CreateNode();
Node &router2 = nexus.CreateNode();
br.SetName("BR_DUT");
router1.SetName("ROUTER_1");
router2.SetName("ROUTER_2");
nexus.AdvanceTime(0);
SuccessOrQuit(Instance::SetGlobalLogLevel(kLogLevelNote));
/**
* Step 1
* - Device: BR (DUT), Router_1, Router_2
* - Description (TREL-8.1): Form the topology. Wait for Router_1 and Router_2 to become routers. Note: Router_1
* and Router_2 MUST NOT be able to communicate directly and not be in each others neighbor table (e.g. this
* may be realized by using the allow/deny list mechanism).
* - Pass Criteria:
* - Verify that topology is formed.
* - The DUT MUST be the network Leader.
* - Router_1 MUST only see Leader as its immediate neighbor (Router_2 MUST not be present in Router_1s
* neighbor table).
* - Router_2 MUST only see Leader as its immediate neighbor and not Router_1.
*/
Log("Step 1: Form the topology");
SuccessOrQuit(br.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
SuccessOrQuit(router1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
br.AllowList(router1);
br.AllowList(router2);
router1.AllowList(br);
router2.AllowList(br);
br.Form();
nexus.AdvanceTime(kFormNetworkTime);
VerifyOrQuit(br.Get<Mle::Mle>().IsLeader());
router1.Join(br);
router2.Join(br);
nexus.AdvanceTime(kAttachToRouterTime);
VerifyOrQuit(router1.Get<Mle::Mle>().IsRouter());
VerifyOrQuit(router2.Get<Mle::Mle>().IsRouter());
nexus.AdvanceTime(kStabilizationTime);
// Verify neighbor tables
VerifyOrQuit(router1.Get<NeighborTable>().FindNeighbor(br.Get<Mac::Mac>().GetExtAddress()) != nullptr);
VerifyOrQuit(router1.Get<NeighborTable>().FindNeighbor(router2.Get<Mac::Mac>().GetExtAddress()) == nullptr);
VerifyOrQuit(router2.Get<NeighborTable>().FindNeighbor(br.Get<Mac::Mac>().GetExtAddress()) != nullptr);
VerifyOrQuit(router2.Get<NeighborTable>().FindNeighbor(router1.Get<Mac::Mac>().GetExtAddress()) == nullptr);
/**
* Step 2
* - Device: Router_1
* - Description (TREL-8.1): Harness instructs device to report its neighbor multi-radio info (which indicates
* which radio links are detected per neighbor/parent)
* - Pass Criteria:
* - Router_1 MUST have correctly detected that the DUT supports both TREL and 15.4 radios (multi-radio neighbor
* info).
* - The DUT MUST send TREL frames using the correct format
*/
Log("Step 2: Router_1 reports its neighbor multi-radio info");
{
const Neighbor *neighbor = router1.Get<NeighborTable>().FindNeighbor(br.Get<Mac::Mac>().GetExtAddress());
VerifyOrQuit(neighbor != nullptr);
VerifyOrQuit(neighbor->GetSupportedRadioTypes().Contains(Mac::kRadioTypeIeee802154));
VerifyOrQuit(neighbor->GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel));
}
/**
* Step 3
* - Device: Router_1
* - Description (TREL-8.1): Harness instructs device to send a ping (of size 500 bytes or more) to the DUT using
* the link-local IPv6 address as the destination. Note: The link-local IPv6 address may be derived from its
* extended address by retrieving neighbor info on Router_1 (at step 2). A larger ping size is used to verify
* behavior with a larger MTU payload on TREL.
* - Pass Criteria:
* - The DUT MUST send a ping response that is successfully received by Router_1.
* - The ping response packet MUST NOT be present in the 802.15.4 capture. (I.e. travels over TREL link.)
* - The TREL frames sent by DUT MUST use the correct TREL format.
*/
Log("Step 3: Router_1 pings the DUT using link-local address");
nexus.SendAndVerifyEchoRequest(router1, br.Get<Mle::Mle>().GetLinkLocalAddress(), kPingPayloadSize,
Ip6::kDefaultHopLimit, kPingResponseTimeout);
/**
* Step 4
* - Device: Router_2
* - Description (TREL-8.1): Harness instructs device to send a ping (of size 500 bytes or more) to the DUT using
* the link-local IPv6 address as the destination.
* - Pass Criteria:
* - The DUT MUST send a ping response that is successfully received by Router_2.
*/
Log("Step 4: Router_2 pings the DUT using link-local address");
nexus.SendAndVerifyEchoRequest(router2, br.Get<Mle::Mle>().GetLinkLocalAddress(), kPingPayloadSize,
Ip6::kDefaultHopLimit, kPingResponseTimeout);
/**
* Step 5
* - Device: Router_1
* - Description (TREL-8.1): Harness instructs device to send a ping (of size 500 bytes or more) to Router_2 using
* mesh-local EID of Router_2 as the destination. Note: this step indirectly verifies the broadcast
* communication by performing address query/resolution.
* - Pass Criteria:
* - The DUT MUST forward a ping response that is successfully received by Router_1
* - The TREL frames sent by DUT MUST use the correct TREL frame format.
*/
Log("Step 5: Router_1 pings Router_2 using mesh-local EID");
nexus.SendAndVerifyEchoRequest(router1, router2.Get<Mle::Mle>().GetMeshLocalEid(), kPingPayloadSize,
Ip6::kDefaultHopLimit, kPingResponseTimeout);
/**
* Step 6
* - Device: Router_2
* - Description (TREL-8.1): Harness instructs device to send a ping (of size 500 bytes or more) to Router_1 using
* mesh-local EID of Router_1 as destination.
* - Pass Criteria:
* - The DUT MUST forward a ping response that is successfully received by Router_2.
* - TREL frames sent by DUT MUST use the correct TREL format.
*/
Log("Step 6: Router_2 pings Router_1 using mesh-local EID");
nexus.SendAndVerifyEchoRequest(router2, router1.Get<Mle::Mle>().GetMeshLocalEid(), kPingPayloadSize,
Ip6::kDefaultHopLimit, kPingResponseTimeout);
nexus.SaveTestInfo("test_1_4_TREL_TC_1.json");
}
#endif // OPENTHREAD_CONFIG_MULTI_RADIO
} // namespace Nexus
} // namespace ot
int main(void)
{
#if OPENTHREAD_CONFIG_MULTI_RADIO
ot::Nexus::Test1_4_Trel_Tc_1();
printf("All tests passed\n");
#else
printf("Multi-radio is not enabled - test skipped\n");
#endif
return 0;
}
+224
View File
@@ -0,0 +1,224 @@
#!/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.1. [1.4] [CERT] Attach and connectivity (unicast/broadcast) between multi-radio and single-radio devices
#
# 8.1.1. Purpose
# To test the following:
# 1. Attaching Thread Devices with different radio links.
# 2. Verifies the detection of radio link types supported by neighbors/children.
# 3. Verifies connectivity between nodes (unicast and broadcast frame exchange with multi-radio support).
#
# Spec Reference | V1.1 Section | V1.3.0 Section
# -------------------------|--------------|---------------
# TREL / Multi-radio Links | N/A | 8.1
pkts = pv.pkts
pv.summary.show()
BR_DUT = pv.vars['BR_DUT']
ROUTER_1 = pv.vars['ROUTER_1']
ROUTER_2 = pv.vars['ROUTER_2']
BR_DUT_RLOC16 = pv.vars['BR_DUT_RLOC16']
ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16']
ROUTER_2_RLOC16 = pv.vars['ROUTER_2_RLOC16']
# Step 1
# - Device: BR (DUT), Router_1, Router_2
# - Description (TREL-8.1): Form the topology. Wait for Router_1 and Router_2 to become routers. Note: Router_1
# and Router_2 MUST NOT be able to communicate directly and not be in each others neighbor table (e.g. this
# may be realized by using the allow/deny list mechanism).
# - Pass Criteria:
# - Verify that topology is formed.
# - The DUT MUST be the network Leader.
# - Router_1 MUST only see Leader as its immediate neighbor (Router_2 MUST not be present in Router_1s
# neighbor table).
# - Router_2 MUST only see Leader as its immediate neighbor and not Router_1.
print("Step 1: Form the topology")
# Verify DUT is leader
pkts.filter_wpan_src64(BR_DUT).\
filter_mle_cmd(consts.MLE_ADVERTISEMENT).\
filter(lambda p: p.mle.tlv.leader_data.router_id == p.mle.tlv.source_addr >> 10).\
must_next()
# Verify Router_1 and Router_2 do not communicate directly on 15.4
pkts.filter_wpan_src64(ROUTER_1).filter_wpan_dst64(ROUTER_2).must_not_next()
pkts.filter_wpan_src64(ROUTER_2).filter_wpan_dst64(ROUTER_1).must_not_next()
# Step 2
# - Device: Router_1
# - Description (TREL-8.1): Harness instructs device to report its neighbor multi-radio info (which indicates
# which radio links are detected per neighbor/parent)
# - Pass Criteria:
# - Router_1 MUST have correctly detected that the DUT supports both TREL and 15.4 radios (multi-radio neighbor
# info).
# - The DUT MUST send TREL frames using the correct format
print("Step 2: Router_1 reports its neighbor multi-radio info")
# Verified by C++ code internally
# Step 3: Router_1 pings the DUT using link-local address
print("Step 3: Router_1 pings the DUT using link-local address")
# Verify ping request from ROUTER_1 to BR_DUT over TREL
# We can't easily decode ICMPv6 inside TREL if tshark fails, so we filter by UDP port and size.
pkts.filter_eth_src(pv.vars['ROUTER_1_ETH']).\
filter(lambda p: p.eth.dst == pv.vars['BR_DUT_ETH']).\
filter(lambda p: p.udp).\
filter(lambda p: p.udp.dstport == pv.vars['BR_DUT_TREL_PORT']).\
filter(lambda p: int(p.udp.length) > 500).\
must_next()
_idx_req = pkts.index
# Verify ping reply from BR_DUT to ROUTER_1 over TREL
pkts.filter_eth_src(pv.vars['BR_DUT_ETH']).\
filter(lambda p: p.eth.dst == pv.vars['ROUTER_1_ETH']).\
filter(lambda p: p.udp).\
filter(lambda p: p.udp.dstport == pv.vars['ROUTER_1_TREL_PORT']).\
filter(lambda p: int(p.udp.length) > 500).\
must_next()
_idx_reply = pkts.index
# Verify that there are no ping replies for this exchange on 15.4
pkts.range(_idx_req, _idx_reply).\
filter_ping_reply().\
filter(lambda p: p.wpan).\
must_not_next()
# Step 4: Router_2 pings the DUT using link-local address
print("Step 4: Router_2 pings the DUT using link-local address")
# Router_2 is 15.4 only, so ping should be over 15.4
_pkt = pkts.filter_ping_request().\
filter_ipv6_src(pv.vars['ROUTER_2_LLA']).\
filter_ipv6_dst(pv.vars['BR_DUT_LLA']).\
filter(lambda p: p.wpan).\
must_next()
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
filter_ipv6_src(pv.vars['BR_DUT_LLA']).\
filter_ipv6_dst(pv.vars['ROUTER_2_LLA']).\
filter(lambda p: p.wpan).\
must_next()
# Step 5: Router_1 pings Router_2 using mesh-local EID
print("Step 5: Router_1 pings Router_2 using mesh-local EID")
# Path: Router_1 -> BR_DUT (TREL) -> Router_2 (15.4)
# 1. Check forwarded request on 15.4 to get identifier
_pkt_154_req = pkts.filter_ping_request().\
filter_ipv6_src(pv.vars['ROUTER_1_MLEID']).\
filter_ipv6_dst(pv.vars['ROUTER_2_MLEID']).\
filter_wpan_src16_dst16(BR_DUT_RLOC16, ROUTER_2_RLOC16).\
filter(lambda p: p.wpan).\
must_next()
_identifier = _pkt_154_req.icmpv6.echo.identifier
# 2. Check original request on TREL (before the 15.4 one)
pkts.range((0, 0), pkts.index).\
filter_eth_src(pv.vars['ROUTER_1_ETH']).\
filter(lambda p: p.eth.dst == pv.vars['BR_DUT_ETH']).\
filter(lambda p: p.udp).\
filter(lambda p: p.udp.dstport == pv.vars['BR_DUT_TREL_PORT']).\
must_next()
# 3. Check reply from Router_2 back to BR_DUT over 15.4
_pkt_154_reply = pkts.filter_ping_reply(identifier=_identifier).\
filter_ipv6_src(pv.vars['ROUTER_2_MLEID']).\
filter_ipv6_dst(pv.vars['ROUTER_1_MLEID']).\
filter_wpan_src16_dst16(ROUTER_2_RLOC16, BR_DUT_RLOC16).\
filter(lambda p: p.wpan).\
must_next()
# 4. Check forwarded reply on TREL (after the 15.4 one)
pkts.range(pkts.index).\
filter_eth_src(pv.vars['BR_DUT_ETH']).\
filter(lambda p: p.eth.dst == pv.vars['ROUTER_1_ETH']).\
filter(lambda p: p.udp).\
filter(lambda p: p.udp.dstport == pv.vars['ROUTER_1_TREL_PORT']).\
must_next()
# Step 6: Router_2 pings Router_1 using mesh-local EID
print("Step 6: Router_2 pings Router_1 using mesh-local EID")
# Path: Router_2 -> BR_DUT (15.4) -> Router_1 (TREL)
# 1. Check request from Router_2 to BR_DUT over 15.4
_pkt_154_req = pkts.filter_ping_request().\
filter_ipv6_src(pv.vars['ROUTER_2_MLEID']).\
filter_ipv6_dst(pv.vars['ROUTER_1_MLEID']).\
filter_wpan_src16_dst16(ROUTER_2_RLOC16, BR_DUT_RLOC16).\
filter(lambda p: p.wpan).\
must_next()
_identifier = _pkt_154_req.icmpv6.echo.identifier
# 2. Check forwarded request on TREL
_idx_154_req = pkts.index
pkts.range(_idx_154_req).\
filter_eth_src(pv.vars['BR_DUT_ETH']).\
filter(lambda p: p.eth.dst == pv.vars['ROUTER_1_ETH']).\
filter(lambda p: p.udp).\
filter(lambda p: p.udp.dstport == pv.vars['ROUTER_1_TREL_PORT']).\
must_next()
# 3. Check reply from Router_1 back to BR_DUT over TREL
_idx_trel_req = pkts.index
pkts.range(_idx_trel_req).\
filter_eth_src(pv.vars['ROUTER_1_ETH']).\
filter(lambda p: p.eth.dst == pv.vars['BR_DUT_ETH']).\
filter(lambda p: p.udp).\
filter(lambda p: p.udp.dstport == pv.vars['BR_DUT_TREL_PORT']).\
must_next()
# 4. Check forwarded reply on 15.4
_idx_trel_reply = pkts.index
pkts.range(_idx_trel_reply).\
filter_ping_reply(identifier=_identifier).\
filter_ipv6_src(pv.vars['ROUTER_1_MLEID']).\
filter_ipv6_dst(pv.vars['ROUTER_2_MLEID']).\
filter_wpan_src16_dst16(BR_DUT_RLOC16, ROUTER_2_RLOC16).\
filter(lambda p: p.wpan).\
must_next()
if __name__ == '__main__':
verify_utils.run_main(verify)
+13
View File
@@ -495,6 +495,11 @@ def apply_patches():
from pktverify import consts, layer_fields
consts.VALID_LAYER_NAMES.add('wpan_tap')
consts.VALID_LAYER_NAMES.add('wpan-tap')
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
@@ -708,6 +713,14 @@ 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
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():
name = pv.test_info.get_node_name(int(node_id))