blob: 77eebcdaf6040ce9940c63c0d160cd6a2250716b [file] [log] [blame]
/*
* Copyright (c) 2020, 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.
*/
#ifndef CSL_TX_SCHEDULER_HPP_
#define CSL_TX_SCHEDULER_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
#include "common/time.hpp"
#include "mac/mac.hpp"
#include "mac/mac_frame.hpp"
#include "thread/indirect_sender_frame_context.hpp"
namespace ot {
/**
* @addtogroup core-mesh-forwarding
*
* @brief
* This module includes definitions for CSL transmission scheduling.
*
* @{
*/
class Child;
/**
* Implements CSL tx scheduling functionality.
*
*/
class CslTxScheduler : public InstanceLocator, private NonCopyable
{
friend class Mac::Mac;
friend class IndirectSender;
public:
static constexpr uint8_t kMaxCslTriggeredTxAttempts = OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS;
/**
* Defines all the child info required for scheduling CSL transmissions.
*
* `Child` class publicly inherits from this class.
*
*/
class ChildInfo
{
public:
uint8_t GetCslTxAttempts(void) const { return mCslTxAttempts; }
void IncrementCslTxAttempts(void) { mCslTxAttempts++; }
void ResetCslTxAttempts(void) { mCslTxAttempts = 0; }
bool IsCslSynchronized(void) const { return mCslSynchronized && mCslPeriod > 0; }
void SetCslSynchronized(bool aCslSynchronized) { mCslSynchronized = aCslSynchronized; }
uint8_t GetCslChannel(void) const { return mCslChannel; }
void SetCslChannel(uint8_t aChannel) { mCslChannel = aChannel; }
uint32_t GetCslTimeout(void) const { return mCslTimeout; }
void SetCslTimeout(uint32_t aTimeout) { mCslTimeout = aTimeout; }
uint16_t GetCslPeriod(void) const { return mCslPeriod; }
void SetCslPeriod(uint16_t aPeriod) { mCslPeriod = aPeriod; }
uint16_t GetCslPhase(void) const { return mCslPhase; }
void SetCslPhase(uint16_t aPhase) { mCslPhase = aPhase; }
TimeMilli GetCslLastHeard(void) const { return mCslLastHeard; }
void SetCslLastHeard(TimeMilli aCslLastHeard) { mCslLastHeard = aCslLastHeard; }
uint64_t GetLastRxTimestamp(void) const { return mLastRxTimestamp; }
void SetLastRxTimestamp(uint64_t aLastRxTimestamp) { mLastRxTimestamp = aLastRxTimestamp; }
private:
uint8_t mCslTxAttempts : 7; ///< Number of CSL triggered tx attempts.
bool mCslSynchronized : 1; ///< Indicates whether or not the child is CSL synchronized.
uint8_t mCslChannel; ///< The channel the device will listen on.
uint32_t mCslTimeout; ///< The sync timeout, in seconds.
uint16_t mCslPeriod; ///< CSL sampled listening period between consecutive channel samples in units of 10
///< symbols (160 microseconds).
/**
* The time in units of 10 symbols from the first symbol of the frame
* containing the CSL IE was transmitted until the next channel sample,
* see IEEE 802.15.4-2015, section 6.12.2.
*
* The Thread standard further defines the CSL phase (see Thread 1.3.1,
* section 3.2.6.3.4, also conforming to IEEE 802.15.4-2020, section
* 6.12.2.1):
* * The "first symbol" from the definition SHALL be interpreted as the
* first symbol of the MAC Header.
* * "until the next channel sample":
* * The CSL Receiver SHALL be ready to receive when the preamble
* time T_pa as specified below is reached.
* * The CSL Receiver SHOULD be ready to receive earlier than T_pa
* and SHOULD stay ready to receive until after the time specified
* in CSL Phase, according to the implementation and accuracy
* expectations.
* * The CSL Transmitter SHALL start transmitting the first symbol
* of the preamble of the frame to transmit at the preamble time
* T_pa = (CSL-Phase-Time – 192 us) (that is, CCA must be
* performed before time T_pa). Here, CSL-Phase-Time is the time
* duration specified by the CslPhase field value (in units of 10
* symbol periods).
* * This implies that the CSL Transmitter SHALL start transmitting
* the first symbol of the MAC Header at the time T_mh =
* CSL-Phase-Time.
*
* Derivation of the next TX timestamp based on this definition and the
* RX timestamp of the packet containing the CSL IE:
*
* Note that RX and TX timestamps are defined to point to the end of the
* synchronization header (SHR).
*
* lastTmh = lastRxTimestamp + phrDuration
*
* nextTmh = lastTmh + symbolPeriod * 10 * (n * cslPeriod + cslPhase)
* = lastTmh + 160us * (n * cslPeriod + cslPhase)
*
* nextTxTimestamp
* = nextTmh - phrDuration
* = lastRxTimestamp + 160us * (n * cslPeriod + cslPhase)
*/
uint16_t mCslPhase;
TimeMilli mCslLastHeard; ///< Radio clock time when last frame containing CSL IE was heard.
uint64_t
mLastRxTimestamp; ///< Radio clock time when last frame containing CSL IE was received, in microseconds.
static_assert(kMaxCslTriggeredTxAttempts < (1 << 7), "mCslTxAttempts cannot fit max!");
};
/**
* Defines the callbacks used by the `CslTxScheduler`.
*
*/
class Callbacks : public InstanceLocator
{
friend class CslTxScheduler;
private:
typedef IndirectSenderBase::FrameContext FrameContext;
/**
* Initializes the callbacks object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Callbacks(Instance &aInstance);
/**
* This callback method requests a frame to be prepared for CSL transmission to a given SSED.
*
* @param[out] aFrame A reference to a MAC frame where the new frame would be placed.
* @param[out] aContext A reference to a `FrameContext` where the context for the new frame would be placed.
* @param[in] aChild The child for which to prepare the frame.
*
* @retval kErrorNone Frame was prepared successfully.
* @retval kErrorAbort CSL transmission should be aborted (no frame for the child).
*
*/
Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
/**
* This callback method notifies the end of CSL frame transmission to a child.
*
* @param[in] aFrame The transmitted frame.
* @param[in] aContext The context associated with the frame when it was prepared.
* @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] aChild The child to which the frame was transmitted.
*
*/
void HandleSentFrameToChild(const Mac::TxFrame &aFrame,
const FrameContext &aContext,
Error aError,
Child &aChild);
};
/**
* Initializes the CSL tx scheduler object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit CslTxScheduler(Instance &aInstance);
/**
* Updates the next CSL transmission (finds the nearest child).
*
* It would then request the `Mac` to do the CSL tx. If the last CSL tx has been fired at `Mac` but hasn't been
* done yet, and it's aborted, this method would set `mCslTxChild` to `nullptr` to notify the `HandleTransmitDone`
* that the operation has been aborted.
*
*/
void Update(void);
/**
* Clears all the states inside `CslTxScheduler` and the related states in each child.
*
*/
void Clear(void);
private:
// Guard time in usec to add when checking delay while preparing the CSL frame for tx.
static constexpr uint32_t kFramePreparationGuardInterval = 1500;
void InitFrameRequestAhead(void);
void RescheduleCslTx(void);
uint32_t GetNextCslTransmissionDelay(const Child &aChild, uint32_t &aDelayFromLastRx, uint32_t aAheadUs) const;
// Callbacks from `Mac`
Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames);
void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError);
void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild);
uint32_t mCslFrameRequestAheadUs;
Child *mCslTxChild;
Message *mCslTxMessage;
Callbacks::FrameContext mFrameContext;
Callbacks mCallbacks;
};
/**
* @}
*
*/
} // namespace ot
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
#endif // CSL_TX_SCHEDULER_HPP_