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