Skip to content

Commit 69c45ce

Browse files
authored
[nexus] add test 5.1.3 Router Address Reallocation (openthread#12365)
Adds a new Nexus test case for 'Router Address Reallocation – DUT attaches to new partition' (5.1.3) as specified in the test specification. Summary of changes: - Implemented Nexus test 5.1.3: - Added test_5_1_3.cpp: Sets up a Leader, Router_1 (DUT), and Router_2 topology. Uses AllowList to dynamically control connectivity, verifying that Router_1 reattaches to a new partition formed by Router_2 after the original Leader is removed. Uses direct core method calls and avoids magic numbers. - Added verify_5_1_3.py: PCAP verification script for test 5.1.3, ensuring MLE Parent Requests, Child ID Requests, and Address Solicit messages follow the specification. - Updated build and execution scripts: - Modified CMakeLists.txt to build the new 5.1.3 test executable. - Updated run_nexus_tests.sh to include 5.1.3 in the default test list.
1 parent 5144638 commit 69c45ce

File tree

4 files changed

+442
-0
lines changed

4 files changed

+442
-0
lines changed

tests/nexus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ endmacro()
115115

116116
ot_nexus_test(5_1_1)
117117
ot_nexus_test(5_1_2)
118+
ot_nexus_test(5_1_3)
118119
ot_nexus_test(border_agent)
119120
ot_nexus_test(border_agent_tracker)
120121
ot_nexus_test(discover_scan)

tests/nexus/run_nexus_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ NEXUS_BIN_DIR="${BUILD_DIR}/tests/nexus"
5050
DEFAULT_TESTS=(
5151
"5_1_1"
5252
"5_1_2"
53+
"5_1_3"
5354
)
5455

5556
# Use provided arguments or the default test list

tests/nexus/test_5_1_3.cpp

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
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 <stdio.h>
30+
31+
#include "platform/nexus_core.hpp"
32+
#include "platform/nexus_node.hpp"
33+
34+
namespace ot {
35+
namespace Nexus {
36+
37+
/**
38+
* Time to advance for a node to form a network and become leader, in milliseconds.
39+
*/
40+
static constexpr uint32_t kFormNetworkTime = 13 * 1000;
41+
42+
/**
43+
* Time to advance for a node to join as a child and upgrade to a router, in milliseconds.
44+
*/
45+
static constexpr uint32_t kAttachToRouterTime = 200 * 1000;
46+
47+
/**
48+
* Maximum value for Partition ID.
49+
*/
50+
static constexpr uint32_t kMaxPartitionId = 0xffffffff;
51+
52+
/**
53+
* Network ID Timeout for Router_2, in seconds.
54+
*/
55+
static constexpr uint8_t kRouter2NetworkIdTimeout = 100;
56+
57+
/**
58+
* Network ID Timeout for Router_1 (DUT), in seconds.
59+
*/
60+
static constexpr uint8_t kRouter1NetworkIdTimeout = 120;
61+
62+
/**
63+
* Time to wait for Router_2 to time out and become leader, in milliseconds.
64+
*/
65+
static constexpr uint32_t kRouter2TimeoutWaitTime = (kRouter2NetworkIdTimeout + 20) * 1000;
66+
67+
/**
68+
* Total time to wait for Router_1 (DUT) to time out and reattach, in milliseconds.
69+
* This accounts for the 120s timeout plus a small buffer for state transitions.
70+
*/
71+
static constexpr uint32_t kRouter1TotalTimeoutWaitTime = (kRouter1NetworkIdTimeout + 20) * 1000;
72+
73+
/**
74+
* Incremental time to advance for Router_1 (DUT) reattachment, in milliseconds.
75+
*/
76+
static constexpr uint32_t kRouter1TimeoutWaitTime = kRouter1TotalTimeoutWaitTime - kRouter2TimeoutWaitTime;
77+
78+
void Test5_1_3(void)
79+
{
80+
/**
81+
* 5.1.3 Router Address Reallocation – DUT attaches to new partition
82+
*
83+
* 5.1.3.1 Topology
84+
* - Set Partition ID on Leader to max value
85+
* - Set Router_2 NETWORK_ID_TIMEOUT to 110 seconds (10 seconds faster than default). If the DUT uses a timeout
86+
* faster than default, timing may need to be adjusted.
87+
*
88+
* 5.1.3.2 Purpose & Description
89+
* The purpose of this test case is to verify that after the removal of the Leader from the network, the DUT will
90+
* first attempt to reattach to the original partition (P1), and then attach to a new partition (P2).
91+
*
92+
* Spec Reference | V1.1 Section | V1.3.0 Section
93+
* -------------------------------------------|-----------------|-----------------
94+
* Router ID Management / Router ID Assignment | 5.9.9 / 5.9.10 | 5.9.9 / 5.9.10
95+
*/
96+
97+
Core nexus;
98+
99+
Node &leader = nexus.CreateNode();
100+
Node &router1 = nexus.CreateNode();
101+
Node &router2 = nexus.CreateNode();
102+
103+
leader.SetName("LEADER");
104+
router1.SetName("ROUTER_1");
105+
router2.SetName("ROUTER_2");
106+
107+
nexus.AdvanceTime(0);
108+
109+
Instance::SetLogLevel(kLogLevelInfo);
110+
111+
/**
112+
* Step 1: Router_2
113+
* - Description: Harness configures the NETWORK ID TIMEOUT to be 110 seconds.
114+
* - Pass Criteria: N/A
115+
*/
116+
router2.Get<Mle::Mle>().SetNetworkIdTimeout(kRouter2NetworkIdTimeout);
117+
118+
/**
119+
* Step 2: All
120+
* - Description: Verify topology is formed correctly
121+
* - Pass Criteria: N/A
122+
*/
123+
124+
/** Use AllowList feature to restrict the topology. */
125+
leader.AllowList(router1);
126+
router1.AllowList(leader);
127+
128+
leader.AllowList(router2);
129+
router2.AllowList(leader);
130+
131+
router1.AllowList(router2);
132+
router2.AllowList(router1);
133+
134+
leader.Get<Mle::Mle>().SetPreferredLeaderPartitionId(kMaxPartitionId);
135+
leader.Form();
136+
nexus.AdvanceTime(kFormNetworkTime);
137+
VerifyOrQuit(leader.Get<Mle::Mle>().IsLeader());
138+
139+
router1.Join(leader);
140+
nexus.AdvanceTime(kAttachToRouterTime);
141+
VerifyOrQuit(router1.Get<Mle::Mle>().IsRouter());
142+
143+
router2.Join(leader);
144+
nexus.AdvanceTime(kAttachToRouterTime);
145+
VerifyOrQuit(router2.Get<Mle::Mle>().IsRouter());
146+
147+
/**
148+
* Step 3: Leader
149+
* - Description: Harness silently powers-off the Leader
150+
* - Pass Criteria: N/A
151+
*/
152+
leader.Get<Mle::Mle>().Stop();
153+
154+
/**
155+
* Step 4: Router_2
156+
* - Description: Times out after 110 seconds and automatically creates a new partition (P2) with itself as the
157+
* Leader of P2
158+
* - Pass Criteria: N/A
159+
*/
160+
nexus.AdvanceTime(kRouter2TimeoutWaitTime);
161+
VerifyOrQuit(router2.Get<Mle::Mle>().IsLeader());
162+
163+
/**
164+
* Step 5: Router_1 (DUT)
165+
* - Description: Times out after 120 seconds and automatically attempts to reattach to original partition (P1)
166+
* - Pass Criteria:
167+
* - The DUT MUST attempt to reattach to its original partition (P1) by sending a MLE Parent Request with an IP
168+
* Hop Limit of 255 to the Link-Local All-Routers multicast address (FF02::2).
169+
* - The following TLVs MUST be present in the MLE Parent Request:
170+
* - Challenge TLV
171+
* - Mode TLV
172+
* - Scan Mask TLV (MUST have E and R flags set)
173+
* - Version TLV
174+
* - The DUT MUST make two separate attempts to reconnect to its original partition (P1) in this manner.
175+
*/
176+
nexus.AdvanceTime(kRouter1TimeoutWaitTime);
177+
178+
/**
179+
* Step 6: Router_1 (DUT)
180+
* - Description: Automatically attempts to attach to any other partition
181+
* - Pass Criteria:
182+
* - The DUT MUST attempt to attach to any other partition within range by sending a MLE Parent Request.
183+
* - The following TLVs MUST be present in the MLE Parent Request:
184+
* - Challenge TLV
185+
* - Mode TLV
186+
* - Scan Mask TLV
187+
* - Version TLV
188+
*/
189+
190+
/**
191+
* Step 7: Router_1 (DUT)
192+
* - Description: Automatically attaches to Router_2’s partition (P2)
193+
* - Pass Criteria:
194+
* - The DUT MUST send a properly formatted Child ID Request to Router_2.
195+
* - The following TLVs MUST be present in the Child ID Request:
196+
* - Link-layer Frame Counter TLV
197+
* - Mode TLV
198+
* - Response TLV
199+
* - Timeout TLV
200+
* - TLV Request TLV
201+
* - Version TLV
202+
* - MLE Frame Counter TLV (optional)
203+
* - The following TLV MUST NOT be present in the Child ID Request:
204+
* - Address Registration TLV
205+
*/
206+
207+
/**
208+
* Step 8: Router_1 (DUT)
209+
* - Description: Automatically sends Address Solicit Request
210+
* - Pass Criteria:
211+
* - The DUT MUST send an Address Solicit Request.
212+
* - Ensure the Address Solicit Request is properly formatted:
213+
* - CoAP Request URI: coap://[<leader address>]:MM/a/as
214+
* - CoAP Payload:
215+
* - MAC Extended Address TLV
216+
* - Status TLV
217+
* - RLOC16 TLV (optional)
218+
*/
219+
nexus.AdvanceTime(kAttachToRouterTime);
220+
VerifyOrQuit(router1.Get<Mle::Mle>().IsRouter());
221+
222+
/**
223+
* Step 9: Router_2
224+
* - Description: Automatically responds with Address Solicit Response Message
225+
* - Pass Criteria: N/A
226+
*/
227+
228+
nexus.SaveTestInfo("test_5_1_3.json");
229+
}
230+
231+
} // namespace Nexus
232+
} // namespace ot
233+
234+
int main(void)
235+
{
236+
ot::Nexus::Test5_1_3();
237+
printf("All tests passed\n");
238+
return 0;
239+
}

0 commit comments

Comments
 (0)