1 /*
2 * Copyright (c) 2018, 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 "test_platform.h"
30
31 #include <openthread/config.h>
32
33 #include "test_util.h"
34 #include "common/code_utils.hpp"
35 #include "instance/instance.hpp"
36 #include "thread/child.hpp"
37
38 namespace ot {
39
40 static Instance *sInstance;
41
42 enum
43 {
44 kMaxChildIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD,
45 };
46
VerifyChildIp6Addresses(const Child & aChild,uint8_t aAddressListLength,const Ip6::Address aAddressList[])47 void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, const Ip6::Address aAddressList[])
48 {
49 Ip6::Address::TypeFilter filters[] = {Ip6::Address::kTypeUnicast, Ip6::Address::kTypeMulticast};
50 bool addressObserved[kMaxChildIp6Addresses];
51 bool hasMeshLocal = false;
52
53 for (uint8_t index = 0; index < aAddressListLength; index++)
54 {
55 VerifyOrQuit(aChild.HasIp6Address(aAddressList[index]));
56 }
57
58 memset(addressObserved, 0, sizeof(addressObserved));
59
60 for (const Ip6::Address &address : aChild.GetIp6Addresses())
61 {
62 bool addressIsInList = false;
63
64 for (uint8_t index = 0; index < aAddressListLength; index++)
65 {
66 if (address == aAddressList[index])
67 {
68 addressIsInList = true;
69 addressObserved[index] = true;
70 break;
71 }
72 }
73
74 VerifyOrQuit(addressIsInList, "Child::IterateIp6Addresses() returned an address not in the expected list");
75 }
76
77 for (uint8_t index = 0; index < aAddressListLength; index++)
78 {
79 Ip6::Address address;
80
81 if (sInstance->Get<Mle::MleRouter>().IsMeshLocalAddress(aAddressList[index]))
82 {
83 SuccessOrQuit(aChild.GetMeshLocalIp6Address(address));
84 VerifyOrQuit(address == aAddressList[index], "GetMeshLocalIp6Address() did not return expected address");
85 hasMeshLocal = true;
86 }
87 else
88 {
89 VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");
90 }
91 }
92
93 if (!hasMeshLocal)
94 {
95 Ip6::Address address;
96
97 VerifyOrQuit(aChild.GetMeshLocalIp6Address(address) == kErrorNotFound,
98 "Child::GetMeshLocalIp6Address() returned an address not in the expected list");
99 }
100 }
101
TestChildIp6Address(void)102 void TestChildIp6Address(void)
103 {
104 Child child;
105 Ip6::Address addresses[kMaxChildIp6Addresses];
106 uint8_t numAddresses;
107 const char *ip6Addresses[] = {
108 "fd00:1234::1234",
109 "ff6b:e251:52fb:0:12e6:b94c:1c28:c56a",
110 "fd00:1234::204c:3d7c:98f6:9a1b",
111 };
112
113 const uint8_t meshLocalIidArray[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
114 Ip6::InterfaceIdentifier meshLocalIid;
115
116 meshLocalIid.SetBytes(meshLocalIidArray);
117
118 sInstance = testInitInstance();
119 VerifyOrQuit(sInstance != nullptr);
120
121 child.Init(*sInstance);
122
123 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
124
125 printf("\nConverting IPv6 addresses from string");
126
127 numAddresses = 0;
128
129 // First addresses uses the mesh local prefix (mesh-local address).
130 addresses[numAddresses] = sInstance->Get<Mle::MleRouter>().GetMeshLocalEid();
131 addresses[numAddresses].SetIid(meshLocalIid);
132
133 numAddresses++;
134
135 for (const char *ip6Address : ip6Addresses)
136 {
137 VerifyOrQuit(numAddresses < kMaxChildIp6Addresses, "Too many IPv6 addresses in the unit test");
138 SuccessOrQuit(addresses[numAddresses++].FromString(ip6Address));
139 }
140
141 printf(" -- PASS\n");
142
143 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
144 printf("Child state after init");
145 child.Clear();
146 VerifyChildIp6Addresses(child, 0, nullptr);
147 printf(" -- PASS\n");
148
149 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
150 printf("Adding a single IPv6 address");
151
152 for (uint8_t index = 0; index < numAddresses; index++)
153 {
154 SuccessOrQuit(child.AddIp6Address(addresses[index]));
155 VerifyChildIp6Addresses(child, 1, &addresses[index]);
156
157 child.ClearIp6Addresses();
158 VerifyChildIp6Addresses(child, 0, nullptr);
159 }
160
161 printf(" -- PASS\n");
162
163 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164 printf("Adding multiple IPv6 addresses");
165
166 for (uint8_t index = 0; index < numAddresses; index++)
167 {
168 SuccessOrQuit(child.AddIp6Address(addresses[index]));
169 VerifyChildIp6Addresses(child, index + 1, addresses);
170 }
171
172 printf(" -- PASS\n");
173
174 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175 printf("Checking for failure when adding an address already in list");
176
177 for (uint8_t index = 0; index < numAddresses; index++)
178 {
179 VerifyOrQuit(child.AddIp6Address(addresses[index]) == kErrorAlready,
180 "AddIp6Address() did not fail when adding same address");
181 VerifyChildIp6Addresses(child, numAddresses, addresses);
182 }
183
184 printf(" -- PASS\n");
185
186 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187 printf("Removing addresses from list starting from front of the list");
188
189 for (uint8_t index = 0; index < numAddresses; index++)
190 {
191 SuccessOrQuit(child.RemoveIp6Address(addresses[index]));
192 VerifyChildIp6Addresses(child, numAddresses - 1 - index, &addresses[index + 1]);
193
194 VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == kErrorNotFound,
195 "RemoveIp6Address() did not fail when removing an address not on the list");
196 }
197
198 VerifyChildIp6Addresses(child, 0, nullptr);
199 printf(" -- PASS\n");
200
201 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
202 printf("Removing addresses from list starting from back of the list");
203
204 for (uint8_t index = 0; index < numAddresses; index++)
205 {
206 SuccessOrQuit(child.AddIp6Address(addresses[index]));
207 }
208
209 for (uint8_t index = numAddresses - 1; index > 0; index--)
210 {
211 SuccessOrQuit(child.RemoveIp6Address(addresses[index]));
212 VerifyChildIp6Addresses(child, index, &addresses[0]);
213
214 VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == kErrorNotFound,
215 "RemoveIp6Address() did not fail when removing an address not on the list");
216 }
217
218 printf(" -- PASS\n");
219
220 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
221 printf("Removing address entries from middle of the list");
222
223 for (uint8_t indexToRemove = 1; indexToRemove < numAddresses - 1; indexToRemove++)
224 {
225 child.ClearIp6Addresses();
226
227 for (uint8_t index = 0; index < numAddresses; index++)
228 {
229 SuccessOrQuit(child.AddIp6Address(addresses[index]));
230 }
231
232 SuccessOrQuit(child.RemoveIp6Address(addresses[indexToRemove]));
233
234 VerifyOrQuit(child.RemoveIp6Address(addresses[indexToRemove]) == kErrorNotFound,
235 "RemoveIp6Address() did not fail when removing an address not on the list");
236
237 {
238 Ip6::Address updatedAddressList[kMaxChildIp6Addresses];
239 uint8_t updatedListIndex = 0;
240
241 for (uint8_t index = 0; index < numAddresses; index++)
242 {
243 if (index != indexToRemove)
244 {
245 updatedAddressList[updatedListIndex++] = addresses[index];
246 }
247 }
248
249 VerifyChildIp6Addresses(child, updatedListIndex, updatedAddressList);
250 }
251 }
252
253 printf(" -- PASS\n");
254
255 testFreeInstance(sInstance);
256 }
257
258 } // namespace ot
259
main(void)260 int main(void)
261 {
262 ot::TestChildIp6Address();
263 printf("\nAll tests passed.\n");
264 return 0;
265 }
266