Skip to content

Commit 60813b8

Browse files
authored
[nexus] add test case 5.1.1 (Attaching) (openthread#12353)
This commit adds a new Nexus test case to verify the "5.1.1 Attaching" scenario from the Thread certification specification. The test case verifies that: 1. A node can form a network and become a Leader. 2. A second node can join the network and become a Router. 3. Connectivity between the Leader and Router is functional using ICMPv6 Echo to Link-Local addresses, verifying both roles as DUT. The test ensures basic network formation and attachment functionality within the Nexus simulation environment.
1 parent 5051fd1 commit 60813b8

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

tests/nexus/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ set(COMMON_INCLUDES
3030
${PROJECT_SOURCE_DIR}/include
3131
${PROJECT_SOURCE_DIR}/src
3232
${PROJECT_SOURCE_DIR}/src/core
33+
${PROJECT_SOURCE_DIR}/tests/nexus
3334
${PROJECT_SOURCE_DIR}/tests/nexus/platform
3435
)
3536

@@ -112,6 +113,7 @@ endmacro()
112113

113114
#----------------------------------------------------------------------------------------------------------------------
114115

116+
ot_nexus_test(5_1_1)
115117
ot_nexus_test(border_agent)
116118
ot_nexus_test(border_agent_tracker)
117119
ot_nexus_test(dtls)

tests/nexus/test_5_1_1.cpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
* Copyright (c) 2026, The OpenThread Authors.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* 3. Neither the name of the copyright holder nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*/
28+
29+
#include <stdarg.h>
30+
#include <stdio.h>
31+
32+
#include "platform/nexus_core.hpp"
33+
#include "platform/nexus_node.hpp"
34+
35+
namespace ot {
36+
namespace Nexus {
37+
38+
/**
39+
* Time to advance for a node to form a network and become leader.
40+
*/
41+
static constexpr uint32_t kFormNetworkTime = 13 * 1000;
42+
43+
/**
44+
* Time to advance for a node to join as a child and upgrade to a router.
45+
* This duration accounts for MLE attach process and ROUTER_SELECTION_JITTER.
46+
*/
47+
static constexpr uint32_t kAttachToRouterTime = 200 * 1000;
48+
49+
/**
50+
* Time to wait for ICMPv6 Echo Reply.
51+
*/
52+
static constexpr uint32_t kEchoResponseTime = 1000;
53+
54+
static void HandleEchoReply(void *aContext,
55+
otMessage *aMessage,
56+
const otMessageInfo *aMessageInfo,
57+
const otIcmp6Header *aIcmpHeader)
58+
{
59+
OT_UNUSED_VARIABLE(aMessage);
60+
OT_UNUSED_VARIABLE(aMessageInfo);
61+
62+
if (aIcmpHeader->mType == OT_ICMP6_TYPE_ECHO_REPLY)
63+
{
64+
*static_cast<bool *>(aContext) = true;
65+
}
66+
}
67+
68+
static void SendAndVerifyEchoRequest(Core &aNexus, Node &aSender, Node &aReceiver, bool &aReceivedEchoReply)
69+
{
70+
Message *message = aSender.Get<Ip6::Icmp>().NewMessage();
71+
Ip6::MessageInfo messageInfo;
72+
73+
VerifyOrQuit(message != nullptr);
74+
75+
messageInfo.SetPeerAddr(aReceiver.Get<Mle::Mle>().GetLinkLocalAddress());
76+
messageInfo.SetHopLimit(64);
77+
78+
aReceivedEchoReply = false;
79+
SuccessOrQuit(aSender.Get<Ip6::Icmp>().SendEchoRequest(*message, messageInfo, 0x1234));
80+
81+
aNexus.AdvanceTime(kEchoResponseTime);
82+
VerifyOrQuit(aReceivedEchoReply, "Echo Reply not received");
83+
}
84+
85+
void Test5_1_1(void)
86+
{
87+
/**
88+
* 5.1.1 Attaching
89+
*
90+
* 5.1.1.1 Topology
91+
* - Topology A
92+
* - Topology B
93+
*
94+
* 5.1.1.2 Purpose & Description
95+
* The purpose of this test case is to show that the DUT is able to both form and attach to a network.
96+
* This test case must be executed twice, first - where the DUT is a Leader and forms a network,
97+
* and second - where the DUT is a router and attaches to a network.
98+
*
99+
* Spec Reference | V1.1 Section | V1.3.0 Section
100+
* ------------------------|--------------|---------------
101+
* Attaching to a Parent | 4.7.1 | 4.5.1
102+
*/
103+
104+
Core nexus;
105+
106+
Node &leader = nexus.CreateNode();
107+
Node &router = nexus.CreateNode();
108+
109+
nexus.AdvanceTime(0);
110+
111+
Instance::SetLogLevel(kLogLevelInfo);
112+
113+
Log("---------------------------------------------------------------------------------------");
114+
Log("Step 1: Leader forms network");
115+
116+
/**
117+
* Step 1: Leader
118+
* - Description: Automatically transmits MLE advertisements.
119+
* - Pass Criteria:
120+
* - Leader is sending properly formatted MLE Advertisements.
121+
* - Advertisements MUST be sent with an IP Hop Limit of 255 to the Link-Local All Nodes multicast address
122+
* (FF02::1).
123+
* - The following TLVs MUST be present in the MLE Advertisements:
124+
* - Leader Data TLV
125+
* - Route64 TLV
126+
* - Source Address TLV
127+
*/
128+
leader.Form();
129+
nexus.AdvanceTime(kFormNetworkTime);
130+
VerifyOrQuit(leader.Get<Mle::Mle>().IsLeader());
131+
132+
Log("---------------------------------------------------------------------------------------");
133+
Log("Step 2-10: Router attaches to Leader and becomes a router");
134+
135+
/**
136+
* Step 2: Router_1
137+
* - Description: Automatically begins the attach process by sending a multicast MLE Parent Request.
138+
*
139+
* Step 3: Leader
140+
* - Description: Automatically responds with a MLE Parent Response.
141+
*
142+
* Step 4: Router_1
143+
* - Description: Automatically responds to the MLE Parent Response by sending a MLE Child ID Request.
144+
*
145+
* Step 5: Leader
146+
* - Description: Automatically unicasts a MLE Child ID Response.
147+
*
148+
* Step 6: Router_1
149+
* - Description: Automatically sends an Address Solicit Request.
150+
*
151+
* Step 7: Leader
152+
* - Description: Automatically sends an Address Solicit Response.
153+
*
154+
* Step 8: Router_1
155+
* - Description: Automatically multicasts a Link Request Message (optional).
156+
*
157+
* Step 9: Leader
158+
* - Description: Automatically unicasts a Link Accept message (conditional).
159+
*
160+
* Step 10: Router_1
161+
* - Description: Automatically transmits MLE advertisements.
162+
*/
163+
router.Join(leader);
164+
nexus.AdvanceTime(kAttachToRouterTime);
165+
VerifyOrQuit(router.Get<Mle::Mle>().IsRouter());
166+
167+
Log("---------------------------------------------------------------------------------------");
168+
Log("Step 11: Verify connectivity using ICMPv6 Echo");
169+
170+
/**
171+
* Step 11: Leader Or Router_1 (not the DUT)
172+
* - Description: Harness verifies connectivity by instructing the reference device to send a ICMPv6 Echo Request to
173+
* the DUT link-local address.
174+
* - Pass Criteria:
175+
* - The DUT MUST respond with ICMPv6 Echo Reply
176+
*/
177+
bool routerReceivedEchoReply = false;
178+
Ip6::Icmp::Handler routerIcmpHandler(HandleEchoReply, &routerReceivedEchoReply);
179+
bool leaderReceivedEchoReply = false;
180+
Ip6::Icmp::Handler leaderIcmpHandler(HandleEchoReply, &leaderReceivedEchoReply);
181+
182+
// 1. Verify Leader as DUT: Router (Reference) sends Echo Request to Leader (DUT) Link-Local address
183+
SuccessOrQuit(router.Get<Ip6::Icmp>().RegisterHandler(routerIcmpHandler));
184+
185+
Log("Step 11.1: Sending Echo Request from Router to Leader Link-Local: %s",
186+
leader.Get<Mle::Mle>().GetLinkLocalAddress().ToString().AsCString());
187+
SendAndVerifyEchoRequest(nexus, router, leader, routerReceivedEchoReply);
188+
Log("Leader (as DUT) responded with Echo Reply successfully");
189+
190+
// 2. Verify Router as DUT: Leader (Reference) sends Echo Request to Router (DUT) Link-Local address
191+
SuccessOrQuit(leader.Get<Ip6::Icmp>().RegisterHandler(leaderIcmpHandler));
192+
193+
Log("Step 11.2: Sending Echo Request from Leader to Router Link-Local: %s",
194+
router.Get<Mle::Mle>().GetLinkLocalAddress().ToString().AsCString());
195+
SendAndVerifyEchoRequest(nexus, leader, router, leaderReceivedEchoReply);
196+
Log("Router (as DUT) responded with Echo Reply successfully");
197+
}
198+
199+
} // namespace Nexus
200+
} // namespace ot
201+
202+
int main(void)
203+
{
204+
ot::Nexus::Test5_1_1();
205+
printf("All tests passed\n");
206+
return 0;
207+
}

0 commit comments

Comments
 (0)