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 the IEEE 802.15.4 MAC.
32  */
33 
34 #ifndef MAC_HPP_
35 #define MAC_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/platform/radio.h>
40 #include <openthread/platform/time.h>
41 
42 #include "common/clearable.hpp"
43 #include "common/locator.hpp"
44 #include "common/log.hpp"
45 #include "common/non_copyable.hpp"
46 #include "common/tasklet.hpp"
47 #include "common/time.hpp"
48 #include "common/timer.hpp"
49 #include "mac/channel_mask.hpp"
50 #include "mac/mac_filter.hpp"
51 #include "mac/mac_frame.hpp"
52 #include "mac/mac_links.hpp"
53 #include "mac/mac_types.hpp"
54 #include "mac/sub_mac.hpp"
55 #include "radio/trel_link.hpp"
56 #include "thread/key_manager.hpp"
57 #include "thread/link_quality.hpp"
58 
59 namespace ot {
60 
61 class Neighbor;
62 
63 /**
64  * @addtogroup core-mac
65  *
66  * @brief
67  *   This module includes definitions for the IEEE 802.15.4 MAC
68  *
69  * @{
70  *
71  */
72 
73 namespace Mac {
74 
75 constexpr uint32_t kDataPollTimeout =
76     OPENTHREAD_CONFIG_MAC_DATA_POLL_TIMEOUT; ///< Timeout for receiving Data Frame (in msec).
77 constexpr uint32_t kSleepDelay = 300;        ///< Max sleep delay when frame is pending (in msec).
78 
79 constexpr uint16_t kScanDurationDefault = OPENTHREAD_CONFIG_MAC_SCAN_DURATION; ///< Duration per channel (in msec).
80 
81 constexpr uint8_t kMaxCsmaBackoffsDirect   = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT;
82 constexpr uint8_t kMaxCsmaBackoffsIndirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_INDIRECT;
83 constexpr uint8_t kMaxCsmaBackoffsCsl      = 0;
84 
85 constexpr uint8_t kDefaultMaxFrameRetriesDirect   = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT;
86 constexpr uint8_t kDefaultMaxFrameRetriesIndirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT;
87 constexpr uint8_t kMaxFrameRetriesCsl             = 0;
88 
89 constexpr uint8_t kTxNumBcast = OPENTHREAD_CONFIG_MAC_TX_NUM_BCAST; ///< Num of times broadcast frame is tx.
90 
91 constexpr uint16_t kMinCslIePeriod = OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD;
92 
93 /**
94  * Defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan.
95  *
96  */
97 typedef otHandleActiveScanResult ActiveScanHandler;
98 
99 /**
100  * Defines an Active Scan result.
101  *
102  */
103 typedef otActiveScanResult ActiveScanResult;
104 
105 /**
106  * Defines the function pointer which is called during an Energy Scan when the scan result for a channel is
107  * ready or when the scan completes.
108  *
109  */
110 typedef otHandleEnergyScanResult EnergyScanHandler;
111 
112 /**
113  * Defines an Energy Scan result.
114  *
115  */
116 typedef otEnergyScanResult EnergyScanResult;
117 
118 /**
119  * Implements the IEEE 802.15.4 MAC.
120  *
121  */
122 class Mac : public InstanceLocator, private NonCopyable
123 {
124     friend class ot::Instance;
125 
126 public:
127     /**
128      * Initializes the MAC object.
129      *
130      * @param[in]  aInstance  A reference to the OpenThread instance.
131      *
132      */
133     explicit Mac(Instance &aInstance);
134 
135     /**
136      * Starts an IEEE 802.15.4 Active Scan.
137      *
138      * @param[in]  aScanChannels  A bit vector indicating which channels to scan. Zero is mapped to all channels.
139      * @param[in]  aScanDuration  The time in milliseconds to spend scanning each channel. Zero duration maps to
140      *                            default value `kScanDurationDefault` = 300 ms.
141      * @param[in]  aHandler       A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon.
142      * @param[in]  aContext       A pointer to an arbitrary context (used when invoking `aHandler` callback).
143      *
144      * @retval kErrorNone  Successfully scheduled the Active Scan request.
145      * @retval kErrorBusy  Could not schedule the scan (a scan is ongoing or scheduled).
146      *
147      */
148     Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
149 
150     /**
151      * Starts an IEEE 802.15.4 Energy Scan.
152      *
153      * @param[in]  aScanChannels     A bit vector indicating on which channels to scan. Zero is mapped to all channels.
154      * @param[in]  aScanDuration     The time in milliseconds to spend scanning each channel. If the duration is set to
155      *                               zero, a single RSSI sample will be taken per channel.
156      * @param[in]  aHandler          A pointer to a function called to pass on scan result or indicate scan completion.
157      * @param[in]  aContext          A pointer to an arbitrary context (used when invoking @p aHandler callback).
158      *
159      * @retval kErrorNone  Accepted the Energy Scan request.
160      * @retval kErrorBusy  Could not start the energy scan.
161      *
162      */
163     Error EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext);
164 
165     /**
166      * Indicates the energy scan for the current channel is complete.
167      *
168      * @param[in]  aEnergyScanMaxRssi  The maximum RSSI encountered on the scanned channel.
169      *
170      */
171     void EnergyScanDone(int8_t aEnergyScanMaxRssi);
172 
173     /**
174      * Indicates whether or not IEEE 802.15.4 Beacon transmissions are enabled.
175      *
176      * @retval TRUE   If IEEE 802.15.4 Beacon transmissions are enabled.
177      * @retval FALSE  If IEEE 802.15.4 Beacon transmissions are not enabled.
178      *
179      */
IsBeaconEnabled(void) const180     bool IsBeaconEnabled(void) const { return mBeaconsEnabled; }
181 
182     /**
183      * Enables/disables IEEE 802.15.4 Beacon transmissions.
184      *
185      * @param[in]  aEnabled  TRUE to enable IEEE 802.15.4 Beacon transmissions, FALSE otherwise.
186      *
187      */
SetBeaconEnabled(bool aEnabled)188     void SetBeaconEnabled(bool aEnabled) { mBeaconsEnabled = aEnabled; }
189 
190     /**
191      * Indicates whether or not rx-on-when-idle is enabled.
192      *
193      * @retval TRUE   If rx-on-when-idle is enabled.
194      * @retval FALSE  If rx-on-when-idle is not enabled.
195      */
GetRxOnWhenIdle(void) const196     bool GetRxOnWhenIdle(void) const { return mRxOnWhenIdle; }
197 
198     /**
199      * Sets the rx-on-when-idle mode.
200      *
201      * @param[in]  aRxOnWhenIdle  The rx-on-when-idle mode.
202      *
203      */
204     void SetRxOnWhenIdle(bool aRxOnWhenIdle);
205 
206     /**
207      * Requests a direct data frame transmission.
208      *
209      */
210     void RequestDirectFrameTransmission(void);
211 
212 #if OPENTHREAD_FTD
213     /**
214      * Requests an indirect data frame transmission.
215      *
216      */
217     void RequestIndirectFrameTransmission(void);
218 
219 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
220     /**
221      * Requests `Mac` to start a CSL tx operation after a delay of @p aDelay time.
222      *
223      * @param[in]  aDelay  Delay time for `Mac` to start a CSL tx, in units of milliseconds.
224      *
225      */
226     void RequestCslFrameTransmission(uint32_t aDelay);
227 #endif
228 
229 #endif
230 
231     /**
232      * Requests transmission of a data poll (MAC Data Request) frame.
233      *
234      * @retval kErrorNone          Data poll transmission request is scheduled successfully.
235      * @retval kErrorInvalidState  The MAC layer is not enabled.
236      *
237      */
238     Error RequestDataPollTransmission(void);
239 
240     /**
241      * Returns a reference to the IEEE 802.15.4 Extended Address.
242      *
243      * @returns A pointer to the IEEE 802.15.4 Extended Address.
244      *
245      */
GetExtAddress(void) const246     const ExtAddress &GetExtAddress(void) const { return mLinks.GetExtAddress(); }
247 
248     /**
249      * Sets the IEEE 802.15.4 Extended Address.
250      *
251      * @param[in]  aExtAddress  A reference to the IEEE 802.15.4 Extended Address.
252      *
253      */
SetExtAddress(const ExtAddress & aExtAddress)254     void SetExtAddress(const ExtAddress &aExtAddress) { mLinks.SetExtAddress(aExtAddress); }
255 
256     /**
257      * Returns the IEEE 802.15.4 Short Address.
258      *
259      * @returns The IEEE 802.15.4 Short Address.
260      *
261      */
GetShortAddress(void) const262     ShortAddress GetShortAddress(void) const { return mLinks.GetShortAddress(); }
263 
264     /**
265      * Sets the IEEE 802.15.4 Short Address.
266      *
267      * @param[in]  aShortAddress  The IEEE 802.15.4 Short Address.
268      *
269      */
SetShortAddress(ShortAddress aShortAddress)270     void SetShortAddress(ShortAddress aShortAddress) { mLinks.SetShortAddress(aShortAddress); }
271 
272     /**
273      * Returns the IEEE 802.15.4 PAN Channel.
274      *
275      * @returns The IEEE 802.15.4 PAN Channel.
276      *
277      */
GetPanChannel(void) const278     uint8_t GetPanChannel(void) const { return mPanChannel; }
279 
280     /**
281      * Sets the IEEE 802.15.4 PAN Channel.
282      *
283      * @param[in]  aChannel  The IEEE 802.15.4 PAN Channel.
284      *
285      * @retval kErrorNone          Successfully set the IEEE 802.15.4 PAN Channel.
286      * @retval kErrorInvalidArgs   The @p aChannel is not in the supported channel mask.
287      *
288      */
289     Error SetPanChannel(uint8_t aChannel);
290 
291     /**
292      * Sets the temporary IEEE 802.15.4 radio channel.
293      *
294      * Allows user to temporarily change the radio channel and use a different channel (during receive)
295      * instead of the PAN channel (from `SetPanChannel()`). A call to `ClearTemporaryChannel()` would clear the
296      * temporary channel and adopt the PAN channel again. The `SetTemporaryChannel()` can be used multiple times in row
297      * (before a call to `ClearTemporaryChannel()`) to change the temporary channel.
298      *
299      * @param[in]  aChannel            A IEEE 802.15.4 channel.
300      *
301      * @retval kErrorNone          Successfully set the temporary channel
302      * @retval kErrorInvalidArgs   The @p aChannel is not in the supported channel mask.
303      *
304      */
305     Error SetTemporaryChannel(uint8_t aChannel);
306 
307     /**
308      * Clears the use of a previously set temporary channel and adopts the PAN channel.
309      *
310      */
311     void ClearTemporaryChannel(void);
312 
313     /**
314      * Returns the supported channel mask.
315      *
316      * @returns The supported channel mask.
317      *
318      */
GetSupportedChannelMask(void) const319     const ChannelMask &GetSupportedChannelMask(void) const { return mSupportedChannelMask; }
320 
321     /**
322      * Sets the supported channel mask
323      *
324      * @param[in] aMask   The supported channel mask.
325      *
326      */
327     void SetSupportedChannelMask(const ChannelMask &aMask);
328 
329     /**
330      * Returns the IEEE 802.15.4 PAN ID.
331      *
332      * @returns The IEEE 802.15.4 PAN ID.
333      *
334      */
GetPanId(void) const335     PanId GetPanId(void) const { return mPanId; }
336 
337     /**
338      * Sets the IEEE 802.15.4 PAN ID.
339      *
340      * @param[in]  aPanId  The IEEE 802.15.4 PAN ID.
341      *
342      */
343     void SetPanId(PanId aPanId);
344 
345     /**
346      * Returns the maximum number of frame retries during direct transmission.
347      *
348      * @returns The maximum number of retries during direct transmission.
349      *
350      */
GetMaxFrameRetriesDirect(void) const351     uint8_t GetMaxFrameRetriesDirect(void) const { return mMaxFrameRetriesDirect; }
352 
353     /**
354      * Sets the maximum number of frame retries during direct transmission.
355      *
356      * @param[in]  aMaxFrameRetriesDirect  The maximum number of retries during direct transmission.
357      *
358      */
SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect)359     void SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect) { mMaxFrameRetriesDirect = aMaxFrameRetriesDirect; }
360 
361 #if OPENTHREAD_FTD
362     /**
363      * Returns the maximum number of frame retries during indirect transmission.
364      *
365      * @returns The maximum number of retries during indirect transmission.
366      *
367      */
GetMaxFrameRetriesIndirect(void) const368     uint8_t GetMaxFrameRetriesIndirect(void) const { return mMaxFrameRetriesIndirect; }
369 
370     /**
371      * Sets the maximum number of frame retries during indirect transmission.
372      *
373      * @param[in]  aMaxFrameRetriesIndirect  The maximum number of retries during indirect transmission.
374      *
375      */
SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect)376     void SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect)
377     {
378         mMaxFrameRetriesIndirect = aMaxFrameRetriesIndirect;
379     }
380 #endif
381 
382     /**
383      * Is called to handle a received frame.
384      *
385      * @param[in]  aFrame  A pointer to the received frame, or `nullptr` if the receive operation was aborted.
386      * @param[in]  aError  kErrorNone when successfully received a frame,
387      *                     kErrorAbort when reception was aborted and a frame was not received.
388      *
389      */
390     void HandleReceivedFrame(RxFrame *aFrame, Error aError);
391 
392     /**
393      * Records CCA status (success/failure) for a frame transmission attempt.
394      *
395      * @param[in] aCcaSuccess   TRUE if the CCA succeeded, FALSE otherwise.
396      * @param[in] aChannel      The channel on which CCA was performed.
397      *
398      */
399     void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel);
400 
401     /**
402      * Records the status of a frame transmission attempt, updating MAC counters.
403      *
404      * Unlike `HandleTransmitDone` which is called after all transmission attempts of frame to indicate final status
405      * of a frame transmission request, this method is invoked on all frame transmission attempts.
406      *
407      * @param[in] aFrame      The transmitted frame.
408      * @param[in] aError      kErrorNone when the frame was transmitted successfully,
409      *                        kErrorNoAck when the frame was transmitted but no ACK was received,
410      *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
411      *                        kErrorAbort when transmission was aborted for other reasons.
412      * @param[in] aRetryCount Indicates number of transmission retries for this frame.
413      * @param[in] aWillRetx   Indicates whether frame will be retransmitted or not. This is applicable only
414      *                        when there was an error in transmission (i.e., `aError` is not NONE).
415      *
416      */
417     void RecordFrameTransmitStatus(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx);
418 
419     /**
420      * Is called to handle transmit events.
421      *
422      * @param[in]  aFrame      The frame that was transmitted.
423      * @param[in]  aAckFrame   A pointer to the ACK frame, `nullptr` if no ACK was received.
424      * @param[in]  aError      kErrorNone when the frame was transmitted successfully,
425      *                         kErrorNoAck when the frame was transmitted but no ACK was received,
426      *                         kErrorChannelAccessFailure when the tx failed due to activity on the channel,
427      *                         kErrorAbort when transmission was aborted for other reasons.
428      *
429      */
430     void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
431 
432     /**
433      * Returns if an active scan is in progress.
434      *
435      */
IsActiveScanInProgress(void) const436     bool IsActiveScanInProgress(void) const { return IsActiveOrPending(kOperationActiveScan); }
437 
438     /**
439      * Returns if an energy scan is in progress.
440      *
441      */
IsEnergyScanInProgress(void) const442     bool IsEnergyScanInProgress(void) const { return IsActiveOrPending(kOperationEnergyScan); }
443 
444 #if OPENTHREAD_FTD
445     /**
446      * Indicates whether the MAC layer is performing an indirect transmission (in middle of a tx).
447      *
448      * @returns TRUE if in middle of an indirect transmission, FALSE otherwise.
449      *
450      */
IsPerformingIndirectTransmit(void) const451     bool IsPerformingIndirectTransmit(void) const { return (mOperation == kOperationTransmitDataIndirect); }
452 #endif
453 
454     /**
455      * Returns if the MAC layer is in transmit state.
456      *
457      * The MAC layer is in transmit state during CSMA/CA, CCA, transmission of Data, Beacon or Data Request frames and
458      * receiving of ACK frames. The MAC layer is not in transmit state during transmission of ACK frames or Beacon
459      * Requests.
460      *
461      */
462     bool IsInTransmitState(void) const;
463 
464     /**
465      * Registers a callback to provide received raw IEEE 802.15.4 frames.
466      *
467      * @param[in]  aPcapCallback     A pointer to a function that is called when receiving an IEEE 802.15.4 link frame
468      *                               or `nullptr` to disable the callback.
469      * @param[in]  aCallbackContext  A pointer to application-specific context.
470      *
471      */
SetPcapCallback(otLinkPcapCallback aPcapCallback,void * aCallbackContext)472     void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext)
473     {
474         mLinks.SetPcapCallback(aPcapCallback, aCallbackContext);
475     }
476 
477     /**
478      * Indicates whether or not promiscuous mode is enabled at the link layer.
479      *
480      * @retval true   Promiscuous mode is enabled.
481      * @retval false  Promiscuous mode is not enabled.
482      *
483      */
IsPromiscuous(void) const484     bool IsPromiscuous(void) const { return mPromiscuous; }
485 
486     /**
487      * Enables or disables the link layer promiscuous mode.
488      *
489      * Promiscuous mode keeps the receiver enabled, overriding the value of mRxOnWhenIdle.
490      *
491      * @param[in]  aPromiscuous  true to enable promiscuous mode, or false otherwise.
492      *
493      */
494     void SetPromiscuous(bool aPromiscuous);
495 
496     /**
497      * Resets mac counters
498      *
499      */
ResetCounters(void)500     void ResetCounters(void) { ClearAllBytes(mCounters); }
501 
502     /**
503      * Returns the MAC counter.
504      *
505      * @returns A reference to the MAC counter.
506      *
507      */
GetCounters(void)508     otMacCounters &GetCounters(void) { return mCounters; }
509 
510 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
511     /**
512      * Returns the MAC retry histogram for direct transmission.
513      *
514      * @param[out]  aNumberOfEntries    A reference to where the size of returned histogram array is placed.
515      *
516      * @returns     A pointer to the histogram of retries (in a form of an array).
517      *              The n-th element indicates that the packet has been sent with n-th retry.
518      *
519      */
520     const uint32_t *GetDirectRetrySuccessHistogram(uint8_t &aNumberOfEntries);
521 
522 #if OPENTHREAD_FTD
523     /**
524      * Returns the MAC retry histogram for indirect transmission.
525      *
526      * @param[out]  aNumberOfEntries    A reference to where the size of returned histogram array is placed.
527      *
528      * @returns     A pointer to the histogram of retries (in a form of an array).
529      *              The n-th element indicates that the packet has been sent with n-th retry.
530      *
531      */
532     const uint32_t *GetIndirectRetrySuccessHistogram(uint8_t &aNumberOfEntries);
533 #endif
534 
535     /**
536      * Resets MAC retry histogram.
537      *
538      */
539     void ResetRetrySuccessHistogram(void);
540 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
541 
542     /**
543      * Returns the noise floor value (currently use the radio receive sensitivity value).
544      *
545      * @returns The noise floor value in dBm.
546      *
547      */
GetNoiseFloor(void) const548     int8_t GetNoiseFloor(void) const { return mLinks.GetNoiseFloor(); }
549 
550     /**
551      * Computes the link margin for a given a received signal strength value using noise floor.
552      *
553      * @param[in] aRss The received signal strength in dBm.
554      *
555      * @returns The link margin for @p aRss in dB based on noise floor.
556      *
557      */
558     uint8_t ComputeLinkMargin(int8_t aRss) const;
559 
560     /**
561      * Returns the current CCA (Clear Channel Assessment) failure rate.
562      *
563      * The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW`
564      * frame transmissions.
565      *
566      * @returns The CCA failure rate with maximum value `0xffff` corresponding to 100% failure rate.
567      *
568      */
GetCcaFailureRate(void) const569     uint16_t GetCcaFailureRate(void) const { return mCcaSuccessRateTracker.GetFailureRate(); }
570 
571     /**
572      * Starts/Stops the Link layer. It may only be used when the Netif Interface is down.
573      *
574      * @param[in]  aEnable The requested State for the MAC layer. true - Start, false - Stop.
575      *
576      */
577     void SetEnabled(bool aEnable);
578 
579     /**
580      * Indicates whether or not the link layer is enabled.
581      *
582      * @retval true   Link layer is enabled.
583      * @retval false  Link layer is not enabled.
584      *
585      */
IsEnabled(void) const586     bool IsEnabled(void) const { return mEnabled; }
587 
588     /**
589      * Clears the Mode2Key stored in PSA ITS.
590      *
591      */
ClearMode2Key(void)592     void ClearMode2Key(void) { mMode2KeyMaterial.Clear(); }
593 
594 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
595     /**
596      * Gets the CSL channel.
597      *
598      * @returns CSL channel.
599      *
600      */
GetCslChannel(void) const601     uint8_t GetCslChannel(void) const { return mCslChannel; }
602 
603     /**
604      * Sets the CSL channel.
605      *
606      * @param[in]  aChannel  The CSL channel.
607      *
608      */
609     void SetCslChannel(uint8_t aChannel);
610 
611     /**
612      * Centralizes CSL state switching conditions evaluating, configuring SubMac accordingly.
613      *
614      */
615     void UpdateCsl(void);
616 
617     /**
618      * Gets the CSL period.
619      *
620      * @returns CSL period in units of 10 symbols.
621      *
622      */
GetCslPeriod(void) const623     uint16_t GetCslPeriod(void) const { return mCslPeriod; }
624 
625     /**
626      * Gets the CSL period in milliseconds.
627      *
628      * If the CSL period cannot be represented exactly in milliseconds, return the rounded value to the nearest
629      * millisecond.
630      *
631      * @returns CSL period in milliseconds.
632      *
633      */
634     uint32_t GetCslPeriodInMsec(void) const;
635 
636     /**
637      * Sets the CSL period.
638      *
639      * @param[in]  aPeriod  The CSL period in 10 symbols.
640      *
641      */
642     void SetCslPeriod(uint16_t aPeriod);
643 
644     /**
645      * This method converts a given CSL period in units of 10 symbols to microseconds.
646      *
647      * @param[in] aPeriodInTenSymbols   The CSL period in unit of 10 symbols.
648      *
649      * @returns The converted CSL period value in microseconds corresponding to @p aPeriodInTenSymbols.
650      *
651      */
652     static uint32_t CslPeriodToUsec(uint16_t aPeriodInTenSymbols);
653 
654     /**
655      * Indicates whether CSL is started at the moment.
656      *
657      * @retval TRUE   If CSL is enabled.
658      * @retval FALSE  If CSL is not enabled.
659      *
660      */
661     bool IsCslEnabled(void) const;
662 
663     /**
664      * Indicates whether Link is capable of starting CSL.
665      *
666      * @retval TRUE   If Link is capable of starting CSL.
667      * @retval FALSE  If link is not capable of starting CSL.
668      *
669      */
670     bool IsCslCapable(void) const;
671 
672     /**
673      * Indicates whether the device is connected to a parent which supports CSL.
674      *
675      * @retval TRUE   If parent supports CSL.
676      * @retval FALSE  If parent does not support CSL.
677      *
678      */
679     bool IsCslSupported(void) const;
680 
681     /**
682      * Returns parent CSL accuracy (clock accuracy and uncertainty).
683      *
684      * @returns The parent CSL accuracy.
685      *
686      */
GetCslParentAccuracy(void) const687     const CslAccuracy &GetCslParentAccuracy(void) const { return mLinks.GetSubMac().GetCslParentAccuracy(); }
688 
689     /**
690      * Sets parent CSL accuracy.
691      *
692      * @param[in] aCslAccuracy  The parent CSL accuracy.
693      *
694      */
SetCslParentAccuracy(const CslAccuracy & aCslAccuracy)695     void SetCslParentAccuracy(const CslAccuracy &aCslAccuracy)
696     {
697         mLinks.GetSubMac().SetCslParentAccuracy(aCslAccuracy);
698     }
699 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
700 
701 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
702     /**
703      * Enables/disables the 802.15.4 radio filter.
704      *
705      * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any
706      * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the
707      * frame over the air (return "no ack" error if ack is requested, otherwise return success).
708      *
709      * @param[in] aFilterEnabled    TRUE to enable radio filter, FALSE to disable.
710      *
711      */
712     void SetRadioFilterEnabled(bool aFilterEnabled);
713 
714     /**
715      * Indicates whether the 802.15.4 radio filter is enabled or not.
716      *
717      * @retval TRUE   If the radio filter is enabled.
718      * @retval FALSE  If the radio filter is disabled.
719      *
720      */
IsRadioFilterEnabled(void) const721     bool IsRadioFilterEnabled(void) const { return mLinks.GetSubMac().IsRadioFilterEnabled(); }
722 #endif
723 
724     /**
725      * Sets the region code.
726      *
727      * The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
728      *
729      * @param[in]  aRegionCode  The radio region code. The `aRegionCode >> 8` is first ascii char
730      *                          and the `aRegionCode & 0xff` is the second ascii char.
731      *
732      * @retval  kErrorFailed          Other platform specific errors.
733      * @retval  kErrorNone            Successfully set region code.
734      * @retval  kErrorNotImplemented  The feature is not implemented.
735      *
736      */
737     Error SetRegion(uint16_t aRegionCode);
738 
739     /**
740      * Get the region code.
741      *
742      * The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
743      *
744      * @param[out] aRegionCode  The radio region code. The `aRegionCode >> 8` is first ascii char
745      *                          and the `aRegionCode & 0xff` is the second ascii char.
746      *
747      * @retval  kErrorFailed          Other platform specific errors.
748      * @retval  kErrorNone            Successfully set region code.
749      * @retval  kErrorNotImplemented  The feature is not implemented.
750      *
751      */
752     Error GetRegion(uint16_t &aRegionCode) const;
753 
754 private:
755     static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW;
756 
757     enum Operation : uint8_t
758     {
759         kOperationIdle = 0,
760         kOperationActiveScan,
761         kOperationEnergyScan,
762         kOperationTransmitBeacon,
763         kOperationTransmitDataDirect,
764         kOperationTransmitPoll,
765         kOperationWaitingForData,
766 #if OPENTHREAD_FTD
767         kOperationTransmitDataIndirect,
768 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
769         kOperationTransmitDataCsl,
770 #endif
771 #endif
772     };
773 
774 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
775     struct RetryHistogram
776     {
777         /**
778          * Histogram of number of retries for a single direct packet until success
779          * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ...
780          *  until max retry limit: packet count]
781          *
782          *  The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT.
783          */
784         uint32_t mTxDirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT];
785 
786         /**
787          * Histogram of number of retries for a single indirect packet until success
788          * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ...
789          *  until max retry limit: packet count]
790          *
791          *  The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT.
792          */
793         uint32_t mTxIndirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT];
794     };
795 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
796 
797     Error ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor);
798     void  ProcessTransmitSecurity(TxFrame &aFrame);
799 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
800     Error ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame);
801 #endif
802 
803     void     UpdateIdleMode(void);
IsPending(Operation aOperation) const804     bool     IsPending(Operation aOperation) const { return mPendingOperations & (1U << aOperation); }
805     bool     IsActiveOrPending(Operation aOperation) const;
SetPending(Operation aOperation)806     void     SetPending(Operation aOperation) { mPendingOperations |= (1U << aOperation); }
ClearPending(Operation aOperation)807     void     ClearPending(Operation aOperation) { mPendingOperations &= ~(1U << aOperation); }
808     void     StartOperation(Operation aOperation);
809     void     FinishOperation(void);
810     void     PerformNextOperation(void);
811     TxFrame *PrepareBeaconRequest(void);
812     TxFrame *PrepareBeacon(void);
813     bool     ShouldSendBeacon(void) const;
814     bool     IsJoinable(void) const;
815     void     BeginTransmit(void);
816     void     UpdateNeighborLinkInfo(Neighbor &aNeighbor, const RxFrame &aRxFrame);
817     bool     HandleMacCommand(RxFrame &aFrame);
818     void     HandleTimer(void);
819 
820     void  Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration);
821     Error UpdateScanChannel(void);
822     void  PerformActiveScan(void);
823     void  ReportActiveScanResult(const RxFrame *aBeaconFrame);
824     Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
825     void  PerformEnergyScan(void);
826     void  ReportEnergyScanResult(int8_t aRssi);
827 
828     void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const;
829     void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const;
830     void LogBeacon(const char *aActionText) const;
831 
832 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
833     uint8_t GetTimeIeOffset(const Frame &aFrame);
834 #endif
835 
836 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
837     void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr);
838 #endif
839 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
840     void ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor);
841 #endif
842     static const char *OperationToString(Operation aOperation);
843 
844     using OperationTask = TaskletIn<Mac, &Mac::PerformNextOperation>;
845     using MacTimer      = TimerMilliIn<Mac, &Mac::HandleTimer>;
846 
847     static const otExtAddress sMode2ExtAddress;
848 
849     bool mEnabled : 1;
850     bool mShouldTxPollBeforeData : 1;
851     bool mRxOnWhenIdle : 1;
852     bool mPromiscuous : 1;
853     bool mBeaconsEnabled : 1;
854     bool mUsingTemporaryChannel : 1;
855 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS
856     bool mShouldDelaySleep : 1;
857     bool mDelayingSleep : 1;
858 #endif
859     Operation   mOperation;
860     uint16_t    mPendingOperations;
861     uint8_t     mBeaconSequence;
862     uint8_t     mDataSequence;
863     uint8_t     mBroadcastTransmitCount;
864     PanId       mPanId;
865     uint8_t     mPanChannel;
866     uint8_t     mRadioChannel;
867     ChannelMask mSupportedChannelMask;
868     uint8_t     mScanChannel;
869     uint16_t    mScanDuration;
870     ChannelMask mScanChannelMask;
871     uint8_t     mMaxFrameRetriesDirect;
872 #if OPENTHREAD_FTD
873     uint8_t mMaxFrameRetriesIndirect;
874 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
875     TimeMilli mCslTxFireTime;
876 #endif
877 #endif
878 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
879     // When Mac::mCslChannel is 0, it indicates that CSL channel has not been specified by the upper layer.
880     uint8_t  mCslChannel;
881     uint16_t mCslPeriod;
882 #endif
883 
884     union
885     {
886         ActiveScanHandler mActiveScanHandler;
887         EnergyScanHandler mEnergyScanHandler;
888     };
889 
890     void *mScanHandlerContext;
891 
892     Links              mLinks;
893     OperationTask      mOperationTask;
894     MacTimer           mTimer;
895     otMacCounters      mCounters;
896     uint32_t           mKeyIdMode2FrameCounter;
897     SuccessRateTracker mCcaSuccessRateTracker;
898     uint16_t           mCcaSampleCount;
899 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
900     RetryHistogram mRetryHistogram;
901 #endif
902 
903 #if OPENTHREAD_CONFIG_MULTI_RADIO
904     RadioTypes mTxPendingRadioLinks;
905     RadioTypes mTxBeaconRadioLinks;
906     Error      mTxError;
907 #endif
908 
909 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
910     Filter mFilter;
911 #endif
912 
913     KeyMaterial mMode2KeyMaterial;
914 };
915 
916 /**
917  * @}
918  *
919  */
920 
921 } // namespace Mac
922 } // namespace ot
923 
924 #endif // MAC_HPP_
925