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