1 /* 2 * Copyright (c) 2019, 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 /** 30 * @file 31 * This file includes definitions for handling indirect transmission. 32 */ 33 34 #ifndef INDIRECT_SENDER_HPP_ 35 #define INDIRECT_SENDER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/locator.hpp" 40 #include "common/message.hpp" 41 #include "common/non_copyable.hpp" 42 #include "mac/data_poll_handler.hpp" 43 #include "mac/mac_frame.hpp" 44 #include "thread/csl_tx_scheduler.hpp" 45 #include "thread/indirect_sender_frame_context.hpp" 46 #include "thread/mle_types.hpp" 47 #include "thread/src_match_controller.hpp" 48 49 namespace ot { 50 51 /** 52 * @addtogroup core-mesh-forwarding 53 * 54 * @brief 55 * This module includes definitions for handling indirect transmissions. 56 * 57 * @{ 58 */ 59 60 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 61 62 class CslNeighbor; 63 #if OPENTHREAD_FTD 64 class Child; 65 #endif 66 67 /** 68 * Implements indirect transmission. 69 */ 70 class IndirectSender : public InstanceLocator, public IndirectSenderBase, private NonCopyable 71 { 72 friend class Instance; 73 #if OPENTHREAD_FTD 74 friend class DataPollHandler; 75 #endif 76 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 77 friend class CslTxScheduler; 78 #endif 79 80 public: 81 /** 82 * Defines all the neighbor info required for indirect (CSL or data-poll) transmission. 83 * 84 * Sub-classes of `Neighbor`, e.g., `CslNeighbor` or `Child` publicly inherits from this class. 85 */ 86 class NeighborInfo 87 { 88 friend class IndirectSender; 89 #if OPENTHREAD_FTD 90 friend class DataPollHandler; 91 friend class SourceMatchController; 92 #endif 93 friend class CslTxScheduler; 94 95 public: 96 /** 97 * Returns the number of queued messages for the child. 98 * 99 * @returns Number of queued messages for the child. 100 */ GetIndirectMessageCount(void) const101 uint16_t GetIndirectMessageCount(void) const { return mQueuedMessageCount; } 102 103 private: GetIndirectMessage(void)104 Message *GetIndirectMessage(void) { return mIndirectMessage; } SetIndirectMessage(Message * aMessage)105 void SetIndirectMessage(Message *aMessage) { mIndirectMessage = aMessage; } 106 GetIndirectFragmentOffset(void) const107 uint16_t GetIndirectFragmentOffset(void) const { return mIndirectFragmentOffset; } SetIndirectFragmentOffset(uint16_t aFragmentOffset)108 void SetIndirectFragmentOffset(uint16_t aFragmentOffset) { mIndirectFragmentOffset = aFragmentOffset; } 109 GetIndirectTxSuccess(void) const110 bool GetIndirectTxSuccess(void) const { return mIndirectTxSuccess; } SetIndirectTxSuccess(bool aTxStatus)111 void SetIndirectTxSuccess(bool aTxStatus) { mIndirectTxSuccess = aTxStatus; } 112 IsIndirectSourceMatchShort(void) const113 bool IsIndirectSourceMatchShort(void) const { return mUseShortAddress; } SetIndirectSourceMatchShort(bool aShort)114 void SetIndirectSourceMatchShort(bool aShort) { mUseShortAddress = aShort; } 115 IsIndirectSourceMatchPending(void) const116 bool IsIndirectSourceMatchPending(void) const { return mSourceMatchPending; } SetIndirectSourceMatchPending(bool aPending)117 void SetIndirectSourceMatchPending(bool aPending) { mSourceMatchPending = aPending; } 118 IncrementIndirectMessageCount(void)119 void IncrementIndirectMessageCount(void) { mQueuedMessageCount++; } DecrementIndirectMessageCount(void)120 void DecrementIndirectMessageCount(void) { mQueuedMessageCount--; } ResetIndirectMessageCount(void)121 void ResetIndirectMessageCount(void) { mQueuedMessageCount = 0; } 122 IsWaitingForMessageUpdate(void) const123 bool IsWaitingForMessageUpdate(void) const { return mWaitingForMessageUpdate; } SetWaitingForMessageUpdate(bool aNeedsUpdate)124 void SetWaitingForMessageUpdate(bool aNeedsUpdate) { mWaitingForMessageUpdate = aNeedsUpdate; } 125 126 const Mac::Address &GetMacAddress(Mac::Address &aMacAddress) const; 127 128 Message *mIndirectMessage; // Current indirect message. 129 uint16_t mIndirectFragmentOffset : 14; // 6LoWPAN fragment offset for the indirect message. 130 bool mIndirectTxSuccess : 1; // Indicates tx success/failure of current indirect message. 131 bool mWaitingForMessageUpdate : 1; // Indicates waiting for updating the indirect message. 132 uint16_t mQueuedMessageCount : 14; // Number of queued indirect messages for the child. 133 bool mUseShortAddress : 1; // Indicates whether to use short or extended address. 134 bool mSourceMatchPending : 1; // Indicates whether or not pending to add to src match table. 135 136 static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < (1UL << 14), 137 "mQueuedMessageCount cannot fit max required!"); 138 }; 139 140 /** 141 * Represents a predicate function for checking if a given `Message` meets specific criteria. 142 * 143 * @param[in] aMessage The message to evaluate. 144 * 145 * @retval TRUE If the @p aMessage satisfies the predicate condition. 146 * @retval FALSE If the @p aMessage does not satisfy the predicate condition. 147 */ 148 typedef bool (&MessageChecker)(const Message &aMessage); 149 150 /** 151 * Initializes the object. 152 * 153 * @param[in] aInstance A reference to the OpenThread instance. 154 */ 155 explicit IndirectSender(Instance &aInstance); 156 157 /** 158 * Enables indirect transmissions. 159 */ Start(void)160 void Start(void) { mEnabled = true; } 161 162 /** 163 * Disables indirect transmission. 164 * 165 * Any previously scheduled indirect transmission is canceled. 166 */ 167 void Stop(void); 168 169 #if OPENTHREAD_FTD 170 /** 171 * Adds a message for indirect transmission to a sleepy child. 172 * 173 * @param[in] aMessage The message to add. 174 * @param[in] aChild The (sleepy) child for indirect transmission. 175 */ 176 void AddMessageForSleepyChild(Message &aMessage, Child &aChild); 177 178 /** 179 * Removes a message for indirect transmission to a sleepy child. 180 * 181 * @param[in] aMessage The message to update. 182 * @param[in] aChild The (sleepy) child for indirect transmission. 183 * 184 * @retval kErrorNone Successfully removed the message for indirect transmission. 185 * @retval kErrorNotFound The message was not scheduled for indirect transmission to the child. 186 */ 187 Error RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild); 188 189 /** 190 * Removes all added messages for a specific child and frees message (with no indirect/direct tx). 191 * 192 * @param[in] aChild A reference to a child whose messages shall be removed. 193 */ 194 void ClearAllMessagesForSleepyChild(Child &aChild); 195 196 /** 197 * Finds the first queued message for a given sleepy child that also satisfies the conditions of a given 198 * `MessageChecker`. 199 * 200 * The caller MUST ensure that @p aChild is sleepy. 201 * 202 * @param[in] aChild The sleepy child to check. 203 * @param[in] aChecker The predicate function to apply. 204 * 205 * @returns A pointer to the matching queued message, or `nullptr` if none is found. 206 */ FindQueuedMessageForSleepyChild(const Child & aChild,MessageChecker aChecker)207 Message *FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) 208 { 209 return AsNonConst(AsConst(this)->FindQueuedMessageForSleepyChild(aChild, aChecker)); 210 } 211 212 /** 213 * Finds the first queued message for a given sleepy child that also satisfies the conditions of a given 214 * `MessageChecker`. 215 * 216 * The caller MUST ensure that @p aChild is sleepy. 217 * 218 * @param[in] aChild The sleepy child to check. 219 * @param[in] aChecker The predicate function to apply. 220 * 221 * @returns A pointer to the matching queued message, or `nullptr` if none is found. 222 */ 223 const Message *FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const; 224 225 /** 226 * Indicates whether there is any queued message for a given sleepy child that also satisfies the conditions of a 227 * given `MessageChecker`. 228 * 229 * The caller MUST ensure that @p aChild is sleepy. 230 * 231 * @param[in] aChild The sleepy child to check for. 232 * @param[in] aChecker The predicate function to apply. 233 * 234 * @retval TRUE There is a queued message satisfying @p aChecker for sleepy child @p aChild. 235 * @retval FALSE There is no queued message satisfying @p aChecker for sleepy child @p aChild. 236 */ HasQueuedMessageForSleepyChild(const Child & aChild,MessageChecker aChecker) const237 bool HasQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const 238 { 239 return (FindQueuedMessageForSleepyChild(aChild, aChecker) != nullptr); 240 } 241 242 /** 243 * Sets whether to use the extended or short address for a child. 244 * 245 * @param[in] aChild A reference to the child. 246 * @param[in] aUseShortAddress `true` to use short address, `false` to use extended address. 247 */ 248 void SetChildUseShortAddress(Child &aChild, bool aUseShortAddress); 249 250 /** 251 * Handles a child mode change and updates any queued messages for the child accordingly. 252 * 253 * @param[in] aChild The child whose device mode was changed. 254 * @param[in] aOldMode The old device mode of the child. 255 */ 256 void HandleChildModeChange(Child &aChild, Mle::DeviceMode aOldMode); 257 258 #endif // OPENTHREAD_FTD 259 260 private: 261 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 262 // Callbacks from `CslTxScheduler` 263 Error PrepareFrameForCslNeighbor(Mac::TxFrame &aFrame, FrameContext &aContext, CslNeighbor &aCslNeighbor); 264 void HandleSentFrameToCslNeighbor(const Mac::TxFrame &aFrame, 265 const FrameContext &aContext, 266 Error aError, 267 CslNeighbor &aCslNeighbor); 268 #endif 269 270 #if OPENTHREAD_FTD 271 // Callbacks from `DataPollHandler` 272 Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild); 273 void HandleSentFrameToChild(const Mac::TxFrame &aFrame, const FrameContext &aContext, Error aError, Child &aChild); 274 void HandleFrameChangeDone(Child &aChild); 275 276 void UpdateIndirectMessage(Child &aChild); 277 void RequestMessageUpdate(Child &aChild); 278 uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, Child &aChild, Message &aMessage); 279 void PrepareEmptyFrame(Mac::TxFrame &aFrame, Child &aChild, bool aAckRequest); 280 void ClearMessagesForRemovedChildren(void); 281 282 static bool AcceptAnyMessage(const Message &aMessage); 283 static bool AcceptSupervisionMessage(const Message &aMessage); 284 #endif // OPENTHREAD_FTD 285 286 bool mEnabled; 287 #if OPENTHREAD_FTD 288 SourceMatchController mSourceMatchController; 289 DataPollHandler mDataPollHandler; 290 #endif 291 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 292 CslTxScheduler mCslTxScheduler; 293 #endif 294 }; 295 296 #endif // #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 297 298 /** 299 * @} 300 */ 301 302 } // namespace ot 303 304 #endif // INDIRECT_SENDER_HPP_ 305