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