blob: ff6821cf55e1f191a6b5b7aee0ad405746dc04bd [file] [log] [blame]
/*
* Copyright (c) 2019, 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 MAC radio links.
*/
#ifndef MAC_LINKS_HPP_
#define MAC_LINKS_HPP_
#include "openthread-core-config.h"
#include "common/debug.hpp"
#include "common/locator.hpp"
#include "mac/mac_frame.hpp"
#include "mac/mac_types.hpp"
#include "mac/sub_mac.hpp"
#include "radio/trel_link.hpp"
namespace ot {
namespace Mac {
/**
* @addtogroup core-mac
*
* @brief
* This module includes definitions for MAC radio links (multi radio).
*
* @{
*
*/
/**
* This class represents tx frames for different radio link types.
*
*/
class TxFrames : InstanceLocator
{
friend class Links;
public:
#if OPENTHREAD_CONFIG_MULTI_RADIO
/**
* This method gets the `TxFrame` for a given radio link type.
*
* This method also updates the selected radio types (from `GetSelectedRadioTypes()`) to include the @p aRadioType.
*
* @param[in] aRadioType A radio link type.
*
* @returns A reference to the `TxFrame` for the given radio link type.
*
*/
TxFrame &GetTxFrame(RadioType aRadioType);
/**
* This method gets the `TxFrame` with the smallest MTU size among a given set of radio types.
*
* This method also updates the selected radio types (from `GetSelectedRadioTypes()`) to include the set
* @p aRadioTypes.
*
* @param[in] aRadioTypes A set of radio link types.
*
* @returns A reference to the `TxFrame` with the smallest MTU size among the set of @p aRadioTypes.
*
*/
TxFrame &GetTxFrame(RadioTypes aRadioTypes);
/**
* This method gets the `TxFrame` for sending a broadcast frame.
*
* This method also updates the selected radio type (from `GetSelectedRadioTypes()`) to include all radio types
* (supported by device).
*
* The broadcast frame is the `TxFrame` with the smallest MTU size among all radio types.
*
* @returns A reference to a `TxFrame` for broadcast.
*
*/
TxFrame &GetBroadcastTxFrame(void);
/**
* This method gets the selected radio types.
*
* This set specifies the radio links the frame should be sent over (in parallel). The set starts a empty after
* method `Clear()` is called. It gets updated through calls to methods `GetTxFrame(aType)`,
* `GetTxFrame(aRadioTypes)`, or `GetBroadcastTxFrame()`.
*
* @returns The selected radio types.
*
*/
RadioTypes GetSelectedRadioTypes(void) const { return mSelectedRadioTypes; }
/**
* This method gets the required radio types.
*
* This set specifies the radio links for which we expect the frame tx to be successful to consider the overall tx
* successful. If the set is empty, successful tx over any radio link is sufficient for overall tx to be considered
* successful. The required radio type set is expected to be a subset of selected radio types.
*
* The set starts as empty after `Clear()` call. It can be updated through `SetRequiredRadioTypes()` method
*
* @returns The required radio types.
*
*/
RadioTypes GetRequiredRadioTypes(void) const { return mRequiredRadioTypes; }
/**
* This method sets the required types.
*
* Please see `GetRequiredRadioTypes()` for more details on how this set is used during tx.
*
* @param[in] aRadioTypes A set of radio link types.
*
*/
void SetRequiredRadioTypes(RadioTypes aRadioTypes) { mRequiredRadioTypes = aRadioTypes; }
#else // #if OPENTHREAD_CONFIG_MULTI_RADIO
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
/**
* This method gets the tx frame.
*
* @returns A reference to `TxFrame`.
*
*/
TxFrame &GetTxFrame(void) { return mTxFrame802154; }
#elif OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
* This method gets the tx frame.
*
* @returns A reference to `TxFrame`.
*
*/
TxFrame &GetTxFrame(void) { return mTxFrameTrel; }
#endif
/**
* This method gets a tx frame for sending a broadcast frame.
*
* @returns A reference to a `TxFrame` for broadcast.
*
*/
TxFrame &GetBroadcastTxFrame(void) { return GetTxFrame(); }
#endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
/**
* This method clears all supported radio tx frames (sets the PSDU length to zero and clears flags).
*
*/
void Clear(void)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mTxFrame802154.SetLength(0);
mTxFrame802154.SetIsARetransmission(false);
mTxFrame802154.SetIsSecurityProcessed(false);
mTxFrame802154.SetCsmaCaEnabled(true); // Set to true by default, only set to `false` for CSL transmission
mTxFrame802154.SetIsHeaderUpdated(false);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mTxFrame802154.SetTxDelay(0);
mTxFrame802154.SetTxDelayBaseTime(0);
#endif
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTxFrameTrel.SetLength(0);
mTxFrameTrel.SetIsARetransmission(false);
mTxFrameTrel.SetIsSecurityProcessed(false);
mTxFrameTrel.SetCsmaCaEnabled(true);
mTxFrameTrel.SetIsHeaderUpdated(false);
#endif
#if OPENTHREAD_CONFIG_MULTI_RADIO
mSelectedRadioTypes.Clear();
mRequiredRadioTypes.Clear();
#endif
}
/**
* This method sets the channel on all supported radio tx frames.
*
* @param[in] aChannel A channel.
*
*/
void SetChannel(uint8_t aChannel)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mTxFrame802154.SetChannel(aChannel);
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTxFrameTrel.SetChannel(aChannel);
#endif
}
/**
* This method sets the Sequence Number value on all supported radio tx frames.
*
* @param[in] aSequence The Sequence Number value.
*
*/
void SetSequence(uint8_t aSequence)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mTxFrame802154.SetSequence(aSequence);
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTxFrameTrel.SetSequence(aSequence);
#endif
}
/**
* This method sets the maximum number of the CSMA-CA backoffs on all supported radio tx
* frames.
*
* @param[in] aMaxCsmaBackoffs The maximum number of CSMA-CA backoffs.
*
*/
void SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mTxFrame802154.SetMaxCsmaBackoffs(aMaxCsmaBackoffs);
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTxFrameTrel.SetMaxCsmaBackoffs(aMaxCsmaBackoffs);
#endif
}
/**
* This method sets the maximum number of retries allowed after a transmission failure on all supported radio tx
* frames.
*
* @param[in] aMaxFrameRetries The maximum number of retries allowed after a transmission failure.
*
*/
void SetMaxFrameRetries(uint8_t aMaxFrameRetries)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mTxFrame802154.SetMaxFrameRetries(aMaxFrameRetries);
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTxFrameTrel.SetMaxFrameRetries(aMaxFrameRetries);
#endif
}
private:
explicit TxFrames(Instance &aInstance);
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
TxFrame &mTxFrame802154;
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
TxFrame &mTxFrameTrel;
#endif
#if OPENTHREAD_CONFIG_MULTI_RADIO
RadioTypes mSelectedRadioTypes;
RadioTypes mRequiredRadioTypes;
#endif
};
/**
* This class represents MAC radio links (multi radio).
*
*/
class Links : public InstanceLocator
{
friend class ot::Instance;
public:
static const int8_t kInvalidRssiValue = SubMac::kInvalidRssiValue; ///< Invalid RSSI value.
/**
* This constructor initializes the `Links` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Links(Instance &aInstance);
/**
* This method sets the PAN ID.
*
* @param[in] aPanId The PAN ID.
*
*/
void SetPanId(PanId aPanId)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.SetPanId(aPanId);
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.SetPanId(aPanId);
#endif
}
/**
* This method gets the MAC Short Address.
*
* @returns The MAC Short Address.
*
*/
ShortAddress GetShortAddress(void) const
{
return
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.GetShortAddress();
#else
mShortAddress;
#endif
}
/**
* This method sets the MAC Short Address.
*
* @param[in] aShortAddress A MAC Short Address.
*
*/
void SetShortAddress(ShortAddress aShortAddress)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.SetShortAddress(aShortAddress);
#else
mShortAddress = aShortAddress;
#endif
}
/**
* This method gets the MAC Extended Address.
*
* @returns The MAC Extended Address.
*
*/
const ExtAddress &GetExtAddress(void) const
{
return
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.GetExtAddress();
#else
mExtAddress;
#endif
}
/**
* This method sets the MAC Extended Address.
*
* @param[in] aExtAddress A MAC Extended Address.
*
*/
void SetExtAddress(const ExtAddress &aExtAddress)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.SetExtAddress(aExtAddress);
#else
mExtAddress = aExtAddress;
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.HandleExtAddressChange();
#endif
}
/**
* This method registers a callback to provide received packet capture for 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)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.SetPcapCallback(aPcapCallback, aCallbackContext);
#endif
OT_UNUSED_VARIABLE(aPcapCallback);
OT_UNUSED_VARIABLE(aCallbackContext);
}
/**
* This method indicates whether radio should stay in Receive or Sleep during CSMA backoff.
*
* @param[in] aRxOnWhenBackoff TRUE to keep radio in Receive, FALSE to put to Sleep during CSMA backoff.
*
*/
void SetRxOnWhenBackoff(bool aRxOnWhenBackoff)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.SetRxOnWhenBackoff(aRxOnWhenBackoff);
#endif
OT_UNUSED_VARIABLE(aRxOnWhenBackoff);
}
/**
* This method enables all radio links.
*
*/
void Enable(void)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
IgnoreError(mSubMac.Enable());
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.Enable();
#endif
}
/**
* This method disables all radio links.
*
*/
void Disable(void)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
IgnoreError(mSubMac.Disable());
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.Disable();
#endif
}
/**
* This method transitions all radio links to Sleep.
*
*/
void Sleep(void)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
IgnoreError(mSubMac.Sleep());
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.Sleep();
#endif
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* This method transitions all radios link to CSL sample state.
*
* CSL sample state is only applicable and used for 15.4 radio link. Other link are transitioned to sleep state.
*
* @param[in] aPanChannel The current phy channel used by the device. This param will only take effect when CSL
* channel hasn't been explicitly specified.
*/
void CslSample(uint8_t aPanChannel)
{
OT_UNUSED_VARIABLE(aPanChannel);
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
IgnoreError(mSubMac.CslSample(aPanChannel));
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.Sleep();
#endif
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* This method transitions all radio links to Receive.
*
* @param[in] aChannel The channel to use for receiving.
*
*/
void Receive(uint8_t aChannel)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
IgnoreError(mSubMac.Receive(aChannel));
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.Receive(aChannel);
#endif
}
/**
* This method gets the radio transmit frames.
*
* @returns The transmit frames.
*
*/
TxFrames &GetTxFrames(void) { return mTxFrames; }
#if !OPENTHREAD_CONFIG_MULTI_RADIO
/**
* This method sends a prepared frame.
*
* The prepared frame is from `GetTxFrames()`. This method is available only in single radio link mode.
*
*/
void Send(void)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
SuccessOrAssert(mSubMac.Send());
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.Send();
#endif
}
#else // #if !OPENTHREAD_CONFIG_MULTI_RADIO
/**
* This method sends prepared frames over a given set of radio links.
*
* The prepared frame must be from `GetTxFrames()`. This method is available only in multi radio link mode.
*
* @param[in] aFrame A reference to a prepared frame.
* @param[in] aRadioTypes A set of radio types to send on.
*
*/
void Send(TxFrame &aFrame, RadioTypes aRadioTypes);
#endif // !OPENTHREAD_CONFIG_MULTI_RADIO
/**
* This method gets the number of transmit retries for the last transmitted frame.
*
* @returns Number of transmit retries.
*
*/
uint8_t GetTransmitRetries(void) const
{
return
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.GetTransmitRetries();
#else
0;
#endif
}
/**
* This method gets the most recent RSSI measurement from radio link.
*
* @returns The RSSI in dBm when it is valid. `kInvalidRssiValue` when RSSI is invalid.
*
*/
int8_t GetRssi(void) const
{
return
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.GetRssi();
#else
kInvalidRssiValue;
#endif
}
/**
* This method begins energy scan.
*
* @param[in] aScanChannel The channel to perform the energy scan on.
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
*
* @retval kErrorNone Successfully started scanning the channel.
* @retval kErrorInvalidState The radio was disabled or transmitting.
* @retval kErrorNotImplemented Energy scan is not supported by radio link.
*
*/
Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
OT_UNUSED_VARIABLE(aScanChannel);
OT_UNUSED_VARIABLE(aScanDuration);
return
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.EnergyScan(aScanChannel, aScanDuration);
#else
kErrorNotImplemented;
#endif
}
/**
* 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
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.GetNoiseFloor();
#else
kDefaultNoiseFloor;
#endif
}
/**
* This methods gets a reference to the `SubMac` instance.
*
* @returns A reference to the `SubMac` instance.
*
*/
SubMac &GetSubMac(void) { return mSubMac; }
/**
* This methods gets a reference to the `SubMac` instance.
*
* @returns A reference to the `SubMac` instance.
*
*/
const SubMac &GetSubMac(void) const { return mSubMac; }
/**
* This method returns a reference to the current MAC key (for Key Mode 1) for a given Frame.
*
* @param[in] aFrame The frame for which to get the MAC key.
*
* @returns A reference to the current MAC key.
*
*/
const KeyMaterial *GetCurrentMacKey(const Frame &aFrame) const;
/**
* This method returns a reference to the temporary MAC key (for Key Mode 1) for a given Frame based on a given
* Key Sequence.
*
* @param[in] aFrame The frame for which to get the MAC key.
* @param[in] aKeySequence The Key Sequence number (MUST be one off (+1 or -1) from current key sequence number).
*
* @returns A reference to the temporary MAC key.
*
*/
const KeyMaterial *GetTemporaryMacKey(const Frame &aFrame, uint32_t aKeySequence) const;
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
* This method sets the current MAC frame counter value from the value from a `TxFrame`.
*
* @param[in] TxFrame The `TxFrame` from which to get the counter value.
*
* @retval kErrorNone If successful.
* @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
void SetMacFrameCounter(TxFrame &aFrame);
#endif
private:
static constexpr int8_t kDefaultNoiseFloor = -100;
SubMac mSubMac;
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
Trel::Link mTrel;
#endif
// `TxFrames` member definition should be after `mSubMac`, `mTrel`
// definitions to allow it to use their methods from its
// constructor.
TxFrames mTxFrames;
#if !OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
ShortAddress mShortAddress;
ExtAddress mExtAddress;
#endif
};
/**
* @}
*
*/
} // namespace Mac
} // namespace ot
#endif // MAC_LINKS_HPP_