• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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