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