| /* |
| * 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/tasklet.hpp" |
| #include "common/timer.hpp" |
| #include "mac/mac_filter.hpp" |
| #include "mac/mac_frame.hpp" |
| #include "thread/key_manager.hpp" |
| #include "thread/link_quality.hpp" |
| #include "thread/network_diagnostic_tlvs.hpp" |
| #include "thread/topology.hpp" |
| |
| namespace ot { |
| |
| /** |
| * @addtogroup core-mac |
| * |
| * @brief |
| * This module includes definitions for the IEEE 802.15.4 MAC |
| * |
| * @{ |
| * |
| */ |
| |
| namespace Mac { |
| |
| /** |
| * Protocol parameters and constants. |
| * |
| */ |
| enum |
| { |
| kMinBE = 3, ///< macMinBE (IEEE 802.15.4-2006). |
| kMaxBE = 5, ///< macMaxBE (IEEE 802.15.4-2006). |
| kMaxCSMABackoffs = 4, ///< macMaxCSMABackoffs (IEEE 802.15.4-2006). |
| kUnitBackoffPeriod = 20, ///< Number of symbols (IEEE 802.15.4-2006). |
| |
| kMinBackoff = 1, ///< Minimum backoff (milliseconds). |
| |
| kAckTimeout = 16, ///< Timeout for waiting on an ACK (milliseconds). |
| kDataPollTimeout = 100, ///< Timeout for receiving Data Frame (milliseconds). |
| kSleepDelay = 300, ///< Max sleep delay when frame is pending (milliseconds). |
| kNonceSize = 13, ///< Size of IEEE 802.15.4 Nonce (bytes). |
| |
| kScanChannelsAll = OT_CHANNEL_ALL, ///< All channels. |
| kScanDurationDefault = 300, ///< Default interval between channels (milliseconds). |
| |
| /** |
| * Maximum number of MAC layer tx attempts for an outbound direct frame. |
| * |
| */ |
| kDirectFrameMacTxAttempts = OPENTHREAD_CONFIG_MAX_TX_ATTEMPTS_DIRECT, |
| |
| /** |
| * Maximum number of MAC layer tx attempts for an outbound indirect frame (for a sleepy child) after receiving |
| * a data request command (data poll) from the child. |
| * |
| */ |
| kIndirectFrameMacTxAttempts = OPENTHREAD_CONFIG_MAX_TX_ATTEMPTS_INDIRECT_PER_POLL, |
| }; |
| |
| /** |
| * This class defines a channel mask. |
| * |
| * It is a wrapper class around a `uint32_t` bit vector representing a set of channels. |
| * |
| */ |
| class ChannelMask |
| { |
| public: |
| enum |
| { |
| kChannelIteratorFirst = 0xff, ///< Value to pass in `GetNextChannel()` to get the first channel in the mask. |
| kInfoStringSize = 45, ///< Recommended buffer size to use with `ToString()`. |
| }; |
| |
| /** |
| * This type defines the fixed-length `String` object returned from `ToString()`. |
| * |
| */ |
| typedef String<kInfoStringSize> InfoString; |
| |
| /** |
| * This constructor initializes a `ChannelMask` instance. |
| * |
| */ |
| ChannelMask(void) |
| : mMask(0) |
| { |
| } |
| |
| /** |
| * This constructor initializes a `ChannelMask` instance with a given mask. |
| * |
| * @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). |
| * |
| */ |
| ChannelMask(uint32_t aMask) |
| : mMask(aMask) |
| { |
| } |
| |
| /** |
| * This method clears the channel mask. |
| * |
| */ |
| void Clear(void) { mMask = 0; } |
| |
| /** |
| * This method gets the channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). |
| * |
| * @returns The channel mask. |
| * |
| */ |
| uint32_t GetMask(void) const { return mMask; } |
| |
| /** |
| * This method sets the channel mask. |
| * |
| * @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). |
| * |
| */ |
| void SetMask(uint32_t aMask) { mMask = aMask; } |
| |
| /** |
| * This method indicates if the mask is empty. |
| * |
| * @returns TRUE if the mask is empty, FALSE otherwise. |
| * |
| */ |
| bool IsEmpty(void) const { return (mMask == 0); } |
| |
| /** |
| * This method indicates if the mask contains only a single channel. |
| * |
| * @returns TRUE if channel mask contains a single channel, FALSE otherwise |
| * |
| */ |
| bool IsSingleChannel(void) const { return ((mMask != 0) && ((mMask & (mMask - 1)) == 0)); } |
| |
| /** |
| * This method indicates if the mask contains a given channel. |
| * |
| * @param[in] aChannel A channel. |
| * |
| * @returns TRUE if the channel @p aChannel is included in the mask, FALSE otherwise. |
| * |
| */ |
| bool ContainsChannel(uint8_t aChannel) const { return ((1U << aChannel) & mMask) != 0; } |
| |
| /** |
| * This method adds a channel to the channel mask. |
| * |
| * @param[in] aChannel A channel |
| * |
| */ |
| void AddChannel(uint8_t aChannel) { mMask |= (1U << aChannel); } |
| |
| /** |
| * This method removes a channel from the channel mask. |
| * |
| * @param[in] aChannel A channel |
| * |
| */ |
| void RemoveChannel(uint8_t aChannel) { mMask &= ~(1U << aChannel); } |
| |
| /** |
| * This method updates the channel mask by intersecting it with another mask. |
| * |
| * @param[in] aOtherMask Another channel mask. |
| * |
| */ |
| void Intersect(const ChannelMask &aOtherMask) { mMask &= aOtherMask.mMask; } |
| |
| /** |
| * This method returns the number of channels in the mask. |
| * |
| * @returns Number of channels in the mask. |
| * |
| */ |
| uint8_t GetNumberOfChannels(void) const; |
| |
| /** |
| * This method gets the next channel in the channel mask. |
| * |
| * This method can be used to iterate over all channels in the channel mask. To get the first channel (channel with |
| * lowest number) in the mask the @p aChannel should be set to `kChannelIteratorFirst`. |
| * |
| * @param[inout] aChannel A reference to a `uint8_t`. |
| * On entry it should contain the previous channel or `kChannelIteratorFirst`. |
| * On exit it contains the next channel. |
| * |
| * @retval OT_ERROR_NONE Got the next channel, @p aChannel updated successfully. |
| * @retval OT_ERROR_NOT_FOUND No next channel in the channel mask (note: @p aChannel may be changed). |
| * |
| */ |
| otError GetNextChannel(uint8_t &aChannel) const; |
| |
| /** |
| * This method overloads `==` operator to indicate whether two masks are equal. |
| * |
| * @param[in] aAnother A reference to another mask to compare with the current one. |
| * |
| * @returns TRUE if the two masks are equal, FALSE otherwise. |
| * |
| */ |
| bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); } |
| |
| /** |
| * This method overloads `!=` operator to indicate whether two masks are different. |
| * |
| * @param[in] aAnother A reference to another mask to compare with the current one. |
| * |
| * @returns TRUE if the two masks are different, FALSE otherwise. |
| * |
| */ |
| bool operator!=(const ChannelMask &aAnother) const { return (mMask != aAnother.mMask); } |
| |
| /** |
| * This method converts the channel mask into a human-readable string. |
| * |
| * Examples of possible output: |
| * - empty mask -> "{ }" |
| * - all channels -> "{ 11-26 }" |
| * - single channel -> "{ 20 }" |
| * - multiple ranges -> "{ 11, 14-17, 20-22, 24, 25 }" |
| * - no range -> "{ 14, 21, 26 }" |
| * |
| * @returns An `InfoString` object representing the channel mask. |
| * |
| */ |
| InfoString ToString(void) const; |
| |
| private: |
| #if (OT_RADIO_CHANNEL_MIN >= 32) || (OT_RADIO_CHANNEL_MAX >= 32) |
| #error `OT_RADIO_CHANNEL_MAX` or `OT_RADIO_CHANNEL_MIN` are larger than 32. `ChannelMask` uses 32 bit mask. |
| #endif |
| |
| uint32_t mMask; |
| }; |
| |
| /** |
| * This class implements a MAC receiver client. |
| * |
| */ |
| class Receiver : public OwnerLocator |
| { |
| friend class Mac; |
| |
| public: |
| /** |
| * This function pointer is called when a MAC frame is received. |
| * |
| * @param[in] aReceiver A reference to the MAC receiver client object. |
| * @param[in] aFrame A reference to the MAC frame. |
| * |
| */ |
| typedef void (*ReceiveFrameHandler)(Receiver &aReceiver, Frame &aFrame); |
| |
| /** |
| * This function pointer is called on a data request command (data poll) timeout, i.e., when the ack in response to |
| * a data request command indicated a frame is pending, but no frame was received after `kDataPollTimeout` interval. |
| * |
| * @param[in] aReceiver A reference to the MAC receiver client object. |
| * |
| */ |
| typedef void (*DataPollTimeoutHandler)(Receiver &aReceiver); |
| |
| /** |
| * This constructor creates a MAC receiver client. |
| * |
| * @param[in] aReceiveFrameHandler A pointer to a function that is called on MAC frame reception. |
| * @param[in] aPollTimeoutHandler A pointer to a function called on data poll timeout (may be set to NULL). |
| * @param[in] aOwner A pointer to owner of this object. |
| * |
| */ |
| Receiver(ReceiveFrameHandler aReceiveFrameHandler, DataPollTimeoutHandler aPollTimeoutHandler, void *aOwner) |
| : OwnerLocator(aOwner) |
| , mReceiveFrameHandler(aReceiveFrameHandler) |
| , mPollTimeoutHandler(aPollTimeoutHandler) |
| , mNext(NULL) |
| { |
| } |
| |
| private: |
| void HandleReceivedFrame(Frame &aFrame) { mReceiveFrameHandler(*this, aFrame); } |
| |
| void HandleDataPollTimeout(void) |
| { |
| if (mPollTimeoutHandler != NULL) |
| { |
| mPollTimeoutHandler(*this); |
| } |
| } |
| |
| ReceiveFrameHandler mReceiveFrameHandler; |
| DataPollTimeoutHandler mPollTimeoutHandler; |
| Receiver * mNext; |
| }; |
| |
| /** |
| * This class implements a MAC sender client. |
| * |
| */ |
| class Sender : public OwnerLocator |
| { |
| friend class Mac; |
| |
| public: |
| /** |
| * This function pointer is called when the MAC is about to transmit the frame asking MAC sender client to provide |
| * the frame. |
| * |
| * @param[in] aSender A reference to the MAC sender client object. |
| * @param[in] aFrame A reference to the MAC frame buffer. |
| * |
| */ |
| typedef otError (*FrameRequestHandler)(Sender &aSender, Frame &aFrame); |
| |
| /** |
| * This function pointer is called when the MAC is done sending the frame. |
| * |
| * @param[in] aSender A reference to the MAC sender client object. |
| * @param[in] aFrame A reference to the MAC frame buffer that was sent. |
| * @param[in] aError The status of the last MSDU transmission. |
| * |
| */ |
| typedef void (*SentFrameHandler)(Sender &aSender, Frame &aFrame, otError aError); |
| |
| /** |
| * This constructor creates a MAC sender client. |
| * |
| * @param[in] aFrameRequestHandler A pointer to a function that is called when about to send a MAC frame. |
| * @param[in] aSentFrameHandler A pointer to a function that is called when done sending the frame. |
| * @param[in] aOwner A pointer to owner of this object. |
| * |
| */ |
| Sender(FrameRequestHandler aFrameRequestHandler, SentFrameHandler aSentFrameHandler, void *aOwner) |
| : OwnerLocator(aOwner) |
| , mFrameRequestHandler(aFrameRequestHandler) |
| , mSentFrameHandler(aSentFrameHandler) |
| , mNext(NULL) |
| { |
| } |
| |
| private: |
| otError HandleFrameRequest(Frame &aFrame) { return mFrameRequestHandler(*this, aFrame); } |
| void HandleSentFrame(Frame &aFrame, otError aError) { mSentFrameHandler(*this, aFrame, aError); } |
| |
| FrameRequestHandler mFrameRequestHandler; |
| SentFrameHandler mSentFrameHandler; |
| Sender * mNext; |
| }; |
| |
| /** |
| * This class implements the IEEE 802.15.4 MAC. |
| * |
| */ |
| class Mac : public InstanceLocator |
| { |
| public: |
| /** |
| * This constructor initializes the MAC object. |
| * |
| * @param[in] aInstance A reference to the OpenThread instance. |
| * |
| */ |
| explicit Mac(Instance &aInstance); |
| |
| /** |
| * This function pointer is called on receiving an IEEE 802.15.4 Beacon during an Active Scan. |
| * |
| * @param[in] aContext A pointer to arbitrary context information. |
| * @param[in] aBeaconFrame A pointer to the Beacon frame or NULL to indicate end of Active Scan operation. |
| * |
| */ |
| typedef void (*ActiveScanHandler)(void *aContext, Frame *aBeaconFrame); |
| |
| /** |
| * 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 arbitrary context information. |
| * |
| * @retval OT_ERROR_NONE Successfully scheduled the Active Scan request. |
| * @retval OT_ERROR_BUSY Could not schedule the scan (a scan is ongoing or scheduled). |
| * |
| */ |
| otError ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext); |
| |
| /** |
| * This method converts a beacon frame to an active scan result of type `otActiveScanResult`. |
| * |
| * @param[in] aBeaconFrame A pointer to a beacon frame. |
| * @param[out] aResult A reference to `otActiveScanResult` where the result is stored. |
| * |
| * @retval OT_ERROR_NONE Successfully converted the beacon into active scan result. |
| * @retval OT_ERROR_INVALID_ARGS The @a aBeaconFrame was NULL. |
| * @retval OT_ERROR_PARSE Failed parsing the beacon frame. |
| * |
| */ |
| otError ConvertBeaconToActiveScanResult(Frame *aBeaconFrame, otActiveScanResult &aResult); |
| |
| /** |
| * This function pointer is called during an Energy Scan when the result for a channel is ready or the scan |
| * completes. |
| * |
| * @param[in] aContext A pointer to arbitrary context information. |
| * @param[in] aResult A valid pointer to the energy scan result information or NULL when the energy scan |
| * completes. |
| * |
| */ |
| typedef void (*EnergyScanHandler)(void *aContext, otEnergyScanResult *aResult); |
| |
| /** |
| * 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 arbitrary context information. |
| * |
| * @retval OT_ERROR_NONE Accepted the Energy Scan request. |
| * @retval OT_ERROR_BUSY Could not start the energy scan. |
| * |
| */ |
| otError 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, FALSE otherwise. |
| * |
| */ |
| 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 registers a new MAC receiver client. |
| * |
| * @param[in] aReceiver A reference to the MAC receiver client. |
| * |
| * @retval OT_ERROR_NONE Successfully registered the receiver. |
| * @retval OT_ERROR_ALREADY The receiver was already registered. |
| * |
| */ |
| otError RegisterReceiver(Receiver &aReceiver); |
| |
| /** |
| * This method registers a new MAC sender client. |
| * |
| * @param[in] aSender A reference to the MAC sender client. |
| * |
| * @retval OT_ERROR_NONE Successfully registered the sender. |
| * @retval OT_ERROR_ALREADY The sender was already registered. |
| * |
| */ |
| otError SendFrameRequest(Sender &aSender); |
| |
| /** |
| * This method registers a Out of Band frame for MAC Transmission. |
| * An Out of Band frame is one that was generated outside of OpenThread. |
| * |
| * @param[in] aOobFrame A pointer to the frame. |
| * |
| * @retval OT_ERROR_NONE Successfully registered the frame. |
| * @retval OT_ERROR_ALREADY MAC layer is busy sending a previously registered frame. |
| * |
| */ |
| otError SendOutOfBandFrameRequest(otRadioFrame *aOobFrame); |
| |
| /** |
| * This method generates a random IEEE 802.15.4 Extended Address. |
| * |
| * @param[out] aExtAddress A pointer to where the generated Extended Address is placed. |
| * |
| */ |
| void GenerateExtAddress(ExtAddress *aExtAddress); |
| |
| /** |
| * 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 mExtAddress; } |
| |
| /** |
| * 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); |
| |
| /** |
| * This method returns the IEEE 802.15.4 Short Address. |
| * |
| * @returns The IEEE 802.15.4 Short Address. |
| * |
| */ |
| ShortAddress GetShortAddress(void) const { return mShortAddress; } |
| |
| /** |
| * This method sets the IEEE 802.15.4 Short Address. |
| * |
| * @param[in] aShortAddress The IEEE 802.15.4 Short Address. |
| * |
| * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Short Address. |
| * |
| */ |
| otError SetShortAddress(ShortAddress 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 OT_ERROR_NONE Successfully set the IEEE 802.15.4 PAN Channel. |
| * @retval OT_ERROR_INVALID_ARGS The @p aChannel is not in the supported channel mask. |
| * |
| */ |
| otError SetPanChannel(uint8_t aChannel); |
| |
| /** |
| * This method returns the IEEE 802.15.4 Radio Channel. |
| * |
| * @returns The IEEE 802.15.4 Radio Channel. |
| * |
| */ |
| uint8_t GetRadioChannel(void) const { return mRadioChannel; } |
| |
| /** |
| * This method sets the IEEE 802.15.4 Radio Channel. It can only be called after successfully calling |
| * `AcquireRadioChannel()`. |
| * |
| * @param[in] aChannel The IEEE 802.15.4 Radio Channel. |
| * |
| * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Radio Channel. |
| * @retval OT_ERROR_INVALID_ARGS The @p aChannel is not in the supported channel mask. |
| * @retval OT_ERROR_INVALID_STATE The acquisition ID is incorrect. |
| * |
| */ |
| otError SetRadioChannel(uint16_t aAcquisitionId, uint8_t aChannel); |
| |
| /** |
| * This method acquires external ownership of the Radio channel so that future calls to `SetRadioChannel)()` will |
| * succeed. |
| * |
| * @param[out] aAcquisitionId The AcquisitionId that the caller should use when calling `SetRadioChannel()`. |
| * |
| * @retval OT_ERROR_NONE Successfully acquired permission to Set the Radio Channel. |
| * @retval OT_ERROR_INVALID_STATE Failed to acquire permission as the radio Channel has already been acquired. |
| * |
| */ |
| otError AcquireRadioChannel(uint16_t *aAcquisitionId); |
| |
| /** |
| * This method releases external ownership of the radio Channel that was acquired with `AcquireRadioChannel()`. The |
| * channel will re-adopt the PAN Channel when this API is called. |
| * |
| * @retval OT_ERROR_NONE Successfully released the IEEE 802.15.4 Radio Channel. |
| * |
| */ |
| otError ReleaseRadioChannel(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 Network Name. |
| * |
| * @returns A pointer to the IEEE 802.15.4 Network Name. |
| * |
| */ |
| const char *GetNetworkName(void) const { return mNetworkName.m8; } |
| |
| /** |
| * This method sets the IEEE 802.15.4 Network Name. |
| * |
| * @param[in] aNetworkName A pointer to the string. Must be null terminated. |
| * |
| * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name. |
| * @retval OT_ERROR_INVALID_ARGS Given name is too long. |
| * |
| */ |
| otError SetNetworkName(const char *aNetworkName); |
| |
| /** |
| * This method sets the IEEE 802.15.4 Network Name. |
| * |
| * @param[in] aBuffer A pointer to the char buffer containing the name. Does not need to be null terminated. |
| * @param[in] aLength Number of chars in the buffer. |
| * |
| * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name. |
| * @retval OT_ERROR_INVALID_ARGS Given name is too long. |
| * |
| */ |
| otError SetNetworkName(const char *aBuffer, uint8_t aLength); |
| |
| /** |
| * This method returns the IEEE 802.15.4 PAN ID. |
| * |
| * @returns The IEEE 802.15.4 PAN ID. |
| * |
| */ |
| uint16_t 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. |
| * |
| * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 PAN ID. |
| * |
| */ |
| otError SetPanId(uint16_t aPanId); |
| |
| /** |
| * This method returns the IEEE 802.15.4 Extended PAN ID. |
| * |
| * @returns A pointer to the IEEE 802.15.4 Extended PAN ID. |
| * |
| */ |
| const uint8_t *GetExtendedPanId(void) const { return mExtendedPanId.m8; } |
| |
| /** |
| * This method sets the IEEE 802.15.4 Extended PAN ID. |
| * |
| * @param[in] aExtPanId The IEEE 802.15.4 Extended PAN ID. |
| * |
| * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Extended PAN ID. |
| * |
| */ |
| otError SetExtendedPanId(const uint8_t *aExtPanId); |
| |
| #if OPENTHREAD_ENABLE_MAC_FILTER |
| /** |
| * This method returns the MAC filter. |
| * |
| * @returns A reference to the MAC filter. |
| * |
| */ |
| Filter &GetFilter(void) { return mFilter; } |
| #endif // OPENTHREAD_ENABLE_MAC_FILTER |
| |
| /** |
| * This method is called to handle a received frame. |
| * |
| * @param[in] aFrame A pointer to the received frame, or NULL if the receive operation was aborted. |
| * @param[in] aError OT_ERROR_NONE when successfully received a frame, |
| * OT_ERROR_ABORT when reception was aborted and a frame was not received. |
| * |
| */ |
| void HandleReceivedFrame(Frame *aFrame, otError aError); |
| |
| /** |
| * This method is called to handle transmission start events. |
| * |
| * @param[in] aFrame A pointer to the frame that is transmitted. |
| */ |
| void HandleTransmitStarted(otRadioFrame *aFrame); |
| |
| /** |
| * This method is called to handle transmit events. |
| * |
| * @param[in] aFrame A pointer to the frame that was transmitted. |
| * @param[in] aAckFrame A pointer to the ACK frame, NULL if no ACK was received. |
| * @param[in] aError OT_ERROR_NONE when the frame was transmitted, |
| * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received, |
| * OT_ERROR_CHANNEL_ACCESS_FAILURE when the tx failed due to activity on the channel, |
| * OT_ERROR_ABORT when transmission was aborted for other reasons. |
| * |
| */ |
| void HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError); |
| |
| /** |
| * This method returns if an active scan is in progress. |
| * |
| */ |
| bool IsActiveScanInProgress(void); |
| |
| /** |
| * This method returns if an energy scan is in progress. |
| * |
| */ |
| bool IsEnergyScanInProgress(void); |
| |
| /** |
| * 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); |
| |
| /** |
| * 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 NULL to disable the callback. |
| * @param[in] aCallbackContext A pointer to application-specific context. |
| * |
| */ |
| void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *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); |
| |
| /** |
| * 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 fills network diagnostic MacCounterTlv. |
| * |
| * @param[in] aMacCountersTlv The reference to the network diagnostic MacCounterTlv. |
| * |
| */ |
| void FillMacCountersTlv(NetworkDiagnostic::MacCountersTlv &aMacCounters) const; |
| |
| /** |
| * This method resets mac counters |
| * |
| */ |
| void ResetCounters(void); |
| |
| #if OPENTHREAD_CONFIG_ENABLE_BEACON_RSP_WHEN_JOINABLE |
| /** |
| * This method indicates if the device is in joinable state or not. |
| * |
| * @retval true Device is joinable. |
| * @retval false Device is non-joinable. |
| * |
| */ |
| bool IsBeaconJoinable(void); |
| #endif // OPENTHREAD_CONFIG_ENABLE_BEACON_RSP_WHEN_JOINABLE |
| |
| /** |
| * This method returns the MAC counter. |
| * |
| * @returns A reference to the MAC counter. |
| * |
| */ |
| otMacCounters &GetCounters(void) { return mCounters; } |
| |
| /** |
| * 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); |
| |
| /** |
| * This method indicates whether or not CSMA backoff is supported by the radio layer. |
| * |
| * @retval true CSMA backoff is supported by the radio. |
| * @retval false CSMA backoff is not supported by the radio. |
| * |
| */ |
| bool RadioSupportsCsmaBackoff(void); |
| |
| /** |
| * This method indicates whether or not transmit retries is supported by the radio layer. |
| * |
| * @retval true Retries (and CSMA) are supported by the radio. |
| * @retval false Retries (and CSMA) are not supported by the radio. |
| * |
| */ |
| bool RadioSupportsRetries(void); |
| |
| /** |
| * 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. |
| * |
| * @retval OT_ERROR_NONE The operation succeeded or the new State equals the current State. |
| * |
| */ |
| otError SetEnabled(bool 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) { return mEnabled; } |
| |
| /** |
| * This method performs AES CCM on the frame which is going to be sent. |
| * |
| * @param[in] aFrame A reference to the MAC frame buffer that is going to be sent. |
| * @param[in] aExtAddress A pointer to the extended address, which will be used to generate nonce |
| * for AES CCM computation. |
| * |
| */ |
| static void ProcessTransmitAesCcm(Frame &aFrame, const ExtAddress *aExtAddress); |
| |
| private: |
| enum |
| { |
| kInvalidRssiValue = 127, |
| kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW, |
| kMaxAcquisitionId = 0xffff, |
| |
| /** |
| * Interval between RSSI samples when performing Energy Scan. |
| * |
| * `mBackoffTimer` is used for adding delay between RSSI samples. If microsecond timer is supported, 128 usec |
| * time between samples is used, otherwise with a millisecond timer the minimum value of 1 msec is used. |
| * |
| */ |
| #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER |
| kEnergyScanRssiSampleInterval = 128, |
| #else |
| kEnergyScanRssiSampleInterval = 1, |
| #endif |
| }; |
| |
| enum Operation |
| { |
| kOperationIdle = 0, |
| kOperationActiveScan, |
| kOperationEnergyScan, |
| kOperationTransmitBeacon, |
| kOperationTransmitData, |
| kOperationWaitingForData, |
| kOperationTransmitOutOfBandFrame, |
| }; |
| |
| /** |
| * This method processes transmit security on the frame which is going to be sent. |
| * |
| * This method prepares the frame, fills Mac auxiliary header, and perform AES CCM immediately in most cases |
| * (depends on @p aProcessAesCcm). If aProcessAesCcm is False, it probably means that some content in the frame |
| * will be updated just before transmission, so AES CCM will be performed after that (before transmission). |
| * |
| * @param[in] aFrame A reference to the MAC frame buffer which is going to be sent. |
| * @param[in] aProcessAesCcm TRUE to perform AES CCM immediately, FALSE otherwise. |
| * |
| */ |
| void ProcessTransmitSecurity(Frame &aFrame, bool aProcessAesCcm); |
| |
| static void GenerateNonce(const ExtAddress &aAddress, |
| uint32_t aFrameCounter, |
| uint8_t aSecurityLevel, |
| uint8_t * aNonce); |
| |
| otError ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor); |
| void UpdateIdleMode(void); |
| void StartOperation(Operation aOperation); |
| void FinishOperation(void); |
| void SendBeaconRequest(Frame &aFrame); |
| void SendBeacon(Frame &aFrame); |
| void StartBackoff(void); |
| void BeginTransmit(void); |
| otError HandleMacCommand(Frame &aFrame); |
| Frame * GetOperationFrame(void); |
| |
| static void HandleMacTimer(Timer &aTimer); |
| void HandleMacTimer(void); |
| static void HandleBackoffTimer(Timer &aTimer); |
| void HandleBackoffTimer(void); |
| static void HandleReceiveTimer(Timer &aTimer); |
| void HandleReceiveTimer(void); |
| static void PerformOperation(Tasklet &aTasklet); |
| void PerformOperation(void); |
| |
| void StartCsmaBackoff(void); |
| |
| void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration, void *aContext); |
| otError UpdateScanChannel(void); |
| void PerformActiveScan(void); |
| void PerformEnergyScan(void); |
| void ReportEnergyScanResult(int8_t aRssi); |
| void SampleRssi(void); |
| |
| otError RadioTransmit(Frame *aSendFrame); |
| otError RadioReceive(uint8_t aChannel); |
| otError RadioSleep(void); |
| |
| void LogFrameRxFailure(const Frame *aFrame, otError aError) const; |
| void LogFrameTxFailure(const Frame &aFrame, otError aError) const; |
| void LogBeacon(const char *aActionText, const BeaconPayload &aBeaconPayload) const; |
| |
| #if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC |
| void ProcessTimeIe(Frame &aFrame); |
| uint8_t GetTimeIeOffset(Frame &aFrame); |
| #endif |
| |
| static const char *OperationToString(Operation aOperation); |
| |
| Operation mOperation; |
| |
| bool mPendingActiveScan : 1; |
| bool mPendingEnergyScan : 1; |
| bool mPendingTransmitBeacon : 1; |
| bool mPendingTransmitData : 1; |
| bool mPendingTransmitOobFrame : 1; |
| bool mPendingWaitingForData : 1; |
| bool mRxOnWhenIdle : 1; |
| bool mBeaconsEnabled : 1; |
| #if OPENTHREAD_CONFIG_STAY_AWAKE_BETWEEN_FRAGMENTS |
| bool mDelaySleep : 1; |
| #endif |
| |
| Tasklet mOperationTask; |
| |
| TimerMilli mMacTimer; |
| #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER |
| TimerMicro mBackoffTimer; |
| #else |
| TimerMilli mBackoffTimer; |
| #endif |
| TimerMilli mReceiveTimer; |
| |
| ExtAddress mExtAddress; |
| ShortAddress mShortAddress; |
| PanId mPanId; |
| uint8_t mPanChannel; |
| uint8_t mRadioChannel; |
| uint16_t mRadioChannelAcquisitionId; |
| ChannelMask mSupportedChannelMask; |
| |
| otNetworkName mNetworkName; |
| otExtendedPanId mExtendedPanId; |
| |
| Sender * mSendHead, *mSendTail; |
| Receiver *mReceiveHead, *mReceiveTail; |
| |
| uint8_t mBeaconSequence; |
| uint8_t mDataSequence; |
| uint8_t mCsmaAttempts; |
| uint8_t mTransmitAttempts; |
| |
| ChannelMask mScanChannelMask; |
| uint16_t mScanDuration; |
| uint8_t mScanChannel; |
| int8_t mEnergyScanCurrentMaxRssi; |
| void * mScanContext; |
| union |
| { |
| ActiveScanHandler mActiveScanHandler; |
| EnergyScanHandler mEnergyScanHandler; |
| }; |
| |
| otLinkPcapCallback mPcapCallback; |
| void * mPcapCallbackContext; |
| |
| #if OPENTHREAD_ENABLE_MAC_FILTER |
| Filter mFilter; |
| #endif // OPENTHREAD_ENABLE_MAC_FILTER |
| |
| Frame *mTxFrame; |
| Frame *mOobFrame; |
| |
| otMacCounters mCounters; |
| uint32_t mKeyIdMode2FrameCounter; |
| |
| SuccessRateTracker mCcaSuccessRateTracker; |
| uint16_t mCcaSampleCount; |
| bool mEnabled; |
| }; |
| |
| /** |
| * @} |
| * |
| */ |
| |
| } // namespace Mac |
| } // namespace ot |
| |
| #endif // MAC_HPP_ |