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.h"
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 
TestMacAddress(void)56 void TestMacAddress(void)
57 {
58     const uint8_t           kExtAddr[OT_EXT_ADDRESS_SIZE] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
59     const Mac::ShortAddress kShortAddr                    = 0x1234;
60 
61     ot::Instance *  instance;
62     Mac::Address    addr;
63     Mac::ExtAddress extAddr;
64     uint8_t         buffer[OT_EXT_ADDRESS_SIZE];
65 
66     instance = testInitInstance();
67     VerifyOrQuit(instance != nullptr, "nullptr instance\n");
68 
69     // Mac::ExtAddress
70 
71     extAddr.GenerateRandom();
72     VerifyOrQuit(extAddr.IsLocal(), "Random Extended Address should have its Local bit set");
73     VerifyOrQuit(!extAddr.IsGroup(), "Random Extended Address should not have its Group bit set");
74 
75     extAddr.CopyTo(buffer);
76     VerifyOrQuit(memcmp(extAddr.m8, buffer, OT_EXT_ADDRESS_SIZE) == 0);
77 
78     extAddr.CopyTo(buffer, Mac::ExtAddress::kReverseByteOrder);
79     VerifyOrQuit(CompareReversed(extAddr.m8, buffer, OT_EXT_ADDRESS_SIZE));
80 
81     extAddr.Set(kExtAddr);
82     VerifyOrQuit(memcmp(extAddr.m8, kExtAddr, OT_EXT_ADDRESS_SIZE) == 0);
83 
84     extAddr.Set(kExtAddr, Mac::ExtAddress::kReverseByteOrder);
85     VerifyOrQuit(CompareReversed(extAddr.m8, kExtAddr, OT_EXT_ADDRESS_SIZE));
86 
87     extAddr.SetLocal(true);
88     VerifyOrQuit(extAddr.IsLocal());
89     extAddr.SetLocal(false);
90     VerifyOrQuit(!extAddr.IsLocal());
91     extAddr.ToggleLocal();
92     VerifyOrQuit(extAddr.IsLocal());
93     extAddr.ToggleLocal();
94     VerifyOrQuit(!extAddr.IsLocal());
95 
96     extAddr.SetGroup(true);
97     VerifyOrQuit(extAddr.IsGroup());
98     extAddr.SetGroup(false);
99     VerifyOrQuit(!extAddr.IsGroup());
100     extAddr.ToggleGroup();
101     VerifyOrQuit(extAddr.IsGroup());
102     extAddr.ToggleGroup();
103     VerifyOrQuit(!extAddr.IsGroup());
104 
105     // Mac::Address
106 
107     VerifyOrQuit(addr.IsNone(), "Address constructor failed");
108     VerifyOrQuit(addr.GetType() == Mac::Address::kTypeNone);
109 
110     addr.SetShort(kShortAddr);
111     VerifyOrQuit(addr.GetType() == Mac::Address::kTypeShort);
112     VerifyOrQuit(addr.IsShort(), "Address::SetShort() failed");
113     VerifyOrQuit(!addr.IsExtended(), "Address::SetShort() failed");
114     VerifyOrQuit(addr.GetShort() == kShortAddr);
115 
116     addr.SetExtended(extAddr);
117     VerifyOrQuit(addr.GetType() == Mac::Address::kTypeExtended);
118     VerifyOrQuit(!addr.IsShort(), "Address::SetExtended() failed");
119     VerifyOrQuit(addr.IsExtended(), "Address::SetExtended() failed");
120     VerifyOrQuit(addr.GetExtended() == extAddr);
121 
122     addr.SetExtended(extAddr.m8, Mac::ExtAddress::kReverseByteOrder);
123     VerifyOrQuit(addr.GetType() == Mac::Address::kTypeExtended);
124     VerifyOrQuit(!addr.IsShort(), "Address::SetExtended() failed");
125     VerifyOrQuit(addr.IsExtended(), "Address::SetExtended() failed");
126     VerifyOrQuit(CompareReversed(addr.GetExtended().m8, extAddr.m8, OT_EXT_ADDRESS_SIZE),
127                  "Address::SetExtended() reverse byte order failed");
128 
129     addr.SetNone();
130     VerifyOrQuit(addr.GetType() == Mac::Address::kTypeNone);
131     VerifyOrQuit(addr.IsNone(), "Address:SetNone() failed");
132     VerifyOrQuit(!addr.IsShort(), "Address::SetNone() failed");
133     VerifyOrQuit(!addr.IsExtended(), "Address::SetNone() failed");
134 
135     VerifyOrQuit(!addr.IsBroadcast(), "Address:SetNone() failed");
136     VerifyOrQuit(!addr.IsShortAddrInvalid());
137 
138     addr.SetExtended(extAddr);
139     VerifyOrQuit(!addr.IsBroadcast());
140     VerifyOrQuit(!addr.IsShortAddrInvalid());
141 
142     addr.SetShort(kShortAddr);
143     VerifyOrQuit(!addr.IsBroadcast());
144     VerifyOrQuit(!addr.IsShortAddrInvalid());
145 
146     addr.SetShort(Mac::kShortAddrBroadcast);
147     VerifyOrQuit(addr.IsBroadcast());
148     VerifyOrQuit(!addr.IsShortAddrInvalid());
149 
150     addr.SetShort(Mac::kShortAddrInvalid);
151     VerifyOrQuit(!addr.IsBroadcast());
152     VerifyOrQuit(addr.IsShortAddrInvalid());
153 
154     testFreeInstance(instance);
155 }
156 
CompareNetworkName(const Mac::NetworkName & aNetworkName,const char * aNameString)157 void CompareNetworkName(const Mac::NetworkName &aNetworkName, const char *aNameString)
158 {
159     uint8_t len = static_cast<uint8_t>(strlen(aNameString));
160 
161     VerifyOrQuit(strcmp(aNetworkName.GetAsCString(), aNameString) == 0);
162 
163     VerifyOrQuit(aNetworkName.GetAsData().GetLength() == len);
164     VerifyOrQuit(memcmp(aNetworkName.GetAsData().GetBuffer(), aNameString, len) == 0);
165 }
166 
TestMacNetworkName(void)167 void TestMacNetworkName(void)
168 {
169     const char kEmptyName[]   = "";
170     const char kName1[]       = "network";
171     const char kName2[]       = "network-name";
172     const char kLongName[]    = "0123456789abcdef";
173     const char kTooLongName[] = "0123456789abcdef0";
174 
175     char             buffer[sizeof(kTooLongName) + 2];
176     uint8_t          len;
177     Mac::NetworkName networkName;
178 
179     CompareNetworkName(networkName, kEmptyName);
180 
181     SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))));
182     CompareNetworkName(networkName, kName1);
183 
184     VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))) == kErrorAlready, "failed to detect duplicate");
185     CompareNetworkName(networkName, kName1);
186 
187     VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1) - 1)) == kErrorAlready,
188                  "failed to detect duplicate");
189 
190     SuccessOrQuit(networkName.Set(Mac::NameData(kName2, sizeof(kName2))));
191     CompareNetworkName(networkName, kName2);
192 
193     SuccessOrQuit(networkName.Set(Mac::NameData(kEmptyName, 0)));
194     CompareNetworkName(networkName, kEmptyName);
195 
196     SuccessOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName))));
197     CompareNetworkName(networkName, kLongName);
198 
199     VerifyOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName) - 1)) == kErrorAlready,
200                  "failed to detect duplicate");
201 
202     SuccessOrQuit(networkName.Set(Mac::NameData(nullptr, 0)));
203     CompareNetworkName(networkName, kEmptyName);
204 
205     SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))));
206 
207     VerifyOrQuit(networkName.Set(Mac::NameData(kTooLongName, sizeof(kTooLongName))) == kErrorInvalidArgs,
208                  "accepted an invalid (too long) name");
209 
210     CompareNetworkName(networkName, kName1);
211 
212     memset(buffer, 'a', sizeof(buffer));
213     len = networkName.GetAsData().CopyTo(buffer, 1);
214     VerifyOrQuit(len == 1, "NameData::CopyTo() failed");
215     VerifyOrQuit(buffer[0] == kName1[0], "NameData::CopyTo() failed");
216     VerifyOrQuit(buffer[1] == 'a', "NameData::CopyTo() failed");
217 
218     memset(buffer, 'a', sizeof(buffer));
219     len = networkName.GetAsData().CopyTo(buffer, sizeof(kName1) - 1);
220     VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed");
221     VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed");
222     VerifyOrQuit(buffer[sizeof(kName1)] == 'a', "NameData::CopyTo() failed");
223 
224     memset(buffer, 'a', sizeof(buffer));
225     len = networkName.GetAsData().CopyTo(buffer, sizeof(buffer));
226     VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed");
227     VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed");
228     VerifyOrQuit(buffer[sizeof(kName1)] == 0, "NameData::CopyTo() failed");
229 }
230 
TestMacHeader(void)231 void TestMacHeader(void)
232 {
233     static const struct
234     {
235         uint16_t fcf;
236         uint8_t  secCtl;
237         uint8_t  headerLength;
238         uint8_t  footerLength;
239     } tests[] = {
240         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrNone | Mac::Frame::kFcfSrcAddrNone, 0, 3, 2},
241         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrNone | Mac::Frame::kFcfSrcAddrShort, 0, 7, 2},
242         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrNone | Mac::Frame::kFcfSrcAddrExt, 0, 13, 2},
243         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrNone, 0, 7, 2},
244         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrNone, 0, 13, 2},
245         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort, 0, 11, 2},
246         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrExt, 0, 17, 2},
247         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrShort, 0, 17, 2},
248         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrExt, 0, 23, 2},
249 
250         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort |
251              Mac::Frame::kFcfPanidCompression,
252          0, 9, 2},
253         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrExt |
254              Mac::Frame::kFcfPanidCompression,
255          0, 15, 2},
256         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrShort |
257              Mac::Frame::kFcfPanidCompression,
258          0, 15, 2},
259         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrExt |
260              Mac::Frame::kFcfPanidCompression,
261          0, 21, 2},
262 
263         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort |
264              Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled,
265          Mac::Frame::kSecMic32 | Mac::Frame::kKeyIdMode1, 15, 6},
266         {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort |
267              Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled,
268          Mac::Frame::kSecMic32 | Mac::Frame::kKeyIdMode2, 19, 6},
269     };
270 
271     for (const auto &test : tests)
272     {
273         uint8_t      psdu[OT_RADIO_FRAME_MAX_SIZE];
274         Mac::TxFrame frame;
275 
276         frame.mPsdu      = psdu;
277         frame.mLength    = 0;
278         frame.mRadioType = 0;
279 
280         frame.InitMacHeader(test.fcf, test.secCtl);
281         VerifyOrQuit(frame.GetHeaderLength() == test.headerLength);
282         VerifyOrQuit(frame.GetFooterLength() == test.footerLength);
283         VerifyOrQuit(frame.GetLength() == test.headerLength + test.footerLength);
284     }
285 }
286 
VerifyChannelMaskContent(const Mac::ChannelMask & aMask,uint8_t * aChannels,uint8_t aLength)287 void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels, uint8_t aLength)
288 {
289     uint8_t index = 0;
290     uint8_t channel;
291 
292     for (channel = Radio::kChannelMin; channel <= Radio::kChannelMax; channel++)
293     {
294         if (index < aLength)
295         {
296             if (channel == aChannels[index])
297             {
298                 index++;
299                 VerifyOrQuit(aMask.ContainsChannel(channel));
300             }
301             else
302             {
303                 VerifyOrQuit(!aMask.ContainsChannel(channel));
304             }
305         }
306     }
307 
308     index   = 0;
309     channel = Mac::ChannelMask::kChannelIteratorFirst;
310 
311     while (aMask.GetNextChannel(channel) == kErrorNone)
312     {
313         VerifyOrQuit(channel == aChannels[index++], "ChannelMask.GetNextChannel() failed");
314     }
315 
316     VerifyOrQuit(index == aLength, "ChannelMask.GetNextChannel() failed");
317 
318     if (aLength == 1)
319     {
320         VerifyOrQuit(aMask.IsSingleChannel());
321     }
322     else
323     {
324         VerifyOrQuit(!aMask.IsSingleChannel());
325     }
326 
327     VerifyOrQuit(aLength == aMask.GetNumberOfChannels());
328 }
329 
TestMacChannelMask(void)330 void TestMacChannelMask(void)
331 {
332     uint8_t allChannels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
333     uint8_t channels1[]   = {11, 14, 15, 16, 17, 20, 21, 22, 24, 25};
334     uint8_t channels2[]   = {14, 21, 26};
335     uint8_t channels3[]   = {14, 21};
336     uint8_t channles4[]   = {20};
337 
338     static const char kEmptyMaskString[]   = "{ }";
339     static const char kAllChannelsString[] = "{ 11-26 }";
340     static const char kChannels1String[]   = "{ 11, 14-17, 20-22, 24, 25 }";
341     static const char kChannels2String[]   = "{ 14, 21, 26 }";
342     static const char kChannels3String[]   = "{ 14, 21 }";
343     static const char kChannels4String[]   = "{ 20 }";
344 
345     Mac::ChannelMask mask1;
346     Mac::ChannelMask mask2(Radio::kSupportedChannels);
347 
348     printf("Testing Mac::ChannelMask\n");
349 
350     VerifyOrQuit(mask1.IsEmpty());
351     printf("empty = %s\n", mask1.ToString().AsCString());
352     VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kEmptyMaskString) == 0);
353 
354     VerifyOrQuit(!mask2.IsEmpty());
355     VerifyOrQuit(mask2.GetMask() == Radio::kSupportedChannels);
356     printf("allChannels = %s\n", mask2.ToString().AsCString());
357     VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kAllChannelsString) == 0);
358 
359     mask1.SetMask(Radio::kSupportedChannels);
360     VerifyOrQuit(!mask1.IsEmpty());
361     VerifyOrQuit(mask1.GetMask() == Radio::kSupportedChannels);
362 
363     VerifyChannelMaskContent(mask1, allChannels, sizeof(allChannels));
364 
365     // Test ChannelMask::RemoveChannel()
366     for (uint8_t index = 0; index < sizeof(allChannels) - 1; index++)
367     {
368         mask1.RemoveChannel(allChannels[index]);
369         VerifyChannelMaskContent(mask1, &allChannels[index + 1], sizeof(allChannels) - 1 - index);
370     }
371 
372     mask1.Clear();
373     VerifyOrQuit(mask1.IsEmpty());
374     VerifyChannelMaskContent(mask1, nullptr, 0);
375 
376     for (uint8_t channel : channels1)
377     {
378         mask1.AddChannel(channel);
379     }
380 
381     printf("channels1 = %s\n", mask1.ToString().AsCString());
382     VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels1String) == 0);
383 
384     VerifyOrQuit(!mask1.IsEmpty());
385     VerifyChannelMaskContent(mask1, channels1, sizeof(channels1));
386 
387     mask2.Clear();
388 
389     for (uint8_t channel : channels2)
390     {
391         mask2.AddChannel(channel);
392     }
393 
394     printf("channels2 = %s\n", mask2.ToString().AsCString());
395     VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels2String) == 0);
396 
397     VerifyOrQuit(!mask2.IsEmpty());
398     VerifyChannelMaskContent(mask2, channels2, sizeof(channels2));
399 
400     mask1.Intersect(mask2);
401     VerifyChannelMaskContent(mask1, channels3, sizeof(channels3));
402     printf("channels3 = %s\n", mask1.ToString().AsCString());
403     VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels3String) == 0);
404 
405     mask2.Clear();
406     mask2.AddChannel(channles4[0]);
407     VerifyChannelMaskContent(mask2, channles4, sizeof(channles4));
408 
409     printf("channels4 = %s\n", mask2.ToString().AsCString());
410     VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels4String) == 0);
411 
412     mask1.Clear();
413     mask2.Clear();
414     VerifyOrQuit(mask1 == mask2);
415 
416     mask1.SetMask(Radio::kSupportedChannels);
417     mask2.SetMask(Radio::kSupportedChannels);
418     VerifyOrQuit(mask1 == mask2);
419 
420     mask1.Clear();
421     VerifyOrQuit(mask1 != mask2);
422 }
423 
TestMacFrameApi(void)424 void TestMacFrameApi(void)
425 {
426     uint8_t ack_psdu1[]     = {0x02, 0x10, 0x5e, 0xd2, 0x9b};
427     uint8_t mac_cmd_psdu1[] = {0x6b, 0xdc, 0x85, 0xce, 0xfa, 0x47, 0x36, 0x07, 0xd9, 0x74, 0x45, 0x8d,
428                                0xb2, 0x6e, 0x81, 0x25, 0xc9, 0xdb, 0xac, 0x2b, 0x0a, 0x0d, 0x00, 0x00,
429                                0x00, 0x00, 0x01, 0x04, 0xaf, 0x14, 0xce, 0xaa, 0x5a, 0xe5};
430 
431     Mac::Frame frame;
432 
433 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
434     uint8_t data_psdu1[]    = {0x29, 0xee, 0x53, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x05,
435                             0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x01};
436     uint8_t mac_cmd_psdu2[] = {0x6b, 0xaa, 0x8d, 0xce, 0xfa, 0x00, 0x68, 0x01, 0x68, 0x0d,
437                                0x08, 0x00, 0x00, 0x00, 0x01, 0x04, 0x0d, 0xed, 0x0b, 0x35,
438                                0x0c, 0x80, 0x3f, 0x04, 0x4b, 0x88, 0x89, 0xd6, 0x59, 0xe1};
439     uint8_t scf; // SecurityControlField
440 #endif
441 
442     // Imm-Ack, Sequence Number: 94
443     //   Frame Control Field: 0x1002
444     //     .... .... .... .010 = Frame Type: Ack (0x2)
445     //     .... .... .... 0... = Security Enabled: False
446     //     .... .... ...0 .... = Frame Pending: False
447     //     .... .... ..0. .... = Acknowledge Request: False
448     //     .... .... .0.. .... = PAN ID Compression: False
449     //     .... ...0 .... .... = Sequence Number Suppression: False
450     //     .... ..0. .... .... = Information Elements Present: False
451     //     .... 00.. .... .... = Destination Addressing Mode: None (0x0)
452     //     ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
453     //     00.. .... .... .... = Source Addressing Mode: None (0x0)
454     //   Sequence Number: 94
455     //   FCS: 0x9bd2 (Correct)
456     frame.mPsdu   = ack_psdu1;
457     frame.mLength = sizeof(ack_psdu1);
458     VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameAck);
459     VerifyOrQuit(!frame.GetSecurityEnabled());
460     VerifyOrQuit(!frame.GetFramePending());
461     VerifyOrQuit(!frame.GetAckRequest());
462     VerifyOrQuit(!frame.IsIePresent());
463     VerifyOrQuit(!frame.IsDstPanIdPresent());
464     VerifyOrQuit(!frame.IsDstAddrPresent());
465     VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006);
466     VerifyOrQuit(!frame.IsSrcAddrPresent());
467     VerifyOrQuit(frame.GetSequence() == 94);
468 
469 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
470     // IEEE 802.15.4-2015 Data
471     //   Sequence Number: 83
472     //   Destination PAN: 0xface
473     //   Destination: 16:6e:0a:00:00:00:00:01
474     //   Extended Source: 16:6e:0a:00:00:00:00:05
475     //   Auxiliary Security Header
476     //     Security Control Field: 0x0d
477     frame.mPsdu   = data_psdu1;
478     frame.mLength = sizeof(data_psdu1);
479     VerifyOrQuit(frame.IsVersion2015());
480     VerifyOrQuit(frame.IsDstPanIdPresent());
481     VerifyOrQuit(frame.IsDstAddrPresent());
482     VerifyOrQuit(frame.IsSrcAddrPresent());
483     SuccessOrQuit(frame.GetSecurityControlField(scf));
484     VerifyOrQuit(scf == 0x0d);
485     frame.SetSecurityControlField(0xff);
486     SuccessOrQuit(frame.GetSecurityControlField(scf));
487     VerifyOrQuit(scf == 0xff);
488 #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
489 
490     // IEEE 802.15.4-2006 Mac Command
491     //   Sequence Number: 133
492     //   Command Identifier: Data Request (0x04)
493     uint8_t commandId;
494     frame.mPsdu   = mac_cmd_psdu1;
495     frame.mLength = sizeof(mac_cmd_psdu1);
496     VerifyOrQuit(frame.GetSequence() == 133);
497     VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006);
498     VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameMacCmd);
499     SuccessOrQuit(frame.GetCommandId(commandId));
500     VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
501     SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdBeaconRequest));
502     SuccessOrQuit(frame.GetCommandId(commandId));
503     VerifyOrQuit(commandId == Mac::Frame::kMacCmdBeaconRequest);
504 
505 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
506     // IEEE 802.15.4-2015 Mac Command
507     //   Sequence Number: 141
508     //   Header IEs
509     //     CSL IE
510     //     Header Termination 2 IE (Payload follows)
511     //   Command Identifier: Data Request (0x04)
512     frame.mPsdu   = mac_cmd_psdu2;
513     frame.mLength = sizeof(mac_cmd_psdu2);
514     VerifyOrQuit(frame.GetSequence() == 141);
515     VerifyOrQuit(frame.IsVersion2015());
516     VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameMacCmd);
517     SuccessOrQuit(frame.GetCommandId(commandId));
518     VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
519     printf("commandId:%d\n", commandId);
520     SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdOrphanNotification));
521     SuccessOrQuit(frame.GetCommandId(commandId));
522     VerifyOrQuit(commandId == Mac::Frame::kMacCmdOrphanNotification);
523 
524 #endif
525 }
526 
TestMacFrameAckGeneration(void)527 void TestMacFrameAckGeneration(void)
528 {
529     Mac::RxFrame receivedFrame;
530     Mac::TxFrame ackFrame;
531     uint8_t      ackFrameBuffer[100];
532 
533     ackFrame.mPsdu   = ackFrameBuffer;
534     ackFrame.mLength = sizeof(ackFrameBuffer);
535 
536     // Received Frame 1
537     // IEEE 802.15.4 Data
538     //   Frame Control Field: 0xdc61
539     //     .... .... .... .001 = Frame Type: Data (0x1)
540     //     .... .... .... 0... = Security Enabled: False
541     //     .... .... ...0 .... = Frame Pending: False
542     //     .... .... ..1. .... = Acknowledge Request: True
543     //     .... .... .1.. .... = PAN ID Compression: True
544     //     .... ...0 .... .... = Sequence Number Suppression: False
545     //     .... ..0. .... .... = Information Elements Present: False
546     //     .... 11.. .... .... = Destination Addressing Mode: Long/64-bit (0x3)
547     //     ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
548     //     11.. .... .... .... = Source Addressing Mode: Long/64-bit (0x3)
549     //  Sequence Number: 189
550     //  Destination PAN: 0xface
551     //  Destination: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)
552     //  Extended Source: 16:6e:0a:00:00:00:00:02 (16:6e:0a:00:00:00:00:02)
553     uint8_t data_psdu1[]  = {0x61, 0xdc, 0xbd, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x02,
554                             0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x7f, 0x33, 0xf0, 0x4d, 0x4c, 0x4d, 0x4c,
555                             0x8b, 0xf0, 0x00, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc2,
556                             0x57, 0x9c, 0x31, 0xb3, 0x2a, 0xa1, 0x86, 0xba, 0x9a, 0xed, 0x5a, 0xb9, 0xa3, 0x59,
557                             0x88, 0xeb, 0xbb, 0x0d, 0xc3, 0xed, 0xeb, 0x8a, 0x53, 0xa6, 0xed, 0xf7, 0xdd, 0x45,
558                             0x6e, 0xf7, 0x9a, 0x17, 0xb4, 0xab, 0xc6, 0x75, 0x71, 0x46, 0x37, 0x93, 0x4a, 0x32,
559                             0xb1, 0x21, 0x9f, 0x9d, 0xb3, 0x65, 0x27, 0xd5, 0xfc, 0x50, 0x16, 0x90, 0xd2, 0xd4};
560     receivedFrame.mPsdu   = data_psdu1;
561     receivedFrame.mLength = sizeof(data_psdu1);
562 
563     ackFrame.GenerateImmAck(receivedFrame, false);
564     VerifyOrQuit(ackFrame.mLength == Mac::Frame::kImmAckLength);
565     VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck);
566     VerifyOrQuit(!ackFrame.GetSecurityEnabled());
567     VerifyOrQuit(!ackFrame.GetFramePending());
568 
569     VerifyOrQuit(!ackFrame.GetAckRequest());
570     VerifyOrQuit(!ackFrame.IsIePresent());
571     VerifyOrQuit(!ackFrame.IsDstPanIdPresent());
572     VerifyOrQuit(!ackFrame.IsDstAddrPresent());
573     VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
574     VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kFcfFrameVersion2006);
575     VerifyOrQuit(ackFrame.GetSequence() == 189);
576 
577 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
578     // Received Frame 2
579     // IEEE 802.15.4 Data
580     //   Frame Control Field: 0xa869, Frame Type: Data, Security Enabled, Acknowledge Request, PAN ID Compression,
581     //   Destination Addressing Mode: Short/16-bit, Frame Version: IEEE Std 802.15.4-2015, Source Addressing Mode:
582     //   Short/16-bit
583     //     .... .... .... .001 = Frame Type: Data (0x1)
584     //     .... .... .... 1... = Security Enabled: True
585     //     .... .... ...0 .... = Frame Pending: False
586     //     .... .... ..1. .... = Acknowledge Request: True
587     //     .... .... .1.. .... = PAN ID Compression: True
588     //     .... ...0 .... .... = Sequence Number Suppression: False
589     //     .... ..0. .... .... = Information Elements Present: False
590     //     .... 10.. .... .... = Destination Addressing Mode: Short/16-bit (0x2)
591     //     ..10 .... .... .... = Frame Version: IEEE Std 802.15.4-2015 (2)
592     //     10.. .... .... .... = Source Addressing Mode: Short/16-bit (0x2)
593     //   Sequence Number: 142
594     //   Destination PAN: 0xface
595     //   Destination: 0x2402
596     //   Source: 0x2400
597     //   [Extended Source: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)]
598     //   [Origin: 2]
599     //   Auxiliary Security Header
600     //     Security Control Field: 0x0d, Security Level: Encryption with 32-bit Message Integrity Code, Key Identifier
601     //     Mode: Indexed Key using the Default Key Source
602     //       .... .101 = Security Level: Encryption with 32-bit Message Integrity Code (0x5)
603     //       ...0 1... = Key Identifier Mode: Indexed Key using the Default Key Source (0x1)
604     //       ..0. .... = Frame Counter Suppression: False
605     //       .0.. .... = ASN in Nonce: False
606     //       0... .... = Reserved: 0x0
607     //     Frame Counter: 2
608     //     Key Identifier Field
609     //       Key Index: 0x01
610     //   MIC: f94e5870
611     //   [Key Number: 0]
612     //   FCS: 0x8c40 (Correct)
613     uint8_t data_psdu2[]  = {0x69, 0xa8, 0x8e, 0xce, 0xfa, 0x02, 0x24, 0x00, 0x24, 0x0d, 0x02,
614                             0x00, 0x00, 0x00, 0x01, 0x6b, 0x64, 0x60, 0x08, 0x55, 0xb8, 0x10,
615                             0x18, 0xc7, 0x40, 0x2e, 0xfb, 0xf3, 0xda, 0xf9, 0x4e, 0x58, 0x70};
616     receivedFrame.mPsdu   = data_psdu2;
617     receivedFrame.mLength = sizeof(data_psdu2);
618 
619     uint8_t     ie_data[6] = {0x04, 0x0d, 0x21, 0x0c, 0x35, 0x0c};
620     Mac::CslIe *csl;
621 
622     IgnoreError(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
623     csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
624     VerifyOrQuit(ackFrame.mLength == 23);
625     VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck);
626     VerifyOrQuit(ackFrame.GetSecurityEnabled());
627     VerifyOrQuit(ackFrame.IsIePresent());
628     VerifyOrQuit(!ackFrame.IsDstPanIdPresent());
629     VerifyOrQuit(ackFrame.IsDstAddrPresent());
630     VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
631     VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kFcfFrameVersion2015);
632     VerifyOrQuit(ackFrame.GetSequence() == 142);
633     VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105);
634 
635 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
636     ackFrame.SetCslIe(123, 456);
637     csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
638     VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456);
639 #endif
640 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
641 }
642 
643 } // namespace ot
644 
main(void)645 int main(void)
646 {
647     ot::TestMacAddress();
648     ot::TestMacNetworkName();
649     ot::TestMacHeader();
650     ot::TestMacChannelMask();
651     ot::TestMacFrameApi();
652     ot::TestMacFrameAckGeneration();
653     printf("All tests passed\n");
654     return 0;
655 }
656