1 /*
2 * Copyright (c) 2016, 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 "common/code_utils.hpp"
30 #include "common/debug.hpp"
31 #include "mac/mac.hpp"
32 #include "mac/mac_frame.hpp"
33 #include "radio/radio.hpp"
34
35 #include "test_platform.h"
36 #include "test_util.hpp"
37
38 namespace ot {
39
CompareReversed(const uint8_t * aFirst,const uint8_t * aSecond,uint16_t aLength)40 bool CompareReversed(const uint8_t *aFirst, const uint8_t *aSecond, uint16_t aLength)
41 {
42 bool matches = true;
43
44 for (uint16_t i = 0; i < aLength; i++)
45 {
46 if (aFirst[i] != aSecond[aLength - 1 - i])
47 {
48 matches = false;
49 break;
50 }
51 }
52
53 return matches;
54 }
55
CompareAddresses(const Mac::Address & aFirst,const Mac::Address & aSecond)56 bool CompareAddresses(const Mac::Address &aFirst, const Mac::Address &aSecond)
57 {
58 bool matches = false;
59
60 VerifyOrExit(aFirst.GetType() == aSecond.GetType());
61
62 switch (aFirst.GetType())
63 {
64 case Mac::Address::kTypeNone:
65 break;
66 case Mac::Address::kTypeShort:
67 VerifyOrExit(aFirst.GetShort() == aSecond.GetShort());
68 break;
69 case Mac::Address::kTypeExtended:
70 VerifyOrExit(aFirst.GetExtended() == aSecond.GetExtended());
71 break;
72 }
73
74 matches = true;
75
76 exit:
77 return matches;
78 }
79
TestMacAddress(void)80 void TestMacAddress(void)
81 {
82 const uint8_t kExtAddr[OT_EXT_ADDRESS_SIZE] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
83 const Mac::ShortAddress kShortAddr = 0x1234;
84
85 Instance *instance;
86 Mac::Address addr;
87 Mac::ExtAddress extAddr;
88 uint8_t buffer[OT_EXT_ADDRESS_SIZE];
89
90 instance = testInitInstance();
91 VerifyOrQuit(instance != nullptr, "nullptr instance\n");
92
93 // Mac::ExtAddress
94
95 extAddr.GenerateRandom();
96 VerifyOrQuit(extAddr.IsLocal(), "Random Extended Address should have its Local bit set");
97 VerifyOrQuit(!extAddr.IsGroup(), "Random Extended Address should not have its Group bit set");
98
99 extAddr.CopyTo(buffer);
100 VerifyOrQuit(memcmp(extAddr.m8, buffer, OT_EXT_ADDRESS_SIZE) == 0);
101
102 extAddr.CopyTo(buffer, Mac::ExtAddress::kReverseByteOrder);
103 VerifyOrQuit(CompareReversed(extAddr.m8, buffer, OT_EXT_ADDRESS_SIZE));
104
105 extAddr.Set(kExtAddr);
106 VerifyOrQuit(memcmp(extAddr.m8, kExtAddr, OT_EXT_ADDRESS_SIZE) == 0);
107
108 extAddr.Set(kExtAddr, Mac::ExtAddress::kReverseByteOrder);
109 VerifyOrQuit(CompareReversed(extAddr.m8, kExtAddr, OT_EXT_ADDRESS_SIZE));
110
111 extAddr.SetLocal(true);
112 VerifyOrQuit(extAddr.IsLocal());
113 extAddr.SetLocal(false);
114 VerifyOrQuit(!extAddr.IsLocal());
115 extAddr.ToggleLocal();
116 VerifyOrQuit(extAddr.IsLocal());
117 extAddr.ToggleLocal();
118 VerifyOrQuit(!extAddr.IsLocal());
119
120 extAddr.SetGroup(true);
121 VerifyOrQuit(extAddr.IsGroup());
122 extAddr.SetGroup(false);
123 VerifyOrQuit(!extAddr.IsGroup());
124 extAddr.ToggleGroup();
125 VerifyOrQuit(extAddr.IsGroup());
126 extAddr.ToggleGroup();
127 VerifyOrQuit(!extAddr.IsGroup());
128
129 // Mac::Address
130
131 VerifyOrQuit(addr.IsNone(), "Address constructor failed");
132 VerifyOrQuit(addr.GetType() == Mac::Address::kTypeNone);
133
134 addr.SetShort(kShortAddr);
135 VerifyOrQuit(addr.GetType() == Mac::Address::kTypeShort);
136 VerifyOrQuit(addr.IsShort(), "Address::SetShort() failed");
137 VerifyOrQuit(!addr.IsExtended(), "Address::SetShort() failed");
138 VerifyOrQuit(addr.GetShort() == kShortAddr);
139
140 addr.SetExtended(extAddr);
141 VerifyOrQuit(addr.GetType() == Mac::Address::kTypeExtended);
142 VerifyOrQuit(!addr.IsShort(), "Address::SetExtended() failed");
143 VerifyOrQuit(addr.IsExtended(), "Address::SetExtended() failed");
144 VerifyOrQuit(addr.GetExtended() == extAddr);
145
146 addr.SetExtended(extAddr.m8, Mac::ExtAddress::kReverseByteOrder);
147 VerifyOrQuit(addr.GetType() == Mac::Address::kTypeExtended);
148 VerifyOrQuit(!addr.IsShort(), "Address::SetExtended() failed");
149 VerifyOrQuit(addr.IsExtended(), "Address::SetExtended() failed");
150 VerifyOrQuit(CompareReversed(addr.GetExtended().m8, extAddr.m8, OT_EXT_ADDRESS_SIZE),
151 "Address::SetExtended() reverse byte order failed");
152
153 addr.SetNone();
154 VerifyOrQuit(addr.GetType() == Mac::Address::kTypeNone);
155 VerifyOrQuit(addr.IsNone(), "Address:SetNone() failed");
156 VerifyOrQuit(!addr.IsShort(), "Address::SetNone() failed");
157 VerifyOrQuit(!addr.IsExtended(), "Address::SetNone() failed");
158
159 VerifyOrQuit(!addr.IsBroadcast(), "Address:SetNone() failed");
160 VerifyOrQuit(!addr.IsShortAddrInvalid());
161
162 addr.SetExtended(extAddr);
163 VerifyOrQuit(!addr.IsBroadcast());
164 VerifyOrQuit(!addr.IsShortAddrInvalid());
165
166 addr.SetShort(kShortAddr);
167 VerifyOrQuit(!addr.IsBroadcast());
168 VerifyOrQuit(!addr.IsShortAddrInvalid());
169
170 addr.SetShort(Mac::kShortAddrBroadcast);
171 VerifyOrQuit(addr.IsBroadcast());
172 VerifyOrQuit(!addr.IsShortAddrInvalid());
173
174 addr.SetShort(Mac::kShortAddrInvalid);
175 VerifyOrQuit(!addr.IsBroadcast());
176 VerifyOrQuit(addr.IsShortAddrInvalid());
177
178 testFreeInstance(instance);
179 }
180
TestMacHeader(void)181 void TestMacHeader(void)
182 {
183 enum AddrType : uint8_t
184 {
185 kNoneAddr,
186 kShrtAddr,
187 kExtdAddr,
188 };
189
190 enum PanIdMode
191 {
192 kNoPanId,
193 kUsePanId1,
194 kUsePanId2,
195 };
196
197 struct TestCase
198 {
199 Mac::Frame::Version mVersion;
200 AddrType mSrcAddrType;
201 PanIdMode mSrcPanIdMode;
202 AddrType mDstAddrType;
203 PanIdMode mDstPanIdMode;
204 Mac::Frame::SecurityLevel mSecurity;
205 Mac::Frame::KeyIdMode mKeyIdMode;
206 uint8_t mHeaderLength;
207 uint8_t mFooterLength;
208 };
209
210 static constexpr Mac::Frame::Version kVer2006 = Mac::Frame::kVersion2006;
211 static constexpr Mac::Frame::Version kVer2015 = Mac::Frame::kVersion2015;
212
213 static constexpr Mac::Frame::SecurityLevel kNoSec = Mac::Frame::kSecurityNone;
214 static constexpr Mac::Frame::SecurityLevel kMic32 = Mac::Frame::kSecurityMic32;
215
216 static constexpr Mac::Frame::KeyIdMode kModeId1 = Mac::Frame::kKeyIdMode1;
217 static constexpr Mac::Frame::KeyIdMode kModeId2 = Mac::Frame::kKeyIdMode2;
218
219 static const char *kAddrTypeStrings[] = {"None", "Short", "Extd"};
220 static const char *kPanIdModeStrings[] = {"No", "Id1", "Id2"};
221
222 static constexpr TestCase kTestCases[] = {
223 {kVer2006, kNoneAddr, kNoPanId, kNoneAddr, kNoPanId, kNoSec, kModeId1, 3, 2},
224 {kVer2006, kShrtAddr, kUsePanId1, kNoneAddr, kNoPanId, kNoSec, kModeId1, 7, 2},
225 {kVer2006, kExtdAddr, kUsePanId1, kNoneAddr, kNoPanId, kNoSec, kModeId1, 13, 2},
226 {kVer2006, kNoneAddr, kNoPanId, kShrtAddr, kUsePanId1, kNoSec, kModeId1, 7, 2},
227 {kVer2006, kNoneAddr, kNoPanId, kExtdAddr, kUsePanId1, kNoSec, kModeId1, 13, 2},
228 {kVer2006, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId2, kNoSec, kModeId1, 11, 2},
229 {kVer2006, kShrtAddr, kUsePanId1, kExtdAddr, kUsePanId2, kNoSec, kModeId1, 17, 2},
230 {kVer2006, kExtdAddr, kUsePanId1, kShrtAddr, kUsePanId2, kNoSec, kModeId1, 17, 2},
231 {kVer2006, kExtdAddr, kUsePanId1, kExtdAddr, kUsePanId2, kNoSec, kModeId1, 23, 2},
232 {kVer2006, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId1, kNoSec, kModeId1, 9, 2},
233 {kVer2006, kShrtAddr, kUsePanId1, kExtdAddr, kUsePanId1, kNoSec, kModeId1, 15, 2},
234 {kVer2006, kExtdAddr, kUsePanId1, kShrtAddr, kUsePanId1, kNoSec, kModeId1, 15, 2},
235 {kVer2006, kExtdAddr, kUsePanId1, kExtdAddr, kUsePanId1, kNoSec, kModeId1, 21, 2},
236 {kVer2006, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId1, kMic32, kModeId1, 15, 6},
237 {kVer2006, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId1, kMic32, kModeId2, 19, 6},
238
239 {kVer2015, kNoneAddr, kNoPanId, kNoneAddr, kNoPanId, kNoSec, kModeId1, 3, 2},
240 {kVer2015, kShrtAddr, kUsePanId1, kNoneAddr, kNoPanId, kNoSec, kModeId1, 7, 2},
241 {kVer2015, kExtdAddr, kUsePanId1, kNoneAddr, kNoPanId, kNoSec, kModeId1, 13, 2},
242 {kVer2015, kNoneAddr, kNoPanId, kShrtAddr, kUsePanId1, kNoSec, kModeId1, 7, 2},
243 {kVer2015, kNoneAddr, kNoPanId, kExtdAddr, kUsePanId1, kNoSec, kModeId1, 13, 2},
244 {kVer2015, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId2, kNoSec, kModeId1, 11, 2},
245 {kVer2015, kShrtAddr, kUsePanId1, kExtdAddr, kUsePanId2, kNoSec, kModeId1, 17, 2},
246 {kVer2015, kExtdAddr, kUsePanId1, kShrtAddr, kUsePanId2, kNoSec, kModeId1, 17, 2},
247 {kVer2015, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId1, kNoSec, kModeId1, 9, 2},
248 {kVer2015, kShrtAddr, kUsePanId1, kExtdAddr, kUsePanId1, kNoSec, kModeId1, 15, 2},
249 {kVer2015, kExtdAddr, kUsePanId1, kShrtAddr, kUsePanId1, kNoSec, kModeId1, 15, 2},
250 {kVer2015, kExtdAddr, kUsePanId1, kExtdAddr, kUsePanId1, kNoSec, kModeId1, 21, 2},
251 {kVer2015, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId1, kMic32, kModeId1, 15, 6},
252 {kVer2015, kShrtAddr, kUsePanId1, kShrtAddr, kUsePanId1, kMic32, kModeId2, 19, 6},
253
254 {kVer2015, kNoneAddr, kNoPanId, kShrtAddr, kNoPanId, kNoSec, kModeId1, 5, 2},
255 {kVer2015, kNoneAddr, kNoPanId, kShrtAddr, kNoPanId, kMic32, kModeId1, 11, 6},
256 {kVer2015, kNoneAddr, kNoPanId, kNoneAddr, kUsePanId1, kNoSec, kModeId1, 5, 2},
257 {kVer2015, kNoneAddr, kNoPanId, kNoneAddr, kUsePanId1, kMic32, kModeId1, 11, 6},
258 {kVer2015, kNoneAddr, kNoPanId, kShrtAddr, kNoPanId, kNoSec, kModeId1, 5, 2},
259 {kVer2015, kNoneAddr, kNoPanId, kExtdAddr, kNoPanId, kNoSec, kModeId1, 11, 2},
260 {kVer2015, kNoneAddr, kNoPanId, kShrtAddr, kNoPanId, kMic32, kModeId1, 11, 6},
261 {kVer2015, kNoneAddr, kNoPanId, kExtdAddr, kNoPanId, kMic32, kModeId1, 17, 6},
262 {kVer2015, kShrtAddr, kNoPanId, kNoneAddr, kNoPanId, kNoSec, kModeId1, 5, 2},
263 {kVer2015, kShrtAddr, kNoPanId, kNoneAddr, kNoPanId, kMic32, kModeId1, 11, 6},
264 {kVer2015, kExtdAddr, kNoPanId, kNoneAddr, kNoPanId, kNoSec, kModeId1, 11, 2},
265 {kVer2015, kExtdAddr, kNoPanId, kNoneAddr, kNoPanId, kMic32, kModeId1, 17, 6},
266 {kVer2015, kExtdAddr, kNoPanId, kExtdAddr, kNoPanId, kNoSec, kModeId1, 19, 2},
267 {kVer2015, kExtdAddr, kNoPanId, kExtdAddr, kNoPanId, kMic32, kModeId1, 25, 6},
268 };
269
270 const uint16_t kPanId1 = 0xbaba;
271 const uint16_t kPanId2 = 0xdede;
272 const uint16_t kShortAddr1 = 0x1234;
273 const uint16_t kShortAddr2 = 0x5678;
274 const uint8_t kExtAddr1[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
275 const uint8_t kExtAddr2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
276
277 char string[100];
278 Mac::ExtAddress extAddr1;
279 Mac::ExtAddress extAddr2;
280
281 extAddr1.Set(kExtAddr1);
282 extAddr2.Set(kExtAddr2);
283
284 printf("TestMacHeader\n");
285
286 for (const TestCase &testCase : kTestCases)
287 {
288 uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
289 Mac::TxFrame frame;
290 Mac::Addresses addresses;
291 Mac::Address address;
292 Mac::PanIds panIds;
293 Mac::PanId panId;
294
295 frame.mPsdu = psdu;
296 frame.mLength = 0;
297 frame.mRadioType = 0;
298
299 VerifyOrQuit(addresses.mSource.IsNone());
300 VerifyOrQuit(addresses.mDestination.IsNone());
301 VerifyOrQuit(!panIds.IsSourcePresent());
302 VerifyOrQuit(!panIds.IsDestinationPresent());
303
304 switch (testCase.mSrcAddrType)
305 {
306 case kNoneAddr:
307 addresses.mSource.SetNone();
308 break;
309 case kShrtAddr:
310 addresses.mSource.SetShort(kShortAddr1);
311 break;
312 case kExtdAddr:
313 addresses.mSource.SetExtended(extAddr1);
314 break;
315 }
316
317 switch (testCase.mDstAddrType)
318 {
319 case kNoneAddr:
320 addresses.mDestination.SetNone();
321 break;
322 case kShrtAddr:
323 addresses.mDestination.SetShort(kShortAddr2);
324 break;
325 case kExtdAddr:
326 addresses.mDestination.SetExtended(extAddr2);
327 break;
328 }
329
330 switch (testCase.mSrcPanIdMode)
331 {
332 case kNoPanId:
333 break;
334 case kUsePanId1:
335 panIds.SetSource(kPanId1);
336 break;
337 case kUsePanId2:
338 panIds.SetSource(kPanId2);
339 break;
340 }
341
342 switch (testCase.mDstPanIdMode)
343 {
344 case kNoPanId:
345 break;
346 case kUsePanId1:
347 panIds.SetDestination(kPanId1);
348 break;
349 case kUsePanId2:
350 panIds.SetDestination(kPanId2);
351 break;
352 }
353
354 frame.InitMacHeader(Mac::Frame::kTypeData, testCase.mVersion, addresses, panIds, testCase.mSecurity,
355 testCase.mKeyIdMode);
356
357 VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength);
358 VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength);
359 VerifyOrQuit(frame.GetLength() == testCase.mHeaderLength + testCase.mFooterLength);
360
361 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeData);
362 VerifyOrQuit(!frame.IsAck());
363 VerifyOrQuit(frame.GetVersion() == testCase.mVersion);
364 VerifyOrQuit(frame.GetSecurityEnabled() == (testCase.mSecurity != kNoSec));
365 VerifyOrQuit(!frame.GetFramePending());
366 VerifyOrQuit(!frame.IsIePresent());
367 VerifyOrQuit(frame.GetAckRequest() == (testCase.mDstAddrType != kNoneAddr));
368
369 VerifyOrQuit(frame.IsSrcAddrPresent() == (testCase.mSrcAddrType != kNoneAddr));
370 SuccessOrQuit(frame.GetSrcAddr(address));
371 VerifyOrQuit(CompareAddresses(address, addresses.mSource));
372 VerifyOrQuit(frame.IsDstAddrPresent() == (testCase.mDstAddrType != kNoneAddr));
373 SuccessOrQuit(frame.GetDstAddr(address));
374 VerifyOrQuit(CompareAddresses(address, addresses.mDestination));
375
376 VerifyOrQuit(frame.IsDstPanIdPresent() == (testCase.mDstPanIdMode != kNoPanId));
377
378 if (frame.IsDstPanIdPresent())
379 {
380 SuccessOrQuit(frame.GetDstPanId(panId));
381 VerifyOrQuit(panId == panIds.GetDestination());
382 VerifyOrQuit(panIds.IsDestinationPresent());
383 }
384
385 if (frame.IsSrcPanIdPresent())
386 {
387 SuccessOrQuit(frame.GetSrcPanId(panId));
388 VerifyOrQuit(panId == panIds.GetSource());
389 VerifyOrQuit(panIds.IsSourcePresent());
390 }
391
392 if (frame.GetSecurityEnabled())
393 {
394 uint8_t security;
395 uint8_t keyIdMode;
396
397 SuccessOrQuit(frame.GetSecurityLevel(security));
398 VerifyOrQuit(security == testCase.mSecurity);
399
400 SuccessOrQuit(frame.GetKeyIdMode(keyIdMode));
401 VerifyOrQuit(keyIdMode == testCase.mKeyIdMode);
402 }
403
404 snprintf(string, sizeof(string), "\nver:%s, src[addr:%s, pan:%s], dst[addr:%s, pan:%s], sec:%s",
405 (testCase.mVersion == kVer2006) ? "2006" : "2015", kAddrTypeStrings[testCase.mSrcAddrType],
406 kPanIdModeStrings[testCase.mSrcPanIdMode], kAddrTypeStrings[testCase.mDstAddrType],
407 kPanIdModeStrings[testCase.mDstPanIdMode], testCase.mSecurity == kNoSec ? "no" : "mic32");
408
409 DumpBuffer(string, frame.GetPsdu(), frame.GetLength());
410 }
411 }
412
VerifyChannelMaskContent(const Mac::ChannelMask & aMask,uint8_t * aChannels,uint8_t aLength)413 void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels, uint8_t aLength)
414 {
415 uint8_t index = 0;
416 uint8_t channel;
417
418 for (channel = Radio::kChannelMin; channel <= Radio::kChannelMax; channel++)
419 {
420 if (index < aLength)
421 {
422 if (channel == aChannels[index])
423 {
424 index++;
425 VerifyOrQuit(aMask.ContainsChannel(channel));
426 }
427 else
428 {
429 VerifyOrQuit(!aMask.ContainsChannel(channel));
430 }
431 }
432 }
433
434 index = 0;
435 channel = Mac::ChannelMask::kChannelIteratorFirst;
436
437 while (aMask.GetNextChannel(channel) == kErrorNone)
438 {
439 VerifyOrQuit(channel == aChannels[index++], "ChannelMask.GetNextChannel() failed");
440 }
441
442 VerifyOrQuit(index == aLength, "ChannelMask.GetNextChannel() failed");
443
444 if (aLength == 1)
445 {
446 VerifyOrQuit(aMask.IsSingleChannel());
447 }
448 else
449 {
450 VerifyOrQuit(!aMask.IsSingleChannel());
451 }
452
453 VerifyOrQuit(aLength == aMask.GetNumberOfChannels());
454 }
455
TestMacChannelMask(void)456 void TestMacChannelMask(void)
457 {
458 uint8_t allChannels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
459 uint8_t channels1[] = {11, 14, 15, 16, 17, 20, 21, 22, 24, 25};
460 uint8_t channels2[] = {14, 21, 26};
461 uint8_t channels3[] = {14, 21};
462 uint8_t channles4[] = {20};
463
464 static const char kEmptyMaskString[] = "{ }";
465 static const char kAllChannelsString[] = "{ 11-26 }";
466 static const char kChannels1String[] = "{ 11, 14-17, 20-22, 24, 25 }";
467 static const char kChannels2String[] = "{ 14, 21, 26 }";
468 static const char kChannels3String[] = "{ 14, 21 }";
469 static const char kChannels4String[] = "{ 20 }";
470
471 Mac::ChannelMask mask1;
472 Mac::ChannelMask mask2(Radio::kSupportedChannels);
473
474 printf("Testing Mac::ChannelMask\n");
475
476 VerifyOrQuit(mask1.IsEmpty());
477 printf("empty = %s\n", mask1.ToString().AsCString());
478 VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kEmptyMaskString) == 0);
479
480 VerifyOrQuit(!mask2.IsEmpty());
481 VerifyOrQuit(mask2.GetMask() == Radio::kSupportedChannels);
482 printf("allChannels = %s\n", mask2.ToString().AsCString());
483 VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kAllChannelsString) == 0);
484
485 mask1.SetMask(Radio::kSupportedChannels);
486 VerifyOrQuit(!mask1.IsEmpty());
487 VerifyOrQuit(mask1.GetMask() == Radio::kSupportedChannels);
488
489 VerifyChannelMaskContent(mask1, allChannels, sizeof(allChannels));
490
491 // Test ChannelMask::RemoveChannel()
492 for (size_t index = 0; index < sizeof(allChannels) - 1; index++)
493 {
494 mask1.RemoveChannel(allChannels[index]);
495 VerifyChannelMaskContent(mask1, &allChannels[index + 1], sizeof(allChannels) - 1 - index);
496 }
497
498 mask1.Clear();
499 VerifyOrQuit(mask1.IsEmpty());
500 VerifyChannelMaskContent(mask1, nullptr, 0);
501
502 for (uint8_t channel : channels1)
503 {
504 mask1.AddChannel(channel);
505 }
506
507 printf("channels1 = %s\n", mask1.ToString().AsCString());
508 VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels1String) == 0);
509
510 VerifyOrQuit(!mask1.IsEmpty());
511 VerifyChannelMaskContent(mask1, channels1, sizeof(channels1));
512
513 mask2.Clear();
514
515 for (uint8_t channel : channels2)
516 {
517 mask2.AddChannel(channel);
518 }
519
520 printf("channels2 = %s\n", mask2.ToString().AsCString());
521 VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels2String) == 0);
522
523 VerifyOrQuit(!mask2.IsEmpty());
524 VerifyChannelMaskContent(mask2, channels2, sizeof(channels2));
525
526 mask1.Intersect(mask2);
527 VerifyChannelMaskContent(mask1, channels3, sizeof(channels3));
528 printf("channels3 = %s\n", mask1.ToString().AsCString());
529 VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels3String) == 0);
530
531 mask2.Clear();
532 mask2.AddChannel(channles4[0]);
533 VerifyChannelMaskContent(mask2, channles4, sizeof(channles4));
534
535 printf("channels4 = %s\n", mask2.ToString().AsCString());
536 VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels4String) == 0);
537
538 mask1.Clear();
539 mask2.Clear();
540 VerifyOrQuit(mask1 == mask2);
541
542 mask1.SetMask(Radio::kSupportedChannels);
543 mask2.SetMask(Radio::kSupportedChannels);
544 VerifyOrQuit(mask1 == mask2);
545
546 mask1.Clear();
547 VerifyOrQuit(mask1 != mask2);
548 }
549
TestMacFrameApi(void)550 void TestMacFrameApi(void)
551 {
552 uint8_t ack_psdu1[] = {0x02, 0x10, 0x5e, 0xd2, 0x9b};
553 uint8_t mac_cmd_psdu1[] = {0x6b, 0xdc, 0x85, 0xce, 0xfa, 0x47, 0x36, 0x07, 0xd9, 0x74, 0x45, 0x8d,
554 0xb2, 0x6e, 0x81, 0x25, 0xc9, 0xdb, 0xac, 0x2b, 0x0a, 0x0d, 0x00, 0x00,
555 0x00, 0x00, 0x01, 0x04, 0xaf, 0x14, 0xce, 0xaa, 0x5a, 0xe5};
556
557 Mac::Frame frame;
558
559 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
560 uint8_t data_psdu1[] = {0x29, 0xee, 0x53, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x05,
561 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x01};
562 uint8_t mac_cmd_psdu2[] = {0x6b, 0xaa, 0x8d, 0xce, 0xfa, 0x00, 0x68, 0x01, 0x68, 0x0d,
563 0x08, 0x00, 0x00, 0x00, 0x01, 0x04, 0x0d, 0xed, 0x0b, 0x35,
564 0x0c, 0x80, 0x3f, 0x04, 0x4b, 0x88, 0x89, 0xd6, 0x59, 0xe1};
565 uint8_t scf; // SecurityControlField
566 #endif
567
568 // Imm-Ack, Sequence Number: 94
569 // Frame Control Field: 0x1002
570 // .... .... .... .010 = Frame Type: Ack (0x2)
571 // .... .... .... 0... = Security Enabled: False
572 // .... .... ...0 .... = Frame Pending: False
573 // .... .... ..0. .... = Acknowledge Request: False
574 // .... .... .0.. .... = PAN ID Compression: False
575 // .... ...0 .... .... = Sequence Number Suppression: False
576 // .... ..0. .... .... = Information Elements Present: False
577 // .... 00.. .... .... = Destination Addressing Mode: None (0x0)
578 // ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
579 // 00.. .... .... .... = Source Addressing Mode: None (0x0)
580 // Sequence Number: 94
581 // FCS: 0x9bd2 (Correct)
582 frame.mPsdu = ack_psdu1;
583 frame.mLength = sizeof(ack_psdu1);
584 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeAck);
585 VerifyOrQuit(!frame.GetSecurityEnabled());
586 VerifyOrQuit(!frame.GetFramePending());
587 VerifyOrQuit(!frame.GetAckRequest());
588 VerifyOrQuit(!frame.IsIePresent());
589 VerifyOrQuit(!frame.IsDstPanIdPresent());
590 VerifyOrQuit(!frame.IsDstAddrPresent());
591 VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
592 VerifyOrQuit(!frame.IsSrcAddrPresent());
593 VerifyOrQuit(frame.GetSequence() == 94);
594
595 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
596 // IEEE 802.15.4-2015 Data
597 // Sequence Number: 83
598 // Destination PAN: 0xface
599 // Destination: 16:6e:0a:00:00:00:00:01
600 // Extended Source: 16:6e:0a:00:00:00:00:05
601 // Auxiliary Security Header
602 // Security Control Field: 0x0d
603 frame.mPsdu = data_psdu1;
604 frame.mLength = sizeof(data_psdu1);
605 VerifyOrQuit(frame.IsVersion2015());
606 VerifyOrQuit(frame.IsDstPanIdPresent());
607 VerifyOrQuit(frame.IsDstAddrPresent());
608 VerifyOrQuit(frame.IsSrcAddrPresent());
609 SuccessOrQuit(frame.GetSecurityControlField(scf));
610 VerifyOrQuit(scf == 0x0d);
611 frame.SetSecurityControlField(0xff);
612 SuccessOrQuit(frame.GetSecurityControlField(scf));
613 VerifyOrQuit(scf == 0xff);
614 #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
615
616 // IEEE 802.15.4-2006 Mac Command
617 // Sequence Number: 133
618 // Command Identifier: Data Request (0x04)
619 uint8_t commandId;
620 frame.mPsdu = mac_cmd_psdu1;
621 frame.mLength = sizeof(mac_cmd_psdu1);
622 VerifyOrQuit(frame.GetSequence() == 133);
623 VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
624 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd);
625 SuccessOrQuit(frame.GetCommandId(commandId));
626 VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
627 SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdBeaconRequest));
628 SuccessOrQuit(frame.GetCommandId(commandId));
629 VerifyOrQuit(commandId == Mac::Frame::kMacCmdBeaconRequest);
630
631 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
632 // IEEE 802.15.4-2015 Mac Command
633 // Sequence Number: 141
634 // Header IEs
635 // CSL IE
636 // Header Termination 2 IE (Payload follows)
637 // Command Identifier: Data Request (0x04)
638 frame.mPsdu = mac_cmd_psdu2;
639 frame.mLength = sizeof(mac_cmd_psdu2);
640 VerifyOrQuit(frame.GetSequence() == 141);
641 VerifyOrQuit(frame.IsVersion2015());
642 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd);
643 SuccessOrQuit(frame.GetCommandId(commandId));
644 VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
645 printf("commandId:%d\n", commandId);
646 SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdOrphanNotification));
647 SuccessOrQuit(frame.GetCommandId(commandId));
648 VerifyOrQuit(commandId == Mac::Frame::kMacCmdOrphanNotification);
649
650 #endif
651 }
652
TestMacFrameAckGeneration(void)653 void TestMacFrameAckGeneration(void)
654 {
655 constexpr uint8_t kImmAckLength = 5;
656
657 Mac::RxFrame receivedFrame;
658 Mac::TxFrame ackFrame;
659 uint8_t ackFrameBuffer[100];
660
661 ackFrame.mPsdu = ackFrameBuffer;
662 ackFrame.mLength = sizeof(ackFrameBuffer);
663
664 // Received Frame 1
665 // IEEE 802.15.4 Data
666 // Frame Control Field: 0xdc61
667 // .... .... .... .001 = Frame Type: Data (0x1)
668 // .... .... .... 0... = Security Enabled: False
669 // .... .... ...0 .... = Frame Pending: False
670 // .... .... ..1. .... = Acknowledge Request: True
671 // .... .... .1.. .... = PAN ID Compression: True
672 // .... ...0 .... .... = Sequence Number Suppression: False
673 // .... ..0. .... .... = Information Elements Present: False
674 // .... 11.. .... .... = Destination Addressing Mode: Long/64-bit (0x3)
675 // ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
676 // 11.. .... .... .... = Source Addressing Mode: Long/64-bit (0x3)
677 // Sequence Number: 189
678 // Destination PAN: 0xface
679 // Destination: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)
680 // Extended Source: 16:6e:0a:00:00:00:00:02 (16:6e:0a:00:00:00:00:02)
681 uint8_t data_psdu1[] = {0x61, 0xdc, 0xbd, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x02,
682 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x7f, 0x33, 0xf0, 0x4d, 0x4c, 0x4d, 0x4c,
683 0x8b, 0xf0, 0x00, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc2,
684 0x57, 0x9c, 0x31, 0xb3, 0x2a, 0xa1, 0x86, 0xba, 0x9a, 0xed, 0x5a, 0xb9, 0xa3, 0x59,
685 0x88, 0xeb, 0xbb, 0x0d, 0xc3, 0xed, 0xeb, 0x8a, 0x53, 0xa6, 0xed, 0xf7, 0xdd, 0x45,
686 0x6e, 0xf7, 0x9a, 0x17, 0xb4, 0xab, 0xc6, 0x75, 0x71, 0x46, 0x37, 0x93, 0x4a, 0x32,
687 0xb1, 0x21, 0x9f, 0x9d, 0xb3, 0x65, 0x27, 0xd5, 0xfc, 0x50, 0x16, 0x90, 0xd2, 0xd4};
688 receivedFrame.mPsdu = data_psdu1;
689 receivedFrame.mLength = sizeof(data_psdu1);
690
691 ackFrame.GenerateImmAck(receivedFrame, false);
692 VerifyOrQuit(ackFrame.mLength == kImmAckLength);
693 VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
694 VerifyOrQuit(!ackFrame.GetSecurityEnabled());
695 VerifyOrQuit(!ackFrame.GetFramePending());
696
697 VerifyOrQuit(!ackFrame.GetAckRequest());
698 VerifyOrQuit(!ackFrame.IsIePresent());
699 VerifyOrQuit(!ackFrame.IsDstPanIdPresent());
700 VerifyOrQuit(!ackFrame.IsDstAddrPresent());
701 VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
702 VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2006);
703 VerifyOrQuit(ackFrame.GetSequence() == 189);
704
705 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
706 // Received Frame 2
707 // IEEE 802.15.4 Data
708 // Frame Control Field: 0xa869, Frame Type: Data, Security Enabled, Acknowledge Request, PAN ID Compression,
709 // Destination Addressing Mode: Short/16-bit, Frame Version: IEEE Std 802.15.4-2015, Source Addressing Mode:
710 // Short/16-bit
711 // .... .... .... .001 = Frame Type: Data (0x1)
712 // .... .... .... 1... = Security Enabled: True
713 // .... .... ...0 .... = Frame Pending: False
714 // .... .... ..1. .... = Acknowledge Request: True
715 // .... .... .1.. .... = PAN ID Compression: True
716 // .... ...0 .... .... = Sequence Number Suppression: False
717 // .... ..0. .... .... = Information Elements Present: False
718 // .... 10.. .... .... = Destination Addressing Mode: Short/16-bit (0x2)
719 // ..10 .... .... .... = Frame Version: IEEE Std 802.15.4-2015 (2)
720 // 10.. .... .... .... = Source Addressing Mode: Short/16-bit (0x2)
721 // Sequence Number: 142
722 // Destination PAN: 0xface
723 // Destination: 0x2402
724 // Source: 0x2400
725 // [Extended Source: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)]
726 // [Origin: 2]
727 // Auxiliary Security Header
728 // Security Control Field: 0x0d, Security Level: Encryption with 32-bit Message Integrity Code, Key Identifier
729 // Mode: Indexed Key using the Default Key Source
730 // .... .101 = Security Level: Encryption with 32-bit Message Integrity Code (0x5)
731 // ...0 1... = Key Identifier Mode: Indexed Key using the Default Key Source (0x1)
732 // ..0. .... = Frame Counter Suppression: False
733 // .0.. .... = ASN in Nonce: False
734 // 0... .... = Reserved: 0x0
735 // Frame Counter: 2
736 // Key Identifier Field
737 // Key Index: 0x01
738 // MIC: f94e5870
739 // [Key Number: 0]
740 // FCS: 0x8c40 (Correct)
741 uint8_t data_psdu2[] = {0x69, 0xa8, 0x8e, 0xce, 0xfa, 0x02, 0x24, 0x00, 0x24, 0x0d, 0x02,
742 0x00, 0x00, 0x00, 0x01, 0x6b, 0x64, 0x60, 0x08, 0x55, 0xb8, 0x10,
743 0x18, 0xc7, 0x40, 0x2e, 0xfb, 0xf3, 0xda, 0xf9, 0x4e, 0x58, 0x70};
744 receivedFrame.mPsdu = data_psdu2;
745 receivedFrame.mLength = sizeof(data_psdu2);
746
747 uint8_t ie_data[6] = {0x04, 0x0d, 0x21, 0x0c, 0x35, 0x0c};
748 Mac::CslIe *csl;
749
750 SuccessOrQuit(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
751
752 csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
753 VerifyOrQuit(ackFrame.mLength == 25);
754 VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
755 VerifyOrQuit(ackFrame.GetSecurityEnabled());
756 VerifyOrQuit(ackFrame.IsIePresent());
757 VerifyOrQuit(ackFrame.IsDstPanIdPresent());
758 VerifyOrQuit(ackFrame.IsDstAddrPresent());
759 VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
760 VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2015);
761 VerifyOrQuit(ackFrame.GetSequence() == 142);
762 VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105);
763
764 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
765 ackFrame.SetCslIe(123, 456);
766 csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
767 VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456);
768 #endif
769 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
770 }
771
772 } // namespace ot
773
main(void)774 int main(void)
775 {
776 ot::TestMacAddress();
777 ot::TestMacHeader();
778 ot::TestMacChannelMask();
779 ot::TestMacFrameApi();
780 ot::TestMacFrameAckGeneration();
781 printf("All tests passed\n");
782 return 0;
783 }
784