blob: 0904351e3de762f63ba6daa82a729e107e801409 [file] [log] [blame]
/*
* Copyright (c) 2016-2018, 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 layer (sub-MAC).
*/
#ifndef SUB_MAC_HPP_
#define SUB_MAC_HPP_
#include "openthread-core-config.h"
#include <openthread/link.h>
#include <openthread/platform/crypto.h>
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/timer.hpp"
#include "mac/mac_frame.hpp"
#include "radio/radio.hpp"
namespace ot {
/**
* @addtogroup core-mac
*
* @brief
* This module includes definitions for the IEEE 802.15.4 MAC (sub-MAC).
*
* @{
*
*/
namespace Mac {
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE."
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE."
#endif
#if !OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
#error "Microsecond timer OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE is required for "\
"OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE"
#endif
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE && !OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
#error "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE is required for OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE."
#endif
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
class LinkRaw;
#endif
/**
* This class implements the IEEE 802.15.4 MAC (sub-MAC).
*
* Sub-MAC layer implements a subset of IEEE802.15.4 MAC primitives which are shared by both MAC layer (in FTD/MTD
* modes) and Raw Link (Radio only mode).
* The sub-MAC layer handles the following (if not provided by radio platform):
*
* - Ack timeout for frame transmission,
* - CSMA backoff logic,
* - Frame re-transmissions,
* - Energy scan on a single channel and RSSI sampling.
*
* It also act as the interface (to radio platform) for setting/getting radio configurations such as short or extended
* addresses and PAN Id.
*
*/
class SubMac : public InstanceLocator, private NonCopyable
{
friend class Radio::Callbacks;
friend class LinkRaw;
public:
static constexpr int8_t kInvalidRssiValue = 127; ///< Invalid Received Signal Strength Indicator (RSSI) value.
/**
* This class defines the callbacks notifying `SubMac` user of changes and events.
*
*/
class Callbacks : public InstanceLocator
{
public:
/**
* This constructor initializes the `Callbacks` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Callbacks(Instance &aInstance);
/**
* This method notifies user of `SubMac` of a received frame.
*
* @param[in] aFrame A pointer to the received frame or `nullptr` if the receive operation failed.
* @param[in] aError kErrorNone when successfully received a frame,
* kErrorAbort when reception was aborted and a frame was not received,
* kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
*
*/
void ReceiveDone(RxFrame *aFrame, Error aError);
/**
* This method notifies user of `SubMac` of CCA status (success/failure) for a frame transmission attempt.
*
* This is intended for updating counters, logging, and/or tracking CCA failure rate statistics.
*
* @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 notifies user of `SubMac` of the status of a frame transmission attempt.
*
* This is intended for updating counters, logging, and/or collecting statistics.
*
* @note Unlike `TransmitDone` which is invoked after all re-transmission attempts to indicate the final status
* of a frame transmission, 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 Current retry count. This is valid only when sub-mac handles frame re-transmissions.
* @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only
* when there was an error in current transmission attempt.
*
*/
void RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
Error aError,
uint8_t aRetryCount,
bool aWillRetx);
/**
* The method notifies user of `SubMac` that the transmit operation has completed, providing, if applicable,
* the received ACK frame.
*
* @param[in] aFrame The transmitted frame.
* @param[in] aAckFrame A pointer to the ACK frame, `nullptr` if no ACK was received.
* @param[in] aError kErrorNone when the frame was transmitted,
* 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.
*
*/
void TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
/**
* This method notifies user of `SubMac` that energy scan is complete.
*
* @param[in] aMaxRssi Maximum RSSI seen on the channel, or `SubMac::kInvalidRssiValue` if failed.
*
*/
void EnergyScanDone(int8_t aMaxRssi);
/**
* This method notifies user of `SubMac` that a specific MAC frame counter is used for transmission.
*
* It is possible that this callback is invoked out of order in terms of counter values (i.e., called for a
* smaller counter value after a call for a larger counter value).
*
* @param[in] aFrameCounter The MAC frame counter value which was used.
*
*/
void FrameCounterUsed(uint32_t aFrameCounter);
};
/**
* This constructor initializes the `SubMac` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit SubMac(Instance &aInstance);
/**
* This method gets the capabilities provided by platform radio.
*
* @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions).
*
*/
otRadioCaps GetRadioCaps(void) const { return mRadioCaps; }
/**
* This method gets the capabilities provided by `SubMac` layer.
*
* @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions).
*
*/
otRadioCaps GetCaps(void) const;
/**
* This method sets the PAN ID.
*
* @param[in] aPanId The PAN ID.
*
*/
void SetPanId(PanId aPanId);
/**
* This method gets the short address.
*
* @returns The short address.
*
*/
ShortAddress GetShortAddress(void) const { return mShortAddress; }
/**
* This method sets the short address.
*
* @param[in] aShortAddress The short address.
*
*/
void SetShortAddress(ShortAddress aShortAddress);
/**
* This function gets the extended address.
*
* @returns A reference to the extended address.
*
*/
const ExtAddress &GetExtAddress(void) const { return mExtAddress; }
/**
* This method sets extended address.
*
* @param[in] aExtAddress The extended address.
*
*/
void SetExtAddress(const ExtAddress &aExtAddress);
/**
* 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);
/**
* 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) { mRxOnWhenBackoff = aRxOnWhenBackoff; }
/**
* This method enables the radio.
*
* @retval kErrorNone Successfully enabled.
* @retval kErrorFailed The radio could not be enabled.
*
*/
Error Enable(void);
/**
* This method disables the radio.
*
* @retval kErrorNone Successfully disabled the radio.
*
*/
Error Disable(void);
/**
* This method transitions the radio to Sleep.
*
* @retval kErrorNone Successfully transitioned to Sleep.
* @retval kErrorBusy The radio was transmitting.
* @retval kErrorInvalidState The radio was disabled.
*
*/
Error Sleep(void);
/**
* This method indicates whether the sub-mac is busy transmitting or scanning.
*
* @retval TRUE if the sub-mac is busy transmitting or scanning.
* @retval FALSE if the sub-mac is not busy transmitting or scanning.
*
*/
bool IsTransmittingOrScanning(void) const { return (mState == kStateTransmit) || (mState == kStateEnergyScan); }
/**
* This method transitions the radio to Receive.
*
* @param[in] aChannel The channel to use for receiving.
*
* @retval kErrorNone Successfully transitioned to Receive.
* @retval kErrorInvalidState The radio was disabled or transmitting.
*
*/
Error Receive(uint8_t aChannel);
/**
* This method gets the radio transmit frame.
*
* @returns The transmit frame.
*
*/
TxFrame &GetTransmitFrame(void) { return mTransmitFrame; }
/**
* This method sends a prepared frame.
*
* The frame should be placed in `GetTransmitFrame()` frame.
*
* The `SubMac` layer handles Ack timeout, CSMA backoff, and frame retransmission.
*
* @retval kErrorNone Successfully started the frame transmission
* @retval kErrorInvalidState The radio was disabled or transmitting.
*
*/
Error Send(void);
/**
* This method gets the number of transmit retries of last transmitted frame.
*
* @returns Number of transmit retries.
*
*/
uint8_t GetTransmitRetries(void) const { return mTransmitRetries; }
/**
* This method gets the most recent RSSI measurement.
*
* @returns The RSSI in dBm when it is valid. `kInvalidRssiValue` when RSSI is invalid.
*
*/
int8_t GetRssi(void) const;
/**
* 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 kErrorBusy The radio is performing energy scanning.
* @retval kErrorInvalidState The radio was disabled or transmitting.
* @retval kErrorNotImplemented Energy scan is not supported (applicable in link-raw/radio mode only).
*
*/
Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
/**
* 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);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* This method configures CSL parameters in 'SubMac'.
*
* @param[in] aPeriod The CSL period.
* @param[in] aChannel The CSL channel.
* @param[in] aShortAddr The short source address of CSL receiver's peer.
* @param[in] aExtAddr The extended source address of CSL receiver's peer.
*
* @retval TRUE if CSL Period or CSL Channel changed.
* @retval FALSE if CSL Period and CSL Channel did not change.
*
*/
bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, otShortAddress aShortAddr, const otExtAddress *aExtAddr);
/**
* This method lets `SubMac` start CSL sample mode given a configured non-zero CSL period.
*
* `SubMac` would switch the radio state between `Receive` and `Sleep` according the CSL timer.
*
*/
void CslSample(void);
/**
* This method returns CSL parent clock accuracy, in ± ppm.
*
* @retval CSL parent clock accuracy.
*
*/
uint8_t GetCslParentClockAccuracy(void) const { return mCslParentAccuracy; }
/**
* This method sets CSL parent clock accuracy, in ± ppm.
*
* @param[in] aCslParentAccuracy CSL parent clock accuracy, in ± ppm.
*
*/
void SetCslParentClockAccuracy(uint8_t aCslParentAccuracy) { mCslParentAccuracy = aCslParentAccuracy; }
/**
* This method sets CSL parent uncertainty, in ±10 us units.
*
* @retval CSL parent uncertainty, in ±10 us units.
*
*/
uint8_t GetCslParentUncertainty(void) const { return mCslParentUncert; }
/**
* 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) { mCslParentUncert = aCslParentUncert; }
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* This method sets MAC keys and key index.
*
* @param[in] aKeyIdMode MAC key ID mode.
* @param[in] aKeyId The key ID.
* @param[in] aPrevKey The previous MAC key.
* @param[in] aCurrKey The current MAC key.
* @param[in] aNextKey The next MAC key.
*
*/
void SetMacKey(uint8_t aKeyIdMode,
uint8_t aKeyId,
const KeyMaterial &aPrevKey,
const KeyMaterial &aCurrKey,
const KeyMaterial &aNextKey);
/**
* This method returns a reference to the current MAC key.
*
* @returns A reference to the current MAC key.
*
*/
const KeyMaterial &GetCurrentMacKey(void) const { return mCurrKey; }
/**
* This method returns a reference to the previous MAC key.
*
* @returns A reference to the previous MAC key.
*
*/
const KeyMaterial &GetPreviousMacKey(void) const { return mPrevKey; }
/**
* This method returns a reference to the next MAC key.
*
* @returns A reference to the next MAC key.
*
*/
const KeyMaterial &GetNextMacKey(void) const { return mNextKey; }
/**
* This method returns the current MAC frame counter value.
*
* @returns The current MAC frame counter value.
*
*/
uint32_t GetFrameCounter(void) const { return mFrameCounter; }
/**
* This method sets the current MAC Frame Counter value.
*
* @param[in] aFrameCounter The MAC Frame Counter value.
*
*/
void SetFrameCounter(uint32_t aFrameCounter);
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
/**
* This method enables/disables the 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) { mRadioFilterEnabled = aFilterEnabled; }
/**
* This method indicates whether the 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 mRadioFilterEnabled; }
#endif
private:
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static void HandleCslTimer(Timer &aTimer);
void HandleCslTimer(void);
void GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter);
#endif
static constexpr uint8_t kCsmaMinBe = 3; // macMinBE (IEEE 802.15.4-2006).
static constexpr uint8_t kCsmaMaxBe = 5; // macMaxBE (IEEE 802.15.4-2006).
static constexpr uint32_t kUnitBackoffPeriod = 20; // Number of symbols (IEEE 802.15.4-2006).
static constexpr uint32_t kAckTimeout = 16; // Timeout for waiting on an ACK (in msec).
static constexpr uint32_t kCcaSampleInterval = 128; // CCA sample interval, 128 usec.
#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
static constexpr uint8_t kRetxDelayMinBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT;
static constexpr uint8_t kRetxDelayMaxBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT;
#endif
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
static constexpr uint32_t kEnergyScanRssiSampleInterval = 128; // RSSI sample interval for energy scan, 128 usec
#else
static constexpr uint32_t kEnergyScanRssiSampleInterval = 1; // RSSI sample interval during energy scan, 1 msec
#endif
enum State : uint8_t
{
kStateDisabled, // Radio is disabled.
kStateSleep, // Radio is in sleep.
kStateReceive, // Radio in in receive.
kStateCsmaBackoff, // CSMA backoff before transmission.
kStateTransmit, // Radio is transmitting.
kStateEnergyScan, // Energy scan.
#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
kStateDelayBeforeRetx, // Delay before retx
#endif
#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
kStateCslTransmit, // CSL transmission.
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
kStateCslSample, // CSL receive.
#endif
};
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
// CSL receive window for the longest possible frame and
// ack duration.
static constexpr uint32_t kMinCslWindow = OPENTHREAD_CONFIG_CSL_MIN_RECEIVE_ON;
// CSL receivers would wake up `kCslReceiveTimeAhead` earlier
// than expected sample window. The value is in usec.
static constexpr uint32_t kCslReceiveTimeAhead = OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD;
#endif
/**
* This method initializes the states of the sub-MAC layer.
*
*/
void Init(void);
bool RadioSupportsCsmaBackoff(void) const
{
return ((mRadioCaps & (OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES)) != 0);
}
bool RadioSupportsTransmitSecurity(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) != 0); }
bool RadioSupportsRetries(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) != 0); }
bool RadioSupportsAckTimeout(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) != 0); }
bool RadioSupportsEnergyScan(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) != 0); }
bool RadioSupportsTransmitTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) != 0); }
bool RadioSupportsReceiveTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RECEIVE_TIMING) != 0); }
bool ShouldHandleTransmitSecurity(void) const;
bool ShouldHandleCsmaBackOff(void) const;
bool ShouldHandleAckTimeout(void) const;
bool ShouldHandleRetries(void) const;
bool ShouldHandleEnergyScan(void) const;
bool ShouldHandleTransmitTargetTime(void) const;
void ProcessTransmitSecurity(void);
void SignalFrameCounterUsed(uint32_t aFrameCounter);
void StartCsmaBackoff(void);
void StartTimerForBackoff(uint8_t aBackoffExponent);
void BeginTransmit(void);
void SampleRssi(void);
void HandleReceiveDone(RxFrame *aFrame, Error aError);
void HandleTransmitStarted(TxFrame &aFrame);
void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
void SignalFrameCounterUsedOnTxDone(const TxFrame &aFrame);
void HandleEnergyScanDone(int8_t aMaxRssi);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
void SetState(State aState);
static const char *StateToString(State aState);
otRadioCaps mRadioCaps;
State mState;
uint8_t mCsmaBackoffs;
uint8_t mTransmitRetries;
ShortAddress mShortAddress;
ExtAddress mExtAddress;
bool mRxOnWhenBackoff : 1;
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
bool mRadioFilterEnabled : 1;
#endif
int8_t mEnergyScanMaxRssi;
TimeMilli mEnergyScanEndTime;
TxFrame & mTransmitFrame;
Callbacks mCallbacks;
otLinkPcapCallback mPcapCallback;
void * mPcapCallbackContext;
KeyMaterial mPrevKey;
KeyMaterial mCurrKey;
KeyMaterial mNextKey;
uint32_t mFrameCounter;
uint8_t mKeyId;
#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
uint8_t mRetxDelayBackOffExponent;
#endif
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
TimerMicro mTimer;
#else
TimerMilli mTimer;
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
uint16_t mCslPeriod; // The CSL sample period, in units of 10 symbols (160 microseconds).
uint8_t mCslChannel : 7; // The CSL sample channel.
bool mIsCslSampling : 1; // Indicates that the radio is receiving in CSL state for platforms not supporting delayed
// reception.
TimeMicro mCslSampleTime; // The CSL sample time of the current period.
TimeMicro mCslLastSync; // The timestamp of the last successful CSL synchronization.
uint8_t mCslParentAccuracy; // Drift of timer used for scheduling CSL tx by the parent, in ± ppm.
uint8_t mCslParentUncert; // Uncertainty of the scheduling CSL of tx by the parent, in ±10 us units.
TimerMicro mCslTimer;
#endif
};
/**
* @}
*
*/
} // namespace Mac
} // namespace ot
#endif // SUB_MAC_HPP_