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  * 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      * Initializes the Header IE.
73      *
74      */
Init(void)75     void Init(void) { mFields.m16 = 0; }
76 
77     /**
78      * 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      * 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      * 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      * 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      * 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  * 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      * 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      * 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      * 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      * 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  * 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      * Initializes the time IE.
211      *
212      */
Init(void)213     void Init(void)
214     {
215         SetVendorOui(kVendorOuiNest);
216         SetSubType(kVendorIeTime);
217     }
218 
219     /**
220      * 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      * 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      * 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      * 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  * Implements IEEE 802.15.4 MAC frame generation and parsing.
273  *
274  */
275 class Frame : public otRadioFrame
276 {
277 public:
278     /**
279      * 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      * 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      * 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      * 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      * 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     static constexpr uint8_t kPreambleSize  = 4;
357     static constexpr uint8_t kSfdSize       = 1;
358     static constexpr uint8_t kPhrSize       = 1;
359     static constexpr uint8_t kPhyHeaderSize = kPreambleSize + kSfdSize + kPhrSize;
360     static constexpr uint8_t kFcfSize       = sizeof(uint16_t);
361     static constexpr uint8_t kDsnSize       = sizeof(uint8_t);
362     static constexpr uint8_t k154FcsSize    = sizeof(uint16_t);
363     static constexpr uint8_t kImmAckLength  = kFcfSize + kDsnSize + k154FcsSize;
364 
365     /**
366      * Defines the fixed-length `String` object returned from `ToInfoString()` method.
367      *
368      */
369     typedef String<kInfoStringSize> InfoString;
370 
371     /**
372      * Indicates whether the frame is empty (no payload).
373      *
374      * @retval TRUE   The frame is empty (no PSDU payload).
375      * @retval FALSE  The frame is not empty.
376      *
377      */
IsEmpty(void) const378     bool IsEmpty(void) const { return (mLength == 0); }
379 
380     /**
381      * Initializes the MAC header.
382      *
383      * Determines and writes the Frame Control Field (FCF) and Security Control in the frame along with
384      * given source and destination addresses and PAN IDs.
385      *
386      * The Ack Request bit in FCF is set if there is destination and it is not broadcast and frame type @p aType is not
387      * ACK. The Frame Pending and IE Present bits are not set.
388      *
389      * @param[in] aType          Frame type.
390      * @param[in] aVerion        Frame version.
391      * @param[in] aAddrs         Frame source and destination addresses (each can be none, short, or extended).
392      * @param[in] aPanIds        Source and destination PAN IDs.
393      * @param[in] aSecurityLevel Frame security level.
394      * @param[in] aKeyIdMode     Frame security key ID mode.
395      *
396      */
397     void InitMacHeader(Type             aType,
398                        Version          aVersion,
399                        const Addresses &aAddrs,
400                        const PanIds    &aPanIds,
401                        SecurityLevel    aSecurityLevel,
402                        KeyIdMode        aKeyIdMode = kKeyIdMode0);
403 
404     /**
405      * Validates the frame.
406      *
407      * @retval kErrorNone    Successfully parsed the MAC header.
408      * @retval kErrorParse   Failed to parse through the MAC header.
409      *
410      */
411     Error ValidatePsdu(void) const;
412 
413     /**
414      * Returns the IEEE 802.15.4 Frame Type.
415      *
416      * @returns The IEEE 802.15.4 Frame Type.
417      *
418      */
GetType(void) const419     uint8_t GetType(void) const { return GetPsdu()[0] & kFcfFrameTypeMask; }
420 
421     /**
422      * Returns whether the frame is an Ack frame.
423      *
424      * @retval TRUE   If this is an Ack.
425      * @retval FALSE  If this is not an Ack.
426      *
427      */
IsAck(void) const428     bool IsAck(void) const { return GetType() == kTypeAck; }
429 
430     /**
431      * Returns the IEEE 802.15.4 Frame Version.
432      *
433      * @returns The IEEE 802.15.4 Frame Version.
434      *
435      */
GetVersion(void) const436     uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; }
437 
438     /**
439      * Returns if this IEEE 802.15.4 frame's version is 2015.
440      *
441      * @returns TRUE if version is 2015, FALSE otherwise.
442      *
443      */
IsVersion2015(void) const444     bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); }
445 
446     /**
447      * Indicates whether or not security is enabled.
448      *
449      * @retval TRUE   If security is enabled.
450      * @retval FALSE  If security is not enabled.
451      *
452      */
GetSecurityEnabled(void) const453     bool GetSecurityEnabled(void) const { return (GetPsdu()[0] & kFcfSecurityEnabled) != 0; }
454 
455     /**
456      * Indicates whether or not the Frame Pending bit is set.
457      *
458      * @retval TRUE   If the Frame Pending bit is set.
459      * @retval FALSE  If the Frame Pending bit is not set.
460      *
461      */
GetFramePending(void) const462     bool GetFramePending(void) const { return (GetPsdu()[0] & kFcfFramePending) != 0; }
463 
464     /**
465      * Sets the Frame Pending bit.
466      *
467      * @param[in]  aFramePending  The Frame Pending bit.
468      *
469      */
470     void SetFramePending(bool aFramePending);
471 
472     /**
473      * Indicates whether or not the Ack Request bit is set.
474      *
475      * @retval TRUE   If the Ack Request bit is set.
476      * @retval FALSE  If the Ack Request bit is not set.
477      *
478      */
GetAckRequest(void) const479     bool GetAckRequest(void) const { return (GetPsdu()[0] & kFcfAckRequest) != 0; }
480 
481     /**
482      * Sets the Ack Request bit.
483      *
484      * @param[in]  aAckRequest  The Ack Request bit.
485      *
486      */
487     void SetAckRequest(bool aAckRequest);
488 
489     /**
490      * Indicates whether or not the PanId Compression bit is set.
491      *
492      * @retval TRUE   If the PanId Compression bit is set.
493      * @retval FALSE  If the PanId Compression bit is not set.
494      *
495      */
IsPanIdCompressed(void) const496     bool IsPanIdCompressed(void) const { return (GetFrameControlField() & kFcfPanidCompression) != 0; }
497 
498     /**
499      * Indicates whether or not IEs present.
500      *
501      * @retval TRUE   If IEs present.
502      * @retval FALSE  If no IE present.
503      *
504      */
IsIePresent(void) const505     bool IsIePresent(void) const { return (GetFrameControlField() & kFcfIePresent) != 0; }
506 
507     /**
508      * Sets the IE Present bit.
509      *
510      * @param[in]  aIePresent   The IE Present bit.
511      *
512      */
513     void SetIePresent(bool aIePresent);
514 
515     /**
516      * Returns the Sequence Number value.
517      *
518      * @returns The Sequence Number value.
519      *
520      */
GetSequence(void) const521     uint8_t GetSequence(void) const { return GetPsdu()[kSequenceIndex]; }
522 
523     /**
524      * Sets the Sequence Number value.
525      *
526      * @param[in]  aSequence  The Sequence Number value.
527      *
528      */
SetSequence(uint8_t aSequence)529     void SetSequence(uint8_t aSequence) { GetPsdu()[kSequenceIndex] = aSequence; }
530 
531     /**
532      * Indicates whether or not the Destination PAN ID is present.
533      *
534      * @returns TRUE if the Destination PAN ID is present, FALSE otherwise.
535      *
536      */
IsDstPanIdPresent(void) const537     bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); }
538 
539     /**
540      * Gets the Destination PAN Identifier.
541      *
542      * @param[out]  aPanId  The Destination PAN Identifier.
543      *
544      * @retval kErrorNone   Successfully retrieved the Destination PAN Identifier.
545      * @retval kErrorParse  Failed to parse the PAN Identifier.
546      *
547      */
548     Error GetDstPanId(PanId &aPanId) const;
549 
550     /**
551      * Sets the Destination PAN Identifier.
552      *
553      * @param[in]  aPanId  The Destination PAN Identifier.
554      *
555      */
556     void SetDstPanId(PanId aPanId);
557 
558     /**
559      * Indicates whether or not the Destination Address is present for this object.
560      *
561      * @retval TRUE   If the Destination Address is present.
562      * @retval FALSE  If the Destination Address is not present.
563      *
564      */
IsDstAddrPresent() const565     bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); }
566 
567     /**
568      * Gets the Destination Address.
569      *
570      * @param[out]  aAddress  The Destination Address.
571      *
572      * @retval kErrorNone  Successfully retrieved the Destination Address.
573      *
574      */
575     Error GetDstAddr(Address &aAddress) const;
576 
577     /**
578      * Sets the Destination Address.
579      *
580      * @param[in]  aShortAddress  The Destination Address.
581      *
582      */
583     void SetDstAddr(ShortAddress aShortAddress);
584 
585     /**
586      * Sets the Destination Address.
587      *
588      * @param[in]  aExtAddress  The Destination Address.
589      *
590      */
591     void SetDstAddr(const ExtAddress &aExtAddress);
592 
593     /**
594      * Sets the Destination Address.
595      *
596      * @param[in]  aAddress  The Destination Address.
597      *
598      */
599     void SetDstAddr(const Address &aAddress);
600 
601     /**
602      * Indicates whether or not the Source Address is present for this object.
603      *
604      * @retval TRUE   If the Source Address is present.
605      * @retval FALSE  If the Source Address is not present.
606      *
607      */
IsSrcPanIdPresent(void) const608     bool IsSrcPanIdPresent(void) const { return IsSrcPanIdPresent(GetFrameControlField()); }
609 
610     /**
611      * Gets the Source PAN Identifier.
612      *
613      * @param[out]  aPanId  The Source PAN Identifier.
614      *
615      * @retval kErrorNone   Successfully retrieved the Source PAN Identifier.
616      *
617      */
618     Error GetSrcPanId(PanId &aPanId) const;
619 
620     /**
621      * Sets the Source PAN Identifier.
622      *
623      * @param[in]  aPanId  The Source PAN Identifier.
624      *
625      * @retval kErrorNone   Successfully set the Source PAN Identifier.
626      *
627      */
628     Error SetSrcPanId(PanId aPanId);
629 
630     /**
631      * Indicates whether or not the Source Address is present for this object.
632      *
633      * @retval TRUE   If the Source Address is present.
634      * @retval FALSE  If the Source Address is not present.
635      *
636      */
IsSrcAddrPresent(void) const637     bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); }
638 
639     /**
640      * Gets the Source Address.
641      *
642      * @param[out]  aAddress  The Source Address.
643      *
644      * @retval kErrorNone  Successfully retrieved the Source Address.
645      *
646      */
647     Error GetSrcAddr(Address &aAddress) const;
648 
649     /**
650      * Sets the Source Address.
651      *
652      * @param[in]  aShortAddress  The Source Address.
653      *
654      */
655     void SetSrcAddr(ShortAddress aShortAddress);
656 
657     /**
658      * Sets the Source Address.
659      *
660      * @param[in]  aExtAddress  The Source Address.
661      *
662      */
663     void SetSrcAddr(const ExtAddress &aExtAddress);
664 
665     /**
666      * Sets the Source Address.
667      *
668      * @param[in]  aAddress  The Source Address.
669      *
670      */
671     void SetSrcAddr(const Address &aAddress);
672 
673     /**
674      * Gets the Security Control Field.
675      *
676      * @param[out]  aSecurityControlField  The Security Control Field.
677      *
678      * @retval kErrorNone   Successfully retrieved the Security Level Identifier.
679      * @retval kErrorParse  Failed to find the security control field in the frame.
680      *
681      */
682     Error GetSecurityControlField(uint8_t &aSecurityControlField) const;
683 
684     /**
685      * Sets the Security Control Field.
686      *
687      * @param[in]  aSecurityControlField  The Security Control Field.
688      *
689      */
690     void SetSecurityControlField(uint8_t aSecurityControlField);
691 
692     /**
693      * Gets the Security Level Identifier.
694      *
695      * @param[out]  aSecurityLevel  The Security Level Identifier.
696      *
697      * @retval kErrorNone  Successfully retrieved the Security Level Identifier.
698      *
699      */
700     Error GetSecurityLevel(uint8_t &aSecurityLevel) const;
701 
702     /**
703      * Gets the Key Identifier Mode.
704      *
705      * @param[out]  aKeyIdMode  The Key Identifier Mode.
706      *
707      * @retval kErrorNone  Successfully retrieved the Key Identifier Mode.
708      *
709      */
710     Error GetKeyIdMode(uint8_t &aKeyIdMode) const;
711 
712     /**
713      * Gets the Frame Counter.
714      *
715      * @param[out]  aFrameCounter  The Frame Counter.
716      *
717      * @retval kErrorNone  Successfully retrieved the Frame Counter.
718      *
719      */
720     Error GetFrameCounter(uint32_t &aFrameCounter) const;
721 
722     /**
723      * Sets the Frame Counter.
724      *
725      * @param[in]  aFrameCounter  The Frame Counter.
726      *
727      */
728     void SetFrameCounter(uint32_t aFrameCounter);
729 
730     /**
731      * Returns a pointer to the Key Source.
732      *
733      * @returns A pointer to the Key Source.
734      *
735      */
736     const uint8_t *GetKeySource(void) const;
737 
738     /**
739      * Sets the Key Source.
740      *
741      * @param[in]  aKeySource  A pointer to the Key Source value.
742      *
743      */
744     void SetKeySource(const uint8_t *aKeySource);
745 
746     /**
747      * Gets the Key Identifier.
748      *
749      * @param[out]  aKeyId  The Key Identifier.
750      *
751      * @retval kErrorNone  Successfully retrieved the Key Identifier.
752      *
753      */
754     Error GetKeyId(uint8_t &aKeyId) const;
755 
756     /**
757      * Sets the Key Identifier.
758      *
759      * @param[in]  aKeyId  The Key Identifier.
760      *
761      */
762     void SetKeyId(uint8_t aKeyId);
763 
764     /**
765      * Gets the Command ID.
766      *
767      * @param[out]  aCommandId  The Command ID.
768      *
769      * @retval kErrorNone  Successfully retrieved the Command ID.
770      *
771      */
772     Error GetCommandId(uint8_t &aCommandId) const;
773 
774     /**
775      * Sets the Command ID.
776      *
777      * @param[in]  aCommandId  The Command ID.
778      *
779      * @retval kErrorNone  Successfully set the Command ID.
780      *
781      */
782     Error SetCommandId(uint8_t aCommandId);
783 
784     /**
785      * Indicates whether the frame is a MAC Data Request command (data poll).
786      *
787      * For 802.15.4-2015 and above frame, the frame should be already decrypted.
788      *
789      * @returns TRUE if frame is a MAC Data Request command, FALSE otherwise.
790      *
791      */
792     bool IsDataRequestCommand(void) const;
793 
794     /**
795      * Returns the MAC Frame Length, namely the IEEE 802.15.4 PSDU length.
796      *
797      * @returns The MAC Frame Length.
798      *
799      */
GetLength(void) const800     uint16_t GetLength(void) const { return mLength; }
801 
802     /**
803      * Sets the MAC Frame Length.
804      *
805      * @param[in]  aLength  The MAC Frame Length.
806      *
807      */
SetLength(uint16_t aLength)808     void SetLength(uint16_t aLength) { mLength = aLength; }
809 
810     /**
811      * Returns the MAC header size.
812      *
813      * @returns The MAC header size.
814      *
815      */
816     uint8_t GetHeaderLength(void) const;
817 
818     /**
819      * Returns the MAC footer size.
820      *
821      * @returns The MAC footer size.
822      *
823      */
824     uint8_t GetFooterLength(void) const;
825 
826     /**
827      * Returns the current MAC Payload length.
828      *
829      * @returns The current MAC Payload length.
830      *
831      */
832     uint16_t GetPayloadLength(void) const;
833 
834     /**
835      * Returns the maximum MAC Payload length for the given MAC header and footer.
836      *
837      * @returns The maximum MAC Payload length for the given MAC header and footer.
838      *
839      */
840     uint16_t GetMaxPayloadLength(void) const;
841 
842     /**
843      * Sets the MAC Payload length.
844      *
845      */
846     void SetPayloadLength(uint16_t aLength);
847 
848     /**
849      * Returns the IEEE 802.15.4 channel used for transmission or reception.
850      *
851      * @returns The IEEE 802.15.4 channel used for transmission or reception.
852      *
853      */
GetChannel(void) const854     uint8_t GetChannel(void) const { return mChannel; }
855 
856     /**
857      * Returns a pointer to the PSDU.
858      *
859      * @returns A pointer to the PSDU.
860      *
861      */
GetPsdu(void)862     uint8_t *GetPsdu(void) { return mPsdu; }
863 
864     /**
865      * Returns a pointer to the PSDU.
866      *
867      * @returns A pointer to the PSDU.
868      *
869      */
GetPsdu(void) const870     const uint8_t *GetPsdu(void) const { return mPsdu; }
871 
872     /**
873      * Returns a pointer to the MAC Header.
874      *
875      * @returns A pointer to the MAC Header.
876      *
877      */
GetHeader(void)878     uint8_t *GetHeader(void) { return GetPsdu(); }
879 
880     /**
881      * Returns a pointer to the MAC Header.
882      *
883      * @returns A pointer to the MAC Header.
884      *
885      */
GetHeader(void) const886     const uint8_t *GetHeader(void) const { return GetPsdu(); }
887 
888     /**
889      * Returns a pointer to the MAC Payload.
890      *
891      * @returns A pointer to the MAC Payload.
892      *
893      */
GetPayload(void)894     uint8_t *GetPayload(void) { return AsNonConst(AsConst(this)->GetPayload()); }
895 
896     /**
897      * Returns a pointer to the MAC Payload.
898      *
899      * @returns A pointer to the MAC Payload.
900      *
901      */
902     const uint8_t *GetPayload(void) const;
903 
904     /**
905      * Returns a pointer to the MAC Footer.
906      *
907      * @returns A pointer to the MAC Footer.
908      *
909      */
GetFooter(void)910     uint8_t *GetFooter(void) { return AsNonConst(AsConst(this)->GetFooter()); }
911 
912     /**
913      * Returns a pointer to the MAC Footer.
914      *
915      * @returns A pointer to the MAC Footer.
916      *
917      */
918     const uint8_t *GetFooter(void) const;
919 
920 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
921 
922     /**
923      * Returns a pointer to the vendor specific Time IE.
924      *
925      * @returns A pointer to the Time IE, `nullptr` if not found.
926      *
927      */
GetTimeIe(void)928     TimeIe *GetTimeIe(void) { return AsNonConst(AsConst(this)->GetTimeIe()); }
929 
930     /**
931      * Returns a pointer to the vendor specific Time IE.
932      *
933      * @returns A pointer to the Time IE, `nullptr` if not found.
934      *
935      */
936     const TimeIe *GetTimeIe(void) const;
937 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
938 
939 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
940     /**
941      * Appends an Header IE at specified index in this frame.
942      *
943      * Also sets the IE present bit in the Frame Control Field (FCF).
944      *
945      * @param[in,out]   aIndex  The index to append IE. If `aIndex` is `0` on input, this method finds the index
946      *                          for the first IE and appends the IE at that position. If the position is not found
947      *                          successfully, `aIndex` will be set to `kInvalidIndex`. Otherwise the IE will be
948      *                          appended at `aIndex` on input. And on output, `aIndex` will be set to the end of the
949      *                          IE just appended.
950      *
951      * @tparam  IeType  The Header IE type, it MUST contain a constant `kHeaderIeId` equal to the IE's Id
952      *                  and a constant `kIeContentSize` indicating the IE body's size.
953      *
954      * @retval kErrorNone      Successfully appended the Header IE.
955      * @retval kErrorNotFound  The position for first IE is not found.
956      *
957      */
958     template <typename IeType> Error AppendHeaderIeAt(uint8_t &aIndex);
959 
960     /**
961      * Returns a pointer to the Header IE.
962      *
963      * @param[in] aIeId  The Element Id of the Header IE.
964      *
965      * @returns A pointer to the Header IE, `nullptr` if not found.
966      *
967      */
GetHeaderIe(uint8_t aIeId)968     uint8_t *GetHeaderIe(uint8_t aIeId) { return AsNonConst(AsConst(this)->GetHeaderIe(aIeId)); }
969 
970     /**
971      * Returns a pointer to the Header IE.
972      *
973      * @param[in] aIeId  The Element Id of the Header IE.
974      *
975      * @returns A pointer to the Header IE, `nullptr` if not found.
976      *
977      */
978     const uint8_t *GetHeaderIe(uint8_t aIeId) const;
979 
980     /**
981      * Returns a pointer to a specific Thread IE.
982      *
983      * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
984      *
985      * @param[in] aSubType  The sub type of the Thread IE.
986      *
987      * @returns A pointer to the Thread IE, `nullptr` if not found.
988      *
989      */
GetThreadIe(uint8_t aSubType)990     uint8_t *GetThreadIe(uint8_t aSubType) { return AsNonConst(AsConst(this)->GetThreadIe(aSubType)); }
991 
992     /**
993      * Returns a pointer to a specific Thread IE.
994      *
995      * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
996      *
997      * @param[in] aSubType  The sub type of the Thread IE.
998      *
999      * @returns A pointer to the Thread IE, `nullptr` if not found.
1000      *
1001      */
1002     const uint8_t *GetThreadIe(uint8_t aSubType) const;
1003 
1004 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1005     /**
1006      * Finds CSL IE in the frame and modify its content.
1007      *
1008      * @param[in] aCslPeriod  CSL Period in CSL IE.
1009      * @param[in] aCslPhase   CSL Phase in CSL IE.
1010      *
1011      */
1012     void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase);
1013 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1014 
1015 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1016     /**
1017      * Finds Enhanced ACK Probing (Vendor Specific) IE and set its value.
1018      *
1019      * @param[in] aValue  A pointer to the value to set.
1020      * @param[in] aLen    The length of @p aValue.
1021      *
1022      */
1023     void SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen);
1024 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1025 
1026 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1027 
1028 #if OPENTHREAD_CONFIG_MULTI_RADIO
1029     /**
1030      * Gets the radio link type of the frame.
1031      *
1032      * @returns Frame's radio link type.
1033      *
1034      */
GetRadioType(void) const1035     RadioType GetRadioType(void) const { return static_cast<RadioType>(mRadioType); }
1036 
1037     /**
1038      * Sets the radio link type of the frame.
1039      *
1040      * @param[in] aRadioType  A radio link type.
1041      *
1042      */
SetRadioType(RadioType aRadioType)1043     void SetRadioType(RadioType aRadioType) { mRadioType = static_cast<uint8_t>(aRadioType); }
1044 #endif
1045 
1046     /**
1047      * Returns the maximum transmission unit size (MTU).
1048      *
1049      * @returns The maximum transmission unit (MTU).
1050      *
1051      */
GetMtu(void) const1052     uint16_t GetMtu(void) const
1053 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
1054     {
1055         return OT_RADIO_FRAME_MAX_SIZE;
1056     }
1057 #else
1058         ;
1059 #endif
1060 
1061     /**
1062      * Returns the FCS size.
1063      *
1064      * @returns This method returns the FCS size.
1065      *
1066      */
GetFcsSize(void) const1067     uint8_t GetFcsSize(void) const
1068 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
1069     {
1070         return k154FcsSize;
1071     }
1072 #else
1073         ;
1074 #endif
1075 
1076     /**
1077      * Returns information about the frame object as an `InfoString` object.
1078      *
1079      * @returns An `InfoString` containing info about the frame.
1080      *
1081      */
1082     InfoString ToInfoString(void) const;
1083 
1084     /**
1085      * Returns the Frame Control field of the frame.
1086      *
1087      * @returns The Frame Control field.
1088      *
1089      */
1090     uint16_t GetFrameControlField(void) const;
1091 
1092 protected:
1093     static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t);
1094     static constexpr uint8_t kFrameCounterSize    = sizeof(uint32_t);
1095     static constexpr uint8_t kCommandIdSize       = sizeof(uint8_t);
1096     static constexpr uint8_t kKeyIndexSize        = sizeof(uint8_t);
1097 
1098     static constexpr uint16_t kFcfFrameTypeMask    = 7 << 0;
1099     static constexpr uint16_t kFcfSecurityEnabled  = 1 << 3;
1100     static constexpr uint16_t kFcfFramePending     = 1 << 4;
1101     static constexpr uint16_t kFcfAckRequest       = 1 << 5;
1102     static constexpr uint16_t kFcfPanidCompression = 1 << 6;
1103     static constexpr uint16_t kFcfIePresent        = 1 << 9;
1104     static constexpr uint16_t kFcfDstAddrNone      = 0 << 10;
1105     static constexpr uint16_t kFcfDstAddrShort     = 2 << 10;
1106     static constexpr uint16_t kFcfDstAddrExt       = 3 << 10;
1107     static constexpr uint16_t kFcfDstAddrMask      = 3 << 10;
1108     static constexpr uint16_t kFcfFrameVersionMask = 3 << 12;
1109     static constexpr uint16_t kFcfSrcAddrNone      = 0 << 14;
1110     static constexpr uint16_t kFcfSrcAddrShort     = 2 << 14;
1111     static constexpr uint16_t kFcfSrcAddrExt       = 3 << 14;
1112     static constexpr uint16_t kFcfSrcAddrMask      = 3 << 14;
1113 
1114     static constexpr uint8_t kSecLevelMask  = 7 << 0;
1115     static constexpr uint8_t kKeyIdModeMask = 3 << 3;
1116 
1117     static constexpr uint8_t kMic0Size   = 0;
1118     static constexpr uint8_t kMic32Size  = 32 / CHAR_BIT;
1119     static constexpr uint8_t kMic64Size  = 64 / CHAR_BIT;
1120     static constexpr uint8_t kMic128Size = 128 / CHAR_BIT;
1121     static constexpr uint8_t kMaxMicSize = kMic128Size;
1122 
1123     static constexpr uint8_t kKeySourceSizeMode0 = 0;
1124     static constexpr uint8_t kKeySourceSizeMode1 = 0;
1125     static constexpr uint8_t kKeySourceSizeMode2 = 4;
1126     static constexpr uint8_t kKeySourceSizeMode3 = 8;
1127 
1128     static constexpr uint8_t kInvalidIndex  = 0xff;
1129     static constexpr uint8_t kInvalidSize   = kInvalidIndex;
1130     static constexpr uint8_t kMaxPsduSize   = kInvalidSize - 1;
1131     static constexpr uint8_t kSequenceIndex = kFcfSize;
1132 
1133     void    SetFrameControlField(uint16_t aFcf);
1134     uint8_t FindDstPanIdIndex(void) const;
1135     uint8_t FindDstAddrIndex(void) const;
1136     uint8_t FindSrcPanIdIndex(void) const;
1137     uint8_t FindSrcAddrIndex(void) const;
1138     uint8_t SkipAddrFieldIndex(void) const;
1139     uint8_t FindSecurityHeaderIndex(void) const;
1140     uint8_t SkipSecurityHeaderIndex(void) const;
1141     uint8_t FindPayloadIndex(void) const;
1142 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1143     uint8_t FindHeaderIeIndex(void) const;
1144 
1145     Error                           InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize);
1146     template <typename IeType> void InitIeContentAt(uint8_t &aIndex);
1147 #endif
1148 
1149     static uint8_t GetKeySourceLength(uint8_t aKeyIdMode);
1150 
IsDstAddrPresent(uint16_t aFcf)1151     static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != kFcfDstAddrNone; }
1152     static bool IsDstPanIdPresent(uint16_t aFcf);
IsSrcAddrPresent(uint16_t aFcf)1153     static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone; }
1154     static bool IsSrcPanIdPresent(uint16_t aFcf);
IsVersion2015(uint16_t aFcf)1155     static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; }
1156 
1157     static uint8_t CalculateAddrFieldSize(uint16_t aFcf);
1158     static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
1159     static uint8_t CalculateMicSize(uint8_t aSecurityControl);
1160 };
1161 
1162 /**
1163  * Supports received IEEE 802.15.4 MAC frame processing.
1164  *
1165  */
1166 class RxFrame : public Frame
1167 {
1168 public:
1169     friend class TxFrame;
1170 
1171     /**
1172      * Returns the RSSI in dBm used for reception.
1173      *
1174      * @returns The RSSI in dBm used for reception.
1175      *
1176      */
GetRssi(void) const1177     int8_t GetRssi(void) const { return mInfo.mRxInfo.mRssi; }
1178 
1179     /**
1180      * Sets the RSSI in dBm used for reception.
1181      *
1182      * @param[in]  aRssi  The RSSI in dBm used for reception.
1183      *
1184      */
SetRssi(int8_t aRssi)1185     void SetRssi(int8_t aRssi) { mInfo.mRxInfo.mRssi = aRssi; }
1186 
1187     /**
1188      * Returns the receive Link Quality Indicator.
1189      *
1190      * @returns The receive Link Quality Indicator.
1191      *
1192      */
GetLqi(void) const1193     uint8_t GetLqi(void) const { return mInfo.mRxInfo.mLqi; }
1194 
1195     /**
1196      * Sets the receive Link Quality Indicator.
1197      *
1198      * @param[in]  aLqi  The receive Link Quality Indicator.
1199      *
1200      */
SetLqi(uint8_t aLqi)1201     void SetLqi(uint8_t aLqi) { mInfo.mRxInfo.mLqi = aLqi; }
1202 
1203     /**
1204      * Indicates whether or not the received frame is acknowledged with frame pending set.
1205      *
1206      * @retval TRUE   This frame is acknowledged with frame pending set.
1207      * @retval FALSE  This frame is acknowledged with frame pending not set.
1208      *
1209      */
IsAckedWithFramePending(void) const1210     bool IsAckedWithFramePending(void) const { return mInfo.mRxInfo.mAckedWithFramePending; }
1211 
1212     /**
1213      * Returns the timestamp when the frame was received.
1214      *
1215      * The value SHALL be the time of the local radio clock in
1216      * microseconds when the end of the SFD (or equivalently: the start
1217      * of the first symbol of the PHR) was present at the local antenna,
1218      * see the definition of a "symbol boundary" in IEEE 802.15.4-2020,
1219      * section 6.5.2 or equivalently the RMARKER definition in section
1220      * 6.9.1 (albeit both unrelated to OT).
1221      *
1222      * The time is relative to the local radio clock as defined by
1223      * `otPlatRadioGetNow`.
1224      *
1225      * @returns The timestamp in microseconds.
1226      */
GetTimestamp(void) const1227     const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; }
1228 
1229     /**
1230      * Performs AES CCM on the frame which is received.
1231      *
1232      * @param[in]  aExtAddress  A reference to the extended address, which will be used to generate nonce
1233      *                          for AES CCM computation.
1234      * @param[in]  aMacKey      A reference to the MAC key to decrypt the received frame.
1235      *
1236      * @retval kErrorNone      Process of received frame AES CCM succeeded.
1237      * @retval kErrorSecurity  Received frame MIC check failed.
1238      *
1239      */
1240     Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey);
1241 
1242 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1243     /**
1244      * Gets the offset to network time.
1245      *
1246      * @returns  The offset to network time.
1247      *
1248      */
ComputeNetworkTimeOffset(void) const1249     int64_t ComputeNetworkTimeOffset(void) const
1250     {
1251         return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp());
1252     }
1253 
1254     /**
1255      * Gets the time sync sequence.
1256      *
1257      * @returns  The time sync sequence.
1258      *
1259      */
ReadTimeSyncSeq(void) const1260     uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); }
1261 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1262 };
1263 
1264 /**
1265  * Supports IEEE 802.15.4 MAC frame generation for transmission.
1266  *
1267  */
1268 class TxFrame : public Frame
1269 {
1270 public:
1271     /**
1272      * Sets the channel on which to send the frame.
1273      *
1274      * It also sets the `RxChannelAfterTxDone` to the same channel.
1275      *
1276      * @param[in]  aChannel  The channel used for transmission.
1277      *
1278      */
SetChannel(uint8_t aChannel)1279     void SetChannel(uint8_t aChannel)
1280     {
1281         mChannel = aChannel;
1282         SetRxChannelAfterTxDone(aChannel);
1283     }
1284 
1285     /**
1286      * Gets the RX channel after frame TX is done.
1287      *
1288      * @returns The RX channel after frame TX is done.
1289      *
1290      */
GetRxChannelAfterTxDone(void) const1291     uint8_t GetRxChannelAfterTxDone(void) const { return mInfo.mTxInfo.mRxChannelAfterTxDone; }
1292 
1293     /**
1294      * Sets the RX channel after frame TX is done.
1295      *
1296      * @param[in] aChannel   The RX channel after frame TX is done.
1297      *
1298      */
SetRxChannelAfterTxDone(uint8_t aChannel)1299     void SetRxChannelAfterTxDone(uint8_t aChannel) { mInfo.mTxInfo.mRxChannelAfterTxDone = aChannel; }
1300 
1301     /**
1302      * Returns the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel
1303      * access failure.
1304      *
1305      * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006.
1306      *
1307      * @returns The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access
1308      *          failure.
1309      *
1310      */
GetMaxCsmaBackoffs(void) const1311     uint8_t GetMaxCsmaBackoffs(void) const { return mInfo.mTxInfo.mMaxCsmaBackoffs; }
1312 
1313     /**
1314      * Sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel
1315      * access failure.
1316      *
1317      * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006.
1318      *
1319      * @param[in]  aMaxCsmaBackoffs  The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring
1320      *                               a channel access failure.
1321      *
1322      */
SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs)1323     void SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs) { mInfo.mTxInfo.mMaxCsmaBackoffs = aMaxCsmaBackoffs; }
1324 
1325     /**
1326      * Returns the maximum number of retries allowed after a transmission failure.
1327      *
1328      * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006.
1329      *
1330      * @returns The maximum number of retries allowed after a transmission failure.
1331      *
1332      */
GetMaxFrameRetries(void) const1333     uint8_t GetMaxFrameRetries(void) const { return mInfo.mTxInfo.mMaxFrameRetries; }
1334 
1335     /**
1336      * Sets the maximum number of retries allowed after a transmission failure.
1337      *
1338      * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006.
1339      *
1340      * @param[in]  aMaxFrameRetries  The maximum number of retries allowed after a transmission failure.
1341      *
1342      */
SetMaxFrameRetries(uint8_t aMaxFrameRetries)1343     void SetMaxFrameRetries(uint8_t aMaxFrameRetries) { mInfo.mTxInfo.mMaxFrameRetries = aMaxFrameRetries; }
1344 
1345     /**
1346      * Indicates whether or not the frame is a retransmission.
1347      *
1348      * @retval TRUE   Frame is a retransmission
1349      * @retval FALSE  This is a new frame and not a retransmission of an earlier frame.
1350      *
1351      */
IsARetransmission(void) const1352     bool IsARetransmission(void) const { return mInfo.mTxInfo.mIsARetx; }
1353 
1354     /**
1355      * Sets the retransmission flag attribute.
1356      *
1357      * @param[in]  aIsARetx  TRUE if frame is a retransmission of an earlier frame, FALSE otherwise.
1358      *
1359      */
SetIsARetransmission(bool aIsARetx)1360     void SetIsARetransmission(bool aIsARetx) { mInfo.mTxInfo.mIsARetx = aIsARetx; }
1361 
1362     /**
1363      * Indicates whether or not CSMA-CA is enabled.
1364      *
1365      * @retval TRUE   CSMA-CA is enabled.
1366      * @retval FALSE  CSMA-CA is not enabled is not enabled.
1367      *
1368      */
IsCsmaCaEnabled(void) const1369     bool IsCsmaCaEnabled(void) const { return mInfo.mTxInfo.mCsmaCaEnabled; }
1370 
1371     /**
1372      * Sets the CSMA-CA enabled attribute.
1373      *
1374      * @param[in]  aCsmaCaEnabled  TRUE if CSMA-CA must be enabled for this packet, FALSE otherwise.
1375      *
1376      */
SetCsmaCaEnabled(bool aCsmaCaEnabled)1377     void SetCsmaCaEnabled(bool aCsmaCaEnabled) { mInfo.mTxInfo.mCsmaCaEnabled = aCsmaCaEnabled; }
1378 
1379     /**
1380      * Returns the key used for frame encryption and authentication (AES CCM).
1381      *
1382      * @returns The pointer to the key.
1383      *
1384      */
GetAesKey(void) const1385     const Mac::KeyMaterial &GetAesKey(void) const
1386     {
1387         return *static_cast<const Mac::KeyMaterial *>(mInfo.mTxInfo.mAesKey);
1388     }
1389 
1390     /**
1391      * Sets the key used for frame encryption and authentication (AES CCM).
1392      *
1393      * @param[in]  aAesKey  The pointer to the key.
1394      *
1395      */
SetAesKey(const Mac::KeyMaterial & aAesKey)1396     void SetAesKey(const Mac::KeyMaterial &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; }
1397 
1398     /**
1399      * Copies the PSDU and all attributes (except for frame link type) from another frame.
1400      *
1401      * @note This method performs a deep copy meaning the content of PSDU buffer from the given frame is copied into
1402      * the PSDU buffer of the current frame.
1403 
1404      * @param[in] aFromFrame  The frame to copy from.
1405      *
1406      */
1407     void CopyFrom(const TxFrame &aFromFrame);
1408 
1409     /**
1410      * Performs AES CCM on the frame which is going to be sent.
1411      *
1412      * @param[in]  aExtAddress  A reference to the extended address, which will be used to generate nonce
1413      *                          for AES CCM computation.
1414      *
1415      */
1416     void ProcessTransmitAesCcm(const ExtAddress &aExtAddress);
1417 
1418     /**
1419      * Indicates whether or not the frame has security processed.
1420      *
1421      * @retval TRUE   The frame already has security processed.
1422      * @retval FALSE  The frame does not have security processed.
1423      *
1424      */
IsSecurityProcessed(void) const1425     bool IsSecurityProcessed(void) const { return mInfo.mTxInfo.mIsSecurityProcessed; }
1426 
1427     /**
1428      * Sets the security processed flag attribute.
1429      *
1430      * @param[in]  aIsSecurityProcessed  TRUE if the frame already has security processed.
1431      *
1432      */
SetIsSecurityProcessed(bool aIsSecurityProcessed)1433     void SetIsSecurityProcessed(bool aIsSecurityProcessed)
1434     {
1435         mInfo.mTxInfo.mIsSecurityProcessed = aIsSecurityProcessed;
1436     }
1437 
1438     /**
1439      * Indicates whether or not the frame contains the CSL IE.
1440      *
1441      * @retval TRUE   The frame contains the CSL IE.
1442      * @retval FALSE  The frame does not contain the CSL IE.
1443      *
1444      */
IsCslIePresent(void) const1445     bool IsCslIePresent(void) const { return mInfo.mTxInfo.mCslPresent; }
1446 
1447     /**
1448      * Sets the CSL IE present flag.
1449      *
1450      * @param[in]  aCslPresent  TRUE if the frame contains the CSL IE.
1451      */
SetCslIePresent(bool aCslPresent)1452     void SetCslIePresent(bool aCslPresent) { mInfo.mTxInfo.mCslPresent = aCslPresent; }
1453 
1454     /**
1455      * Indicates whether or not the frame header is updated.
1456      *
1457      * @retval TRUE   The frame already has the header updated.
1458      * @retval FALSE  The frame does not have the header updated.
1459      *
1460      */
IsHeaderUpdated(void) const1461     bool IsHeaderUpdated(void) const { return mInfo.mTxInfo.mIsHeaderUpdated; }
1462 
1463     /**
1464      * Sets the header updated flag attribute.
1465      *
1466      * @param[in]  aIsHeaderUpdated  TRUE if the frame header is updated.
1467      *
1468      */
SetIsHeaderUpdated(bool aIsHeaderUpdated)1469     void SetIsHeaderUpdated(bool aIsHeaderUpdated) { mInfo.mTxInfo.mIsHeaderUpdated = aIsHeaderUpdated; }
1470 
1471 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1472     /**
1473      * Sets the Time IE offset.
1474      *
1475      * @param[in]  aOffset  The Time IE offset, 0 means no Time IE.
1476      *
1477      */
SetTimeIeOffset(uint8_t aOffset)1478     void SetTimeIeOffset(uint8_t aOffset) { mInfo.mTxInfo.mIeInfo->mTimeIeOffset = aOffset; }
1479 
1480     /**
1481      * Gets the Time IE offset.
1482      *
1483      * @returns The Time IE offset, 0 means no Time IE.
1484      *
1485      */
GetTimeIeOffset(void) const1486     uint8_t GetTimeIeOffset(void) const { return mInfo.mTxInfo.mIeInfo->mTimeIeOffset; }
1487 
1488     /**
1489      * Sets the offset to network time.
1490      *
1491      * @param[in]  aNetworkTimeOffset  The offset to network time.
1492      *
1493      */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1494     void SetNetworkTimeOffset(int64_t aNetworkTimeOffset)
1495     {
1496         mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset;
1497     }
1498 
1499     /**
1500      * Sets the time sync sequence.
1501      *
1502      * @param[in]  aTimeSyncSeq  The time sync sequence.
1503      *
1504      */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1505     void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; }
1506 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1507 
1508     /**
1509      * Generate Imm-Ack in this frame object.
1510      *
1511      * @param[in]    aFrame             A reference to the frame received.
1512      * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
1513      *
1514      */
1515     void GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending);
1516 
1517     /**
1518      * Generate Enh-Ack in this frame object.
1519      *
1520      * @param[in]    aRxFrame           A reference to the received frame.
1521      * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
1522      * @param[in]    aIeData            A pointer to the IE data portion of the ACK to be sent.
1523      * @param[in]    aIeLength          The length of IE data portion of the ACK to be sent.
1524      *
1525      * @retval  kErrorNone           Successfully generated Enh Ack.
1526      * @retval  kErrorParse          @p aRxFrame has incorrect format.
1527      *
1528      */
1529     Error GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength);
1530 
1531 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
1532     /**
1533      * Set TX delay field for the frame.
1534      *
1535      * @param[in]    aTxDelay    The delay time for the TX frame.
1536      *
1537      */
SetTxDelay(uint32_t aTxDelay)1538     void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; }
1539 
1540     /**
1541      * Set TX delay base time field for the frame.
1542      *
1543      * @param[in]    aTxDelayBaseTime    The delay base time for the TX frame.
1544      *
1545      */
SetTxDelayBaseTime(uint32_t aTxDelayBaseTime)1546     void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; }
1547 #endif
1548 };
1549 
1550 OT_TOOL_PACKED_BEGIN
1551 class Beacon
1552 {
1553 public:
1554     static constexpr uint16_t kSuperFrameSpec = 0x0fff; ///< Superframe Specification value.
1555 
1556     /**
1557      * Initializes the Beacon message.
1558      *
1559      */
Init(void)1560     void Init(void)
1561     {
1562         mSuperframeSpec     = HostSwap16(kSuperFrameSpec);
1563         mGtsSpec            = 0;
1564         mPendingAddressSpec = 0;
1565     }
1566 
1567     /**
1568      * Indicates whether or not the beacon appears to be a valid Thread Beacon message.
1569      *
1570      * @retval TRUE   If the beacon appears to be a valid Thread Beacon message.
1571      * @retval FALSE  If the beacon does not appear to be a valid Thread Beacon message.
1572      *
1573      */
IsValid(void) const1574     bool IsValid(void) const
1575     {
1576         return (mSuperframeSpec == HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) && (mPendingAddressSpec == 0);
1577     }
1578 
1579     /**
1580      * Returns the pointer to the beacon payload.
1581      *
1582      * @returns A pointer to the beacon payload.
1583      *
1584      */
GetPayload(void)1585     uint8_t *GetPayload(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
1586 
1587     /**
1588      * Returns the pointer to the beacon payload.
1589      *
1590      * @returns A pointer to the beacon payload.
1591      *
1592      */
GetPayload(void) const1593     const uint8_t *GetPayload(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
1594 
1595 private:
1596     uint16_t mSuperframeSpec;
1597     uint8_t  mGtsSpec;
1598     uint8_t  mPendingAddressSpec;
1599 } OT_TOOL_PACKED_END;
1600 
1601 /**
1602  * Implements IEEE 802.15.4 Beacon Payload generation and parsing.
1603  *
1604  */
1605 OT_TOOL_PACKED_BEGIN
1606 class BeaconPayload
1607 {
1608 public:
1609     static constexpr uint8_t kProtocolId      = 3;                     ///< Thread Protocol ID.
1610     static constexpr uint8_t kProtocolVersion = 2;                     ///< Thread Protocol version.
1611     static constexpr uint8_t kVersionOffset   = 4;                     ///< Version field bit offset.
1612     static constexpr uint8_t kVersionMask     = 0xf << kVersionOffset; ///< Version field mask.
1613     static constexpr uint8_t kNativeFlag      = 1 << 3;                ///< Native Commissioner flag.
1614     static constexpr uint8_t kJoiningFlag     = 1 << 0;                ///< Joining Permitted flag.
1615 
1616     /**
1617      * Initializes the Beacon Payload.
1618      *
1619      */
Init(void)1620     void Init(void)
1621     {
1622         mProtocolId = kProtocolId;
1623         mFlags      = kProtocolVersion << kVersionOffset;
1624     }
1625 
1626     /**
1627      * Indicates whether or not the beacon appears to be a valid Thread Beacon Payload.
1628      *
1629      * @retval TRUE   If the beacon appears to be a valid Thread Beacon Payload.
1630      * @retval FALSE  If the beacon does not appear to be a valid Thread Beacon Payload.
1631      *
1632      */
IsValid(void) const1633     bool IsValid(void) const { return (mProtocolId == kProtocolId); }
1634 
1635     /**
1636      * Returns the Protocol ID value.
1637      *
1638      * @returns the Protocol ID value.
1639      *
1640      */
GetProtocolId(void) const1641     uint8_t GetProtocolId(void) const { return mProtocolId; }
1642 
1643     /**
1644      * Returns the Protocol Version value.
1645      *
1646      * @returns The Protocol Version value.
1647      *
1648      */
GetProtocolVersion(void) const1649     uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; }
1650 
1651     /**
1652      * Indicates whether or not the Native Commissioner flag is set.
1653      *
1654      * @retval TRUE   If the Native Commissioner flag is set.
1655      * @retval FALSE  If the Native Commissioner flag is not set.
1656      *
1657      */
IsNative(void) const1658     bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; }
1659 
1660     /**
1661      * Clears the Native Commissioner flag.
1662      *
1663      */
ClearNative(void)1664     void ClearNative(void) { mFlags &= ~kNativeFlag; }
1665 
1666     /**
1667      * Sets the Native Commissioner flag.
1668      *
1669      */
SetNative(void)1670     void SetNative(void) { mFlags |= kNativeFlag; }
1671 
1672     /**
1673      * Indicates whether or not the Joining Permitted flag is set.
1674      *
1675      * @retval TRUE   If the Joining Permitted flag is set.
1676      * @retval FALSE  If the Joining Permitted flag is not set.
1677      *
1678      */
IsJoiningPermitted(void) const1679     bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; }
1680 
1681     /**
1682      * Clears the Joining Permitted flag.
1683      *
1684      */
ClearJoiningPermitted(void)1685     void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; }
1686 
1687     /**
1688      * Sets the Joining Permitted flag.
1689      *
1690      */
SetJoiningPermitted(void)1691     void SetJoiningPermitted(void)
1692     {
1693         mFlags |= kJoiningFlag;
1694 
1695 #if OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION != 2 // check against kProtocolVersion
1696         mFlags &= ~kVersionMask;
1697         mFlags |= OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION << kVersionOffset;
1698 #endif
1699     }
1700 
1701     /**
1702      * Gets the Network Name field.
1703      *
1704      * @returns The Network Name field as `NameData`.
1705      *
1706      */
GetNetworkName(void) const1707     MeshCoP::NameData GetNetworkName(void) const { return MeshCoP::NameData(mNetworkName, sizeof(mNetworkName)); }
1708 
1709     /**
1710      * Sets the Network Name field.
1711      *
1712      * @param[in]  aNameData  The Network Name (as a `NameData`).
1713      *
1714      */
SetNetworkName(const MeshCoP::NameData & aNameData)1715     void SetNetworkName(const MeshCoP::NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); }
1716 
1717     /**
1718      * Returns the Extended PAN ID field.
1719      *
1720      * @returns The Extended PAN ID field.
1721      *
1722      */
GetExtendedPanId(void) const1723     const otExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
1724 
1725     /**
1726      * Sets the Extended PAN ID field.
1727      *
1728      * @param[in]  aExtPanId  An Extended PAN ID.
1729      *
1730      */
SetExtendedPanId(const otExtendedPanId & aExtPanId)1731     void SetExtendedPanId(const otExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; }
1732 
1733 private:
1734     uint8_t         mProtocolId;
1735     uint8_t         mFlags;
1736     char            mNetworkName[MeshCoP::NetworkName::kMaxSize];
1737     otExtendedPanId mExtendedPanId;
1738 } OT_TOOL_PACKED_END;
1739 
1740 /**
1741  * Implements CSL IE data structure.
1742  *
1743  */
1744 OT_TOOL_PACKED_BEGIN
1745 class CslIe
1746 {
1747 public:
1748     static constexpr uint8_t kHeaderIeId    = 0x1a;
1749     static constexpr uint8_t kIeContentSize = sizeof(uint16_t) * 2;
1750 
1751     /**
1752      * Returns the CSL Period.
1753      *
1754      * @returns the CSL Period.
1755      *
1756      */
GetPeriod(void) const1757     uint16_t GetPeriod(void) const { return HostSwap16(mPeriod); }
1758 
1759     /**
1760      * Sets the CSL Period.
1761      *
1762      * @param[in]  aPeriod  The CSL Period.
1763      *
1764      */
SetPeriod(uint16_t aPeriod)1765     void SetPeriod(uint16_t aPeriod) { mPeriod = HostSwap16(aPeriod); }
1766 
1767     /**
1768      * Returns the CSL Phase.
1769      *
1770      * @returns the CSL Phase.
1771      *
1772      */
GetPhase(void) const1773     uint16_t GetPhase(void) const { return HostSwap16(mPhase); }
1774 
1775     /**
1776      * Sets the CSL Phase.
1777      *
1778      * @param[in]  aPhase  The CSL Phase.
1779      *
1780      */
SetPhase(uint16_t aPhase)1781     void SetPhase(uint16_t aPhase) { mPhase = HostSwap16(aPhase); }
1782 
1783 private:
1784     uint16_t mPhase;
1785     uint16_t mPeriod;
1786 } OT_TOOL_PACKED_END;
1787 
1788 /**
1789  * Implements Termination2 IE.
1790  *
1791  * Is empty for template specialization.
1792  *
1793  */
1794 class Termination2Ie
1795 {
1796 public:
1797     static constexpr uint8_t kHeaderIeId    = 0x7f;
1798     static constexpr uint8_t kIeContentSize = 0;
1799 };
1800 
1801 /**
1802  * @}
1803  *
1804  */
1805 
1806 } // namespace Mac
1807 } // namespace ot
1808 
1809 #endif // MAC_FRAME_HPP_
1810