Files
openthread/tests/nexus/test_1_4_TREL_TC_2.cpp
Abtin Keshavarzian fbdf10fc42 [radio] move multi-radio link types to namespace Radio (#13334)
This commit moves multi-radio link type definitions under
`OPENTHREAD_CONFIG_MULTI_RADIO` from `Mac` to `namespace Radio`
in `radio_types.hpp`:

- `Mac::RadioType` -> `Radio::Type` (`kTypeIeee802154`, `kTypeTrel`)
- `Mac::kNumRadioTypes` -> `Radio::kNumTypes`
- `Mac::RadioTypes` -> `Radio::Types`

Moving these types to `namespace Radio` improves module encapsulation
and layering. Call sites across `src/core/` (`Mac`, `RadioSelector`,
`Message`) and Nexus tests are updated accordingly.
2026-07-15 13:05:56 -07:00

276 lines
13 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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 {
#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)
AllowLinkBetween(leader, router1);
// Leader <-> Router_2
AllowLinkBetween(leader, router2);
// Router_1 (DUT) <-> Router_3
AllowLinkBetween(router1, router3);
// Router_1 (DUT) <-> Router_4
AllowLinkBetween(router1, router4);
// Router_1 (DUT) <-> ED_1
AllowLinkBetween(router1, ed1);
// Enable TREL (mDNS) on all TREL nodes.
SuccessOrQuit(router1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
SuccessOrQuit(leader.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
SuccessOrQuit(router4.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
leader.Form();
nexus.AdvanceTime(kFormNetworkTime);
VerifyOrQuit(leader.Get<Mle::Mle>().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<Mle::Mle>().IsRouter());
VerifyOrQuit(router2.Get<Mle::Mle>().IsRouter());
VerifyOrQuit(router3.Get<Mle::Mle>().IsRouter());
VerifyOrQuit(router4.Get<Mle::Mle>().IsRouter());
VerifyOrQuit(ed1.Get<Mle::Mle>().IsChild());
VerifyOrQuit(ed1.Get<Mle::Mle>().GetParent().GetExtAddress() == router1.Get<Mac::Mac>().GetExtAddress());
// Verify neighbors
{
const Neighbor *neighbor = leader.Get<NeighborTable>().FindNeighbor(router1.Get<Mac::Mac>().GetExtAddress());
VerifyOrQuit(neighbor != nullptr);
VerifyOrQuit(neighbor->GetSupportedRadioTypes().Contains(ot::Radio::kTypeTrel));
}
{
const Neighbor *neighbor = router1.Get<NeighborTable>().FindNeighbor(router4.Get<Mac::Mac>().GetExtAddress());
VerifyOrQuit(neighbor != nullptr);
VerifyOrQuit(neighbor->GetSupportedRadioTypes().Contains(ot::Radio::kTypeTrel));
}
VerifyOrQuit(leader.Get<NeighborTable>().FindNeighbor(router2.Get<Mac::Mac>().GetExtAddress()) != nullptr);
VerifyOrQuit(router2.Get<NeighborTable>().FindNeighbor(leader.Get<Mac::Mac>().GetExtAddress()) != nullptr);
VerifyOrQuit(router2.Get<NeighborTable>().FindNeighbor(router1.Get<Mac::Mac>().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<Mle::Mle>().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<Mle::Mle>().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<Mle::Mle>().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<Mle::Mle>().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<Mle::Mle>().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<Mle::Mle>().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;
}