• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_header_ie.hpp"
44 #include "mac/mac_types.hpp"
45 #include "meshcop/network_name.hpp"
46 
47 namespace ot {
48 namespace Mac {
49 
50 /**
51  * @addtogroup core-mac
52  *
53  * @{
54  */
55 
56 /**
57  * Implements IEEE 802.15.4 MAC frame generation and parsing.
58  */
59 class Frame : public otRadioFrame
60 {
61 public:
62     /**
63      * Represents the MAC frame type.
64      *
65      * Values match the Frame Type field in Frame Control Field (FCF)  as an `uint16_t`.
66      */
67     enum Type : uint16_t
68     {
69         kTypeBeacon       = 0, ///< Beacon Frame Type.
70         kTypeData         = 1, ///< Data Frame Type.
71         kTypeAck          = 2, ///< Ack Frame Type.
72         kTypeMacCmd       = 3, ///< MAC Command Frame Type.
73         kTypeMultipurpose = 5, ///< Multipurpose Frame Type.
74     };
75 
76     /**
77      * Represents the MAC frame version.
78      *
79      * Values match the Version field in Frame Control Field (FCF) as an `uint16_t`.
80      */
81     enum Version : uint16_t
82     {
83         kVersion2003 = 0 << 12, ///< 2003 Frame Version.
84         kVersion2006 = 1 << 12, ///< 2006 Frame Version.
85         kVersion2015 = 2 << 12, ///< 2015 Frame Version.
86     };
87 
88     /**
89      * Represents the MAC frame security level.
90      *
91      * Values match the Security Level field in Security Control Field as an `uint8_t`.
92      */
93     enum SecurityLevel : uint8_t
94     {
95         kSecurityNone      = 0, ///< No security.
96         kSecurityMic32     = 1, ///< No encryption, MIC-32 authentication.
97         kSecurityMic64     = 2, ///< No encryption, MIC-64 authentication.
98         kSecurityMic128    = 3, ///< No encryption, MIC-128 authentication.
99         kSecurityEnc       = 4, ///< Encryption, no authentication
100         kSecurityEncMic32  = 5, ///< Encryption with MIC-32 authentication.
101         kSecurityEncMic64  = 6, ///< Encryption with MIC-64 authentication.
102         kSecurityEncMic128 = 7, ///< Encryption with MIC-128 authentication.
103     };
104 
105     /**
106      * Represents the MAC frame security key identifier mode.
107      *
108      * Values match the Key Identifier Mode field in Security Control Field as an `uint8_t`.
109      */
110     enum KeyIdMode : uint8_t
111     {
112         kKeyIdMode0 = 0 << 3, ///< Key ID Mode 0 - Key is determined implicitly.
113         kKeyIdMode1 = 1 << 3, ///< Key ID Mode 1 - Key is determined from Key Index field.
114         kKeyIdMode2 = 2 << 3, ///< Key ID Mode 2 - Key is determined from 4-bytes Key Source and Index fields.
115         kKeyIdMode3 = 3 << 3, ///< Key ID Mode 3 - Key is determined from 8-bytes Key Source and Index fields.
116     };
117 
118     /**
119      * Represents a subset of MAC Command Identifiers.
120      */
121     enum CommandId : uint8_t
122     {
123         kMacCmdAssociationRequest         = 1,
124         kMacCmdAssociationResponse        = 2,
125         kMacCmdDisassociationNotification = 3,
126         kMacCmdDataRequest                = 4,
127         kMacCmdPanidConflictNotification  = 5,
128         kMacCmdOrphanNotification         = 6,
129         kMacCmdBeaconRequest              = 7,
130         kMacCmdCoordinatorRealignment     = 8,
131         kMacCmdGtsRequest                 = 9,
132     };
133 
134     static constexpr uint16_t kInfoStringSize = 128; ///< Max chars for `InfoString` (ToInfoString()).
135 
136     static constexpr uint8_t kPreambleSize  = 4;
137     static constexpr uint8_t kSfdSize       = 1;
138     static constexpr uint8_t kPhrSize       = 1;
139     static constexpr uint8_t kPhyHeaderSize = kPreambleSize + kSfdSize + kPhrSize;
140     static constexpr uint8_t kFcfSize       = sizeof(uint16_t);
141     static constexpr uint8_t kDsnSize       = sizeof(uint8_t);
142     static constexpr uint8_t k154FcsSize    = sizeof(uint16_t);
143     static constexpr uint8_t kImmAckLength  = kFcfSize + kDsnSize + k154FcsSize;
144 
145     /**
146      * Defines the fixed-length `String` object returned from `ToInfoString()` method.
147      */
148     typedef String<kInfoStringSize> InfoString;
149 
150     /**
151      * Indicates whether the frame is empty (no payload).
152      *
153      * @retval TRUE   The frame is empty (no PSDU payload).
154      * @retval FALSE  The frame is not empty.
155      */
IsEmpty(void) const156     bool IsEmpty(void) const { return (mLength == 0); }
157 
158     /**
159      * Validates the frame.
160      *
161      * @retval kErrorNone    Successfully parsed the MAC header.
162      * @retval kErrorParse   Failed to parse through the MAC header.
163      */
164     Error ValidatePsdu(void) const;
165 
166     /**
167      * Returns the IEEE 802.15.4 Frame Type.
168      *
169      * @returns The IEEE 802.15.4 Frame Type.
170      */
GetType(void) const171     uint8_t GetType(void) const { return GetPsdu()[0] & kFcfFrameTypeMask; }
172 
173     /**
174      * Returns whether the frame is an Ack frame.
175      *
176      * @retval TRUE   If this is an Ack.
177      * @retval FALSE  If this is not an Ack.
178      */
IsAck(void) const179     bool IsAck(void) const { return GetType() == kTypeAck; }
180 
181 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
182     /**
183      * This method returns whether the frame is an IEEE 802.15.4 Wake-up frame.
184      *
185      * @retval TRUE   If this is a Wake-up frame.
186      * @retval FALSE  If this is not a Wake-up frame.
187      */
188     bool IsWakeupFrame(void) const;
189 
190     /**
191      * This method returns the Rendezvous Time IE of a wake-up frame.
192      *
193      * @returns Pointer to the Rendezvous Time IE.
194      */
GetRendezvousTimeIe(void)195     RendezvousTimeIe *GetRendezvousTimeIe(void) { return AsNonConst(AsConst(this)->GetRendezvousTimeIe()); }
196 
197     /**
198      * This method returns the Rendezvous Time IE of a wake-up frame.
199      *
200      * @returns Const pointer to the Rendezvous Time IE.
201      */
GetRendezvousTimeIe(void) const202     const RendezvousTimeIe *GetRendezvousTimeIe(void) const
203     {
204         const uint8_t *ie = GetHeaderIe(RendezvousTimeIe::kHeaderIeId);
205 
206         return (ie != nullptr) ? reinterpret_cast<const RendezvousTimeIe *>(ie + sizeof(HeaderIe)) : nullptr;
207     }
208 
209     /**
210      * This method returns the Connection IE of a wake-up frame.
211      *
212      * @returns Pointer to the Connection IE.
213      */
GetConnectionIe(void)214     ConnectionIe *GetConnectionIe(void) { return AsNonConst(AsConst(this)->GetConnectionIe()); }
215 
216     /**
217      * This method returns the Connection IE of a wake-up frame.
218      *
219      * @returns Const pointer to the Connection IE.
220      */
GetConnectionIe(void) const221     const ConnectionIe *GetConnectionIe(void) const
222     {
223         const uint8_t *ie = GetThreadIe(ConnectionIe::kThreadIeSubtype);
224 
225         return (ie != nullptr) ? reinterpret_cast<const ConnectionIe *>(ie + sizeof(HeaderIe)) : nullptr;
226     }
227 #endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
228 
229     /**
230      * Returns the IEEE 802.15.4 Frame Version.
231      *
232      * @returns The IEEE 802.15.4 Frame Version.
233      */
GetVersion(void) const234     uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; }
235 
236     /**
237      * Returns if this IEEE 802.15.4 frame's version is 2015.
238      *
239      * @returns TRUE if version is 2015, FALSE otherwise.
240      */
IsVersion2015(void) const241     bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); }
242 
243     /**
244      * Indicates whether or not security is enabled.
245      *
246      * @retval TRUE   If security is enabled.
247      * @retval FALSE  If security is not enabled.
248      */
GetSecurityEnabled(void) const249     bool GetSecurityEnabled(void) const { return IsSecurityEnabled(GetFrameControlField()); }
250 
251     /**
252      * Indicates whether or not the Frame Pending bit is set.
253      *
254      * @retval TRUE   If the Frame Pending bit is set.
255      * @retval FALSE  If the Frame Pending bit is not set.
256      */
GetFramePending(void) const257     bool GetFramePending(void) const { return IsFramePending(GetFrameControlField()); }
258 
259     /**
260      * Sets the Frame Pending bit.
261      *
262      * @note This method must not be called on a Multipurpose frame with short Frame Control field.
263      *
264      * @param[in]  aFramePending  The Frame Pending bit.
265      */
266     void SetFramePending(bool aFramePending);
267 
268     /**
269      * Indicates whether or not the Ack Request bit is set.
270      *
271      * @retval TRUE   If the Ack Request bit is set.
272      * @retval FALSE  If the Ack Request bit is not set.
273      */
GetAckRequest(void) const274     bool GetAckRequest(void) const { return IsAckRequest(GetFrameControlField()); }
275 
276     /**
277      * Sets the Ack Request bit.
278      *
279      * @note This method must not be called on a Multipurpose frame with short Frame Control field.
280      *
281      * @param[in]  aAckRequest  The Ack Request bit.
282      */
283     void SetAckRequest(bool aAckRequest);
284 
285     /**
286      * Indicates whether or not the PanId Compression bit is set.
287      *
288      * @note This method must not be called on a Multipurpose frame, which lacks this flag.
289      *
290      * @retval TRUE   If the PanId Compression bit is set.
291      * @retval FALSE  If the PanId Compression bit is not set.
292      */
IsPanIdCompressed(void) const293     bool IsPanIdCompressed(void) const { return (GetFrameControlField() & kFcfPanidCompression) != 0; }
294 
295     /**
296      * Indicates whether or not IEs present.
297      *
298      * @retval TRUE   If IEs present.
299      * @retval FALSE  If no IE present.
300      */
IsIePresent(void) const301     bool IsIePresent(void) const { return IsIePresent(GetFrameControlField()); }
302 
303     /**
304      * Sets the IE Present bit.
305      *
306      * @note This method must not be called on a Multipurpose frame with short Frame Control field.
307      *
308      * @param[in]  aIePresent   The IE Present bit.
309      */
310     void SetIePresent(bool aIePresent);
311 
312     /**
313      * Returns the Sequence Number value.
314      *
315      * @returns The Sequence Number value.
316      */
317     uint8_t GetSequence(void) const;
318 
319     /**
320      * Sets the Sequence Number value.
321      *
322      * @param[in]  aSequence  The Sequence Number value.
323      */
324     void SetSequence(uint8_t aSequence);
325 
326     /**
327      * Indicates whether or not the Sequence Number is present.
328      *
329      * @returns TRUE if the Sequence Number is present, FALSE otherwise.
330      */
IsSequencePresent(void) const331     uint8_t IsSequencePresent(void) const { return IsSequencePresent(GetFrameControlField()); }
332 
333     /**
334      * Indicates whether or not the Destination PAN ID is present.
335      *
336      * @returns TRUE if the Destination PAN ID is present, FALSE otherwise.
337      */
IsDstPanIdPresent(void) const338     bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); }
339 
340     /**
341      * Gets the Destination PAN Identifier.
342      *
343      * @param[out]  aPanId  The Destination PAN Identifier.
344      *
345      * @retval kErrorNone   Successfully retrieved the Destination PAN Identifier.
346      * @retval kErrorParse  Failed to parse the PAN Identifier.
347      */
348     Error GetDstPanId(PanId &aPanId) const;
349 
350     /**
351      * Indicates whether or not the Destination Address is present for this object.
352      *
353      * @retval TRUE   If the Destination Address is present.
354      * @retval FALSE  If the Destination Address is not present.
355      */
IsDstAddrPresent() const356     bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); }
357 
358     /**
359      * Gets the Destination Address.
360      *
361      * @param[out]  aAddress  The Destination Address.
362      *
363      * @retval kErrorNone  Successfully retrieved the Destination Address.
364      */
365     Error GetDstAddr(Address &aAddress) const;
366 
367     /**
368      * Indicates whether or not the Source Address is present for this object.
369      *
370      * @retval TRUE   If the Source Address is present.
371      * @retval FALSE  If the Source Address is not present.
372      */
IsSrcPanIdPresent(void) const373     bool IsSrcPanIdPresent(void) const { return IsSrcPanIdPresent(GetFrameControlField()); }
374 
375     /**
376      * Gets the Source PAN Identifier.
377      *
378      * @param[out]  aPanId  The Source PAN Identifier.
379      *
380      * @retval kErrorNone   Successfully retrieved the Source PAN Identifier.
381      */
382     Error GetSrcPanId(PanId &aPanId) const;
383 
384     /**
385      * Indicates whether or not the Source Address is present for this object.
386      *
387      * @retval TRUE   If the Source Address is present.
388      * @retval FALSE  If the Source Address is not present.
389      */
IsSrcAddrPresent(void) const390     bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); }
391 
392     /**
393      * Gets the Source Address.
394      *
395      * @param[out]  aAddress  The Source Address.
396      *
397      * @retval kErrorNone  Successfully retrieved the Source Address.
398      */
399     Error GetSrcAddr(Address &aAddress) const;
400 
401     /**
402      * Gets the Security Control Field.
403      *
404      * @param[out]  aSecurityControlField  The Security Control Field.
405      *
406      * @retval kErrorNone   Successfully retrieved the Security Level Identifier.
407      * @retval kErrorParse  Failed to find the security control field in the frame.
408      */
409     Error GetSecurityControlField(uint8_t &aSecurityControlField) const;
410 
411     /**
412      * Gets the Security Level Identifier.
413      *
414      * @param[out]  aSecurityLevel  The Security Level Identifier.
415      *
416      * @retval kErrorNone  Successfully retrieved the Security Level Identifier.
417      */
418     Error GetSecurityLevel(uint8_t &aSecurityLevel) const;
419 
420     /**
421      * Gets the Key Identifier Mode.
422      *
423      * @param[out]  aKeyIdMode  The Key Identifier Mode.
424      *
425      * @retval kErrorNone  Successfully retrieved the Key Identifier Mode.
426      */
427     Error GetKeyIdMode(uint8_t &aKeyIdMode) const;
428 
429     /**
430      * Gets the Frame Counter.
431      *
432      * @param[out]  aFrameCounter  The Frame Counter.
433      *
434      * @retval kErrorNone  Successfully retrieved the Frame Counter.
435      */
436     Error GetFrameCounter(uint32_t &aFrameCounter) const;
437 
438     /**
439      * Sets the Frame Counter.
440      *
441      * @param[in]  aFrameCounter  The Frame Counter.
442      */
443     void SetFrameCounter(uint32_t aFrameCounter);
444 
445     /**
446      * Returns a pointer to the Key Source.
447      *
448      * @returns A pointer to the Key Source.
449      */
450     const uint8_t *GetKeySource(void) const;
451 
452     /**
453      * Sets the Key Source.
454      *
455      * @param[in]  aKeySource  A pointer to the Key Source value.
456      */
457     void SetKeySource(const uint8_t *aKeySource);
458 
459     /**
460      * Gets the Key Identifier.
461      *
462      * @param[out]  aKeyId  The Key Identifier.
463      *
464      * @retval kErrorNone  Successfully retrieved the Key Identifier.
465      */
466     Error GetKeyId(uint8_t &aKeyId) const;
467 
468     /**
469      * Sets the Key Identifier.
470      *
471      * @param[in]  aKeyId  The Key Identifier.
472      */
473     void SetKeyId(uint8_t aKeyId);
474 
475     /**
476      * Gets the Command ID.
477      *
478      * @param[out]  aCommandId  The Command ID.
479      *
480      * @retval kErrorNone  Successfully retrieved the Command ID.
481      */
482     Error GetCommandId(uint8_t &aCommandId) const;
483 
484     /**
485      * Indicates whether the frame is a MAC Data Request command (data poll).
486      *
487      * For 802.15.4-2015 and above frame, the frame should be already decrypted.
488      *
489      * @returns TRUE if frame is a MAC Data Request command, FALSE otherwise.
490      */
491     bool IsDataRequestCommand(void) const;
492 
493     /**
494      * Returns the MAC Frame Length, namely the IEEE 802.15.4 PSDU length.
495      *
496      * @returns The MAC Frame Length.
497      */
GetLength(void) const498     uint16_t GetLength(void) const { return mLength; }
499 
500     /**
501      * Sets the MAC Frame Length.
502      *
503      * @param[in]  aLength  The MAC Frame Length.
504      */
SetLength(uint16_t aLength)505     void SetLength(uint16_t aLength) { mLength = aLength; }
506 
507     /**
508      * Returns the MAC header size.
509      *
510      * @returns The MAC header size.
511      */
512     uint8_t GetHeaderLength(void) const;
513 
514     /**
515      * Returns the MAC footer size.
516      *
517      * @returns The MAC footer size.
518      */
519     uint8_t GetFooterLength(void) const;
520 
521     /**
522      * Returns the current MAC Payload length.
523      *
524      * @returns The current MAC Payload length.
525      */
526     uint16_t GetPayloadLength(void) const;
527 
528     /**
529      * Returns the maximum MAC Payload length for the given MAC header and footer.
530      *
531      * @returns The maximum MAC Payload length for the given MAC header and footer.
532      */
533     uint16_t GetMaxPayloadLength(void) const;
534 
535     /**
536      * Sets the MAC Payload length.
537      */
538     void SetPayloadLength(uint16_t aLength);
539 
540     /**
541      * Returns the IEEE 802.15.4 channel used for transmission or reception.
542      *
543      * @returns The IEEE 802.15.4 channel used for transmission or reception.
544      */
GetChannel(void) const545     uint8_t GetChannel(void) const { return mChannel; }
546 
547     /**
548      * Returns a pointer to the PSDU.
549      *
550      * @returns A pointer to the PSDU.
551      */
GetPsdu(void)552     uint8_t *GetPsdu(void) { return mPsdu; }
553 
554     /**
555      * Returns a pointer to the PSDU.
556      *
557      * @returns A pointer to the PSDU.
558      */
GetPsdu(void) const559     const uint8_t *GetPsdu(void) const { return mPsdu; }
560 
561     /**
562      * Returns a pointer to the MAC Header.
563      *
564      * @returns A pointer to the MAC Header.
565      */
GetHeader(void)566     uint8_t *GetHeader(void) { return GetPsdu(); }
567 
568     /**
569      * Returns a pointer to the MAC Header.
570      *
571      * @returns A pointer to the MAC Header.
572      */
GetHeader(void) const573     const uint8_t *GetHeader(void) const { return GetPsdu(); }
574 
575     /**
576      * Returns a pointer to the MAC Payload.
577      *
578      * @returns A pointer to the MAC Payload.
579      */
GetPayload(void)580     uint8_t *GetPayload(void) { return AsNonConst(AsConst(this)->GetPayload()); }
581 
582     /**
583      * Returns a pointer to the MAC Payload.
584      *
585      * @returns A pointer to the MAC Payload.
586      */
587     const uint8_t *GetPayload(void) const;
588 
589     /**
590      * Returns a pointer to the MAC Footer.
591      *
592      * @returns A pointer to the MAC Footer.
593      */
GetFooter(void)594     uint8_t *GetFooter(void) { return AsNonConst(AsConst(this)->GetFooter()); }
595 
596     /**
597      * Returns a pointer to the MAC Footer.
598      *
599      * @returns A pointer to the MAC Footer.
600      */
601     const uint8_t *GetFooter(void) const;
602 
603 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
604 
605     /**
606      * Returns a pointer to the vendor specific Time IE.
607      *
608      * @returns A pointer to the Time IE, `nullptr` if not found.
609      */
GetTimeIe(void)610     TimeIe *GetTimeIe(void) { return AsNonConst(AsConst(this)->GetTimeIe()); }
611 
612     /**
613      * Returns a pointer to the vendor specific Time IE.
614      *
615      * @returns A pointer to the Time IE, `nullptr` if not found.
616      */
617     const TimeIe *GetTimeIe(void) const;
618 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
619 
620 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
621     /**
622      * Returns a pointer to the Header IE.
623      *
624      * @param[in] aIeId  The Element Id of the Header IE.
625      *
626      * @returns A pointer to the Header IE, `nullptr` if not found.
627      */
GetHeaderIe(uint8_t aIeId)628     uint8_t *GetHeaderIe(uint8_t aIeId) { return AsNonConst(AsConst(this)->GetHeaderIe(aIeId)); }
629 
630     /**
631      * Returns a pointer to the Header IE.
632      *
633      * @param[in] aIeId  The Element Id of the Header IE.
634      *
635      * @returns A pointer to the Header IE, `nullptr` if not found.
636      */
637     const uint8_t *GetHeaderIe(uint8_t aIeId) const;
638 
639     /**
640      * Returns a pointer to a specific Thread IE.
641      *
642      * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
643      *
644      * @param[in] aSubType  The sub type of the Thread IE.
645      *
646      * @returns A pointer to the Thread IE, `nullptr` if not found.
647      */
GetThreadIe(uint8_t aSubType)648     uint8_t *GetThreadIe(uint8_t aSubType) { return AsNonConst(AsConst(this)->GetThreadIe(aSubType)); }
649 
650     /**
651      * Returns a pointer to a specific Thread IE.
652      *
653      * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
654      *
655      * @param[in] aSubType  The sub type of the Thread IE.
656      *
657      * @returns A pointer to the Thread IE, `nullptr` if not found.
658      */
659     const uint8_t *GetThreadIe(uint8_t aSubType) const;
660 
661 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
662     /**
663      * Finds CSL IE in the frame and modify its content.
664      *
665      * @param[in] aCslPeriod  CSL Period in CSL IE.
666      * @param[in] aCslPhase   CSL Phase in CSL IE.
667      */
668     void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase);
669 
670     /**
671      * Indicates whether or not the frame contains CSL IE.
672      *
673      * @retval TRUE   If the frame contains CSL IE.
674      * @retval FALSE  If the frame doesn't contain CSL IE.
675      */
676     bool HasCslIe(void) const;
677 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
678 
679 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
680     /**
681      * Returns a pointer to a CSL IE.
682      *
683      * @returns A pointer to the CSL IE, `nullptr` if not found.
684      */
685     const CslIe *GetCslIe(void) const;
686 
687     /**
688      * Returns a pointer to a CSL IE.
689      *
690      * @returns A pointer to the CSL IE, `nullptr` if not found.
691      */
GetCslIe(void)692     CslIe *GetCslIe(void) { return AsNonConst(AsConst(this)->GetCslIe()); }
693 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
694 
695 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
696     /**
697      * Finds Enhanced ACK Probing (Vendor Specific) IE and set its value.
698      *
699      * @param[in] aValue  A pointer to the value to set.
700      * @param[in] aLen    The length of @p aValue.
701      */
702     void SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen);
703 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
704 
705 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
706 
707 #if OPENTHREAD_CONFIG_MULTI_RADIO
708     /**
709      * Gets the radio link type of the frame.
710      *
711      * @returns Frame's radio link type.
712      */
GetRadioType(void) const713     RadioType GetRadioType(void) const { return static_cast<RadioType>(mRadioType); }
714 
715     /**
716      * Sets the radio link type of the frame.
717      *
718      * @param[in] aRadioType  A radio link type.
719      */
SetRadioType(RadioType aRadioType)720     void SetRadioType(RadioType aRadioType) { mRadioType = static_cast<uint8_t>(aRadioType); }
721 #endif
722 
723     /**
724      * Returns the maximum transmission unit size (MTU).
725      *
726      * @returns The maximum transmission unit (MTU).
727      */
GetMtu(void) const728     uint16_t GetMtu(void) const
729 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
730     {
731         return OT_RADIO_FRAME_MAX_SIZE;
732     }
733 #else
734         ;
735 #endif
736 
737     /**
738      * Returns the FCS size.
739      *
740      * @returns This method returns the FCS size.
741      */
GetFcsSize(void) const742     uint8_t GetFcsSize(void) const
743 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
744     {
745         return k154FcsSize;
746     }
747 #else
748         ;
749 #endif
750 
751     /**
752      * Returns information about the frame object as an `InfoString` object.
753      *
754      * @returns An `InfoString` containing info about the frame.
755      */
756     InfoString ToInfoString(void) const;
757 
758     /**
759      * Returns the Frame Control field of the frame.
760      *
761      * @returns The Frame Control field.
762      */
GetFrameControlField(void) const763     uint16_t GetFrameControlField(void) const
764     {
765         uint16_t fcf = mPsdu[0];
766 
767 #if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
768         if (!IsShortFcf(fcf))
769 #endif
770         {
771             fcf |= (mPsdu[1] << 8);
772         }
773 
774         return fcf;
775     }
776 
777 protected:
778     static constexpr uint8_t kShortFcfSize        = sizeof(uint8_t);
779     static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t);
780     static constexpr uint8_t kFrameCounterSize    = sizeof(uint32_t);
781     static constexpr uint8_t kCommandIdSize       = sizeof(uint8_t);
782     static constexpr uint8_t kKeyIndexSize        = sizeof(uint8_t);
783 
784     static constexpr uint16_t kFcfFrameTypeMask = 7 << 0;
785 
786     static constexpr uint16_t kFcfAddrNone  = 0;
787     static constexpr uint16_t kFcfAddrShort = 2;
788     static constexpr uint16_t kFcfAddrExt   = 3;
789     static constexpr uint16_t kFcfAddrMask  = 3;
790 
791     // Frame Control field format for general MAC frame
792     static constexpr uint16_t kFcfSecurityEnabled     = 1 << 3;
793     static constexpr uint16_t kFcfFramePending        = 1 << 4;
794     static constexpr uint16_t kFcfAckRequest          = 1 << 5;
795     static constexpr uint16_t kFcfPanidCompression    = 1 << 6;
796     static constexpr uint16_t kFcfSequenceSuppression = 1 << 8;
797     static constexpr uint16_t kFcfIePresent           = 1 << 9;
798     static constexpr uint16_t kFcfDstAddrShift        = 10;
799     static constexpr uint16_t kFcfDstAddrNone         = kFcfAddrNone << kFcfDstAddrShift;
800     static constexpr uint16_t kFcfDstAddrShort        = kFcfAddrShort << kFcfDstAddrShift;
801     static constexpr uint16_t kFcfDstAddrExt          = kFcfAddrExt << kFcfDstAddrShift;
802     static constexpr uint16_t kFcfDstAddrMask         = kFcfAddrMask << kFcfDstAddrShift;
803     static constexpr uint16_t kFcfFrameVersionMask    = 3 << 12;
804     static constexpr uint16_t kFcfSrcAddrShift        = 14;
805     static constexpr uint16_t kFcfSrcAddrNone         = kFcfAddrNone << kFcfSrcAddrShift;
806     static constexpr uint16_t kFcfSrcAddrShort        = kFcfAddrShort << kFcfSrcAddrShift;
807     static constexpr uint16_t kFcfSrcAddrExt          = kFcfAddrExt << kFcfSrcAddrShift;
808     static constexpr uint16_t kFcfSrcAddrMask         = kFcfAddrMask << kFcfSrcAddrShift;
809 
810     // Frame Control field format for MAC Multipurpose frame
811     static constexpr uint16_t kMpFcfLongFrame           = 1 << 3;
812     static constexpr uint16_t kMpFcfDstAddrShift        = 4;
813     static constexpr uint16_t kMpFcfDstAddrNone         = kFcfAddrNone << kMpFcfDstAddrShift;
814     static constexpr uint16_t kMpFcfDstAddrShort        = kFcfAddrShort << kMpFcfDstAddrShift;
815     static constexpr uint16_t kMpFcfDstAddrExt          = kFcfAddrExt << kMpFcfDstAddrShift;
816     static constexpr uint16_t kMpFcfDstAddrMask         = kFcfAddrMask << kMpFcfDstAddrShift;
817     static constexpr uint16_t kMpFcfSrcAddrShift        = 6;
818     static constexpr uint16_t kMpFcfSrcAddrNone         = kFcfAddrNone << kMpFcfSrcAddrShift;
819     static constexpr uint16_t kMpFcfSrcAddrShort        = kFcfAddrShort << kMpFcfSrcAddrShift;
820     static constexpr uint16_t kMpFcfSrcAddrExt          = kFcfAddrExt << kMpFcfSrcAddrShift;
821     static constexpr uint16_t kMpFcfSrcAddrMask         = kFcfAddrMask << kMpFcfSrcAddrShift;
822     static constexpr uint16_t kMpFcfPanidPresent        = 1 << 8;
823     static constexpr uint16_t kMpFcfSecurityEnabled     = 1 << 9;
824     static constexpr uint16_t kMpFcfSequenceSuppression = 1 << 10;
825     static constexpr uint16_t kMpFcfFramePending        = 1 << 11;
826     static constexpr uint16_t kMpFcfAckRequest          = 1 << 14;
827     static constexpr uint16_t kMpFcfIePresent           = 1 << 15;
828 
829     static constexpr uint8_t kSecLevelMask  = 7 << 0;
830     static constexpr uint8_t kKeyIdModeMask = 3 << 3;
831 
832     static constexpr uint8_t kMic0Size   = 0;
833     static constexpr uint8_t kMic32Size  = 32 / kBitsPerByte;
834     static constexpr uint8_t kMic64Size  = 64 / kBitsPerByte;
835     static constexpr uint8_t kMic128Size = 128 / kBitsPerByte;
836     static constexpr uint8_t kMaxMicSize = kMic128Size;
837 
838     static constexpr uint8_t kKeySourceSizeMode0 = 0;
839     static constexpr uint8_t kKeySourceSizeMode1 = 0;
840     static constexpr uint8_t kKeySourceSizeMode2 = 4;
841     static constexpr uint8_t kKeySourceSizeMode3 = 8;
842 
843     static constexpr uint8_t kInvalidIndex = 0xff;
844     static constexpr uint8_t kInvalidSize  = kInvalidIndex;
845     static constexpr uint8_t kMaxPsduSize  = kInvalidSize - 1;
846 
847     void    SetFrameControlField(uint16_t aFcf);
848     uint8_t SkipSequenceIndex(void) const;
849     uint8_t FindDstPanIdIndex(void) const;
850     uint8_t FindDstAddrIndex(void) const;
851     uint8_t FindSrcPanIdIndex(void) const;
852     uint8_t FindSrcAddrIndex(void) const;
853     uint8_t SkipAddrFieldIndex(void) const;
854     uint8_t FindSecurityHeaderIndex(void) const;
855     uint8_t SkipSecurityHeaderIndex(void) const;
856     uint8_t FindPayloadIndex(void) const;
857 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
858     uint8_t FindHeaderIeIndex(void) const;
859 #endif
860 
861 #if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
GetFcfSize(uint16_t aFcf)862     static uint8_t GetFcfSize(uint16_t aFcf) { return IsShortFcf(aFcf) ? kShortFcfSize : kFcfSize; }
863 #else
864     // clang-format off
GetFcfSize(uint16_t)865     static uint8_t GetFcfSize(uint16_t /* aFcf */) { return kFcfSize; }
866     // clang-format on
867 #endif
868 
869 #if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
Select(uint16_t aFcf)870     template <uint16_t kValue, uint16_t kMpValue> static uint16_t Select(uint16_t aFcf)
871     {
872         return IsMultipurpose(aFcf) ? kMpValue : kValue;
873     }
874 #else
Select(uint16_t)875     template <uint16_t kValue, uint16_t kMpValue> static uint16_t Select(uint16_t /* aFcf */) { return kValue; }
876 #endif
877 
MaskFcf(uint16_t aFcf)878     template <uint16_t kValue, uint16_t kMpValue> static uint16_t MaskFcf(uint16_t aFcf)
879     {
880         return aFcf & Select<kValue, kMpValue>(aFcf);
881     }
882 
GetFcfDstAddr(uint16_t aFcf)883     static uint16_t GetFcfDstAddr(uint16_t aFcf)
884     {
885         return MaskFcf<kFcfDstAddrMask, kMpFcfDstAddrMask>(aFcf) >> Select<kFcfDstAddrShift, kMpFcfDstAddrShift>(aFcf);
886     }
887 
GetFcfSrcAddr(uint16_t aFcf)888     static uint16_t GetFcfSrcAddr(uint16_t aFcf)
889     {
890         return MaskFcf<kFcfSrcAddrMask, kMpFcfSrcAddrMask>(aFcf) >> Select<kFcfSrcAddrShift, kMpFcfSrcAddrShift>(aFcf);
891     }
892 
IsMultipurpose(uint16_t aFcf)893     static bool IsMultipurpose(uint16_t aFcf) { return (aFcf & kFcfFrameTypeMask) == kTypeMultipurpose; }
IsShortFcf(uint16_t aFcf)894     static bool IsShortFcf(uint16_t aFcf)
895     {
896         return (aFcf & (kFcfFrameTypeMask | kMpFcfLongFrame)) == (kTypeMultipurpose | 0);
897     }
IsSequencePresent(uint16_t aFcf)898     static bool IsSequencePresent(uint16_t aFcf)
899     {
900         return !MaskFcf<kFcfSequenceSuppression, kMpFcfSequenceSuppression>(aFcf);
901     }
IsDstAddrPresent(uint16_t aFcf)902     static bool IsDstAddrPresent(uint16_t aFcf) { return MaskFcf<kFcfDstAddrMask, kMpFcfDstAddrMask>(aFcf); }
903     static bool IsDstPanIdPresent(uint16_t aFcf);
IsSrcAddrPresent(uint16_t aFcf)904     static bool IsSrcAddrPresent(uint16_t aFcf) { return MaskFcf<kFcfSrcAddrMask, kMpFcfSrcAddrMask>(aFcf); }
905     static bool IsSrcPanIdPresent(uint16_t aFcf);
IsSecurityEnabled(uint16_t aFcf)906     static bool IsSecurityEnabled(uint16_t aFcf) { return MaskFcf<kFcfSecurityEnabled, kMpFcfSecurityEnabled>(aFcf); }
IsFramePending(uint16_t aFcf)907     static bool IsFramePending(uint16_t aFcf) { return MaskFcf<kFcfFramePending, kMpFcfFramePending>(aFcf); }
IsIePresent(uint16_t aFcf)908     static bool IsIePresent(uint16_t aFcf) { return MaskFcf<kFcfIePresent, kMpFcfIePresent>(aFcf); }
IsAckRequest(uint16_t aFcf)909     static bool IsAckRequest(uint16_t aFcf) { return MaskFcf<kFcfAckRequest, kMpFcfAckRequest>(aFcf); }
IsVersion2015(uint16_t aFcf)910     static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; }
911 
912     static uint16_t DetermineFcfAddrType(const Address &aAddress, uint16_t aBitShift);
913 
914     static uint8_t CalculateAddrFieldSize(uint16_t aFcf);
915     static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
916     static uint8_t CalculateKeySourceSize(uint8_t aSecurityControl);
917     static uint8_t CalculateMicSize(uint8_t aSecurityControl);
918 };
919 
920 /**
921  * Supports received IEEE 802.15.4 MAC frame processing.
922  */
923 class RxFrame : public Frame
924 {
925 public:
926     friend class TxFrame;
927 
928     /**
929      * Returns the RSSI in dBm used for reception.
930      *
931      * @returns The RSSI in dBm used for reception.
932      */
GetRssi(void) const933     int8_t GetRssi(void) const { return mInfo.mRxInfo.mRssi; }
934 
935     /**
936      * Sets the RSSI in dBm used for reception.
937      *
938      * @param[in]  aRssi  The RSSI in dBm used for reception.
939      */
SetRssi(int8_t aRssi)940     void SetRssi(int8_t aRssi) { mInfo.mRxInfo.mRssi = aRssi; }
941 
942     /**
943      * Returns the receive Link Quality Indicator.
944      *
945      * @returns The receive Link Quality Indicator.
946      */
GetLqi(void) const947     uint8_t GetLqi(void) const { return mInfo.mRxInfo.mLqi; }
948 
949     /**
950      * Sets the receive Link Quality Indicator.
951      *
952      * @param[in]  aLqi  The receive Link Quality Indicator.
953      */
SetLqi(uint8_t aLqi)954     void SetLqi(uint8_t aLqi) { mInfo.mRxInfo.mLqi = aLqi; }
955 
956     /**
957      * Indicates whether or not the received frame is acknowledged with frame pending set.
958      *
959      * @retval TRUE   This frame is acknowledged with frame pending set.
960      * @retval FALSE  This frame is acknowledged with frame pending not set.
961      */
IsAckedWithFramePending(void) const962     bool IsAckedWithFramePending(void) const { return mInfo.mRxInfo.mAckedWithFramePending; }
963 
964     /**
965      * Returns the timestamp when the frame was received.
966      *
967      * The value SHALL be the time of the local radio clock in
968      * microseconds when the end of the SFD (or equivalently: the start
969      * of the first symbol of the PHR) was present at the local antenna,
970      * see the definition of a "symbol boundary" in IEEE 802.15.4-2020,
971      * section 6.5.2 or equivalently the RMARKER definition in section
972      * 6.9.1 (albeit both unrelated to OT).
973      *
974      * The time is relative to the local radio clock as defined by
975      * `Radio::GetNow()`.
976      *
977      * @returns The timestamp in microseconds.
978      */
GetTimestamp(void) const979     const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; }
980 
981     /**
982      * Performs AES CCM on the frame which is received.
983      *
984      * @param[in]  aExtAddress  A reference to the extended address, which will be used to generate nonce
985      *                          for AES CCM computation.
986      * @param[in]  aMacKey      A reference to the MAC key to decrypt the received frame.
987      *
988      * @retval kErrorNone      Process of received frame AES CCM succeeded.
989      * @retval kErrorSecurity  Received frame MIC check failed.
990      */
991     Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey);
992 
993 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
994     /**
995      * Gets the offset to network time.
996      *
997      * @returns  The offset to network time.
998      */
ComputeNetworkTimeOffset(void) const999     int64_t ComputeNetworkTimeOffset(void) const
1000     {
1001         return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp());
1002     }
1003 
1004     /**
1005      * Gets the time sync sequence.
1006      *
1007      * @returns  The time sync sequence.
1008      */
ReadTimeSyncSeq(void) const1009     uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); }
1010 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1011 };
1012 
1013 /**
1014  * Supports IEEE 802.15.4 MAC frame generation for transmission.
1015  */
1016 class TxFrame : public Frame
1017 {
1018 public:
1019     /**
1020      * Represents header information.
1021      */
1022     struct Info : public Clearable<Info>
1023     {
1024         /**
1025          * Initializes the `Info` by clearing all its fields (setting all bytes to zero).
1026          */
Infoot::Mac::TxFrame::Info1027         Info(void) { Clear(); }
1028 
1029         /**
1030          * Prepares MAC headers based on `Info` fields in a given `TxFrame`.
1031          *
1032          * This method uses the `Info` structure to construct the MAC address and security headers in @p aTxFrame.
1033          * It determines the Frame Control Field (FCF), including setting the appropriate frame type, security level,
1034          * and addressing mode flags. It populates the source and destination addresses and PAN IDs within the MAC
1035          * header based on the information provided in the `Info` structure.
1036          *
1037          * It sets the Ack Request bit in the FCF if the following criteria are met:
1038          *   - A destination address is present
1039          *   - The destination address is not the broadcast address
1040          *   - The frame type is not an ACK frame
1041          *
1042          * The header IE entries are prepared based on `mAppendTimeIe` and `mAppendCslIe` flags and the IE Present
1043          * flag in FCF is determined accordingly.
1044          *
1045          * The Frame Pending flag in FCF is not set. It may need to be set separately depending on the specific
1046          * requirements of the frame being transmitted.
1047          *
1048          * @param[in,out] aTxFrame  The `TxFrame` instance in which to prepare and append the MAC headers.
1049          */
1050         void PrepareHeadersIn(TxFrame &aTxFrame) const;
1051 
1052         Type          mType;                 ///< Frame type.
1053         Version       mVersion;              ///< Frame version.
1054         Addresses     mAddrs;                ///< Frame source and destination addresses.
1055         PanIds        mPanIds;               ///< Source and destination PAN Ids.
1056         SecurityLevel mSecurityLevel;        ///< Frame security level.
1057         KeyIdMode     mKeyIdMode;            ///< Frame security key ID mode.
1058         CommandId     mCommandId;            ///< Command ID (applicable when `mType == kTypeMacCmd`).
1059         bool          mSuppressSequence : 1; ///< Whether to suppress seq number.
1060 
1061 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1062 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1063         bool mAppendTimeIe : 1; ///< Whether to append Time IE.
1064 #endif
1065 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1066         bool mAppendCslIe : 1; ///< Whether to append CSL IE.
1067 #endif
1068         bool mEmptyPayload : 1; ///< Whether payload is empty (to decide about appending Termination2 IE).
1069 #endif
1070     };
1071 
1072     /**
1073      * Sets the channel on which to send the frame.
1074      *
1075      * It also sets the `RxChannelAfterTxDone` to the same channel.
1076      *
1077      * @param[in]  aChannel  The channel used for transmission.
1078      */
SetChannel(uint8_t aChannel)1079     void SetChannel(uint8_t aChannel)
1080     {
1081         mChannel = aChannel;
1082         SetRxChannelAfterTxDone(aChannel);
1083     }
1084 
1085     /**
1086      * Sets TX power to send the frame.
1087      *
1088      * @param[in]  aTxPower  The tx power used for transmission.
1089      */
SetTxPower(int8_t aTxPower)1090     void SetTxPower(int8_t aTxPower) { mInfo.mTxInfo.mTxPower = aTxPower; }
1091 
1092     /**
1093      * Gets the RX channel after frame TX is done.
1094      *
1095      * @returns The RX channel after frame TX is done.
1096      */
GetRxChannelAfterTxDone(void) const1097     uint8_t GetRxChannelAfterTxDone(void) const { return mInfo.mTxInfo.mRxChannelAfterTxDone; }
1098 
1099     /**
1100      * Sets the RX channel after frame TX is done.
1101      *
1102      * @param[in] aChannel   The RX channel after frame TX is done.
1103      */
SetRxChannelAfterTxDone(uint8_t aChannel)1104     void SetRxChannelAfterTxDone(uint8_t aChannel) { mInfo.mTxInfo.mRxChannelAfterTxDone = aChannel; }
1105 
1106     /**
1107      * Returns the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel
1108      * access failure.
1109      *
1110      * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006.
1111      *
1112      * @returns The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access
1113      *          failure.
1114      */
GetMaxCsmaBackoffs(void) const1115     uint8_t GetMaxCsmaBackoffs(void) const { return mInfo.mTxInfo.mMaxCsmaBackoffs; }
1116 
1117     /**
1118      * Sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel
1119      * access failure.
1120      *
1121      * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006.
1122      *
1123      * @param[in]  aMaxCsmaBackoffs  The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring
1124      *                               a channel access failure.
1125      */
SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs)1126     void SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs) { mInfo.mTxInfo.mMaxCsmaBackoffs = aMaxCsmaBackoffs; }
1127 
1128     /**
1129      * Returns the maximum number of retries allowed after a transmission failure.
1130      *
1131      * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006.
1132      *
1133      * @returns The maximum number of retries allowed after a transmission failure.
1134      */
GetMaxFrameRetries(void) const1135     uint8_t GetMaxFrameRetries(void) const { return mInfo.mTxInfo.mMaxFrameRetries; }
1136 
1137     /**
1138      * Sets the maximum number of retries allowed after a transmission failure.
1139      *
1140      * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006.
1141      *
1142      * @param[in]  aMaxFrameRetries  The maximum number of retries allowed after a transmission failure.
1143      */
SetMaxFrameRetries(uint8_t aMaxFrameRetries)1144     void SetMaxFrameRetries(uint8_t aMaxFrameRetries) { mInfo.mTxInfo.mMaxFrameRetries = aMaxFrameRetries; }
1145 
1146     /**
1147      * Indicates whether or not the frame is a retransmission.
1148      *
1149      * @retval TRUE   Frame is a retransmission
1150      * @retval FALSE  This is a new frame and not a retransmission of an earlier frame.
1151      */
IsARetransmission(void) const1152     bool IsARetransmission(void) const { return mInfo.mTxInfo.mIsARetx; }
1153 
1154     /**
1155      * Sets the retransmission flag attribute.
1156      *
1157      * @param[in]  aIsARetx  TRUE if frame is a retransmission of an earlier frame, FALSE otherwise.
1158      */
SetIsARetransmission(bool aIsARetx)1159     void SetIsARetransmission(bool aIsARetx) { mInfo.mTxInfo.mIsARetx = aIsARetx; }
1160 
1161     /**
1162      * Indicates whether or not CSMA-CA is enabled.
1163      *
1164      * @retval TRUE   CSMA-CA is enabled.
1165      * @retval FALSE  CSMA-CA is not enabled is not enabled.
1166      */
IsCsmaCaEnabled(void) const1167     bool IsCsmaCaEnabled(void) const { return mInfo.mTxInfo.mCsmaCaEnabled; }
1168 
1169     /**
1170      * Sets the CSMA-CA enabled attribute.
1171      *
1172      * @param[in]  aCsmaCaEnabled  TRUE if CSMA-CA must be enabled for this packet, FALSE otherwise.
1173      */
SetCsmaCaEnabled(bool aCsmaCaEnabled)1174     void SetCsmaCaEnabled(bool aCsmaCaEnabled) { mInfo.mTxInfo.mCsmaCaEnabled = aCsmaCaEnabled; }
1175 
1176     /**
1177      * Returns the key used for frame encryption and authentication (AES CCM).
1178      *
1179      * @returns The pointer to the key.
1180      */
GetAesKey(void) const1181     const Mac::KeyMaterial &GetAesKey(void) const
1182     {
1183         return *static_cast<const Mac::KeyMaterial *>(mInfo.mTxInfo.mAesKey);
1184     }
1185 
1186     /**
1187      * Sets the key used for frame encryption and authentication (AES CCM).
1188      *
1189      * @param[in]  aAesKey  The pointer to the key.
1190      */
SetAesKey(const Mac::KeyMaterial & aAesKey)1191     void SetAesKey(const Mac::KeyMaterial &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; }
1192 
1193     /**
1194      * Copies the PSDU and all attributes (except for frame link type) from another frame.
1195      *
1196      * @note This method performs a deep copy meaning the content of PSDU buffer from the given frame is copied into
1197      * the PSDU buffer of the current frame.
1198 
1199      * @param[in] aFromFrame  The frame to copy from.
1200      */
1201     void CopyFrom(const TxFrame &aFromFrame);
1202 
1203     /**
1204      * Performs AES CCM on the frame which is going to be sent.
1205      *
1206      * @param[in]  aExtAddress  A reference to the extended address, which will be used to generate nonce
1207      *                          for AES CCM computation.
1208      */
1209     void ProcessTransmitAesCcm(const ExtAddress &aExtAddress);
1210 
1211     /**
1212      * Indicates whether or not the frame has security processed.
1213      *
1214      * @retval TRUE   The frame already has security processed.
1215      * @retval FALSE  The frame does not have security processed.
1216      */
IsSecurityProcessed(void) const1217     bool IsSecurityProcessed(void) const { return mInfo.mTxInfo.mIsSecurityProcessed; }
1218 
1219     /**
1220      * Sets the security processed flag attribute.
1221      *
1222      * @param[in]  aIsSecurityProcessed  TRUE if the frame already has security processed.
1223      */
SetIsSecurityProcessed(bool aIsSecurityProcessed)1224     void SetIsSecurityProcessed(bool aIsSecurityProcessed)
1225     {
1226         mInfo.mTxInfo.mIsSecurityProcessed = aIsSecurityProcessed;
1227     }
1228 
1229     /**
1230      * Indicates whether or not the frame contains the CSL IE.
1231      *
1232      * @retval TRUE   The frame contains the CSL IE.
1233      * @retval FALSE  The frame does not contain the CSL IE.
1234      */
IsCslIePresent(void) const1235     bool IsCslIePresent(void) const { return mInfo.mTxInfo.mCslPresent; }
1236 
1237     /**
1238      * Sets the CSL IE present flag.
1239      *
1240      * @param[in]  aCslPresent  TRUE if the frame contains the CSL IE.
1241      */
SetCslIePresent(bool aCslPresent)1242     void SetCslIePresent(bool aCslPresent) { mInfo.mTxInfo.mCslPresent = aCslPresent; }
1243 
1244     /**
1245      * Indicates whether or not the frame header is updated.
1246      *
1247      * @retval TRUE   The frame already has the header updated.
1248      * @retval FALSE  The frame does not have the header updated.
1249      */
IsHeaderUpdated(void) const1250     bool IsHeaderUpdated(void) const { return mInfo.mTxInfo.mIsHeaderUpdated; }
1251 
1252     /**
1253      * Sets the header updated flag attribute.
1254      *
1255      * @param[in]  aIsHeaderUpdated  TRUE if the frame header is updated.
1256      */
SetIsHeaderUpdated(bool aIsHeaderUpdated)1257     void SetIsHeaderUpdated(bool aIsHeaderUpdated) { mInfo.mTxInfo.mIsHeaderUpdated = aIsHeaderUpdated; }
1258 
1259 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1260     /**
1261      * Sets the Time IE offset.
1262      *
1263      * @param[in]  aOffset  The Time IE offset, 0 means no Time IE.
1264      */
SetTimeIeOffset(uint8_t aOffset)1265     void SetTimeIeOffset(uint8_t aOffset) { mInfo.mTxInfo.mIeInfo->mTimeIeOffset = aOffset; }
1266 
1267     /**
1268      * Gets the Time IE offset.
1269      *
1270      * @returns The Time IE offset, 0 means no Time IE.
1271      */
GetTimeIeOffset(void) const1272     uint8_t GetTimeIeOffset(void) const { return mInfo.mTxInfo.mIeInfo->mTimeIeOffset; }
1273 
1274     /**
1275      * Sets the offset to network time.
1276      *
1277      * @param[in]  aNetworkTimeOffset  The offset to network time.
1278      */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1279     void SetNetworkTimeOffset(int64_t aNetworkTimeOffset)
1280     {
1281         mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset;
1282     }
1283 
1284     /**
1285      * Sets the time sync sequence.
1286      *
1287      * @param[in]  aTimeSyncSeq  The time sync sequence.
1288      */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1289     void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; }
1290 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1291 
1292     /**
1293      * Generate Imm-Ack in this frame object.
1294      *
1295      * @param[in]    aFrame             A reference to the frame received.
1296      * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
1297      */
1298     void GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending);
1299 
1300     /**
1301      * Generate Enh-Ack in this frame object.
1302      *
1303      * @param[in]    aRxFrame           A reference to the received frame.
1304      * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
1305      * @param[in]    aIeData            A pointer to the IE data portion of the ACK to be sent.
1306      * @param[in]    aIeLength          The length of IE data portion of the ACK to be sent.
1307      *
1308      * @retval  kErrorNone           Successfully generated Enh Ack.
1309      * @retval  kErrorParse          @p aRxFrame has incorrect format.
1310      */
1311     Error GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength);
1312 
1313 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1314     /**
1315      * Generate IEE 802.15.4 Wake-up frame.
1316      *
1317      * @param[in]    aPanId     A destination PAN identifier
1318      * @param[in]    aDest      A destination address (short or extended)
1319      * @param[in]    aSource    A source address (short or extended)
1320      *
1321      * @retval  kErrorNone        Successfully generated Wake-up frame.
1322      * @retval  kErrorInvalidArgs @p aDest or @p aSource have incorrect type.
1323      */
1324     Error GenerateWakeupFrame(PanId aPanId, const Address &aDest, const Address &aSource);
1325 #endif
1326 
1327 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
1328     /**
1329      * Set TX delay field for the frame.
1330      *
1331      * @param[in]    aTxDelay    The delay time for the TX frame.
1332      */
SetTxDelay(uint32_t aTxDelay)1333     void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; }
1334 
1335     /**
1336      * Set TX delay base time field for the frame.
1337      *
1338      * @param[in]    aTxDelayBaseTime    The delay base time for the TX frame.
1339      */
SetTxDelayBaseTime(uint32_t aTxDelayBaseTime)1340     void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; }
1341 #endif
1342 };
1343 
1344 OT_TOOL_PACKED_BEGIN
1345 class Beacon
1346 {
1347 public:
1348     static constexpr uint16_t kSuperFrameSpec = 0x0fff; ///< Superframe Specification value.
1349 
1350     /**
1351      * Initializes the Beacon message.
1352      */
Init(void)1353     void Init(void)
1354     {
1355         mSuperframeSpec     = LittleEndian::HostSwap16(kSuperFrameSpec);
1356         mGtsSpec            = 0;
1357         mPendingAddressSpec = 0;
1358     }
1359 
1360     /**
1361      * Indicates whether or not the beacon appears to be a valid Thread Beacon message.
1362      *
1363      * @retval TRUE   If the beacon appears to be a valid Thread Beacon message.
1364      * @retval FALSE  If the beacon does not appear to be a valid Thread Beacon message.
1365      */
IsValid(void) const1366     bool IsValid(void) const
1367     {
1368         return (mSuperframeSpec == LittleEndian::HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) &&
1369                (mPendingAddressSpec == 0);
1370     }
1371 
1372     /**
1373      * Returns the pointer to the beacon payload.
1374      *
1375      * @returns A pointer to the beacon payload.
1376      */
GetPayload(void)1377     uint8_t *GetPayload(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
1378 
1379     /**
1380      * Returns the pointer to the beacon payload.
1381      *
1382      * @returns A pointer to the beacon payload.
1383      */
GetPayload(void) const1384     const uint8_t *GetPayload(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
1385 
1386 private:
1387     uint16_t mSuperframeSpec;
1388     uint8_t  mGtsSpec;
1389     uint8_t  mPendingAddressSpec;
1390 } OT_TOOL_PACKED_END;
1391 
1392 /**
1393  * Implements IEEE 802.15.4 Beacon Payload generation and parsing.
1394  */
1395 OT_TOOL_PACKED_BEGIN
1396 class BeaconPayload
1397 {
1398 public:
1399     static constexpr uint8_t kProtocolId      = 3;                     ///< Thread Protocol ID.
1400     static constexpr uint8_t kProtocolVersion = 2;                     ///< Thread Protocol version.
1401     static constexpr uint8_t kVersionOffset   = 4;                     ///< Version field bit offset.
1402     static constexpr uint8_t kVersionMask     = 0xf << kVersionOffset; ///< Version field mask.
1403     static constexpr uint8_t kNativeFlag      = 1 << 3;                ///< Native Commissioner flag.
1404     static constexpr uint8_t kJoiningFlag     = 1 << 0;                ///< Joining Permitted flag.
1405 
1406     /**
1407      * Initializes the Beacon Payload.
1408      */
Init(void)1409     void Init(void)
1410     {
1411         mProtocolId = kProtocolId;
1412         mFlags      = kProtocolVersion << kVersionOffset;
1413     }
1414 
1415     /**
1416      * Indicates whether or not the beacon appears to be a valid Thread Beacon Payload.
1417      *
1418      * @retval TRUE   If the beacon appears to be a valid Thread Beacon Payload.
1419      * @retval FALSE  If the beacon does not appear to be a valid Thread Beacon Payload.
1420      */
IsValid(void) const1421     bool IsValid(void) const { return (mProtocolId == kProtocolId); }
1422 
1423     /**
1424      * Returns the Protocol ID value.
1425      *
1426      * @returns the Protocol ID value.
1427      */
GetProtocolId(void) const1428     uint8_t GetProtocolId(void) const { return mProtocolId; }
1429 
1430     /**
1431      * Returns the Protocol Version value.
1432      *
1433      * @returns The Protocol Version value.
1434      */
GetProtocolVersion(void) const1435     uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; }
1436 
1437     /**
1438      * Indicates whether or not the Native Commissioner flag is set.
1439      *
1440      * @retval TRUE   If the Native Commissioner flag is set.
1441      * @retval FALSE  If the Native Commissioner flag is not set.
1442      */
IsNative(void) const1443     bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; }
1444 
1445     /**
1446      * Clears the Native Commissioner flag.
1447      */
ClearNative(void)1448     void ClearNative(void) { mFlags &= ~kNativeFlag; }
1449 
1450     /**
1451      * Sets the Native Commissioner flag.
1452      */
SetNative(void)1453     void SetNative(void) { mFlags |= kNativeFlag; }
1454 
1455     /**
1456      * Indicates whether or not the Joining Permitted flag is set.
1457      *
1458      * @retval TRUE   If the Joining Permitted flag is set.
1459      * @retval FALSE  If the Joining Permitted flag is not set.
1460      */
IsJoiningPermitted(void) const1461     bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; }
1462 
1463     /**
1464      * Clears the Joining Permitted flag.
1465      */
ClearJoiningPermitted(void)1466     void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; }
1467 
1468     /**
1469      * Sets the Joining Permitted flag.
1470      */
SetJoiningPermitted(void)1471     void SetJoiningPermitted(void)
1472     {
1473         mFlags |= kJoiningFlag;
1474 
1475 #if OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION != 2 // check against kProtocolVersion
1476         mFlags &= ~kVersionMask;
1477         mFlags |= OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION << kVersionOffset;
1478 #endif
1479     }
1480 
1481     /**
1482      * Gets the Network Name field.
1483      *
1484      * @returns The Network Name field as `NameData`.
1485      */
GetNetworkName(void) const1486     MeshCoP::NameData GetNetworkName(void) const { return MeshCoP::NameData(mNetworkName, sizeof(mNetworkName)); }
1487 
1488     /**
1489      * Sets the Network Name field.
1490      *
1491      * @param[in]  aNameData  The Network Name (as a `NameData`).
1492      */
SetNetworkName(const MeshCoP::NameData & aNameData)1493     void SetNetworkName(const MeshCoP::NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); }
1494 
1495     /**
1496      * Returns the Extended PAN ID field.
1497      *
1498      * @returns The Extended PAN ID field.
1499      */
GetExtendedPanId(void) const1500     const otExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
1501 
1502     /**
1503      * Sets the Extended PAN ID field.
1504      *
1505      * @param[in]  aExtPanId  An Extended PAN ID.
1506      */
SetExtendedPanId(const otExtendedPanId & aExtPanId)1507     void SetExtendedPanId(const otExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; }
1508 
1509 private:
1510     uint8_t         mProtocolId;
1511     uint8_t         mFlags;
1512     char            mNetworkName[MeshCoP::NetworkName::kMaxSize];
1513     otExtendedPanId mExtendedPanId;
1514 } OT_TOOL_PACKED_END;
1515 
1516 /**
1517  * @}
1518  */
1519 
1520 } // namespace Mac
1521 } // namespace ot
1522 
1523 #endif // MAC_FRAME_HPP_
1524