866 lines
30 KiB
C++
866 lines
30 KiB
C++
/*
|
|
* Copyright (c) 2016, The OpenThread Authors.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the copyright holder nor the
|
|
* names of its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* This file includes definitions for the IEEE 802.15.4 MAC.
|
|
*/
|
|
|
|
#ifndef MAC_HPP_
|
|
#define MAC_HPP_
|
|
|
|
#include "openthread-core-config.h"
|
|
|
|
#include <openthread/platform/radio.h>
|
|
#include <openthread/platform/time.h>
|
|
|
|
#include "common/locator.hpp"
|
|
#include "common/log.hpp"
|
|
#include "common/non_copyable.hpp"
|
|
#include "common/tasklet.hpp"
|
|
#include "common/time.hpp"
|
|
#include "common/timer.hpp"
|
|
#include "mac/channel_mask.hpp"
|
|
#include "mac/mac_filter.hpp"
|
|
#include "mac/mac_frame.hpp"
|
|
#include "mac/mac_links.hpp"
|
|
#include "mac/mac_types.hpp"
|
|
#include "mac/sub_mac.hpp"
|
|
#include "radio/trel_link.hpp"
|
|
#include "thread/key_manager.hpp"
|
|
#include "thread/link_quality.hpp"
|
|
|
|
namespace ot {
|
|
|
|
class Neighbor;
|
|
|
|
/**
|
|
* @addtogroup core-mac
|
|
*
|
|
* @brief
|
|
* This module includes definitions for the IEEE 802.15.4 MAC
|
|
*
|
|
* @{
|
|
*
|
|
*/
|
|
|
|
namespace Mac {
|
|
|
|
constexpr uint32_t kDataPollTimeout = 100; ///< Timeout for receiving Data Frame (in msec).
|
|
constexpr uint32_t kSleepDelay = 300; ///< Max sleep delay when frame is pending (in msec).
|
|
|
|
constexpr uint16_t kScanDurationDefault = OPENTHREAD_CONFIG_MAC_SCAN_DURATION; ///< Duration per channel (in msec).
|
|
|
|
constexpr uint8_t kMaxCsmaBackoffsDirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT;
|
|
constexpr uint8_t kMaxCsmaBackoffsIndirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_INDIRECT;
|
|
constexpr uint8_t kMaxCsmaBackoffsCsl = 0;
|
|
|
|
constexpr uint8_t kDefaultMaxFrameRetriesDirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT;
|
|
constexpr uint8_t kDefaultMaxFrameRetriesIndirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT;
|
|
constexpr uint8_t kMaxFrameRetriesCsl = 0;
|
|
|
|
constexpr uint8_t kTxNumBcast = OPENTHREAD_CONFIG_MAC_TX_NUM_BCAST; ///< Num of times broadcast frame is tx.
|
|
|
|
/**
|
|
* This type defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan.
|
|
*
|
|
*/
|
|
typedef otHandleActiveScanResult ActiveScanHandler;
|
|
|
|
/**
|
|
* This type defines an Active Scan result.
|
|
*
|
|
*/
|
|
typedef otActiveScanResult ActiveScanResult;
|
|
|
|
/**
|
|
* This type defines the function pointer which is called during an Energy Scan when the scan result for a channel is
|
|
* ready or when the scan completes.
|
|
*
|
|
*/
|
|
typedef otHandleEnergyScanResult EnergyScanHandler;
|
|
|
|
/**
|
|
* This type defines an Energy Scan result.
|
|
*
|
|
*/
|
|
typedef otEnergyScanResult EnergyScanResult;
|
|
|
|
/**
|
|
* This class implements the IEEE 802.15.4 MAC.
|
|
*
|
|
*/
|
|
class Mac : public InstanceLocator, private NonCopyable
|
|
{
|
|
friend class ot::Instance;
|
|
|
|
public:
|
|
/**
|
|
* This constructor initializes the MAC object.
|
|
*
|
|
* @param[in] aInstance A reference to the OpenThread instance.
|
|
*
|
|
*/
|
|
explicit Mac(Instance &aInstance);
|
|
|
|
/**
|
|
* This method starts an IEEE 802.15.4 Active Scan.
|
|
*
|
|
* @param[in] aScanChannels A bit vector indicating which channels to scan. Zero is mapped to all channels.
|
|
* @param[in] aScanDuration The time in milliseconds to spend scanning each channel. Zero duration maps to
|
|
* default value `kScanDurationDefault` = 300 ms.
|
|
* @param[in] aHandler A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon.
|
|
* @param[in] aContext A pointer to an arbitrary context (used when invoking `aHandler` callback).
|
|
*
|
|
* @retval kErrorNone Successfully scheduled the Active Scan request.
|
|
* @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled).
|
|
*
|
|
*/
|
|
Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
|
|
|
|
/**
|
|
* This method starts an IEEE 802.15.4 Energy Scan.
|
|
*
|
|
* @param[in] aScanChannels A bit vector indicating on which channels to scan. Zero is mapped to all channels.
|
|
* @param[in] aScanDuration The time in milliseconds to spend scanning each channel. If the duration is set to
|
|
* zero, a single RSSI sample will be taken per channel.
|
|
* @param[in] aHandler A pointer to a function called to pass on scan result or indicate scan completion.
|
|
* @param[in] aContext A pointer to an arbitrary context (used when invoking @p aHandler callback).
|
|
*
|
|
* @retval kErrorNone Accepted the Energy Scan request.
|
|
* @retval kErrorBusy Could not start the energy scan.
|
|
*
|
|
*/
|
|
Error EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext);
|
|
|
|
/**
|
|
* This method indicates the energy scan for the current channel is complete.
|
|
*
|
|
* @param[in] aEnergyScanMaxRssi The maximum RSSI encountered on the scanned channel.
|
|
*
|
|
*/
|
|
void EnergyScanDone(int8_t aEnergyScanMaxRssi);
|
|
|
|
/**
|
|
* This method indicates whether or not IEEE 802.15.4 Beacon transmissions are enabled.
|
|
*
|
|
* @retval TRUE If IEEE 802.15.4 Beacon transmissions are enabled.
|
|
* @retval FALSE If IEEE 802.15.4 Beacon transmissions are not enabled.
|
|
*
|
|
*/
|
|
bool IsBeaconEnabled(void) const { return mBeaconsEnabled; }
|
|
|
|
/**
|
|
* This method enables/disables IEEE 802.15.4 Beacon transmissions.
|
|
*
|
|
* @param[in] aEnabled TRUE to enable IEEE 802.15.4 Beacon transmissions, FALSE otherwise.
|
|
*
|
|
*/
|
|
void SetBeaconEnabled(bool aEnabled) { mBeaconsEnabled = aEnabled; }
|
|
|
|
/**
|
|
* This method indicates whether or not rx-on-when-idle is enabled.
|
|
*
|
|
* @retval TRUE If rx-on-when-idle is enabled.
|
|
* @retval FALSE If rx-on-when-idle is not enabled.
|
|
*/
|
|
bool GetRxOnWhenIdle(void) const { return mRxOnWhenIdle; }
|
|
|
|
/**
|
|
* This method sets the rx-on-when-idle mode.
|
|
*
|
|
* @param[in] aRxOnWhenIdle The rx-on-when-idle mode.
|
|
*
|
|
*/
|
|
void SetRxOnWhenIdle(bool aRxOnWhenIdle);
|
|
|
|
/**
|
|
* This method requests a direct data frame transmission.
|
|
*
|
|
*/
|
|
void RequestDirectFrameTransmission(void);
|
|
|
|
#if OPENTHREAD_FTD
|
|
/**
|
|
* This method requests an indirect data frame transmission.
|
|
*
|
|
*/
|
|
void RequestIndirectFrameTransmission(void);
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
|
/**
|
|
* This method requests `Mac` to start a CSL tx operation after a delay of @p aDelay time.
|
|
*
|
|
* @param[in] aDelay Delay time for `Mac` to start a CSL tx, in units of milliseconds.
|
|
*
|
|
*/
|
|
void RequestCslFrameTransmission(uint32_t aDelay);
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/**
|
|
* This method requests transmission of a data poll (MAC Data Request) frame.
|
|
*
|
|
* @retval kErrorNone Data poll transmission request is scheduled successfully.
|
|
* @retval kErrorInvalidState The MAC layer is not enabled.
|
|
*
|
|
*/
|
|
Error RequestDataPollTransmission(void);
|
|
|
|
/**
|
|
* This method returns a reference to the IEEE 802.15.4 Extended Address.
|
|
*
|
|
* @returns A pointer to the IEEE 802.15.4 Extended Address.
|
|
*
|
|
*/
|
|
const ExtAddress &GetExtAddress(void) const { return mLinks.GetExtAddress(); }
|
|
|
|
/**
|
|
* This method sets the IEEE 802.15.4 Extended Address.
|
|
*
|
|
* @param[in] aExtAddress A reference to the IEEE 802.15.4 Extended Address.
|
|
*
|
|
*/
|
|
void SetExtAddress(const ExtAddress &aExtAddress) { mLinks.SetExtAddress(aExtAddress); }
|
|
|
|
/**
|
|
* This method returns the IEEE 802.15.4 Short Address.
|
|
*
|
|
* @returns The IEEE 802.15.4 Short Address.
|
|
*
|
|
*/
|
|
ShortAddress GetShortAddress(void) const { return mLinks.GetShortAddress(); }
|
|
|
|
/**
|
|
* This method sets the IEEE 802.15.4 Short Address.
|
|
*
|
|
* @param[in] aShortAddress The IEEE 802.15.4 Short Address.
|
|
*
|
|
*/
|
|
void SetShortAddress(ShortAddress aShortAddress) { mLinks.SetShortAddress(aShortAddress); }
|
|
|
|
/**
|
|
* This method returns the IEEE 802.15.4 PAN Channel.
|
|
*
|
|
* @returns The IEEE 802.15.4 PAN Channel.
|
|
*
|
|
*/
|
|
uint8_t GetPanChannel(void) const { return mPanChannel; }
|
|
|
|
/**
|
|
* This method sets the IEEE 802.15.4 PAN Channel.
|
|
*
|
|
* @param[in] aChannel The IEEE 802.15.4 PAN Channel.
|
|
*
|
|
* @retval kErrorNone Successfully set the IEEE 802.15.4 PAN Channel.
|
|
* @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask.
|
|
*
|
|
*/
|
|
Error SetPanChannel(uint8_t aChannel);
|
|
|
|
/**
|
|
* This method sets the temporary IEEE 802.15.4 radio channel.
|
|
*
|
|
* This method allows user to temporarily change the radio channel and use a different channel (during receive)
|
|
* instead of the PAN channel (from `SetPanChannel()`). A call to `ClearTemporaryChannel()` would clear the
|
|
* temporary channel and adopt the PAN channel again. The `SetTemporaryChannel()` can be used multiple times in row
|
|
* (before a call to `ClearTemporaryChannel()`) to change the temporary channel.
|
|
*
|
|
* @param[in] aChannel A IEEE 802.15.4 channel.
|
|
*
|
|
* @retval kErrorNone Successfully set the temporary channel
|
|
* @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask.
|
|
*
|
|
*/
|
|
Error SetTemporaryChannel(uint8_t aChannel);
|
|
|
|
/**
|
|
* This method clears the use of a previously set temporary channel and adopts the PAN channel.
|
|
*
|
|
*/
|
|
void ClearTemporaryChannel(void);
|
|
|
|
/**
|
|
* This method returns the supported channel mask.
|
|
*
|
|
* @returns The supported channel mask.
|
|
*
|
|
*/
|
|
const ChannelMask &GetSupportedChannelMask(void) const { return mSupportedChannelMask; }
|
|
|
|
/**
|
|
* This method sets the supported channel mask
|
|
*
|
|
* @param[in] aMask The supported channel mask.
|
|
*
|
|
*/
|
|
void SetSupportedChannelMask(const ChannelMask &aMask);
|
|
|
|
/**
|
|
* This method returns the IEEE 802.15.4 PAN ID.
|
|
*
|
|
* @returns The IEEE 802.15.4 PAN ID.
|
|
*
|
|
*/
|
|
PanId GetPanId(void) const { return mPanId; }
|
|
|
|
/**
|
|
* This method sets the IEEE 802.15.4 PAN ID.
|
|
*
|
|
* @param[in] aPanId The IEEE 802.15.4 PAN ID.
|
|
*
|
|
*/
|
|
void SetPanId(PanId aPanId);
|
|
|
|
/**
|
|
* This method returns the maximum number of frame retries during direct transmission.
|
|
*
|
|
* @returns The maximum number of retries during direct transmission.
|
|
*
|
|
*/
|
|
uint8_t GetMaxFrameRetriesDirect(void) const { return mMaxFrameRetriesDirect; }
|
|
|
|
/**
|
|
* This method sets the maximum number of frame retries during direct transmission.
|
|
*
|
|
* @param[in] aMaxFrameRetriesDirect The maximum number of retries during direct transmission.
|
|
*
|
|
*/
|
|
void SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect) { mMaxFrameRetriesDirect = aMaxFrameRetriesDirect; }
|
|
|
|
#if OPENTHREAD_FTD
|
|
/**
|
|
* This method returns the maximum number of frame retries during indirect transmission.
|
|
*
|
|
* @returns The maximum number of retries during indirect transmission.
|
|
*
|
|
*/
|
|
uint8_t GetMaxFrameRetriesIndirect(void) const { return mMaxFrameRetriesIndirect; }
|
|
|
|
/**
|
|
* This method sets the maximum number of frame retries during indirect transmission.
|
|
*
|
|
* @param[in] aMaxFrameRetriesIndirect The maximum number of retries during indirect transmission.
|
|
*
|
|
*/
|
|
void SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect)
|
|
{
|
|
mMaxFrameRetriesIndirect = aMaxFrameRetriesIndirect;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* This method is called to handle a received frame.
|
|
*
|
|
* @param[in] aFrame A pointer to the received frame, or `nullptr` if the receive operation was aborted.
|
|
* @param[in] aError kErrorNone when successfully received a frame,
|
|
* kErrorAbort when reception was aborted and a frame was not received.
|
|
*
|
|
*/
|
|
void HandleReceivedFrame(RxFrame *aFrame, Error aError);
|
|
|
|
/**
|
|
* This method records CCA status (success/failure) for a frame transmission attempt.
|
|
*
|
|
* @param[in] aCcaSuccess TRUE if the CCA succeeded, FALSE otherwise.
|
|
* @param[in] aChannel The channel on which CCA was performed.
|
|
*
|
|
*/
|
|
void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel);
|
|
|
|
/**
|
|
* This method records the status of a frame transmission attempt, updating MAC counters.
|
|
*
|
|
* Unlike `HandleTransmitDone` which is called after all transmission attempts of frame to indicate final status
|
|
* of a frame transmission request, this method is invoked on all frame transmission attempts.
|
|
*
|
|
* @param[in] aFrame The transmitted frame.
|
|
* @param[in] aAckFrame A pointer to the ACK frame, or `nullptr` if no ACK was received.
|
|
* @param[in] aError kErrorNone when the frame was transmitted successfully,
|
|
* kErrorNoAck when the frame was transmitted but no ACK was received,
|
|
* kErrorChannelAccessFailure tx failed due to activity on the channel,
|
|
* kErrorAbort when transmission was aborted for other reasons.
|
|
* @param[in] aRetryCount Indicates number of transmission retries for this frame.
|
|
* @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only
|
|
* when there was an error in transmission (i.e., `aError` is not NONE).
|
|
*
|
|
*/
|
|
void RecordFrameTransmitStatus(const TxFrame &aFrame,
|
|
const RxFrame *aAckFrame,
|
|
Error aError,
|
|
uint8_t aRetryCount,
|
|
bool aWillRetx);
|
|
|
|
/**
|
|
* This method is called to handle transmit events.
|
|
*
|
|
* @param[in] aFrame The frame that was transmitted.
|
|
* @param[in] aAckFrame A pointer to the ACK frame, `nullptr` if no ACK was received.
|
|
* @param[in] aError kErrorNone when the frame was transmitted successfully,
|
|
* kErrorNoAck when the frame was transmitted but no ACK was received,
|
|
* kErrorChannelAccessFailure when the tx failed due to activity on the channel,
|
|
* kErrorAbort when transmission was aborted for other reasons.
|
|
*
|
|
*/
|
|
void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
|
|
|
|
/**
|
|
* This method returns if an active scan is in progress.
|
|
*
|
|
*/
|
|
bool IsActiveScanInProgress(void) const { return IsActiveOrPending(kOperationActiveScan); }
|
|
|
|
/**
|
|
* This method returns if an energy scan is in progress.
|
|
*
|
|
*/
|
|
bool IsEnergyScanInProgress(void) const { return IsActiveOrPending(kOperationEnergyScan); }
|
|
|
|
#if OPENTHREAD_FTD
|
|
/**
|
|
* This method indicates whether the MAC layer is performing an indirect transmission (in middle of a tx).
|
|
*
|
|
* @returns TRUE if in middle of an indirect transmission, FALSE otherwise.
|
|
*
|
|
*/
|
|
bool IsPerformingIndirectTransmit(void) const { return (mOperation == kOperationTransmitDataIndirect); }
|
|
#endif
|
|
|
|
/**
|
|
* This method returns if the MAC layer is in transmit state.
|
|
*
|
|
* The MAC layer is in transmit state during CSMA/CA, CCA, transmission of Data, Beacon or Data Request frames and
|
|
* receiving of ACK frames. The MAC layer is not in transmit state during transmission of ACK frames or Beacon
|
|
* Requests.
|
|
*
|
|
*/
|
|
bool IsInTransmitState(void) const;
|
|
|
|
/**
|
|
* This method registers a callback to provide received raw IEEE 802.15.4 frames.
|
|
*
|
|
* @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame
|
|
* or `nullptr` to disable the callback.
|
|
* @param[in] aCallbackContext A pointer to application-specific context.
|
|
*
|
|
*/
|
|
void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext)
|
|
{
|
|
mLinks.SetPcapCallback(aPcapCallback, aCallbackContext);
|
|
}
|
|
|
|
/**
|
|
* This method indicates whether or not promiscuous mode is enabled at the link layer.
|
|
*
|
|
* @retval true Promiscuous mode is enabled.
|
|
* @retval false Promiscuous mode is not enabled.
|
|
*
|
|
*/
|
|
bool IsPromiscuous(void) const { return mPromiscuous; }
|
|
|
|
/**
|
|
* This method enables or disables the link layer promiscuous mode.
|
|
*
|
|
* Promiscuous mode keeps the receiver enabled, overriding the value of mRxOnWhenIdle.
|
|
*
|
|
* @param[in] aPromiscuous true to enable promiscuous mode, or false otherwise.
|
|
*
|
|
*/
|
|
void SetPromiscuous(bool aPromiscuous);
|
|
|
|
/**
|
|
* This method resets mac counters
|
|
*
|
|
*/
|
|
void ResetCounters(void) { memset(&mCounters, 0, sizeof(mCounters)); }
|
|
|
|
/**
|
|
* This method returns the MAC counter.
|
|
*
|
|
* @returns A reference to the MAC counter.
|
|
*
|
|
*/
|
|
otMacCounters &GetCounters(void) { return mCounters; }
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
|
|
/**
|
|
* This method returns the MAC retry histogram for direct transmission.
|
|
*
|
|
* @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed.
|
|
*
|
|
* @returns A pointer to the histogram of retries (in a form of an array).
|
|
* The n-th element indicates that the packet has been sent with n-th retry.
|
|
*
|
|
*/
|
|
const uint32_t *GetDirectRetrySuccessHistogram(uint8_t &aNumberOfEntries);
|
|
|
|
#if OPENTHREAD_FTD
|
|
/**
|
|
* This method returns the MAC retry histogram for indirect transmission.
|
|
*
|
|
* @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed.
|
|
*
|
|
* @returns A pointer to the histogram of retries (in a form of an array).
|
|
* The n-th element indicates that the packet has been sent with n-th retry.
|
|
*
|
|
*/
|
|
const uint32_t *GetIndirectRetrySuccessHistogram(uint8_t &aNumberOfEntries);
|
|
#endif
|
|
|
|
/**
|
|
* This method resets MAC retry histogram.
|
|
*
|
|
*/
|
|
void ResetRetrySuccessHistogram(void);
|
|
#endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
|
|
|
|
/**
|
|
* This method returns the noise floor value (currently use the radio receive sensitivity value).
|
|
*
|
|
* @returns The noise floor value in dBm.
|
|
*
|
|
*/
|
|
int8_t GetNoiseFloor(void) { return mLinks.GetNoiseFloor(); }
|
|
|
|
/**
|
|
* This method returns the current CCA (Clear Channel Assessment) failure rate.
|
|
*
|
|
* The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW`
|
|
* frame transmissions.
|
|
*
|
|
* @returns The CCA failure rate with maximum value `0xffff` corresponding to 100% failure rate.
|
|
*
|
|
*/
|
|
uint16_t GetCcaFailureRate(void) const { return mCcaSuccessRateTracker.GetFailureRate(); }
|
|
|
|
/**
|
|
* This method Starts/Stops the Link layer. It may only be used when the Netif Interface is down.
|
|
*
|
|
* @param[in] aEnable The requested State for the MAC layer. true - Start, false - Stop.
|
|
*
|
|
*/
|
|
void SetEnabled(bool aEnable) { mEnabled = aEnable; }
|
|
|
|
/**
|
|
* This method indicates whether or not the link layer is enabled.
|
|
*
|
|
* @retval true Link layer is enabled.
|
|
* @retval false Link layer is not enabled.
|
|
*
|
|
*/
|
|
bool IsEnabled(void) const { return mEnabled; }
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
|
/**
|
|
* This method gets the CSL channel.
|
|
*
|
|
* @returns CSL channel.
|
|
*
|
|
*/
|
|
uint8_t GetCslChannel(void) const { return mLinks.GetSubMac().GetCslChannel(); }
|
|
|
|
/**
|
|
* This method sets the CSL channel.
|
|
*
|
|
* @param[in] aChannel The CSL channel.
|
|
*
|
|
*/
|
|
void SetCslChannel(uint8_t aChannel);
|
|
|
|
/**
|
|
* This method indicates if CSL channel has been explicitly specified by the upper layer.
|
|
*
|
|
* @returns If CSL channel has been specified.
|
|
*
|
|
*/
|
|
bool IsCslChannelSpecified(void) const { return mLinks.GetSubMac().IsCslChannelSpecified(); }
|
|
|
|
/**
|
|
* This method gets the CSL period.
|
|
*
|
|
* @returns CSL period in units of 10 symbols.
|
|
*
|
|
*/
|
|
uint16_t GetCslPeriod(void) const { return mLinks.GetSubMac().GetCslPeriod(); }
|
|
|
|
/**
|
|
* This method sets the CSL period.
|
|
*
|
|
* @param[in] aPeriod The CSL period in 10 symbols.
|
|
*
|
|
*/
|
|
void SetCslPeriod(uint16_t aPeriod);
|
|
|
|
/**
|
|
* This method indicates whether CSL is started at the moment.
|
|
*
|
|
* @retval TRUE If CSL is enabled.
|
|
* @retval FALSE If CSL is not enabled.
|
|
*
|
|
*/
|
|
bool IsCslEnabled(void) const;
|
|
|
|
/**
|
|
* This method indicates whether Link is capable of starting CSL.
|
|
*
|
|
* @retval TRUE If Link is capable of starting CSL.
|
|
* @retval FALSE If link is not capable of starting CSL.
|
|
*
|
|
*/
|
|
bool IsCslCapable(void) const;
|
|
|
|
/**
|
|
* This method returns CSL parent clock accuracy, in ± ppm.
|
|
*
|
|
* @retval CSL parent clock accuracy, in ± ppm.
|
|
*
|
|
*/
|
|
uint8_t GetCslParentClockAccuracy(void) const { return mLinks.GetSubMac().GetCslParentClockAccuracy(); }
|
|
|
|
/**
|
|
* This method sets CSL parent clock accuracy, in ± ppm.
|
|
*
|
|
* @param[in] aCslParentAccuracy CSL parent clock accuracy, in ± ppm.
|
|
*
|
|
*/
|
|
void SetCslParentClockAccuracy(uint8_t aCslParentAccuracy)
|
|
{
|
|
mLinks.GetSubMac().SetCslParentClockAccuracy(aCslParentAccuracy);
|
|
}
|
|
|
|
/**
|
|
* This method returns CSL parent uncertainty, in ±10 us units.
|
|
*
|
|
* @retval CSL parent uncertainty, in ±10 us units.
|
|
*
|
|
*/
|
|
uint8_t GetCslParentUncertainty(void) const { return mLinks.GetSubMac().GetCslParentUncertainty(); }
|
|
|
|
/**
|
|
* This method returns CSL parent uncertainty, in ±10 us units.
|
|
*
|
|
* @param[in] aCslParentUncert CSL parent uncertainty, in ±10 us units.
|
|
*
|
|
*/
|
|
void SetCslParentUncertainty(uint8_t aCslParentUncert)
|
|
{
|
|
mLinks.GetSubMac().SetCslParentUncertainty(aCslParentUncert);
|
|
}
|
|
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
|
|
/**
|
|
* This method enables/disables the 802.15.4 radio filter.
|
|
*
|
|
* When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any
|
|
* frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the
|
|
* frame over the air (return "no ack" error if ack is requested, otherwise return success).
|
|
*
|
|
* @param[in] aFilterEnabled TRUE to enable radio filter, FALSE to disable.
|
|
*
|
|
*/
|
|
void SetRadioFilterEnabled(bool aFilterEnabled);
|
|
|
|
/**
|
|
* This method indicates whether the 802.15.4 radio filter is enabled or not.
|
|
*
|
|
* @retval TRUE If the radio filter is enabled.
|
|
* @retval FALSE If the radio filter is disabled.
|
|
*
|
|
*/
|
|
bool IsRadioFilterEnabled(void) const { return mLinks.GetSubMac().IsRadioFilterEnabled(); }
|
|
#endif
|
|
|
|
private:
|
|
static constexpr int8_t kInvalidRssiValue = SubMac::kInvalidRssiValue;
|
|
static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW;
|
|
|
|
enum Operation : uint8_t
|
|
{
|
|
kOperationIdle = 0,
|
|
kOperationActiveScan,
|
|
kOperationEnergyScan,
|
|
kOperationTransmitBeacon,
|
|
kOperationTransmitDataDirect,
|
|
kOperationTransmitPoll,
|
|
kOperationWaitingForData,
|
|
#if OPENTHREAD_FTD
|
|
kOperationTransmitDataIndirect,
|
|
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
|
kOperationTransmitDataCsl,
|
|
#endif
|
|
#endif
|
|
};
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
|
|
struct RetryHistogram
|
|
{
|
|
/**
|
|
* Histogram of number of retries for a single direct packet until success
|
|
* [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ...
|
|
* until max retry limit: packet count]
|
|
*
|
|
* The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT.
|
|
*/
|
|
uint32_t mTxDirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT];
|
|
|
|
/**
|
|
* Histogram of number of retries for a single indirect packet until success
|
|
* [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ...
|
|
* until max retry limit: packet count]
|
|
*
|
|
* The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT.
|
|
*/
|
|
uint32_t mTxIndirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT];
|
|
};
|
|
#endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
|
|
|
|
Error ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor);
|
|
void ProcessTransmitSecurity(TxFrame &aFrame);
|
|
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
|
|
Error ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame);
|
|
#endif
|
|
|
|
void UpdateIdleMode(void);
|
|
bool IsPending(Operation aOperation) const { return mPendingOperations & (1U << aOperation); }
|
|
bool IsActiveOrPending(Operation aOperation) const;
|
|
void SetPending(Operation aOperation) { mPendingOperations |= (1U << aOperation); }
|
|
void ClearPending(Operation aOperation) { mPendingOperations &= ~(1U << aOperation); }
|
|
void StartOperation(Operation aOperation);
|
|
void FinishOperation(void);
|
|
void PerformNextOperation(void);
|
|
TxFrame *PrepareBeaconRequest(void);
|
|
TxFrame *PrepareBeacon(void);
|
|
bool ShouldSendBeacon(void) const;
|
|
bool IsJoinable(void) const;
|
|
void BeginTransmit(void);
|
|
bool HandleMacCommand(RxFrame &aFrame);
|
|
|
|
static void HandleTimer(Timer &aTimer);
|
|
void HandleTimer(void);
|
|
static void HandleOperationTask(Tasklet &aTasklet);
|
|
|
|
void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration);
|
|
Error UpdateScanChannel(void);
|
|
void PerformActiveScan(void);
|
|
void ReportActiveScanResult(const RxFrame *aBeaconFrame);
|
|
Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
|
|
void PerformEnergyScan(void);
|
|
void ReportEnergyScanResult(int8_t aRssi);
|
|
|
|
void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const;
|
|
void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const;
|
|
void LogBeacon(const char *aActionText) const;
|
|
|
|
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
|
uint8_t GetTimeIeOffset(const Frame &aFrame);
|
|
#endif
|
|
|
|
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
|
void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr);
|
|
#endif
|
|
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
|
void ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor);
|
|
#endif
|
|
static const char *OperationToString(Operation aOperation);
|
|
|
|
static const otExtAddress sMode2ExtAddress;
|
|
|
|
bool mEnabled : 1;
|
|
bool mShouldTxPollBeforeData : 1;
|
|
bool mRxOnWhenIdle : 1;
|
|
bool mPromiscuous : 1;
|
|
bool mBeaconsEnabled : 1;
|
|
bool mUsingTemporaryChannel : 1;
|
|
#if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS
|
|
bool mShouldDelaySleep : 1;
|
|
bool mDelayingSleep : 1;
|
|
#endif
|
|
Operation mOperation;
|
|
uint16_t mPendingOperations;
|
|
uint8_t mBeaconSequence;
|
|
uint8_t mDataSequence;
|
|
uint8_t mBroadcastTransmitCount;
|
|
PanId mPanId;
|
|
uint8_t mPanChannel;
|
|
uint8_t mRadioChannel;
|
|
ChannelMask mSupportedChannelMask;
|
|
uint8_t mScanChannel;
|
|
uint16_t mScanDuration;
|
|
ChannelMask mScanChannelMask;
|
|
uint8_t mMaxFrameRetriesDirect;
|
|
#if OPENTHREAD_FTD
|
|
uint8_t mMaxFrameRetriesIndirect;
|
|
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
|
TimeMilli mCslTxFireTime;
|
|
#endif
|
|
#endif
|
|
|
|
union
|
|
{
|
|
ActiveScanHandler mActiveScanHandler;
|
|
EnergyScanHandler mEnergyScanHandler;
|
|
};
|
|
|
|
void *mScanHandlerContext;
|
|
|
|
Links mLinks;
|
|
Tasklet mOperationTask;
|
|
TimerMilli mTimer;
|
|
otMacCounters mCounters;
|
|
uint32_t mKeyIdMode2FrameCounter;
|
|
SuccessRateTracker mCcaSuccessRateTracker;
|
|
uint16_t mCcaSampleCount;
|
|
#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
|
|
RetryHistogram mRetryHistogram;
|
|
#endif
|
|
|
|
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
|
RadioTypes mTxPendingRadioLinks;
|
|
RadioTypes mTxBeaconRadioLinks;
|
|
Error mTxError;
|
|
#endif
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
|
|
Filter mFilter;
|
|
#endif
|
|
|
|
KeyMaterial mMode2KeyMaterial;
|
|
};
|
|
|
|
/**
|
|
* @}
|
|
*
|
|
*/
|
|
|
|
} // namespace Mac
|
|
} // namespace ot
|
|
|
|
#endif // MAC_HPP_
|