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