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::TxFrame::Info frameInfo;
295 Mac::Address address;
296 Mac::PanId panId;
297
298 frame.mPsdu = psdu;
299 frame.mLength = 0;
300 frame.mRadioType = 0;
301
302 VerifyOrQuit(frameInfo.mAddrs.mSource.IsNone());
303 VerifyOrQuit(frameInfo.mAddrs.mDestination.IsNone());
304 VerifyOrQuit(!frameInfo.mPanIds.IsSourcePresent());
305 VerifyOrQuit(!frameInfo.mPanIds.IsDestinationPresent());
306
307 switch (testCase.mSrcAddrType)
308 {
309 case kNoneAddr:
310 frameInfo.mAddrs.mSource.SetNone();
311 break;
312 case kShrtAddr:
313 frameInfo.mAddrs.mSource.SetShort(kShortAddr1);
314 break;
315 case kExtdAddr:
316 frameInfo.mAddrs.mSource.SetExtended(extAddr1);
317 break;
318 }
319
320 switch (testCase.mDstAddrType)
321 {
322 case kNoneAddr:
323 frameInfo.mAddrs.mDestination.SetNone();
324 break;
325 case kShrtAddr:
326 frameInfo.mAddrs.mDestination.SetShort(kShortAddr2);
327 break;
328 case kExtdAddr:
329 frameInfo.mAddrs.mDestination.SetExtended(extAddr2);
330 break;
331 }
332
333 switch (testCase.mSrcPanIdMode)
334 {
335 case kNoPanId:
336 break;
337 case kUsePanId1:
338 frameInfo.mPanIds.SetSource(kPanId1);
339 break;
340 case kUsePanId2:
341 frameInfo.mPanIds.SetSource(kPanId2);
342 break;
343 }
344
345 switch (testCase.mDstPanIdMode)
346 {
347 case kNoPanId:
348 break;
349 case kUsePanId1:
350 frameInfo.mPanIds.SetDestination(kPanId1);
351 break;
352 case kUsePanId2:
353 frameInfo.mPanIds.SetDestination(kPanId2);
354 break;
355 }
356
357 frameInfo.mType = Mac::Frame::kTypeData;
358 frameInfo.mVersion = testCase.mVersion;
359 frameInfo.mSecurityLevel = testCase.mSecurity;
360 frameInfo.mKeyIdMode = testCase.mKeyIdMode;
361 frameInfo.mSuppressSequence = testCase.mSuppressSequence;
362
363 frameInfo.PrepareHeadersIn(frame);
364
365 VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength);
366 VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength);
367 VerifyOrQuit(frame.GetLength() == testCase.mHeaderLength + testCase.mFooterLength);
368
369 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeData);
370 VerifyOrQuit(!frame.IsAck());
371 VerifyOrQuit(frame.GetVersion() == testCase.mVersion);
372 VerifyOrQuit(frame.GetSecurityEnabled() == (testCase.mSecurity != kNoSec));
373 VerifyOrQuit(!frame.GetFramePending());
374 VerifyOrQuit(!frame.IsIePresent());
375 VerifyOrQuit(frame.GetAckRequest() == (testCase.mDstAddrType != kNoneAddr));
376
377 VerifyOrQuit(frame.IsSrcAddrPresent() == (testCase.mSrcAddrType != kNoneAddr));
378 SuccessOrQuit(frame.GetSrcAddr(address));
379 VerifyOrQuit(CompareAddresses(address, frameInfo.mAddrs.mSource));
380 VerifyOrQuit(frame.IsDstAddrPresent() == (testCase.mDstAddrType != kNoneAddr));
381 SuccessOrQuit(frame.GetDstAddr(address));
382 VerifyOrQuit(CompareAddresses(address, frameInfo.mAddrs.mDestination));
383
384 VerifyOrQuit(frame.IsDstPanIdPresent() == (testCase.mDstPanIdMode != kNoPanId));
385
386 if (frame.IsDstPanIdPresent())
387 {
388 SuccessOrQuit(frame.GetDstPanId(panId));
389 VerifyOrQuit(panId == frameInfo.mPanIds.GetDestination());
390 VerifyOrQuit(frameInfo.mPanIds.IsDestinationPresent());
391 }
392
393 if (frame.IsSrcPanIdPresent())
394 {
395 SuccessOrQuit(frame.GetSrcPanId(panId));
396 VerifyOrQuit(panId == frameInfo.mPanIds.GetSource());
397 VerifyOrQuit(frameInfo.mPanIds.IsSourcePresent());
398 }
399
400 if (frame.GetSecurityEnabled())
401 {
402 uint8_t security;
403 uint8_t keyIdMode;
404
405 SuccessOrQuit(frame.GetSecurityLevel(security));
406 VerifyOrQuit(security == testCase.mSecurity);
407
408 SuccessOrQuit(frame.GetKeyIdMode(keyIdMode));
409 VerifyOrQuit(keyIdMode == testCase.mKeyIdMode);
410 }
411
412 offset = snprintf(string, sizeof(string), "\nver:%s, src[addr:%s, pan:%s], dst[addr:%s, pan:%s], sec:%s",
413 (testCase.mVersion == kVer2006) ? "2006" : "2015", kAddrTypeStrings[testCase.mSrcAddrType],
414 kPanIdModeStrings[testCase.mSrcPanIdMode], kAddrTypeStrings[testCase.mDstAddrType],
415 kPanIdModeStrings[testCase.mDstPanIdMode], testCase.mSecurity == kNoSec ? "no" : "mic32");
416
417 if (!testCase.mSuppressSequence)
418 {
419 VerifyOrQuit(frame.IsSequencePresent());
420 offset += snprintf(string + offset, sizeof(string) - offset, ", seq:%u", frame.GetSequence());
421 }
422 else
423 {
424 VerifyOrQuit(!frame.IsSequencePresent());
425 }
426 DumpBuffer(string, frame.GetPsdu(), frame.GetLength());
427 }
428 }
429
VerifyChannelMaskContent(const Mac::ChannelMask & aMask,uint8_t * aChannels,uint8_t aLength)430 void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels, uint8_t aLength)
431 {
432 uint8_t index = 0;
433 uint8_t channel;
434
435 for (channel = Radio::kChannelMin; channel <= Radio::kChannelMax; channel++)
436 {
437 if (index < aLength)
438 {
439 if (channel == aChannels[index])
440 {
441 index++;
442 VerifyOrQuit(aMask.ContainsChannel(channel));
443 }
444 else
445 {
446 VerifyOrQuit(!aMask.ContainsChannel(channel));
447 }
448 }
449 }
450
451 index = 0;
452 channel = Mac::ChannelMask::kChannelIteratorFirst;
453
454 while (aMask.GetNextChannel(channel) == kErrorNone)
455 {
456 VerifyOrQuit(channel == aChannels[index++], "ChannelMask.GetNextChannel() failed");
457 }
458
459 VerifyOrQuit(index == aLength, "ChannelMask.GetNextChannel() failed");
460
461 if (aLength == 1)
462 {
463 VerifyOrQuit(aMask.IsSingleChannel());
464 }
465 else
466 {
467 VerifyOrQuit(!aMask.IsSingleChannel());
468 }
469
470 VerifyOrQuit(aLength == aMask.GetNumberOfChannels());
471 }
472
TestMacChannelMask(void)473 void TestMacChannelMask(void)
474 {
475 uint8_t allChannels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
476 uint8_t channels1[] = {11, 14, 15, 16, 17, 20, 21, 22, 24, 25};
477 uint8_t channels2[] = {14, 21, 26};
478 uint8_t channels3[] = {14, 21};
479 uint8_t channles4[] = {20};
480
481 static const char kEmptyMaskString[] = "{ }";
482 static const char kAllChannelsString[] = "{ 11-26 }";
483 static const char kChannels1String[] = "{ 11, 14-17, 20-22, 24, 25 }";
484 static const char kChannels2String[] = "{ 14, 21, 26 }";
485 static const char kChannels3String[] = "{ 14, 21 }";
486 static const char kChannels4String[] = "{ 20 }";
487
488 Mac::ChannelMask mask1;
489 Mac::ChannelMask mask2(Radio::kSupportedChannels);
490
491 printf("Testing Mac::ChannelMask\n");
492
493 VerifyOrQuit(mask1.IsEmpty());
494 printf("empty = %s\n", mask1.ToString().AsCString());
495 VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kEmptyMaskString) == 0);
496
497 VerifyOrQuit(!mask2.IsEmpty());
498 VerifyOrQuit(mask2.GetMask() == Radio::kSupportedChannels);
499 printf("allChannels = %s\n", mask2.ToString().AsCString());
500 VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kAllChannelsString) == 0);
501
502 mask1.SetMask(Radio::kSupportedChannels);
503 VerifyOrQuit(!mask1.IsEmpty());
504 VerifyOrQuit(mask1.GetMask() == Radio::kSupportedChannels);
505
506 VerifyChannelMaskContent(mask1, allChannels, sizeof(allChannels));
507
508 // Test ChannelMask::RemoveChannel()
509 for (size_t index = 0; index < sizeof(allChannels) - 1; index++)
510 {
511 mask1.RemoveChannel(allChannels[index]);
512 VerifyChannelMaskContent(mask1, &allChannels[index + 1], sizeof(allChannels) - 1 - index);
513 }
514
515 mask1.Clear();
516 VerifyOrQuit(mask1.IsEmpty());
517 VerifyChannelMaskContent(mask1, nullptr, 0);
518
519 for (uint8_t channel : channels1)
520 {
521 mask1.AddChannel(channel);
522 }
523
524 printf("channels1 = %s\n", mask1.ToString().AsCString());
525 VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels1String) == 0);
526
527 VerifyOrQuit(!mask1.IsEmpty());
528 VerifyChannelMaskContent(mask1, channels1, sizeof(channels1));
529
530 mask2.Clear();
531
532 for (uint8_t channel : channels2)
533 {
534 mask2.AddChannel(channel);
535 }
536
537 printf("channels2 = %s\n", mask2.ToString().AsCString());
538 VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels2String) == 0);
539
540 VerifyOrQuit(!mask2.IsEmpty());
541 VerifyChannelMaskContent(mask2, channels2, sizeof(channels2));
542
543 mask1.Intersect(mask2);
544 VerifyChannelMaskContent(mask1, channels3, sizeof(channels3));
545 printf("channels3 = %s\n", mask1.ToString().AsCString());
546 VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels3String) == 0);
547
548 mask2.Clear();
549 mask2.AddChannel(channles4[0]);
550 VerifyChannelMaskContent(mask2, channles4, sizeof(channles4));
551
552 printf("channels4 = %s\n", mask2.ToString().AsCString());
553 VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels4String) == 0);
554
555 mask1.Clear();
556 mask2.Clear();
557 VerifyOrQuit(mask1 == mask2);
558
559 mask1.SetMask(Radio::kSupportedChannels);
560 mask2.SetMask(Radio::kSupportedChannels);
561 VerifyOrQuit(mask1 == mask2);
562
563 mask1.Clear();
564 VerifyOrQuit(mask1 != mask2);
565 }
566
TestMacFrameApi(void)567 void TestMacFrameApi(void)
568 {
569 uint8_t ack_psdu1[] = {0x02, 0x10, 0x5e, 0xd2, 0x9b};
570 uint8_t mac_cmd_psdu1[] = {0x6b, 0xdc, 0x85, 0xce, 0xfa, 0x47, 0x36, 0x07, 0xd9, 0x74, 0x45, 0x8d,
571 0xb2, 0x6e, 0x81, 0x25, 0xc9, 0xdb, 0xac, 0x2b, 0x0a, 0x0d, 0x00, 0x00,
572 0x00, 0x00, 0x01, 0x04, 0xaf, 0x14, 0xce, 0xaa, 0x5a, 0xe5};
573
574 Mac::Frame frame;
575
576 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
577 uint8_t data_psdu1[] = {0x29, 0xee, 0x53, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x05,
578 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x01};
579 uint8_t mac_cmd_psdu2[] = {0x6b, 0xaa, 0x8d, 0xce, 0xfa, 0x00, 0x68, 0x01, 0x68, 0x0d,
580 0x08, 0x00, 0x00, 0x00, 0x01, 0x04, 0x0d, 0xed, 0x0b, 0x35,
581 0x0c, 0x80, 0x3f, 0x04, 0x4b, 0x88, 0x89, 0xd6, 0x59, 0xe1};
582 uint8_t scf; // SecurityControlField
583 #endif
584
585 // Imm-Ack, Sequence Number: 94
586 // Frame Control Field: 0x1002
587 // .... .... .... .010 = Frame Type: Ack (0x2)
588 // .... .... .... 0... = Security Enabled: False
589 // .... .... ...0 .... = Frame Pending: False
590 // .... .... ..0. .... = Acknowledge Request: False
591 // .... .... .0.. .... = PAN ID Compression: False
592 // .... ...0 .... .... = Sequence Number Suppression: False
593 // .... ..0. .... .... = Information Elements Present: False
594 // .... 00.. .... .... = Destination Addressing Mode: None (0x0)
595 // ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
596 // 00.. .... .... .... = Source Addressing Mode: None (0x0)
597 // Sequence Number: 94
598 // FCS: 0x9bd2 (Correct)
599 frame.mPsdu = ack_psdu1;
600 frame.mLength = sizeof(ack_psdu1);
601 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeAck);
602 VerifyOrQuit(!frame.GetSecurityEnabled());
603 VerifyOrQuit(!frame.GetFramePending());
604 VerifyOrQuit(!frame.GetAckRequest());
605 VerifyOrQuit(!frame.IsIePresent());
606 VerifyOrQuit(!frame.IsDstPanIdPresent());
607 VerifyOrQuit(!frame.IsDstAddrPresent());
608 VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
609 VerifyOrQuit(!frame.IsSrcAddrPresent());
610 VerifyOrQuit(frame.IsSequencePresent());
611 VerifyOrQuit(frame.GetSequence() == 94);
612
613 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
614 // IEEE 802.15.4-2015 Data
615 // Sequence Number: 83
616 // Destination PAN: 0xface
617 // Destination: 16:6e:0a:00:00:00:00:01
618 // Extended Source: 16:6e:0a:00:00:00:00:05
619 // Auxiliary Security Header
620 // Security Control Field: 0x0d
621 frame.mPsdu = data_psdu1;
622 frame.mLength = sizeof(data_psdu1);
623 VerifyOrQuit(frame.IsVersion2015());
624 VerifyOrQuit(frame.IsDstPanIdPresent());
625 VerifyOrQuit(frame.IsDstAddrPresent());
626 VerifyOrQuit(frame.IsSrcAddrPresent());
627 SuccessOrQuit(frame.GetSecurityControlField(scf));
628 VerifyOrQuit(scf == 0x0d);
629 #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
630
631 // IEEE 802.15.4-2006 Mac Command
632 // Sequence Number: 133
633 // Command Identifier: Data Request (0x04)
634 uint8_t commandId;
635 frame.mPsdu = mac_cmd_psdu1;
636 frame.mLength = sizeof(mac_cmd_psdu1);
637 VerifyOrQuit(frame.IsSequencePresent());
638 VerifyOrQuit(frame.GetSequence() == 133);
639 VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
640 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd);
641 SuccessOrQuit(frame.GetCommandId(commandId));
642 VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
643
644 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
645 // IEEE 802.15.4-2015 Mac Command
646 // Sequence Number: 141
647 // Header IEs
648 // CSL IE
649 // Header Termination 2 IE (Payload follows)
650 // Command Identifier: Data Request (0x04)
651 frame.mPsdu = mac_cmd_psdu2;
652 frame.mLength = sizeof(mac_cmd_psdu2);
653 VerifyOrQuit(frame.IsSequencePresent());
654 VerifyOrQuit(frame.GetSequence() == 141);
655 VerifyOrQuit(frame.IsVersion2015());
656 VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd);
657 SuccessOrQuit(frame.GetCommandId(commandId));
658 VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
659 printf("commandId:%d\n", commandId);
660
661 #endif
662 }
663
TestMacFrameAckGeneration(void)664 void TestMacFrameAckGeneration(void)
665 {
666 constexpr uint8_t kImmAckLength = 5;
667
668 Mac::RxFrame receivedFrame;
669 Mac::TxFrame ackFrame;
670 uint8_t ackFrameBuffer[100];
671
672 ackFrame.mPsdu = ackFrameBuffer;
673 ackFrame.mLength = sizeof(ackFrameBuffer);
674
675 // Received Frame 1
676 // IEEE 802.15.4 Data
677 // Frame Control Field: 0xdc61
678 // .... .... .... .001 = Frame Type: Data (0x1)
679 // .... .... .... 0... = Security Enabled: False
680 // .... .... ...0 .... = Frame Pending: False
681 // .... .... ..1. .... = Acknowledge Request: True
682 // .... .... .1.. .... = PAN ID Compression: True
683 // .... ...0 .... .... = Sequence Number Suppression: False
684 // .... ..0. .... .... = Information Elements Present: False
685 // .... 11.. .... .... = Destination Addressing Mode: Long/64-bit (0x3)
686 // ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
687 // 11.. .... .... .... = Source Addressing Mode: Long/64-bit (0x3)
688 // Sequence Number: 189
689 // Destination PAN: 0xface
690 // Destination: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)
691 // Extended Source: 16:6e:0a:00:00:00:00:02 (16:6e:0a:00:00:00:00:02)
692 uint8_t data_psdu1[] = {0x61, 0xdc, 0xbd, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x02,
693 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x7f, 0x33, 0xf0, 0x4d, 0x4c, 0x4d, 0x4c,
694 0x8b, 0xf0, 0x00, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc2,
695 0x57, 0x9c, 0x31, 0xb3, 0x2a, 0xa1, 0x86, 0xba, 0x9a, 0xed, 0x5a, 0xb9, 0xa3, 0x59,
696 0x88, 0xeb, 0xbb, 0x0d, 0xc3, 0xed, 0xeb, 0x8a, 0x53, 0xa6, 0xed, 0xf7, 0xdd, 0x45,
697 0x6e, 0xf7, 0x9a, 0x17, 0xb4, 0xab, 0xc6, 0x75, 0x71, 0x46, 0x37, 0x93, 0x4a, 0x32,
698 0xb1, 0x21, 0x9f, 0x9d, 0xb3, 0x65, 0x27, 0xd5, 0xfc, 0x50, 0x16, 0x90, 0xd2, 0xd4};
699 receivedFrame.mPsdu = data_psdu1;
700 receivedFrame.mLength = sizeof(data_psdu1);
701
702 ackFrame.GenerateImmAck(receivedFrame, false);
703 VerifyOrQuit(ackFrame.mLength == kImmAckLength);
704 VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
705 VerifyOrQuit(!ackFrame.GetSecurityEnabled());
706 VerifyOrQuit(!ackFrame.GetFramePending());
707
708 VerifyOrQuit(!ackFrame.GetAckRequest());
709 VerifyOrQuit(!ackFrame.IsIePresent());
710 VerifyOrQuit(!ackFrame.IsDstPanIdPresent());
711 VerifyOrQuit(!ackFrame.IsDstAddrPresent());
712 VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
713 VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2006);
714 VerifyOrQuit(ackFrame.IsSequencePresent());
715 VerifyOrQuit(ackFrame.GetSequence() == 189);
716
717 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
718 // Received Frame 2
719 // IEEE 802.15.4 Data
720 // Frame Control Field: 0xa869, Frame Type: Data, Security Enabled, Acknowledge Request, PAN ID Compression,
721 // Destination Addressing Mode: Short/16-bit, Frame Version: IEEE Std 802.15.4-2015, Source Addressing Mode:
722 // Short/16-bit
723 // .... .... .... .001 = Frame Type: Data (0x1)
724 // .... .... .... 1... = Security Enabled: True
725 // .... .... ...0 .... = Frame Pending: False
726 // .... .... ..1. .... = Acknowledge Request: True
727 // .... .... .1.. .... = PAN ID Compression: True
728 // .... ...0 .... .... = Sequence Number Suppression: False
729 // .... ..0. .... .... = Information Elements Present: False
730 // .... 10.. .... .... = Destination Addressing Mode: Short/16-bit (0x2)
731 // ..10 .... .... .... = Frame Version: IEEE Std 802.15.4-2015 (2)
732 // 10.. .... .... .... = Source Addressing Mode: Short/16-bit (0x2)
733 // Sequence Number: 142
734 // Destination PAN: 0xface
735 // Destination: 0x2402
736 // Source: 0x2400
737 // [Extended Source: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)]
738 // [Origin: 2]
739 // Auxiliary Security Header
740 // Security Control Field: 0x0d, Security Level: Encryption with 32-bit Message Integrity Code, Key Identifier
741 // Mode: Indexed Key using the Default Key Source
742 // .... .101 = Security Level: Encryption with 32-bit Message Integrity Code (0x5)
743 // ...0 1... = Key Identifier Mode: Indexed Key using the Default Key Source (0x1)
744 // ..0. .... = Frame Counter Suppression: False
745 // .0.. .... = ASN in Nonce: False
746 // 0... .... = Reserved: 0x0
747 // Frame Counter: 2
748 // Key Identifier Field
749 // Key Index: 0x01
750 // MIC: f94e5870
751 // [Key Number: 0]
752 // FCS: 0x8c40 (Correct)
753 uint8_t data_psdu2[] = {0x69, 0xa8, 0x8e, 0xce, 0xfa, 0x02, 0x24, 0x00, 0x24, 0x0d, 0x02,
754 0x00, 0x00, 0x00, 0x01, 0x6b, 0x64, 0x60, 0x08, 0x55, 0xb8, 0x10,
755 0x18, 0xc7, 0x40, 0x2e, 0xfb, 0xf3, 0xda, 0xf9, 0x4e, 0x58, 0x70};
756 receivedFrame.mPsdu = data_psdu2;
757 receivedFrame.mLength = sizeof(data_psdu2);
758
759 uint8_t ie_data[6] = {0x04, 0x0d, 0x21, 0x0c, 0x35, 0x0c};
760 Mac::CslIe *csl;
761
762 SuccessOrQuit(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
763
764 csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
765 VerifyOrQuit(ackFrame.mLength == 25);
766 VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
767 VerifyOrQuit(ackFrame.GetSecurityEnabled());
768 VerifyOrQuit(ackFrame.IsIePresent());
769 VerifyOrQuit(ackFrame.IsDstPanIdPresent());
770 VerifyOrQuit(ackFrame.IsDstAddrPresent());
771 VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
772 VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2015);
773 VerifyOrQuit(ackFrame.IsSequencePresent());
774 VerifyOrQuit(ackFrame.GetSequence() == 142);
775 VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105);
776
777 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
778 ackFrame.SetCslIe(123, 456);
779 csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
780 VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456);
781 #endif
782 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
783 }
784
785 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
786 constexpr uint16_t kMpFcfLongFrame = 1 << 3;
787 constexpr uint16_t kMpFcfDstAddrShift = 4;
788 constexpr uint16_t kMpFcfDstAddrExt = 3 << kMpFcfDstAddrShift;
789 constexpr uint16_t kMpFcfSrcAddrShift = 6;
790 constexpr uint16_t kMpFcfSrcAddrShort = 2 << kMpFcfSrcAddrShift;
791 constexpr uint16_t kMpFcfSrcAddrExt = 3 << kMpFcfSrcAddrShift;
792 constexpr uint16_t kMpFcfPanidPresent = 1 << 8;
793 constexpr uint16_t kMpFcfSecurityEnabled = 1 << 9;
794 constexpr uint16_t kMpFcfSequenceSuppression = 1 << 10;
795 constexpr uint16_t kMpFcfAckRequest = 1 << 14;
796 constexpr uint16_t kMpFcfIePresent = 1 << 15;
797
TestMacWakeupFrameGeneration(void)798 void TestMacWakeupFrameGeneration(void)
799 {
800 constexpr static uint8_t kSrcExtaddr[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
801 constexpr static uint8_t kDstExtaddr[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87};
802 constexpr static uint8_t kKeySource[] = {0, 0, 0, 0x1c};
803
804 constexpr static uint8_t kWakeupPsdu[] = {
805 // Frame Control
806 Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
807 (kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
808 // PAN ID
809 0xce, 0xfa,
810 // Destination Address
811 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0,
812 // Source Address
813 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
814 // Security Header
815 Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x1c, 0x1d,
816 // Rendezvous Time IE
817 0x82, 0x0e, 0xcd, 0xab,
818 // Connection IE
819 0x05, 0x00, 0x9b, 0xb8, 0xea, 0x01, 0x1c};
820
821 uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
822 Mac::Address src;
823 Mac::Address dst;
824 Mac::Address addr;
825 Mac::TxFrame txFrame;
826 Mac::Frame rxFrame;
827 Mac::ConnectionIe *connectionIe;
828
829 printf("TestMacWakeupFrameGeneration\n");
830
831 src.SetExtended(kSrcExtaddr);
832 dst.SetExtended(kDstExtaddr);
833 txFrame.mPsdu = psdu;
834 txFrame.mLength = 0;
835 txFrame.mRadioType = 0;
836
837 SuccessOrQuit(txFrame.GenerateWakeupFrame(0xface, dst, src));
838
839 // Validate that the frame satisfies the wake-up frame definition
840 VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
841 VerifyOrQuit(!txFrame.GetAckRequest());
842 VerifyOrQuit(txFrame.GetRendezvousTimeIe() != nullptr);
843 VerifyOrQuit(txFrame.GetConnectionIe() != nullptr);
844 VerifyOrQuit(txFrame.GetPayloadLength() == 0);
845 SuccessOrQuit(txFrame.GetSrcAddr(addr));
846 VerifyOrQuit(CompareAddresses(src, addr));
847 SuccessOrQuit(txFrame.GetDstAddr(addr));
848 VerifyOrQuit(CompareAddresses(dst, addr));
849
850 // Initialize remaining fields and check if the frame has the expected contents
851 txFrame.SetFrameCounter(0xfcfcfcfc);
852 txFrame.SetKeySource(kKeySource);
853 txFrame.SetKeyId(0x1d);
854 txFrame.GetRendezvousTimeIe()->SetRendezvousTime(0xabcd);
855 connectionIe = txFrame.GetConnectionIe();
856 connectionIe->SetRetryInterval(1);
857 connectionIe->SetRetryCount(12);
858
859 VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd);
860 VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
861 VerifyOrQuit(connectionIe->GetRetryCount() == 12);
862 VerifyOrQuit(txFrame.GetLength() == sizeof(kWakeupPsdu) + txFrame.GetFooterLength());
863 VerifyOrQuit(memcmp(psdu, kWakeupPsdu, sizeof(kWakeupPsdu)) == 0);
864
865 // Initialize RX Frame with the same PSDU and check if it's recognized as wake-up frame
866 rxFrame.mPsdu = psdu;
867 rxFrame.mLength = txFrame.GetLength();
868 rxFrame.mRadioType = 0;
869
870 SuccessOrQuit(rxFrame.ValidatePsdu());
871 VerifyOrQuit(rxFrame.IsWakeupFrame());
872 }
873
TestMacWakeupFrameDetectionNegative(void)874 void TestMacWakeupFrameDetectionNegative(void)
875 {
876 struct TestCase
877 {
878 uint8_t *mPsdu;
879 uint8_t mLength;
880 };
881
882 uint8_t ackRequestedPsdu[] = {
883 // Frame Control
884 Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
885 (kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfAckRequest | kMpFcfIePresent) >>
886 8,
887 // PAN ID
888 0xCE, 0xFA,
889 // Destination Address
890 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
891 // Source Address
892 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
893 // Security Header
894 Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
895 // Rendezvous Time IE
896 0x82, 0x0E, 0xCD, 0xAB,
897 // Connection IE
898 0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
899 // Footer
900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
901
902 uint8_t shortAddressPsdu[] = {
903 // Frame Control
904 Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrShort,
905 (kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
906 // PAN ID
907 0xCE, 0xFA,
908 // Destination Address
909 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
910 // Source Address
911 0x55, 0x55,
912 // Security Header
913 Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
914 // Rendezvous Time IE
915 0x82, 0x0E, 0xCD, 0xAB,
916 // Connection IE
917 0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
918 // Footer
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
920
921 uint8_t noRendezvousIePsdu[] = {
922 // Frame Control
923 Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
924 (kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
925 // PAN ID
926 0xCE, 0xFA,
927 // Destination Address
928 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
929 // Source Address
930 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
931 // Security Header
932 Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
933 // Connection IE
934 0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
935 // Footer
936 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
937
938 uint8_t noConnectionIePsdu[] = {
939 // Frame Control
940 Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
941 (kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
942 // PAN ID
943 0xCE, 0xFA,
944 // Destination Address
945 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
946 // Source Address
947 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
948 // Security Header
949 Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
950 // Rendezvous Time IE
951 0x82, 0x0E, 0xCD, 0xAB,
952 // Connection IE
953 0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x02, 0x1C,
954 // Footer
955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
956
957 uint8_t keyIdMode1Psdu[] = {
958 // Frame Control
959 Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
960 (kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
961 // PAN ID
962 0xCE, 0xFA,
963 // Destination Address
964 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
965 // Source Address
966 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
967 // Security Header
968 Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x1D,
969 // Rendezvous Time IE
970 0x82, 0x0E, 0xCD, 0xAB,
971 // Connection IE
972 0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
973 // Footer
974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
975
976 const TestCase testCases[] = {
977 {ackRequestedPsdu, sizeof(ackRequestedPsdu)}, {shortAddressPsdu, sizeof(shortAddressPsdu)},
978 {noRendezvousIePsdu, sizeof(noRendezvousIePsdu)}, {noConnectionIePsdu, sizeof(noConnectionIePsdu)},
979 {keyIdMode1Psdu, sizeof(keyIdMode1Psdu)},
980 };
981
982 Mac::Frame rxFrame;
983
984 printf("TestMacWakeupFrameDetectionNegative\n");
985
986 for (const TestCase &testCase : testCases)
987 {
988 rxFrame.mPsdu = testCase.mPsdu;
989 rxFrame.mLength = testCase.mLength;
990 rxFrame.mRadioType = 0;
991
992 SuccessOrQuit(rxFrame.ValidatePsdu());
993 VerifyOrQuit(!rxFrame.IsWakeupFrame());
994 }
995 }
996 #endif
997 } // namespace ot
998
main(void)999 int main(void)
1000 {
1001 ot::TestMacAddress();
1002 ot::TestMacHeader();
1003 ot::TestMacChannelMask();
1004 ot::TestMacFrameApi();
1005 ot::TestMacFrameAckGeneration();
1006 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1007 ot::TestMacWakeupFrameGeneration();
1008 ot::TestMacWakeupFrameDetectionNegative();
1009 #endif
1010 printf("All tests passed\n");
1011 return 0;
1012 }
1013