1 /* 2 * Copyright (c) 2020, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef CSL_TX_SCHEDULER_HPP_ 30 #define CSL_TX_SCHEDULER_HPP_ 31 32 #include "openthread-core-config.h" 33 34 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 35 36 #include "common/locator.hpp" 37 #include "common/message.hpp" 38 #include "common/non_copyable.hpp" 39 #include "common/time.hpp" 40 #include "mac/mac.hpp" 41 #include "mac/mac_frame.hpp" 42 #include "thread/indirect_sender_frame_context.hpp" 43 44 namespace ot { 45 46 /** 47 * @addtogroup core-mesh-forwarding 48 * 49 * @brief 50 * This module includes definitions for CSL transmission scheduling. 51 * 52 * @{ 53 */ 54 55 class Child; 56 57 /** 58 * This class implements CSL tx scheduling functionality. 59 * 60 */ 61 class CslTxScheduler : public InstanceLocator, private NonCopyable 62 { 63 friend class Mac::Mac; 64 friend class IndirectSender; 65 66 public: 67 static constexpr uint8_t kMaxCslTriggeredTxAttempts = OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS; 68 69 /** 70 * This class defines all the child info required for scheduling CSL transmissions. 71 * 72 * `Child` class publicly inherits from this class. 73 * 74 */ 75 class ChildInfo 76 { 77 public: GetCslTxAttempts(void) const78 uint8_t GetCslTxAttempts(void) const { return mCslTxAttempts; } IncrementCslTxAttempts(void)79 void IncrementCslTxAttempts(void) { mCslTxAttempts++; } ResetCslTxAttempts(void)80 void ResetCslTxAttempts(void) { mCslTxAttempts = 0; } 81 IsCslSynchronized(void) const82 bool IsCslSynchronized(void) const { return mCslSynchronized && mCslPeriod > 0; } SetCslSynchronized(bool aCslSynchronized)83 void SetCslSynchronized(bool aCslSynchronized) { mCslSynchronized = aCslSynchronized; } 84 GetCslChannel(void) const85 uint8_t GetCslChannel(void) const { return mCslChannel; } SetCslChannel(uint8_t aChannel)86 void SetCslChannel(uint8_t aChannel) { mCslChannel = aChannel; } 87 GetCslTimeout(void) const88 uint32_t GetCslTimeout(void) const { return mCslTimeout; } SetCslTimeout(uint32_t aTimeout)89 void SetCslTimeout(uint32_t aTimeout) { mCslTimeout = aTimeout; } 90 GetCslPeriod(void) const91 uint16_t GetCslPeriod(void) const { return mCslPeriod; } SetCslPeriod(uint16_t aPeriod)92 void SetCslPeriod(uint16_t aPeriod) { mCslPeriod = aPeriod; } 93 GetCslPhase(void) const94 uint16_t GetCslPhase(void) const { return mCslPhase; } SetCslPhase(uint16_t aPhase)95 void SetCslPhase(uint16_t aPhase) { mCslPhase = aPhase; } 96 GetCslLastHeard(void) const97 TimeMilli GetCslLastHeard(void) const { return mCslLastHeard; } SetCslLastHeard(TimeMilli aCslLastHeard)98 void SetCslLastHeard(TimeMilli aCslLastHeard) { mCslLastHeard = aCslLastHeard; } 99 GetLastRxTimestamp(void) const100 uint64_t GetLastRxTimestamp(void) const { return mLastRxTimstamp; } SetLastRxTimestamp(uint64_t aLastRxTimestamp)101 void SetLastRxTimestamp(uint64_t aLastRxTimestamp) { mLastRxTimstamp = aLastRxTimestamp; } 102 103 private: 104 uint8_t mCslTxAttempts : 7; ///< Number of CSL triggered tx attempts. 105 bool mCslSynchronized : 1; ///< Indicates whether or not the child is CSL synchronized. 106 uint8_t mCslChannel; ///< The channel the device will listen on. 107 uint32_t mCslTimeout; ///< The sync timeout, in seconds. 108 uint16_t mCslPeriod; ///< CSL sampled listening period in units of 10 symbols (160 microseconds). 109 uint16_t mCslPhase; ///< The time when the next CSL sample will start. 110 TimeMilli mCslLastHeard; ///< Time when last frame containing CSL IE was heard. 111 uint64_t mLastRxTimstamp; ///< Time when last frame containing CSL IE was received, in microseconds. 112 113 static_assert(kMaxCslTriggeredTxAttempts < (1 << 7), "mCslTxAttempts cannot fit max!"); 114 }; 115 116 /** 117 * This class defines the callbacks used by the `CslTxScheduler`. 118 * 119 */ 120 class Callbacks : public InstanceLocator 121 { 122 friend class CslTxScheduler; 123 124 private: 125 typedef IndirectSenderBase::FrameContext FrameContext; 126 127 /** 128 * This constructor initializes the callbacks object. 129 * 130 * @param[in] aInstance A reference to the OpenThread instance. 131 * 132 */ 133 explicit Callbacks(Instance &aInstance); 134 135 /** 136 * This callback method requests a frame to be prepared for CSL transmission to a given SSED. 137 * 138 * @param[out] aFrame A reference to a MAC frame where the new frame would be placed. 139 * @param[out] aContext A reference to a `FrameContext` where the context for the new frame would be placed. 140 * @param[in] aChild The child for which to prepare the frame. 141 * 142 * @retval kErrorNone Frame was prepared successfully. 143 * @retval kErrorAbort CSL transmission should be aborted (no frame for the child). 144 * 145 */ 146 Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild); 147 148 /** 149 * This callback method notifies the end of CSL frame transmission to a child. 150 * 151 * @param[in] aFrame The transmitted frame. 152 * @param[in] aContext The context associated with the frame when it was prepared. 153 * @param[in] aError kErrorNone when the frame was transmitted successfully, 154 * kErrorNoAck when the frame was transmitted but no ACK was received, 155 * kErrorChannelAccessFailure tx failed due to activity on the channel, 156 * kErrorAbort when transmission was aborted for other reasons. 157 * @param[in] aChild The child to which the frame was transmitted. 158 * 159 */ 160 void HandleSentFrameToChild(const Mac::TxFrame &aFrame, 161 const FrameContext &aContext, 162 Error aError, 163 Child & aChild); 164 }; 165 /** 166 * This constructor initializes the CSL tx scheduler object. 167 * 168 * @param[in] aInstance A reference to the OpenThread instance. 169 * 170 */ 171 explicit CslTxScheduler(Instance &aInstance); 172 173 /** 174 * This method updates the next CSL transmission (finds the nearest child). 175 * 176 * 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 177 * done yet, and it's aborted, this method would set `mCslTxChild` to `nullptr` to notify the `HandleTransmitDone` 178 * that the operation has been aborted. 179 * 180 */ 181 void Update(void); 182 183 /** 184 * This method clears all the states inside `CslTxScheduler` and the related states in each child. 185 * 186 */ 187 void Clear(void); 188 189 private: 190 void InitFrameRequestAhead(void); 191 void RescheduleCslTx(void); 192 193 uint32_t GetNextCslTransmissionDelay(const Child &aChild, uint32_t &aDelayFromLastRx) const; 194 195 // Callbacks from `Mac` 196 Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames); 197 void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError); 198 199 void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild); 200 201 uint32_t mCslFrameRequestAheadUs; 202 Child * mCslTxChild; 203 Message * mCslTxMessage; 204 Callbacks::FrameContext mFrameContext; 205 Callbacks mCallbacks; 206 }; 207 208 /** 209 * @} 210 * 211 */ 212 213 } // namespace ot 214 215 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 216 217 #endif // CSL_TX_SCHEDULER_HPP_ 218