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 * 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 * 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 mLastRxTimestamp; } SetLastRxTimestamp(uint64_t aLastRxTimestamp)101 void SetLastRxTimestamp(uint64_t aLastRxTimestamp) { mLastRxTimestamp = 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 between consecutive channel samples in units of 10 109 ///< symbols (160 microseconds). 110 111 /** 112 * The time in units of 10 symbols from the first symbol of the frame 113 * containing the CSL IE was transmitted until the next channel sample, 114 * see IEEE 802.15.4-2015, section 6.12.2. 115 * 116 * The Thread standard further defines the CSL phase (see Thread 1.4, 117 * section 3.2.6.3.4, also conforming to IEEE 802.15.4-2020, section 118 * 6.12.2.1): 119 * * The "first symbol" from the definition SHALL be interpreted as the 120 * first symbol of the MAC Header. 121 * * "until the next channel sample": 122 * * The CSL Receiver SHALL be ready to receive when the preamble 123 * time T_pa as specified below is reached. 124 * * The CSL Receiver SHOULD be ready to receive earlier than T_pa 125 * and SHOULD stay ready to receive until after the time specified 126 * in CSL Phase, according to the implementation and accuracy 127 * expectations. 128 * * The CSL Transmitter SHALL start transmitting the first symbol 129 * of the preamble of the frame to transmit at the preamble time 130 * T_pa = (CSL-Phase-Time – 192 us) (that is, CCA must be 131 * performed before time T_pa). Here, CSL-Phase-Time is the time 132 * duration specified by the CslPhase field value (in units of 10 133 * symbol periods). 134 * * This implies that the CSL Transmitter SHALL start transmitting 135 * the first symbol of the MAC Header at the time T_mh = 136 * CSL-Phase-Time. 137 * 138 * Derivation of the next TX timestamp based on this definition and the 139 * RX timestamp of the packet containing the CSL IE: 140 * 141 * Note that RX and TX timestamps are defined to point to the end of the 142 * synchronization header (SHR). 143 * 144 * lastTmh = lastRxTimestamp + phrDuration 145 * 146 * nextTmh = lastTmh + symbolPeriod * 10 * (n * cslPeriod + cslPhase) 147 * = lastTmh + 160us * (n * cslPeriod + cslPhase) 148 * 149 * nextTxTimestamp 150 * = nextTmh - phrDuration 151 * = lastRxTimestamp + 160us * (n * cslPeriod + cslPhase) 152 */ 153 uint16_t mCslPhase; 154 TimeMilli mCslLastHeard; ///< Radio clock time when last frame containing CSL IE was heard. 155 uint64_t 156 mLastRxTimestamp; ///< Radio clock time when last frame containing CSL IE was received, in microseconds. 157 158 static_assert(kMaxCslTriggeredTxAttempts < (1 << 7), "mCslTxAttempts cannot fit max!"); 159 }; 160 161 /** 162 * Defines the callbacks used by the `CslTxScheduler`. 163 * 164 */ 165 class Callbacks : public InstanceLocator 166 { 167 friend class CslTxScheduler; 168 169 private: 170 typedef IndirectSenderBase::FrameContext FrameContext; 171 172 /** 173 * Initializes the callbacks object. 174 * 175 * @param[in] aInstance A reference to the OpenThread instance. 176 * 177 */ 178 explicit Callbacks(Instance &aInstance); 179 180 /** 181 * This callback method requests a frame to be prepared for CSL transmission to a given SSED. 182 * 183 * @param[out] aFrame A reference to a MAC frame where the new frame would be placed. 184 * @param[out] aContext A reference to a `FrameContext` where the context for the new frame would be placed. 185 * @param[in] aChild The child for which to prepare the frame. 186 * 187 * @retval kErrorNone Frame was prepared successfully. 188 * @retval kErrorAbort CSL transmission should be aborted (no frame for the child). 189 * 190 */ 191 Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild); 192 193 /** 194 * This callback method notifies the end of CSL frame transmission to a child. 195 * 196 * @param[in] aFrame The transmitted frame. 197 * @param[in] aContext The context associated with the frame when it was prepared. 198 * @param[in] aError kErrorNone when the frame was transmitted successfully, 199 * kErrorNoAck when the frame was transmitted but no ACK was received, 200 * kErrorChannelAccessFailure tx failed due to activity on the channel, 201 * kErrorAbort when transmission was aborted for other reasons. 202 * @param[in] aChild The child to which the frame was transmitted. 203 * 204 */ 205 void HandleSentFrameToChild(const Mac::TxFrame &aFrame, 206 const FrameContext &aContext, 207 Error aError, 208 Child &aChild); 209 }; 210 /** 211 * Initializes the CSL tx scheduler object. 212 * 213 * @param[in] aInstance A reference to the OpenThread instance. 214 * 215 */ 216 explicit CslTxScheduler(Instance &aInstance); 217 218 /** 219 * Updates the next CSL transmission (finds the nearest child). 220 * 221 * 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 222 * done yet, and it's aborted, this method would set `mCslTxChild` to `nullptr` to notify the `HandleTransmitDone` 223 * that the operation has been aborted. 224 * 225 */ 226 void Update(void); 227 228 /** 229 * Clears all the states inside `CslTxScheduler` and the related states in each child. 230 * 231 */ 232 void Clear(void); 233 234 private: 235 // Guard time in usec to add when checking delay while preparing the CSL frame for tx. 236 static constexpr uint32_t kFramePreparationGuardInterval = 1500; 237 238 void InitFrameRequestAhead(void); 239 void RescheduleCslTx(void); 240 241 uint32_t GetNextCslTransmissionDelay(const Child &aChild, uint32_t &aDelayFromLastRx, uint32_t aAheadUs) const; 242 243 // Callbacks from `Mac` 244 Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames); 245 void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError); 246 247 void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild); 248 249 uint32_t mCslFrameRequestAheadUs; 250 Child *mCslTxChild; 251 Message *mCslTxMessage; 252 Callbacks::FrameContext mFrameContext; 253 Callbacks mCallbacks; 254 }; 255 256 /** 257 * @} 258 * 259 */ 260 261 } // namespace ot 262 263 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 264 265 #endif // CSL_TX_SCHEDULER_HPP_ 266