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 #if OPENTHREAD_FTD 40 41 #include "common/locator.hpp" 42 #include "common/message.hpp" 43 #include "common/non_copyable.hpp" 44 #include "mac/data_poll_handler.hpp" 45 #include "mac/mac_frame.hpp" 46 #include "thread/csl_tx_scheduler.hpp" 47 #include "thread/indirect_sender_frame_context.hpp" 48 #include "thread/mle_types.hpp" 49 #include "thread/src_match_controller.hpp" 50 51 namespace ot { 52 53 /** 54 * @addtogroup core-mesh-forwarding 55 * 56 * @brief 57 * This module includes definitions for handling indirect transmissions. 58 * 59 * @{ 60 */ 61 62 class Child; 63 64 /** 65 * This class implements indirect transmission. 66 * 67 */ 68 class IndirectSender : public InstanceLocator, public IndirectSenderBase, private NonCopyable 69 { 70 friend class Instance; 71 friend class DataPollHandler::Callbacks; 72 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 73 friend class CslTxScheduler::Callbacks; 74 #endif 75 76 public: 77 /** 78 * This class defines all the child info required for indirect transmission. 79 * 80 * `Child` class publicly inherits from this class. 81 * 82 */ 83 class ChildInfo 84 { 85 friend class IndirectSender; 86 friend class DataPollHandler; 87 friend class CslTxScheduler; 88 friend class SourceMatchController; 89 90 public: 91 /** 92 * This method returns the number of queued messages for the child. 93 * 94 * @returns Number of queued messages for the child. 95 * 96 */ GetIndirectMessageCount(void) const97 uint16_t GetIndirectMessageCount(void) const { return mQueuedMessageCount; } 98 99 private: GetIndirectMessage(void)100 Message *GetIndirectMessage(void) { return mIndirectMessage; } SetIndirectMessage(Message * aMessage)101 void SetIndirectMessage(Message *aMessage) { mIndirectMessage = aMessage; } 102 GetIndirectFragmentOffset(void) const103 uint16_t GetIndirectFragmentOffset(void) const { return mIndirectFragmentOffset; } SetIndirectFragmentOffset(uint16_t aFragmentOffset)104 void SetIndirectFragmentOffset(uint16_t aFragmentOffset) { mIndirectFragmentOffset = aFragmentOffset; } 105 GetIndirectTxSuccess(void) const106 bool GetIndirectTxSuccess(void) const { return mIndirectTxSuccess; } SetIndirectTxSuccess(bool aTxStatus)107 void SetIndirectTxSuccess(bool aTxStatus) { mIndirectTxSuccess = aTxStatus; } 108 IsIndirectSourceMatchShort(void) const109 bool IsIndirectSourceMatchShort(void) const { return mUseShortAddress; } SetIndirectSourceMatchShort(bool aShort)110 void SetIndirectSourceMatchShort(bool aShort) { mUseShortAddress = aShort; } 111 IsIndirectSourceMatchPending(void) const112 bool IsIndirectSourceMatchPending(void) const { return mSourceMatchPending; } SetIndirectSourceMatchPending(bool aPending)113 void SetIndirectSourceMatchPending(bool aPending) { mSourceMatchPending = aPending; } 114 IncrementIndirectMessageCount(void)115 void IncrementIndirectMessageCount(void) { mQueuedMessageCount++; } DecrementIndirectMessageCount(void)116 void DecrementIndirectMessageCount(void) { mQueuedMessageCount--; } ResetIndirectMessageCount(void)117 void ResetIndirectMessageCount(void) { mQueuedMessageCount = 0; } 118 IsWaitingForMessageUpdate(void) const119 bool IsWaitingForMessageUpdate(void) const { return mWaitingForMessageUpdate; } SetWaitingForMessageUpdate(bool aNeedsUpdate)120 void SetWaitingForMessageUpdate(bool aNeedsUpdate) { mWaitingForMessageUpdate = aNeedsUpdate; } 121 122 const Mac::Address &GetMacAddress(Mac::Address &aMacAddress) const; 123 124 Message *mIndirectMessage; // Current indirect message. 125 uint16_t mIndirectFragmentOffset : 14; // 6LoWPAN fragment offset for the indirect message. 126 bool mIndirectTxSuccess : 1; // Indicates tx success/failure of current indirect message. 127 bool mWaitingForMessageUpdate : 1; // Indicates waiting for updating the indirect message. 128 uint16_t mQueuedMessageCount : 14; // Number of queued indirect messages for the child. 129 bool mUseShortAddress : 1; // Indicates whether to use short or extended address. 130 bool mSourceMatchPending : 1; // Indicates whether or not pending to add to src match table. 131 132 static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < (1UL << 14), 133 "mQueuedMessageCount cannot fit max required!"); 134 }; 135 136 /** 137 * This constructor initializes the object. 138 * 139 * @param[in] aInstance A reference to the OpenThread instance. 140 * 141 */ 142 explicit IndirectSender(Instance &aInstance); 143 144 /** 145 * This method enables indirect transmissions. 146 * 147 */ Start(void)148 void Start(void) { mEnabled = true; } 149 150 /** 151 * This method disables indirect transmission. 152 * 153 * Any previously scheduled indirect transmission is canceled. 154 * 155 */ 156 void Stop(void); 157 158 /** 159 * This method adds a message for indirect transmission to a sleepy child. 160 * 161 * @param[in] aMessage The message to add. 162 * @param[in] aChild The (sleepy) child for indirect transmission. 163 * 164 */ 165 void AddMessageForSleepyChild(Message &aMessage, Child &aChild); 166 167 /** 168 * This method removes a message for indirect transmission to a sleepy child. 169 * 170 * @param[in] aMessage The message to update. 171 * @param[in] aChild The (sleepy) child for indirect transmission. 172 * 173 * @retval kErrorNone Successfully removed the message for indirect transmission. 174 * @retval kErrorNotFound The message was not scheduled for indirect transmission to the child. 175 * 176 */ 177 Error RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild); 178 179 /** 180 * This method removes all added messages for a specific child and frees message (with no indirect/direct tx). 181 * 182 * @param[in] aChild A reference to a child whose messages shall be removed. 183 * 184 */ 185 void ClearAllMessagesForSleepyChild(Child &aChild); 186 187 /** 188 * This method sets whether to use the extended or short address for a child. 189 * 190 * @param[in] aChild A reference to the child. 191 * @param[in] aUseShortAddress `true` to use short address, `false` to use extended address. 192 * 193 */ 194 void SetChildUseShortAddress(Child &aChild, bool aUseShortAddress); 195 196 /** 197 * This method handles a child mode change and updates any queued messages for the child accordingly. 198 * 199 * @param[in] aChild The child whose device mode was changed. 200 * @param[in] aOldMode The old device mode of the child. 201 * 202 */ 203 void HandleChildModeChange(Child &aChild, Mle::DeviceMode aOldMode); 204 205 private: 206 /** 207 * Indicates whether to set/enable 15.4 ack request in the MAC header of a supervision message. 208 * 209 */ 210 static constexpr bool kSupervisionMsgAckRequest = (OPENTHREAD_CONFIG_CHILD_SUPERVISION_MSG_NO_ACK_REQUEST == 0); 211 212 // Callbacks from DataPollHandler 213 Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild); 214 void HandleSentFrameToChild(const Mac::TxFrame &aFrame, const FrameContext &aContext, Error aError, Child &aChild); 215 void HandleFrameChangeDone(Child &aChild); 216 217 void UpdateIndirectMessage(Child &aChild); 218 Message *FindIndirectMessage(Child &aChild, bool aSupervisionTypeOnly = false); 219 void RequestMessageUpdate(Child &aChild); 220 uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, Child &aChild, Message &aMessage); 221 void PrepareEmptyFrame(Mac::TxFrame &aFrame, Child &aChild, bool aAckRequest); 222 void ClearMessagesForRemovedChildren(void); 223 224 bool mEnabled; 225 SourceMatchController mSourceMatchController; 226 DataPollHandler mDataPollHandler; 227 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 228 CslTxScheduler mCslTxScheduler; 229 #endif 230 }; 231 232 /** 233 * @} 234 * 235 */ 236 237 } // namespace ot 238 239 #endif // OPENTHREAD_FTD 240 241 #endif // INDIRECT_SENDER_HPP_ 242