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