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