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_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 CslNeighbor; 56 57 /** 58 * Implements CSL tx scheduling functionality. 59 */ 60 class CslTxScheduler : public InstanceLocator, private NonCopyable 61 { 62 friend class Mac::Mac; 63 friend class IndirectSender; 64 65 public: 66 static constexpr uint8_t kMaxCslTriggeredTxAttempts = OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS; 67 68 /** 69 * Defines all the neighbor info required for scheduling CSL transmissions. 70 * 71 * `CslNeighbor` publicly inherits from this class. 72 */ 73 class NeighborInfo 74 { 75 public: GetCslTxAttempts(void) const76 uint8_t GetCslTxAttempts(void) const { return mCslTxAttempts; } IncrementCslTxAttempts(void)77 void IncrementCslTxAttempts(void) { mCslTxAttempts++; } ResetCslTxAttempts(void)78 void ResetCslTxAttempts(void) { mCslTxAttempts = 0; } 79 IsCslSynchronized(void) const80 bool IsCslSynchronized(void) const { return mCslSynchronized && mCslPeriod > 0; } SetCslSynchronized(bool aCslSynchronized)81 void SetCslSynchronized(bool aCslSynchronized) { mCslSynchronized = aCslSynchronized; } 82 GetCslChannel(void) const83 uint8_t GetCslChannel(void) const { return mCslChannel; } SetCslChannel(uint8_t aChannel)84 void SetCslChannel(uint8_t aChannel) { mCslChannel = aChannel; } 85 GetCslTimeout(void) const86 uint32_t GetCslTimeout(void) const { return mCslTimeout; } SetCslTimeout(uint32_t aTimeout)87 void SetCslTimeout(uint32_t aTimeout) { mCslTimeout = aTimeout; } 88 GetCslPeriod(void) const89 uint16_t GetCslPeriod(void) const { return mCslPeriod; } SetCslPeriod(uint16_t aPeriod)90 void SetCslPeriod(uint16_t aPeriod) { mCslPeriod = aPeriod; } 91 GetCslPhase(void) const92 uint16_t GetCslPhase(void) const { return mCslPhase; } SetCslPhase(uint16_t aPhase)93 void SetCslPhase(uint16_t aPhase) { mCslPhase = aPhase; } 94 GetCslLastHeard(void) const95 TimeMilli GetCslLastHeard(void) const { return mCslLastHeard; } SetCslLastHeard(TimeMilli aCslLastHeard)96 void SetCslLastHeard(TimeMilli aCslLastHeard) { mCslLastHeard = aCslLastHeard; } 97 GetLastRxTimestamp(void) const98 uint64_t GetLastRxTimestamp(void) const { return mLastRxTimestamp; } SetLastRxTimestamp(uint64_t aLastRxTimestamp)99 void SetLastRxTimestamp(uint64_t aLastRxTimestamp) { mLastRxTimestamp = aLastRxTimestamp; } 100 101 private: 102 uint8_t mCslTxAttempts : 7; ///< Number of CSL triggered tx attempts. 103 bool mCslSynchronized : 1; ///< Indicates whether or not the child is CSL synchronized. 104 uint8_t mCslChannel; ///< The channel the device will listen on. 105 uint32_t mCslTimeout; ///< The sync timeout, in seconds. 106 uint16_t mCslPeriod; ///< CSL sampled listening period between consecutive channel samples in units of 10 107 ///< symbols (160 microseconds). 108 109 /** 110 * The time in units of 10 symbols from the first symbol of the frame 111 * containing the CSL IE was transmitted until the next channel sample, 112 * see IEEE 802.15.4-2015, section 6.12.2. 113 * 114 * The Thread standard further defines the CSL phase (see Thread 1.4, 115 * section 3.2.6.3.4, also conforming to IEEE 802.15.4-2020, section 116 * 6.12.2.1): 117 * * The "first symbol" from the definition SHALL be interpreted as the 118 * first symbol of the MAC Header. 119 * * "until the next channel sample": 120 * * The CSL Receiver SHALL be ready to receive when the preamble 121 * time T_pa as specified below is reached. 122 * * The CSL Receiver SHOULD be ready to receive earlier than T_pa 123 * and SHOULD stay ready to receive until after the time specified 124 * in CSL Phase, according to the implementation and accuracy 125 * expectations. 126 * * The CSL Transmitter SHALL start transmitting the first symbol 127 * of the preamble of the frame to transmit at the preamble time 128 * T_pa = (CSL-Phase-Time – 192 us) (that is, CCA must be 129 * performed before time T_pa). Here, CSL-Phase-Time is the time 130 * duration specified by the CslPhase field value (in units of 10 131 * symbol periods). 132 * * This implies that the CSL Transmitter SHALL start transmitting 133 * the first symbol of the MAC Header at the time T_mh = 134 * CSL-Phase-Time. 135 * 136 * Derivation of the next TX timestamp based on this definition and the 137 * RX timestamp of the packet containing the CSL IE: 138 * 139 * Note that RX and TX timestamps are defined to point to the end of the 140 * synchronization header (SHR). 141 * 142 * lastTmh = lastRxTimestamp + phrDuration 143 * 144 * nextTmh = lastTmh + symbolPeriod * 10 * (n * cslPeriod + cslPhase) 145 * = lastTmh + 160us * (n * cslPeriod + cslPhase) 146 * 147 * nextTxTimestamp 148 * = nextTmh - phrDuration 149 * = lastRxTimestamp + 160us * (n * cslPeriod + cslPhase) 150 */ 151 uint16_t mCslPhase; 152 TimeMilli mCslLastHeard; ///< Radio clock time when last frame containing CSL IE was heard. 153 uint64_t 154 mLastRxTimestamp; ///< Radio clock time when last frame containing CSL IE was received, in microseconds. 155 156 static_assert(kMaxCslTriggeredTxAttempts < (1 << 7), "mCslTxAttempts cannot fit max!"); 157 }; 158 159 /** 160 * Initializes the CSL tx scheduler object. 161 * 162 * @param[in] aInstance A reference to the OpenThread instance. 163 */ 164 explicit CslTxScheduler(Instance &aInstance); 165 166 /** 167 * Updates the next CSL transmission (finds the nearest child). 168 * 169 * 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 170 * done yet, and it's aborted, this method would clear current tx CSL neighbor to notify the `HandleTransmitDone` 171 * that the operation has been aborted. 172 */ 173 void Update(void); 174 175 /** 176 * Clears all the states inside `CslTxScheduler` and the related states in each child. 177 */ 178 void Clear(void); 179 180 /** 181 * Updates the value of `mCslFrameRequestAheadUs`, based on bus speed, bus latency and `Mac::kCslRequestAhead`. 182 */ 183 void UpdateFrameRequestAhead(void); 184 185 private: 186 // Guard time in usec to add when checking delay while preparing the CSL frame for tx. 187 static constexpr uint32_t kFramePreparationGuardInterval = 1500; 188 189 typedef IndirectSenderBase::FrameContext FrameContext; 190 191 void RescheduleCslTx(void); 192 193 uint32_t GetNextCslTransmissionDelay(const CslNeighbor &aCslNeighbor, 194 uint32_t &aDelayFromLastRx, 195 uint32_t aAheadUs) const; 196 197 // Callbacks from `Mac` 198 Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames); 199 void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError); 200 201 void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, CslNeighbor &aaCslNeighbor); 202 203 uint32_t mCslFrameRequestAheadUs; 204 CslNeighbor *mCslTxNeighbor; 205 Message *mCslTxMessage; 206 FrameContext mFrameContext; 207 }; 208 209 /** 210 * @} 211 */ 212 213 } // namespace ot 214 215 #endif // OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 216 217 #endif // CSL_TX_SCHEDULER_HPP_ 218