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 /**
30  * @file
31  *   This file includes definitions for generating and processing IEEE 802.15.4 MAC frames.
32  */
33 
34 #ifndef MAC_FRAME_HPP_
35 #define MAC_FRAME_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <limits.h>
40 #include <stdint.h>
41 
42 #include "common/encoding.hpp"
43 #include "mac/mac_types.hpp"
44 
45 namespace ot {
46 namespace Mac {
47 
48 using ot::Encoding::LittleEndian::HostSwap16;
49 using ot::Encoding::LittleEndian::HostSwap64;
50 using ot::Encoding::LittleEndian::ReadUint24;
51 using ot::Encoding::LittleEndian::WriteUint24;
52 
53 /**
54  * @addtogroup core-mac
55  *
56  * @{
57  *
58  */
59 
60 /**
61  * This class implements IEEE 802.15.4 IE (Information Element) header generation and parsing.
62  *
63  */
64 OT_TOOL_PACKED_BEGIN
65 class HeaderIe
66 {
67 public:
68     /**
69      * This method initializes the Header IE.
70      *
71      */
Init(void)72     void Init(void) { mFields.m16 = 0; }
73 
74     /**
75      * This method initializes the Header IE with Id and Length.
76      *
77      * @param[in]  aId   The IE Element Id.
78      * @param[in]  aLen  The IE content length.
79      *
80      */
81     void Init(uint16_t aId, uint8_t aLen);
82 
83     /**
84      * This method returns the IE Element Id.
85      *
86      * @returns the IE Element Id.
87      *
88      */
GetId(void) const89     uint16_t GetId(void) const { return (HostSwap16(mFields.m16) & kIdMask) >> kIdOffset; }
90 
91     /**
92      * This method sets the IE Element Id.
93      *
94      * @param[in]  aID  The IE Element Id.
95      *
96      */
SetId(uint16_t aId)97     void SetId(uint16_t aId)
98     {
99         mFields.m16 = HostSwap16((HostSwap16(mFields.m16) & ~kIdMask) | ((aId << kIdOffset) & kIdMask));
100     }
101 
102     /**
103      * This method returns the IE content length.
104      *
105      * @returns the IE content length.
106      *
107      */
GetLength(void) const108     uint8_t GetLength(void) const { return mFields.m8[0] & kLengthMask; }
109 
110     /**
111      * This method sets the IE content length.
112      *
113      * @param[in]  aLength  The IE content length.
114      *
115      */
SetLength(uint8_t aLength)116     void SetLength(uint8_t aLength) { mFields.m8[0] = (mFields.m8[0] & ~kLengthMask) | (aLength & kLengthMask); }
117 
118 private:
119     // Header IE format:
120     //
121     // +-----------+------------+--------+
122     // | Bits: 0-6 |    7-14    |   15   |
123     // +-----------+------------+--------+
124     // | Length    | Element ID | Type=0 |
125     // +-----------+------------+--------+
126 
127     static constexpr uint8_t  kSize       = 2;
128     static constexpr uint8_t  kIdOffset   = 7;
129     static constexpr uint8_t  kLengthMask = 0x7f;
130     static constexpr uint16_t kIdMask     = 0x00ff << kIdOffset;
131 
132     union OT_TOOL_PACKED_FIELD
133     {
134         uint8_t  m8[kSize];
135         uint16_t m16;
136     } mFields;
137 
138 } OT_TOOL_PACKED_END;
139 
140 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || \
141     OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
142 /**
143  * This class implements vendor specific Header IE generation and parsing.
144  *
145  */
146 OT_TOOL_PACKED_BEGIN
147 class VendorIeHeader
148 {
149 public:
150     static constexpr uint8_t kHeaderIeId    = 0x00;
151     static constexpr uint8_t kIeContentSize = sizeof(uint8_t) * 4;
152 
153     /**
154      * This method returns the Vendor OUI.
155      *
156      * @returns the Vendor OUI.
157      *
158      */
GetVendorOui(void) const159     uint32_t GetVendorOui(void) const { return ReadUint24(mOui); }
160 
161     /**
162      * This method sets the Vendor OUI.
163      *
164      * @param[in]  aVendorOui  A Vendor OUI.
165      *
166      */
SetVendorOui(uint32_t aVendorOui)167     void SetVendorOui(uint32_t aVendorOui) { WriteUint24(aVendorOui, mOui); }
168 
169     /**
170      * This method returns the Vendor IE sub-type.
171      *
172      * @returns the Vendor IE sub-type.
173      *
174      */
GetSubType(void) const175     uint8_t GetSubType(void) const { return mSubType; }
176 
177     /**
178      * This method sets the Vendor IE sub-type.
179      *
180      * @param[in] the Vendor IE sub-type.
181      *
182      */
SetSubType(uint8_t aSubType)183     void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
184 
185 private:
186     static constexpr uint8_t kOuiSize = 3;
187 
188     uint8_t mOui[kOuiSize];
189     uint8_t mSubType;
190 } OT_TOOL_PACKED_END;
191 
192 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
193 /**
194  * This class implements Time Header IE generation and parsing.
195  *
196  */
197 OT_TOOL_PACKED_BEGIN
198 class TimeIe : public VendorIeHeader
199 {
200 public:
201     static constexpr uint32_t kVendorOuiNest = 0x18b430;
202     static constexpr uint8_t  kVendorIeTime  = 0x01;
203     static constexpr uint8_t  kHeaderIeId    = VendorIeHeader::kHeaderIeId;
204     static constexpr uint8_t  kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t);
205 
206     /**
207      * This method initializes the time IE.
208      *
209      */
Init(void)210     void Init(void)
211     {
212         SetVendorOui(kVendorOuiNest);
213         SetSubType(kVendorIeTime);
214     }
215 
216     /**
217      * This method returns the time sync sequence.
218      *
219      * @returns the time sync sequence.
220      *
221      */
GetSequence(void) const222     uint8_t GetSequence(void) const { return mSequence; }
223 
224     /**
225      * This method sets the tine sync sequence.
226      *
227      * @param[in]  aSequence The time sync sequence.
228      *
229      */
SetSequence(uint8_t aSequence)230     void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
231 
232     /**
233      * This method returns the network time.
234      *
235      * @returns the network time, in microseconds.
236      *
237      */
GetTime(void) const238     uint64_t GetTime(void) const { return HostSwap64(mTime); }
239 
240     /**
241      * This method sets the network time.
242      *
243      * @param[in]  aTime  The network time.
244      *
245      */
SetTime(uint64_t aTime)246     void SetTime(uint64_t aTime) { mTime = HostSwap64(aTime); }
247 
248 private:
249     uint8_t  mSequence;
250     uint64_t mTime;
251 } OT_TOOL_PACKED_END;
252 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
253 
254 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
255 class ThreadIe
256 {
257 public:
258     static constexpr uint8_t  kHeaderIeId               = VendorIeHeader::kHeaderIeId;
259     static constexpr uint8_t  kIeContentSize            = VendorIeHeader::kIeContentSize;
260     static constexpr uint32_t kVendorOuiThreadCompanyId = 0xeab89b;
261     static constexpr uint8_t  kEnhAckProbingIe          = 0x00;
262 };
263 #endif
264 
265 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE ||
266        // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
267 
268 /**
269  * This class implements IEEE 802.15.4 MAC frame generation and parsing.
270  *
271  */
272 class Frame : public otRadioFrame
273 {
274 public:
275     static constexpr uint8_t kFcfSize             = sizeof(uint16_t);
276     static constexpr uint8_t kDsnSize             = sizeof(uint8_t);
277     static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t);
278     static constexpr uint8_t kFrameCounterSize    = sizeof(uint32_t);
279     static constexpr uint8_t kCommandIdSize       = sizeof(uint8_t);
280     static constexpr uint8_t k154FcsSize          = sizeof(uint16_t);
281 
282     static constexpr uint16_t kFcfFrameBeacon      = 0 << 0;
283     static constexpr uint16_t kFcfFrameData        = 1 << 0;
284     static constexpr uint16_t kFcfFrameAck         = 2 << 0;
285     static constexpr uint16_t kFcfFrameMacCmd      = 3 << 0;
286     static constexpr uint16_t kFcfFrameTypeMask    = 7 << 0;
287     static constexpr uint16_t kFcfSecurityEnabled  = 1 << 3;
288     static constexpr uint16_t kFcfFramePending     = 1 << 4;
289     static constexpr uint16_t kFcfAckRequest       = 1 << 5;
290     static constexpr uint16_t kFcfPanidCompression = 1 << 6;
291     static constexpr uint16_t kFcfIePresent        = 1 << 9;
292     static constexpr uint16_t kFcfDstAddrNone      = 0 << 10;
293     static constexpr uint16_t kFcfDstAddrShort     = 2 << 10;
294     static constexpr uint16_t kFcfDstAddrExt       = 3 << 10;
295     static constexpr uint16_t kFcfDstAddrMask      = 3 << 10;
296     static constexpr uint16_t kFcfFrameVersion2006 = 1 << 12;
297     static constexpr uint16_t kFcfFrameVersion2015 = 2 << 12;
298     static constexpr uint16_t kFcfFrameVersionMask = 3 << 12;
299     static constexpr uint16_t kFcfSrcAddrNone      = 0 << 14;
300     static constexpr uint16_t kFcfSrcAddrShort     = 2 << 14;
301     static constexpr uint16_t kFcfSrcAddrExt       = 3 << 14;
302     static constexpr uint16_t kFcfSrcAddrMask      = 3 << 14;
303 
304     static constexpr uint8_t kSecNone      = 0 << 0;
305     static constexpr uint8_t kSecMic32     = 1 << 0;
306     static constexpr uint8_t kSecMic64     = 2 << 0;
307     static constexpr uint8_t kSecMic128    = 3 << 0;
308     static constexpr uint8_t kSecEnc       = 4 << 0;
309     static constexpr uint8_t kSecEncMic32  = 5 << 0;
310     static constexpr uint8_t kSecEncMic64  = 6 << 0;
311     static constexpr uint8_t kSecEncMic128 = 7 << 0;
312     static constexpr uint8_t kSecLevelMask = 7 << 0;
313 
314     static constexpr uint8_t kMic0Size   = 0;
315     static constexpr uint8_t kMic32Size  = 32 / CHAR_BIT;
316     static constexpr uint8_t kMic64Size  = 64 / CHAR_BIT;
317     static constexpr uint8_t kMic128Size = 128 / CHAR_BIT;
318     static constexpr uint8_t kMaxMicSize = kMic128Size;
319 
320     static constexpr uint8_t kKeyIdMode0    = 0 << 3;
321     static constexpr uint8_t kKeyIdMode1    = 1 << 3;
322     static constexpr uint8_t kKeyIdMode2    = 2 << 3;
323     static constexpr uint8_t kKeyIdMode3    = 3 << 3;
324     static constexpr uint8_t kKeyIdModeMask = 3 << 3;
325 
326     static constexpr uint8_t kKeySourceSizeMode0 = 0;
327     static constexpr uint8_t kKeySourceSizeMode1 = 0;
328     static constexpr uint8_t kKeySourceSizeMode2 = 4;
329     static constexpr uint8_t kKeySourceSizeMode3 = 8;
330 
331     static constexpr uint8_t kKeyIndexSize = sizeof(uint8_t);
332 
333     static constexpr uint8_t kMacCmdAssociationRequest         = 1;
334     static constexpr uint8_t kMacCmdAssociationResponse        = 2;
335     static constexpr uint8_t kMacCmdDisassociationNotification = 3;
336     static constexpr uint8_t kMacCmdDataRequest                = 4;
337     static constexpr uint8_t kMacCmdPanidConflictNotification  = 5;
338     static constexpr uint8_t kMacCmdOrphanNotification         = 6;
339     static constexpr uint8_t kMacCmdBeaconRequest              = 7;
340     static constexpr uint8_t kMacCmdCoordinatorRealignment     = 8;
341     static constexpr uint8_t kMacCmdGtsRequest                 = 9;
342 
343     static constexpr uint8_t kImmAckLength = kFcfSize + kDsnSize + k154FcsSize;
344 
345     static constexpr uint16_t kInfoStringSize = 128; ///< Max chars for `InfoString` (ToInfoString()).
346 
347     /**
348      * This type defines the fixed-length `String` object returned from `ToInfoString()` method.
349      *
350      */
351     typedef String<kInfoStringSize> InfoString;
352 
353     /**
354      * This method indicates whether the frame is empty (no payload).
355      *
356      * @retval TRUE   The frame is empty (no PSDU payload).
357      * @retval FALSE  The frame is not empty.
358      *
359      */
IsEmpty(void) const360     bool IsEmpty(void) const { return (mLength == 0); }
361 
362     /**
363      * This method initializes the MAC header.
364      *
365      * @param[in]  aFcf          The Frame Control field.
366      * @param[in]  aSecurityCtl  The Security Control field.
367      *
368      */
369     void InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl);
370 
371     /**
372      * This method validates the frame.
373      *
374      * @retval kErrorNone    Successfully parsed the MAC header.
375      * @retval kErrorParse   Failed to parse through the MAC header.
376      *
377      */
378     Error ValidatePsdu(void) const;
379 
380     /**
381      * This method returns the IEEE 802.15.4 Frame Type.
382      *
383      * @returns The IEEE 802.15.4 Frame Type.
384      *
385      */
GetType(void) const386     uint8_t GetType(void) const { return GetPsdu()[0] & kFcfFrameTypeMask; }
387 
388     /**
389      * This method returns whether the frame is an Ack frame.
390      *
391      * @retval TRUE   If this is an Ack.
392      * @retval FALSE  If this is not an Ack.
393      *
394      */
IsAck(void) const395     bool IsAck(void) const { return GetType() == kFcfFrameAck; }
396 
397     /**
398      * This method returns the IEEE 802.15.4 Frame Version.
399      *
400      * @returns The IEEE 802.15.4 Frame Version.
401      *
402      */
GetVersion(void) const403     uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; }
404 
405     /**
406      * This method returns if this IEEE 802.15.4 frame's version is 2015.
407      *
408      * @returns TRUE if version is 2015, FALSE otherwise.
409      *
410      */
IsVersion2015(void) const411     bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); }
412 
413     /**
414      * This method indicates whether or not security is enabled.
415      *
416      * @retval TRUE   If security is enabled.
417      * @retval FALSE  If security is not enabled.
418      *
419      */
GetSecurityEnabled(void) const420     bool GetSecurityEnabled(void) const { return (GetPsdu()[0] & kFcfSecurityEnabled) != 0; }
421 
422     /**
423      * This method indicates whether or not the Frame Pending bit is set.
424      *
425      * @retval TRUE   If the Frame Pending bit is set.
426      * @retval FALSE  If the Frame Pending bit is not set.
427      *
428      */
GetFramePending(void) const429     bool GetFramePending(void) const { return (GetPsdu()[0] & kFcfFramePending) != 0; }
430 
431     /**
432      * This method sets the Frame Pending bit.
433      *
434      * @param[in]  aFramePending  The Frame Pending bit.
435      *
436      */
437     void SetFramePending(bool aFramePending);
438 
439     /**
440      * This method indicates whether or not the Ack Request bit is set.
441      *
442      * @retval TRUE   If the Ack Request bit is set.
443      * @retval FALSE  If the Ack Request bit is not set.
444      *
445      */
GetAckRequest(void) const446     bool GetAckRequest(void) const { return (GetPsdu()[0] & kFcfAckRequest) != 0; }
447 
448     /**
449      * This method sets the Ack Request bit.
450      *
451      * @param[in]  aAckRequest  The Ack Request bit.
452      *
453      */
454     void SetAckRequest(bool aAckRequest);
455 
456     /**
457      * This method indicates whether or not the PanId Compression bit is set.
458      *
459      * @retval TRUE   If the PanId Compression bit is set.
460      * @retval FALSE  If the PanId Compression bit is not set.
461      *
462      */
IsPanIdCompressed(void) const463     bool IsPanIdCompressed(void) const { return (GetFrameControlField() & kFcfPanidCompression) != 0; }
464 
465     /**
466      * This method indicates whether or not IEs present.
467      *
468      * @retval TRUE   If IEs present.
469      * @retval FALSE  If no IE present.
470      *
471      */
IsIePresent(void) const472     bool IsIePresent(void) const { return (GetFrameControlField() & kFcfIePresent) != 0; }
473 
474     /**
475      * This method returns the Sequence Number value.
476      *
477      * @returns The Sequence Number value.
478      *
479      */
GetSequence(void) const480     uint8_t GetSequence(void) const { return GetPsdu()[kSequenceIndex]; }
481 
482     /**
483      * This method sets the Sequence Number value.
484      *
485      * @param[in]  aSequence  The Sequence Number value.
486      *
487      */
SetSequence(uint8_t aSequence)488     void SetSequence(uint8_t aSequence) { GetPsdu()[kSequenceIndex] = aSequence; }
489 
490     /**
491      * This method indicates whether or not the Destination PAN ID is present.
492      *
493      * @returns TRUE if the Destination PAN ID is present, FALSE otherwise.
494      *
495      */
IsDstPanIdPresent(void) const496     bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); }
497 
498     /**
499      * This method gets the Destination PAN Identifier.
500      *
501      * @param[out]  aPanId  The Destination PAN Identifier.
502      *
503      * @retval kErrorNone   Successfully retrieved the Destination PAN Identifier.
504      * @retval kErrorParse  Failed to parse the PAN Identifier.
505      *
506      */
507     Error GetDstPanId(PanId &aPanId) const;
508 
509     /**
510      * This method sets the Destination PAN Identifier.
511      *
512      * @param[in]  aPanId  The Destination PAN Identifier.
513      *
514      */
515     void SetDstPanId(PanId aPanId);
516 
517     /**
518      * This method indicates whether or not the Destination Address is present for this object.
519      *
520      * @retval TRUE   If the Destination Address is present.
521      * @retval FALSE  If the Destination Address is not present.
522      *
523      */
IsDstAddrPresent() const524     bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); }
525 
526     /**
527      * This method gets the Destination Address.
528      *
529      * @param[out]  aAddress  The Destination Address.
530      *
531      * @retval kErrorNone  Successfully retrieved the Destination Address.
532      *
533      */
534     Error GetDstAddr(Address &aAddress) const;
535 
536     /**
537      * This method sets the Destination Address.
538      *
539      * @param[in]  aShortAddress  The Destination Address.
540      *
541      */
542     void SetDstAddr(ShortAddress aShortAddress);
543 
544     /**
545      * This method sets the Destination Address.
546      *
547      * @param[in]  aExtAddress  The Destination Address.
548      *
549      */
550     void SetDstAddr(const ExtAddress &aExtAddress);
551 
552     /**
553      * This method sets the Destination Address.
554      *
555      * @param[in]  aAddress  The Destination Address.
556      *
557      */
558     void SetDstAddr(const Address &aAddress);
559 
560     /**
561      * This method indicates whether or not the Source Address is present for this object.
562      *
563      * @retval TRUE   If the Source Address is present.
564      * @retval FALSE  If the Source Address is not present.
565      *
566      */
IsSrcPanIdPresent(void) const567     bool IsSrcPanIdPresent(void) const { return IsSrcPanIdPresent(GetFrameControlField()); }
568 
569     /**
570      * This method gets the Source PAN Identifier.
571      *
572      * @param[out]  aPanId  The Source PAN Identifier.
573      *
574      * @retval kErrorNone   Successfully retrieved the Source PAN Identifier.
575      *
576      */
577     Error GetSrcPanId(PanId &aPanId) const;
578 
579     /**
580      * This method sets the Source PAN Identifier.
581      *
582      * @param[in]  aPanId  The Source PAN Identifier.
583      *
584      * @retval kErrorNone   Successfully set the Source PAN Identifier.
585      *
586      */
587     Error SetSrcPanId(PanId aPanId);
588 
589     /**
590      * This method indicates whether or not the Source Address is present for this object.
591      *
592      * @retval TRUE   If the Source Address is present.
593      * @retval FALSE  If the Source Address is not present.
594      *
595      */
IsSrcAddrPresent(void) const596     bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); }
597 
598     /**
599      * This method gets the Source Address.
600      *
601      * @param[out]  aAddress  The Source Address.
602      *
603      * @retval kErrorNone  Successfully retrieved the Source Address.
604      *
605      */
606     Error GetSrcAddr(Address &aAddress) const;
607 
608     /**
609      * This method sets the Source Address.
610      *
611      * @param[in]  aShortAddress  The Source Address.
612      *
613      */
614     void SetSrcAddr(ShortAddress aShortAddress);
615 
616     /**
617      * This method sets the Source Address.
618      *
619      * @param[in]  aExtAddress  The Source Address.
620      *
621      */
622     void SetSrcAddr(const ExtAddress &aExtAddress);
623 
624     /**
625      * This method sets the Source Address.
626      *
627      * @param[in]  aAddress  The Source Address.
628      *
629      */
630     void SetSrcAddr(const Address &aAddress);
631 
632     /**
633      * This method gets the Security Control Field.
634      *
635      * @param[out]  aSecurityControlField  The Security Control Field.
636      *
637      * @retval kErrorNone   Successfully retrieved the Security Level Identifier.
638      * @retval kErrorParse  Failed to find the security control field in the frame.
639      *
640      */
641     Error GetSecurityControlField(uint8_t &aSecurityControlField) const;
642 
643     /**
644      * This method sets the Security Control Field.
645      *
646      * @param[in]  aSecurityControlField  The Security Control Field.
647      *
648      */
649     void SetSecurityControlField(uint8_t aSecurityControlField);
650 
651     /**
652      * This method gets the Security Level Identifier.
653      *
654      * @param[out]  aSecurityLevel  The Security Level Identifier.
655      *
656      * @retval kErrorNone  Successfully retrieved the Security Level Identifier.
657      *
658      */
659     Error GetSecurityLevel(uint8_t &aSecurityLevel) const;
660 
661     /**
662      * This method gets the Key Identifier Mode.
663      *
664      * @param[out]  aSecurityLevel  The Key Identifier Mode.
665      *
666      * @retval kErrorNone  Successfully retrieved the Key Identifier Mode.
667      *
668      */
669     Error GetKeyIdMode(uint8_t &aKeyIdMode) const;
670 
671     /**
672      * This method gets the Frame Counter.
673      *
674      * @param[out]  aFrameCounter  The Frame Counter.
675      *
676      * @retval kErrorNone  Successfully retrieved the Frame Counter.
677      *
678      */
679     Error GetFrameCounter(uint32_t &aFrameCounter) const;
680 
681     /**
682      * This method sets the Frame Counter.
683      *
684      * @param[in]  aFrameCounter  The Frame Counter.
685      *
686      */
687     void SetFrameCounter(uint32_t aFrameCounter);
688 
689     /**
690      * This method returns a pointer to the Key Source.
691      *
692      * @returns A pointer to the Key Source.
693      *
694      */
695     const uint8_t *GetKeySource(void) const;
696 
697     /**
698      * This method sets the Key Source.
699      *
700      * @param[in]  aKeySource  A pointer to the Key Source value.
701      *
702      */
703     void SetKeySource(const uint8_t *aKeySource);
704 
705     /**
706      * This method gets the Key Identifier.
707      *
708      * @param[out]  aKeyId  The Key Identifier.
709      *
710      * @retval kErrorNone  Successfully retrieved the Key Identifier.
711      *
712      */
713     Error GetKeyId(uint8_t &aKeyId) const;
714 
715     /**
716      * This method sets the Key Identifier.
717      *
718      * @param[in]  aKeyId  The Key Identifier.
719      *
720      */
721     void SetKeyId(uint8_t aKeyId);
722 
723     /**
724      * This method gets the Command ID.
725      *
726      * @param[out]  aCommandId  The Command ID.
727      *
728      * @retval kErrorNone  Successfully retrieved the Command ID.
729      *
730      */
731     Error GetCommandId(uint8_t &aCommandId) const;
732 
733     /**
734      * This method sets the Command ID.
735      *
736      * @param[in]  aCommandId  The Command ID.
737      *
738      * @retval kErrorNone  Successfully set the Command ID.
739      *
740      */
741     Error SetCommandId(uint8_t aCommandId);
742 
743     /**
744      * This method indicates whether the frame is a MAC Data Request command (data poll).
745      *
746      * For 802.15.4-2015 and above frame, the frame should be already decrypted.
747      *
748      * @returns TRUE if frame is a MAC Data Request command, FALSE otherwise.
749      *
750      */
751     bool IsDataRequestCommand(void) const;
752 
753     /**
754      * This method returns the MAC Frame Length.
755      *
756      * @returns The MAC Frame Length.
757      *
758      */
GetLength(void) const759     uint16_t GetLength(void) const { return mLength; }
760 
761     /**
762      * This method sets the MAC Frame Length.
763      *
764      * @param[in]  aLength  The MAC Frame Length.
765      *
766      */
SetLength(uint16_t aLength)767     void SetLength(uint16_t aLength) { mLength = aLength; }
768 
769     /**
770      * This method returns the MAC header size.
771      *
772      * @returns The MAC header size.
773      *
774      */
775     uint8_t GetHeaderLength(void) const;
776 
777     /**
778      * This method returns the MAC footer size.
779      *
780      * @returns The MAC footer size.
781      *
782      */
783     uint8_t GetFooterLength(void) const;
784 
785     /**
786      * This method returns the current MAC Payload length.
787      *
788      * @returns The current MAC Payload length.
789      *
790      */
791     uint16_t GetPayloadLength(void) const;
792 
793     /**
794      * This method returns the maximum MAC Payload length for the given MAC header and footer.
795      *
796      * @returns The maximum MAC Payload length for the given MAC header and footer.
797      *
798      */
799     uint16_t GetMaxPayloadLength(void) const;
800 
801     /**
802      * This method sets the MAC Payload length.
803      *
804      */
805     void SetPayloadLength(uint16_t aLength);
806 
807     /**
808      * This method returns the IEEE 802.15.4 channel used for transmission or reception.
809      *
810      * @returns The IEEE 802.15.4 channel used for transmission or reception.
811      *
812      */
GetChannel(void) const813     uint8_t GetChannel(void) const { return mChannel; }
814 
815     /**
816      * This method sets the IEEE 802.15.4 channel used for transmission or reception.
817      *
818      * @param[in]  aChannel  The IEEE 802.15.4 channel used for transmission or reception.
819      *
820      */
SetChannel(uint8_t aChannel)821     void SetChannel(uint8_t aChannel) { mChannel = aChannel; }
822 
823     /**
824      * This method returns the IEEE 802.15.4 PSDU length.
825      *
826      * @returns The IEEE 802.15.4 PSDU length.
827      *
828      */
GetPsduLength(void) const829     uint16_t GetPsduLength(void) const { return mLength; }
830 
831     /**
832      * This method returns a pointer to the PSDU.
833      *
834      * @returns A pointer to the PSDU.
835      *
836      */
GetPsdu(void)837     uint8_t *GetPsdu(void) { return mPsdu; }
838 
839     /**
840      * This const method returns a pointer to the PSDU.
841      *
842      * @returns A pointer to the PSDU.
843      *
844      */
GetPsdu(void) const845     const uint8_t *GetPsdu(void) const { return mPsdu; }
846 
847     /**
848      * This method returns a pointer to the MAC Header.
849      *
850      * @returns A pointer to the MAC Header.
851      *
852      */
GetHeader(void)853     uint8_t *GetHeader(void) { return GetPsdu(); }
854 
855     /**
856      * This const method returns a pointer to the MAC Header.
857      *
858      * @returns A pointer to the MAC Header.
859      *
860      */
GetHeader(void) const861     const uint8_t *GetHeader(void) const { return GetPsdu(); }
862 
863     /**
864      * This method returns a pointer to the MAC Payload.
865      *
866      * @returns A pointer to the MAC Payload.
867      *
868      */
GetPayload(void)869     uint8_t *GetPayload(void) { return const_cast<uint8_t *>(const_cast<const Frame *>(this)->GetPayload()); }
870 
871     /**
872      * This const method returns a pointer to the MAC Payload.
873      *
874      * @returns A pointer to the MAC Payload.
875      *
876      */
877     const uint8_t *GetPayload(void) const;
878 
879     /**
880      * This method returns a pointer to the MAC Footer.
881      *
882      * @returns A pointer to the MAC Footer.
883      *
884      */
GetFooter(void)885     uint8_t *GetFooter(void) { return const_cast<uint8_t *>(const_cast<const Frame *>(this)->GetFooter()); }
886 
887     /**
888      * This const method returns a pointer to the MAC Footer.
889      *
890      * @returns A pointer to the MAC Footer.
891      *
892      */
893     const uint8_t *GetFooter(void) const;
894 
895 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
896 
897     /**
898      * This method returns a pointer to the vendor specific Time IE.
899      *
900      * @returns A pointer to the Time IE, nullptr if not found.
901      *
902      */
GetTimeIe(void)903     TimeIe *GetTimeIe(void) { return const_cast<TimeIe *>(const_cast<const Frame *>(this)->GetTimeIe()); }
904 
905     /**
906      * This method returns a pointer to the vendor specific Time IE.
907      *
908      * @returns A pointer to the Time IE, nullptr if not found.
909      *
910      */
911     const TimeIe *GetTimeIe(void) const;
912 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
913 
914 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
915     /**
916      * This template method appends an Header IE at specified index in this frame.
917      *
918      * @param[in,out]   aIndex  The index to append IE. If `aIndex` is `0` on input, this method finds the index
919      *                          for the first IE and appends the IE at that position. If the position is not found
920      *                          successfully, `aIndex` will be set to `kInvalidIndex`. Otherwise the IE will be
921      *                          appended at `aIndex` on input. And on output, `aIndex` will be set to the end of the
922      *                          IE just appended.
923      *
924      * @tparam  IeType  The Header IE type, it MUST contain a constant `kHeaderIeId` equal to the IE's Id
925      *                  and a constant `kIeContentSize` indicating the IE body's size.
926      *
927      * @retval kErrorNone      Successfully appended the Header IE.
928      * @retval kErrorNotFound  The position for first IE is not found.
929      *
930      */
931     template <typename IeType> Error AppendHeaderIeAt(uint8_t &aIndex);
932 
933     /**
934      * This method returns a pointer to the Header IE.
935      *
936      * @param[in] aIeId  The Element Id of the Header IE.
937      *
938      * @returns A pointer to the Header IE, nullptr if not found.
939      *
940      */
GetHeaderIe(uint8_t aIeId)941     uint8_t *GetHeaderIe(uint8_t aIeId)
942     {
943         return const_cast<uint8_t *>(const_cast<const Frame *>(this)->GetHeaderIe(aIeId));
944     }
945 
946     /**
947      * This method returns a pointer to the Header IE.
948      *
949      * @param[in] aIeId  The Element Id of the Header IE.
950      *
951      * @returns A pointer to the Header IE, nullptr if not found.
952      *
953      */
954     const uint8_t *GetHeaderIe(uint8_t aIeId) const;
955 
956     /**
957      * This method returns a pointer to a specific Thread IE.
958      *
959      * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
960      *
961      * @param[in] aSubType  The sub type of the Thread IE.
962      *
963      * @returns A pointer to the Thread IE, nullptr if not found.
964      *
965      */
GetThreadIe(uint8_t aSubType)966     uint8_t *GetThreadIe(uint8_t aSubType)
967     {
968         return const_cast<uint8_t *>(const_cast<const Frame *>(this)->GetThreadIe(aSubType));
969     }
970 
971     /**
972      * This method returns a pointer to a specific Thread IE.
973      *
974      * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
975      *
976      * @param[in] aSubType  The sub type of the Thread IE.
977      *
978      * @returns A pointer to the Thread IE, nullptr if not found.
979      *
980      */
981     const uint8_t *GetThreadIe(uint8_t aSubType) const;
982 
983 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
984     /**
985      * This method finds CSL IE in the frame and modify its content.
986      *
987      * @param[in] aCslPeriod  CSL Period in CSL IE.
988      * @param[in] aCslPhase   CSL Phase in CSL IE.
989      *
990      */
991     void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase);
992 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
993 
994 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
995     /**
996      * This method finds Enhanced ACK Probing (Vendor Specific) IE and set its value.
997      *
998      * @param[in] aValue  A pointer to the value to set.
999      * @param[in] aLen    The length of @p aValue.
1000      *
1001      */
1002     void SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen);
1003 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1004 
1005 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1006 
1007 #if OPENTHREAD_CONFIG_MULTI_RADIO
1008     /**
1009      * This method gets the radio link type of the frame.
1010      *
1011      * @returns Frame's radio link type.
1012      *
1013      */
GetRadioType(void) const1014     RadioType GetRadioType(void) const { return static_cast<RadioType>(mRadioType); }
1015 
1016     /**
1017      * This method sets the radio link type of the frame.
1018      *
1019      * @param[in] aRadioType  A radio link type.
1020      *
1021      */
SetRadioType(RadioType aRadioType)1022     void SetRadioType(RadioType aRadioType) { mRadioType = static_cast<uint8_t>(aRadioType); }
1023 #endif
1024 
1025     /**
1026      * This method returns the maximum transmission unit size (MTU).
1027      *
1028      * @returns The maximum transmission unit (MTU).
1029      *
1030      */
GetMtu(void) const1031     uint16_t GetMtu(void) const
1032 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
1033     {
1034         return OT_RADIO_FRAME_MAX_SIZE;
1035     }
1036 #else
1037         ;
1038 #endif
1039 
1040     /**
1041      * This method returns the FCS size.
1042      *
1043      * @returns This method returns the FCS size.
1044      *
1045      */
GetFcsSize(void) const1046     uint8_t GetFcsSize(void) const
1047 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
1048     {
1049         return k154FcsSize;
1050     }
1051 #else
1052         ;
1053 #endif
1054 
1055     /**
1056      * This method returns information about the frame object as an `InfoString` object.
1057      *
1058      * @returns An `InfoString` containing info about the frame.
1059      *
1060      */
1061     InfoString ToInfoString(void) const;
1062 
1063     /**
1064      * This method returns the Frame Control field of the frame.
1065      *
1066      * @returns The Frame Control field.
1067      *
1068      */
1069     uint16_t GetFrameControlField(void) const;
1070 
1071 protected:
1072     static constexpr uint8_t kInvalidIndex  = 0xff;
1073     static constexpr uint8_t kInvalidSize   = kInvalidIndex;
1074     static constexpr uint8_t kMaxPsduSize   = kInvalidSize - 1;
1075     static constexpr uint8_t kSequenceIndex = kFcfSize;
1076 
1077     uint8_t FindDstPanIdIndex(void) const;
1078     uint8_t FindDstAddrIndex(void) const;
1079     uint8_t FindSrcPanIdIndex(void) const;
1080     uint8_t FindSrcAddrIndex(void) const;
1081     uint8_t SkipAddrFieldIndex(void) const;
1082     uint8_t FindSecurityHeaderIndex(void) const;
1083     uint8_t SkipSecurityHeaderIndex(void) const;
1084     uint8_t FindPayloadIndex(void) const;
1085 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1086     uint8_t FindHeaderIeIndex(void) const;
1087 
1088     Error                           InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize);
1089     template <typename IeType> void InitIeContentAt(uint8_t &aIndex);
1090 #endif
1091 
1092     static uint8_t GetKeySourceLength(uint8_t aKeyIdMode);
1093 
IsDstAddrPresent(uint16_t aFcf)1094     static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != kFcfDstAddrNone; }
1095     static bool IsDstPanIdPresent(uint16_t aFcf);
IsSrcAddrPresent(uint16_t aFcf)1096     static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone; }
1097     static bool IsSrcPanIdPresent(uint16_t aFcf);
IsVersion2015(uint16_t aFcf)1098     static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kFcfFrameVersion2015; }
1099 
1100     static uint8_t CalculateAddrFieldSize(uint16_t aFcf);
1101     static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
1102     static uint8_t CalculateMicSize(uint8_t aSecurityControl);
1103 };
1104 
1105 /**
1106  * This class supports received IEEE 802.15.4 MAC frame processing.
1107  *
1108  */
1109 class RxFrame : public Frame
1110 {
1111 public:
1112     friend class TxFrame;
1113 
1114     /**
1115      * This method returns the RSSI in dBm used for reception.
1116      *
1117      * @returns The RSSI in dBm used for reception.
1118      *
1119      */
GetRssi(void) const1120     int8_t GetRssi(void) const { return mInfo.mRxInfo.mRssi; }
1121 
1122     /**
1123      * This method sets the RSSI in dBm used for reception.
1124      *
1125      * @param[in]  aRssi  The RSSI in dBm used for reception.
1126      *
1127      */
SetRssi(int8_t aRssi)1128     void SetRssi(int8_t aRssi) { mInfo.mRxInfo.mRssi = aRssi; }
1129 
1130     /**
1131      * This method returns the receive Link Quality Indicator.
1132      *
1133      * @returns The receive Link Quality Indicator.
1134      *
1135      */
GetLqi(void) const1136     uint8_t GetLqi(void) const { return mInfo.mRxInfo.mLqi; }
1137 
1138     /**
1139      * This method sets the receive Link Quality Indicator.
1140      *
1141      * @param[in]  aLqi  The receive Link Quality Indicator.
1142      *
1143      */
SetLqi(uint8_t aLqi)1144     void SetLqi(uint8_t aLqi) { mInfo.mRxInfo.mLqi = aLqi; }
1145 
1146     /**
1147      * This method indicates whether or not the received frame is acknowledged with frame pending set.
1148      *
1149      * @retval TRUE   This frame is acknowledged with frame pending set.
1150      * @retval FALSE  This frame is acknowledged with frame pending not set.
1151      *
1152      */
IsAckedWithFramePending(void) const1153     bool IsAckedWithFramePending(void) const { return mInfo.mRxInfo.mAckedWithFramePending; }
1154 
1155     /**
1156      * This method returns the timestamp when the frame was received.
1157      *
1158      * @returns The timestamp when the frame was received, in microseconds.
1159      *
1160      */
GetTimestamp(void) const1161     const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; }
1162 
1163     /**
1164      * This method performs AES CCM on the frame which is received.
1165      *
1166      * @param[in]  aExtAddress  A reference to the extended address, which will be used to generate nonce
1167      *                          for AES CCM computation.
1168      * @param[in]  aMacKey      A reference to the MAC key to decrypt the received frame.
1169      *
1170      * @retval kErrorNone      Process of received frame AES CCM succeeded.
1171      * @retval kErrorSecurity  Received frame MIC check failed.
1172      *
1173      */
1174     Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey);
1175 
1176 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1177     /**
1178      * This method gets the offset to network time.
1179      *
1180      * @returns  The offset to network time.
1181      *
1182      */
ComputeNetworkTimeOffset(void) const1183     int64_t ComputeNetworkTimeOffset(void) const
1184     {
1185         return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp());
1186     }
1187 
1188     /**
1189      * This method gets the time sync sequence.
1190      *
1191      * @returns  The time sync sequence.
1192      *
1193      */
ReadTimeSyncSeq(void) const1194     uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); }
1195 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1196 };
1197 
1198 /**
1199  * This class supports IEEE 802.15.4 MAC frame generation for transmission.
1200  *
1201  */
1202 class TxFrame : public Frame
1203 {
1204 public:
1205     /**
1206      * This method returns the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel
1207      * access failure.
1208      *
1209      * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006.
1210      *
1211      * @returns The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access
1212      *          failure.
1213      *
1214      */
GetMaxCsmaBackoffs(void) const1215     uint8_t GetMaxCsmaBackoffs(void) const { return mInfo.mTxInfo.mMaxCsmaBackoffs; }
1216 
1217     /**
1218      * This method sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel
1219      * access failure.
1220      *
1221      * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006.
1222      *
1223      * @param[in]  aMaxCsmaBackoffs  The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring
1224      *                               a channel access failure.
1225      *
1226      */
SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs)1227     void SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs) { mInfo.mTxInfo.mMaxCsmaBackoffs = aMaxCsmaBackoffs; }
1228 
1229     /**
1230      * This method returns the maximum number of retries allowed after a transmission failure.
1231      *
1232      * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006.
1233      *
1234      * @returns The maximum number of retries allowed after a transmission failure.
1235      *
1236      */
GetMaxFrameRetries(void) const1237     uint8_t GetMaxFrameRetries(void) const { return mInfo.mTxInfo.mMaxFrameRetries; }
1238 
1239     /**
1240      * This method sets the maximum number of retries allowed after a transmission failure.
1241      *
1242      * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006.
1243      *
1244      * @param[in]  aMaxFrameRetries  The maximum number of retries allowed after a transmission failure.
1245      *
1246      */
SetMaxFrameRetries(uint8_t aMaxFrameRetries)1247     void SetMaxFrameRetries(uint8_t aMaxFrameRetries) { mInfo.mTxInfo.mMaxFrameRetries = aMaxFrameRetries; }
1248 
1249     /**
1250      * This method indicates whether or not the frame is a retransmission.
1251      *
1252      * @retval TRUE   Frame is a retransmission
1253      * @retval FALSE  This is a new frame and not a retransmission of an earlier frame.
1254      *
1255      */
IsARetransmission(void) const1256     bool IsARetransmission(void) const { return mInfo.mTxInfo.mIsARetx; }
1257 
1258     /**
1259      * This method sets the retransmission flag attribute.
1260      *
1261      * @param[in]  aIsARetx  TRUE if frame is a retransmission of an earlier frame, FALSE otherwise.
1262      *
1263      */
SetIsARetransmission(bool aIsARetx)1264     void SetIsARetransmission(bool aIsARetx) { mInfo.mTxInfo.mIsARetx = aIsARetx; }
1265 
1266     /**
1267      * This method indicates whether or not CSMA-CA is enabled.
1268      *
1269      * @retval TRUE   CSMA-CA is enabled.
1270      * @retval FALSE  CSMA-CA is not enabled is not enabled.
1271      *
1272      */
IsCsmaCaEnabled(void) const1273     bool IsCsmaCaEnabled(void) const { return mInfo.mTxInfo.mCsmaCaEnabled; }
1274 
1275     /**
1276      * This method sets the CSMA-CA enabled attribute.
1277      *
1278      * @param[in]  aCsmaCaEnabled  TRUE if CSMA-CA must be enabled for this packet, FALSE otherwise.
1279      *
1280      */
SetCsmaCaEnabled(bool aCsmaCaEnabled)1281     void SetCsmaCaEnabled(bool aCsmaCaEnabled) { mInfo.mTxInfo.mCsmaCaEnabled = aCsmaCaEnabled; }
1282 
1283     /**
1284      * This method returns the key used for frame encryption and authentication (AES CCM).
1285      *
1286      * @returns The pointer to the key.
1287      *
1288      */
GetAesKey(void) const1289     const Mac::Key &GetAesKey(void) const { return *static_cast<const Mac::Key *>(mInfo.mTxInfo.mAesKey); }
1290 
1291     /**
1292      * This method sets the key used for frame encryption and authentication (AES CCM).
1293      *
1294      * @param[in]  aAesKey  The pointer to the key.
1295      *
1296      */
SetAesKey(const Mac::Key & aAesKey)1297     void SetAesKey(const Mac::Key &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; }
1298 
1299     /**
1300      * This method copies the PSDU and all attributes (except for frame link type) from another frame.
1301      *
1302      * @note This method performs a deep copy meaning the content of PSDU buffer from the given frame is copied into
1303      * the PSDU buffer of the current frame.
1304 
1305      * @param[in] aFromFrame  The frame to copy from.
1306      *
1307      */
1308     void CopyFrom(const TxFrame &aFromFrame);
1309 
1310     /**
1311      * This method performs AES CCM on the frame which is going to be sent.
1312      *
1313      * @param[in]  aExtAddress  A reference to the extended address, which will be used to generate nonce
1314      *                          for AES CCM computation.
1315      *
1316      */
1317     void ProcessTransmitAesCcm(const ExtAddress &aExtAddress);
1318 
1319     /**
1320      * This method indicates whether or not the frame has security processed.
1321      *
1322      * @retval TRUE   The frame already has security processed.
1323      * @retval FALSE  The frame does not have security processed.
1324      *
1325      */
IsSecurityProcessed(void) const1326     bool IsSecurityProcessed(void) const { return mInfo.mTxInfo.mIsSecurityProcessed; }
1327 
1328     /**
1329      * This method sets the security processed flag attribute.
1330      *
1331      * @param[in]  aIsSecurityProcessed  TRUE if the frame already has security processed.
1332      *
1333      */
SetIsSecurityProcessed(bool aIsSecurityProcessed)1334     void SetIsSecurityProcessed(bool aIsSecurityProcessed)
1335     {
1336         mInfo.mTxInfo.mIsSecurityProcessed = aIsSecurityProcessed;
1337     }
1338 
1339     /**
1340      * This method indicates whether or not the frame header is updated.
1341      *
1342      * @retval TRUE   The frame already has the header updated.
1343      * @retval FALSE  The frame does not have the header updated.
1344      *
1345      */
IsHeaderUpdated(void) const1346     bool IsHeaderUpdated(void) const { return mInfo.mTxInfo.mIsHeaderUpdated; }
1347 
1348     /**
1349      * This method sets the header updated flag attribute.
1350      *
1351      * @param[in]  aIsHeaderUpdated  TRUE if the frame header is updated.
1352      *
1353      */
SetIsHeaderUpdated(bool aIsHeaderUpdated)1354     void SetIsHeaderUpdated(bool aIsHeaderUpdated) { mInfo.mTxInfo.mIsHeaderUpdated = aIsHeaderUpdated; }
1355 
1356 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1357     /**
1358      * This method sets the Time IE offset.
1359      *
1360      * @param[in]  aOffset  The Time IE offset, 0 means no Time IE.
1361      *
1362      */
SetTimeIeOffset(uint8_t aOffset)1363     void SetTimeIeOffset(uint8_t aOffset) { mInfo.mTxInfo.mIeInfo->mTimeIeOffset = aOffset; }
1364 
1365     /**
1366      * This method gets the Time IE offset.
1367      *
1368      * @returns The Time IE offset, 0 means no Time IE.
1369      *
1370      */
GetTimeIeOffset(void) const1371     uint8_t GetTimeIeOffset(void) const { return mInfo.mTxInfo.mIeInfo->mTimeIeOffset; }
1372 
1373     /**
1374      * This method sets the offset to network time.
1375      *
1376      * @param[in]  aNetworkTimeOffset  The offset to network time.
1377      *
1378      */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1379     void SetNetworkTimeOffset(int64_t aNetworkTimeOffset)
1380     {
1381         mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset;
1382     }
1383 
1384     /**
1385      * This method sets the time sync sequence.
1386      *
1387      * @param[in]  aTimeSyncSeq  The time sync sequence.
1388      *
1389      */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1390     void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; }
1391 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1392 
1393     /**
1394      * Generate Imm-Ack in this frame object.
1395      *
1396      * @param[in]    aFrame             A reference to the frame received.
1397      * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
1398      *
1399      */
1400     void GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending);
1401 
1402     /**
1403      * Generate Enh-Ack in this frame object.
1404      *
1405      * @param[in]    aFrame             A reference to the frame received.
1406      * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
1407      * @param[in]    aIeData            A pointer to the IE data portion of the ACK to be sent.
1408      * @param[in]    aIeLength          The length of IE data portion of the ACK to be sent.
1409      *
1410      * @retval  kErrorNone           Successfully generated Enh Ack.
1411      * @retval  kErrorParse          @p aFrame has incorrect format.
1412      *
1413      */
1414     Error GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength);
1415 
1416 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
1417     /**
1418      * Set TX delay field for the frame.
1419      *
1420      * @param[in]    aTxDelay    The delay time for the TX frame.
1421      *
1422      */
SetTxDelay(uint32_t aTxDelay)1423     void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; }
1424 
1425     /**
1426      * Set TX delay base time field for the frame.
1427      *
1428      * @param[in]    aTxDelayBaseTime    The delay base time for the TX frame.
1429      *
1430      */
SetTxDelayBaseTime(uint32_t aTxDelayBaseTime)1431     void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; }
1432 #endif
1433 };
1434 
1435 OT_TOOL_PACKED_BEGIN
1436 class Beacon
1437 {
1438 public:
1439     static constexpr uint16_t kSuperFrameSpec = 0x0fff; ///< Superframe Specification value.
1440 
1441     /**
1442      * This method initializes the Beacon message.
1443      *
1444      */
Init(void)1445     void Init(void)
1446     {
1447         mSuperframeSpec     = HostSwap16(kSuperFrameSpec);
1448         mGtsSpec            = 0;
1449         mPendingAddressSpec = 0;
1450     }
1451 
1452     /**
1453      * This method indicates whether or not the beacon appears to be a valid Thread Beacon message.
1454      *
1455      * @retval TRUE   If the beacon appears to be a valid Thread Beacon message.
1456      * @retval FALSE  If the beacon does not appear to be a valid Thread Beacon message.
1457      *
1458      */
IsValid(void) const1459     bool IsValid(void) const
1460     {
1461         return (mSuperframeSpec == HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) && (mPendingAddressSpec == 0);
1462     }
1463 
1464     /**
1465      * This method returns the pointer to the beacon payload.
1466      *
1467      * @returns A pointer to the beacon payload.
1468      *
1469      */
GetPayload(void)1470     uint8_t *GetPayload(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
1471 
1472     /**
1473      * This method returns the pointer to the beacon payload.
1474      *
1475      * @returns A pointer to the beacon payload.
1476      *
1477      */
GetPayload(void) const1478     const uint8_t *GetPayload(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
1479 
1480 private:
1481     uint16_t mSuperframeSpec;
1482     uint8_t  mGtsSpec;
1483     uint8_t  mPendingAddressSpec;
1484 } OT_TOOL_PACKED_END;
1485 
1486 /**
1487  * This class implements IEEE 802.15.4 Beacon Payload generation and parsing.
1488  *
1489  */
1490 OT_TOOL_PACKED_BEGIN
1491 class BeaconPayload
1492 {
1493 public:
1494     static constexpr uint8_t kProtocolId      = 3;                     ///< Thread Protocol ID.
1495     static constexpr uint8_t kProtocolVersion = 2;                     ///< Thread Protocol version.
1496     static constexpr uint8_t kVersionOffset   = 4;                     ///< Version field bit offset.
1497     static constexpr uint8_t kVersionMask     = 0xf << kVersionOffset; ///< Version field mask.
1498     static constexpr uint8_t kNativeFlag      = 1 << 3;                ///< Native Commissioner flag.
1499     static constexpr uint8_t kJoiningFlag     = 1 << 0;                ///< Joining Permitted flag.
1500 
1501     static constexpr uint16_t kInfoStringSize = 92; ///< Max chars for the info string (@sa ToInfoString()).
1502 
1503     /**
1504      * This type defines the fixed-length `String` object returned from `ToInfoString()` method.
1505      *
1506      */
1507     typedef String<kInfoStringSize> InfoString;
1508 
1509     /**
1510      * This method initializes the Beacon Payload.
1511      *
1512      */
Init(void)1513     void Init(void)
1514     {
1515         mProtocolId = kProtocolId;
1516         mFlags      = kProtocolVersion << kVersionOffset;
1517     }
1518 
1519     /**
1520      * This method indicates whether or not the beacon appears to be a valid Thread Beacon Payload.
1521      *
1522      * @retval TRUE   If the beacon appears to be a valid Thread Beacon Payload.
1523      * @retval FALSE  If the beacon does not appear to be a valid Thread Beacon Payload.
1524      *
1525      */
IsValid(void) const1526     bool IsValid(void) const { return (mProtocolId == kProtocolId); }
1527 
1528     /**
1529      * This method returns the Protocol ID value.
1530      *
1531      * @returns the Protocol ID value.
1532      *
1533      */
GetProtocolId(void) const1534     uint8_t GetProtocolId(void) const { return mProtocolId; }
1535 
1536     /**
1537      * This method returns the Protocol Version value.
1538      *
1539      * @returns The Protocol Version value.
1540      *
1541      */
GetProtocolVersion(void) const1542     uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; }
1543 
1544     /**
1545      * This method indicates whether or not the Native Commissioner flag is set.
1546      *
1547      * @retval TRUE   If the Native Commissioner flag is set.
1548      * @retval FALSE  If the Native Commissioner flag is not set.
1549      *
1550      */
IsNative(void) const1551     bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; }
1552 
1553     /**
1554      * This method clears the Native Commissioner flag.
1555      *
1556      */
ClearNative(void)1557     void ClearNative(void) { mFlags &= ~kNativeFlag; }
1558 
1559     /**
1560      * This method sets the Native Commissioner flag.
1561      *
1562      */
SetNative(void)1563     void SetNative(void) { mFlags |= kNativeFlag; }
1564 
1565     /**
1566      * This method indicates whether or not the Joining Permitted flag is set.
1567      *
1568      * @retval TRUE   If the Joining Permitted flag is set.
1569      * @retval FALSE  If the Joining Permitted flag is not set.
1570      *
1571      */
IsJoiningPermitted(void) const1572     bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; }
1573 
1574     /**
1575      * This method clears the Joining Permitted flag.
1576      *
1577      */
ClearJoiningPermitted(void)1578     void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; }
1579 
1580     /**
1581      * This method sets the Joining Permitted flag.
1582      *
1583      */
SetJoiningPermitted(void)1584     void SetJoiningPermitted(void)
1585     {
1586         mFlags |= kJoiningFlag;
1587 
1588 #if OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION != 2 // check against kProtocolVersion
1589         mFlags &= ~kVersionMask;
1590         mFlags |= OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION << kVersionOffset;
1591 #endif
1592     }
1593 
1594     /**
1595      * This method gets the Network Name field.
1596      *
1597      * @returns The Network Name field as `NameData`.
1598      *
1599      */
GetNetworkName(void) const1600     NameData GetNetworkName(void) const { return NameData(mNetworkName, sizeof(mNetworkName)); }
1601 
1602     /**
1603      * This method sets the Network Name field.
1604      *
1605      * @param[in]  aNameData  The Network Name (as a `NameData`).
1606      *
1607      */
SetNetworkName(const NameData & aNameData)1608     void SetNetworkName(const NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); }
1609 
1610     /**
1611      * This method returns the Extended PAN ID field.
1612      *
1613      * @returns The Extended PAN ID field.
1614      *
1615      */
GetExtendedPanId(void) const1616     const ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
1617 
1618     /**
1619      * This method sets the Extended PAN ID field.
1620      *
1621      * @param[in]  aExtPanId  An Extended PAN ID.
1622      *
1623      */
SetExtendedPanId(const ExtendedPanId & aExtPanId)1624     void SetExtendedPanId(const ExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; }
1625 
1626     /**
1627      * This method returns information about the Beacon as a `InfoString`.
1628      *
1629      * @returns An `InfoString` representing the beacon payload.
1630      *
1631      */
1632     InfoString ToInfoString(void) const;
1633 
1634 private:
1635     uint8_t       mProtocolId;
1636     uint8_t       mFlags;
1637     char          mNetworkName[NetworkName::kMaxSize];
1638     ExtendedPanId mExtendedPanId;
1639 } OT_TOOL_PACKED_END;
1640 
1641 /**
1642  * This class implements CSL IE data structure.
1643  *
1644  */
1645 OT_TOOL_PACKED_BEGIN
1646 class CslIe
1647 {
1648 public:
1649     static constexpr uint8_t kHeaderIeId    = 0x1a;
1650     static constexpr uint8_t kIeContentSize = sizeof(uint16_t) * 2;
1651 
1652     /**
1653      * This method returns the CSL Period.
1654      *
1655      * @returns the CSL Period.
1656      *
1657      */
GetPeriod(void) const1658     uint16_t GetPeriod(void) const { return HostSwap16(mPeriod); }
1659 
1660     /**
1661      * This method sets the CSL Period.
1662      *
1663      * @param[in]  aPeriod  The CSL Period.
1664      *
1665      */
SetPeriod(uint16_t aPeriod)1666     void SetPeriod(uint16_t aPeriod) { mPeriod = HostSwap16(aPeriod); }
1667 
1668     /**
1669      * This method returns the CSL Phase.
1670      *
1671      * @returns the CSL Phase.
1672      *
1673      */
GetPhase(void) const1674     uint16_t GetPhase(void) const { return HostSwap16(mPhase); }
1675 
1676     /**
1677      * This method sets the CSL Phase.
1678      *
1679      * @param[in]  aPhase  The CSL Phase.
1680      *
1681      */
SetPhase(uint16_t aPhase)1682     void SetPhase(uint16_t aPhase) { mPhase = HostSwap16(aPhase); }
1683 
1684 private:
1685     uint16_t mPhase;
1686     uint16_t mPeriod;
1687 } OT_TOOL_PACKED_END;
1688 
1689 /**
1690  * This class implements Termination2 IE.
1691  *
1692  * This class is empty for template specialization.
1693  *
1694  */
1695 class Termination2Ie
1696 {
1697 public:
1698     static constexpr uint8_t kHeaderIeId    = 0x7f;
1699     static constexpr uint8_t kIeContentSize = 0;
1700 };
1701 
1702 /**
1703  * @}
1704  *
1705  */
1706 
1707 } // namespace Mac
1708 } // namespace ot
1709 
1710 #endif // MAC_FRAME_HPP_
1711