1 /*
2 * Copyright (c) 2024, 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 #include <string.h>
32
33 #include "platform/nexus_core.hpp"
34 #include "platform/nexus_node.hpp"
35
36 namespace ot {
37 namespace Nexus {
38
39 static constexpr uint16_t kNumberOfRoles = (Mle::kRoleLeader + 1);
40
41 typedef uint16_t RoleStats[kNumberOfRoles];
42
CaculateRoleStats(Core & aNexus,RoleStats & aRoleStats)43 static void CaculateRoleStats(Core &aNexus, RoleStats &aRoleStats)
44 {
45 ClearAllBytes(aRoleStats);
46
47 for (Node &node : aNexus.GetNodes())
48 {
49 aRoleStats[node.Get<Mle::Mle>().GetRole()]++;
50 }
51 }
52
CheckRoleStats(const RoleStats & aRoleStats)53 static bool CheckRoleStats(const RoleStats &aRoleStats)
54 {
55 return (aRoleStats[Mle::kRoleLeader] == 1) && (aRoleStats[Mle::kRoleDetached] == 0) &&
56 (aRoleStats[Mle::kRoleDisabled] == 0);
57 }
58
Test(void)59 void Test(void)
60 {
61 static constexpr uint16_t kNumNodes = 200;
62
63 // All times in msec
64 static constexpr uint32_t kMaxWaitTime = 20 * Time::kOneMinuteInMsec;
65 static constexpr uint32_t kStatCollectionInterval = 125;
66 static constexpr uint32_t kExtraSimulTimAfterPass = 5 * Time::kOneSecondInMsec;
67
68 Core nexus;
69 Node *leader;
70 RoleStats roleStats;
71
72 for (uint16_t i = 0; i < kNumNodes; i++)
73 {
74 nexus.CreateNode();
75 }
76
77 nexus.AdvanceTime(0);
78
79 Log("Starting %u nodes simultaneously", kNumNodes);
80
81 leader = nexus.GetNodes().GetHead();
82 leader->Form();
83
84 for (Node &node : nexus.GetNodes())
85 {
86 if (&node == leader)
87 {
88 continue;
89 }
90
91 node.Join(*leader);
92 }
93
94 for (uint32_t step = 0; step < kMaxWaitTime / kStatCollectionInterval; step++)
95 {
96 if ((step % 20) == 0)
97 {
98 Log("+----------+----------+----------+----------+----------+");
99 Log("| Leader | Router | Child | Detached | Disabled |");
100 Log("+----------+----------+----------+----------+----------+");
101 }
102
103 CaculateRoleStats(nexus, roleStats);
104
105 Log("| %8u | %8u | %8u | %8u | %8u |", roleStats[Mle::kRoleLeader], roleStats[Mle::kRoleRouter],
106 roleStats[Mle::kRoleChild], roleStats[Mle::kRoleDetached], roleStats[Mle::kRoleDisabled]);
107
108 nexus.AdvanceTime(kStatCollectionInterval);
109
110 if (CheckRoleStats(roleStats))
111 {
112 break;
113 }
114 }
115
116 VerifyOrQuit(CheckRoleStats(roleStats));
117
118 Log("=========================================================");
119 Log("All nodes are now part of the same partition");
120 Log("Network stabilized after %u sec", nexus.GetNow().GetValue() / Time::kOneSecondInMsec);
121 Log("Continue simulation for another %u sec", kExtraSimulTimAfterPass / Time::kOneSecondInMsec);
122 Log("=========================================================");
123
124 for (uint32_t step = 0; step < kExtraSimulTimAfterPass / kStatCollectionInterval; step++)
125 {
126 if ((step % 20) == 0)
127 {
128 Log("+----------+----------+----------+----------+----------+");
129 Log("| Leader | Router | Child | Detached | Disabled |");
130 Log("+----------+----------+----------+----------+----------+");
131 }
132
133 CaculateRoleStats(nexus, roleStats);
134
135 Log("| %8u | %8u | %8u | %8u | %8u |", roleStats[Mle::kRoleLeader], roleStats[Mle::kRoleRouter],
136 roleStats[Mle::kRoleChild], roleStats[Mle::kRoleDetached], roleStats[Mle::kRoleDisabled]);
137
138 nexus.AdvanceTime(kStatCollectionInterval);
139 }
140 }
141
142 } // namespace Nexus
143 } // namespace ot
144
main(void)145 int main(void)
146 {
147 ot::Nexus::Test();
148 printf("All tests passed\n");
149 return 0;
150 }
151