1 /* 2 * Copyright (c) 2017, 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 data poll (mac data request command) sender. 32 */ 33 34 #ifndef DATA_POLL_MANAGER_HPP_ 35 #define DATA_POLL_MANAGER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/code_utils.hpp" 40 #include "common/locator.hpp" 41 #include "common/non_copyable.hpp" 42 #include "common/timer.hpp" 43 #include "mac/mac.hpp" 44 #include "mac/mac_frame.hpp" 45 #include "thread/topology.hpp" 46 47 namespace ot { 48 49 /** 50 * @addtogroup core-data-poll-sender 51 * 52 * @brief 53 * This module includes definitions for data poll sender. 54 * 55 * @{ 56 */ 57 58 /** 59 * This class implements the data poll (mac data request command) sender. 60 * 61 */ 62 63 class DataPollSender : public InstanceLocator, private NonCopyable 64 { 65 public: 66 static constexpr uint8_t kDefaultFastPolls = 8; ///< Default number of fast poll tx (@sa StartFastPolls). 67 static constexpr uint8_t kMaxFastPolls = 15; ///< Maximum number of fast poll tx allowed. 68 static constexpr uint8_t kMaxFastPollsUsers = 63; ///< Maximum number of the users of fast poll tx allowed. 69 70 /** 71 * This constructor initializes the data poll sender object. 72 * 73 * @param[in] aInstance A reference to the OpenThread instance. 74 * 75 */ 76 explicit DataPollSender(Instance &aInstance); 77 78 /** 79 * This method instructs the data poll sender to start sending periodic data polls. 80 * 81 */ 82 void StartPolling(void); 83 84 /** 85 * This method instructs the data poll sender to stop sending periodic data polls. 86 * 87 */ 88 void StopPolling(void); 89 90 /** 91 * This method enqueues a data poll (an IEEE 802.15.4 Data Request) message. 92 * 93 * @retval kErrorNone Successfully enqueued a data poll message 94 * @retval kErrorAlready A data poll message is already enqueued. 95 * @retval kErrorInvalidState Device is not in rx-off-when-idle mode. 96 * @retval kErrorNoBufs Insufficient message buffers available. 97 * 98 */ 99 Error SendDataPoll(void); 100 101 /** 102 * This method sets/clears a user-specified/external data poll period. 103 * 104 * Value of zero for `aPeriod` clears the user-specified poll period. 105 * 106 * If the user provides a non-zero poll period, the user value specifies the maximum period between data 107 * request transmissions. Note that OpenThread may send data request transmissions more frequently when expecting 108 * a control-message from a parent or in case of data poll transmission failures or timeouts, or when the specified 109 * value is larger than the child timeout. 110 * 111 * A non-zero `aPeriod` should be larger than or equal to `OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD` (10ms) or 112 * this method returns `kErrorInvalidArgs`. If a non-zero `aPeriod` is larger than maximum value of 113 * `0x3FFFFFF ((1 << 26) - 1)`, it would be clipped to this value. 114 * 115 * @param[in] aPeriod The data poll period in milliseconds. 116 * 117 * @retval kErrorNone Successfully set/cleared user-specified poll period. 118 * @retval kErrorInvalidArgs If aPeriod is invalid. 119 * 120 */ 121 Error SetExternalPollPeriod(uint32_t aPeriod); 122 123 /** 124 * This method gets the current user-specified/external data poll period. 125 * 126 * @returns The data poll period in milliseconds. 127 * 128 */ GetExternalPollPeriod(void) const129 uint32_t GetExternalPollPeriod(void) const { return mExternalPollPeriod; } 130 131 /** 132 * This method informs the data poll sender of success/error status of a previously requested poll frame 133 * transmission. 134 * 135 * In case of transmit failure, the data poll sender may choose to send the next data poll more quickly (up to 136 * some fixed number of attempts). 137 * 138 * @param[in] aFrame The data poll frame. 139 * @param[in] aError Error status of a data poll message transmission. 140 * 141 */ 142 void HandlePollSent(Mac::TxFrame &aFrame, Error aError); 143 144 /** 145 * This method informs the data poll sender that a data poll timeout happened, i.e., when the ack in response to 146 * a data request command indicated that a frame was pending, but no frame was received after timeout interval. 147 * 148 * Data poll sender may choose to transmit another data poll immediately (up to some fixed number of attempts). 149 * 150 */ 151 void HandlePollTimeout(void); 152 153 /** 154 * This method informs the data poll sender to process a received MAC frame. 155 * 156 * @param[in] aFrame A reference to the received frame to process. 157 * 158 */ 159 void ProcessRxFrame(const Mac::RxFrame &aFrame); 160 161 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 162 /** 163 * This method informs the data poll sender to process a transmitted MAC frame. 164 * 165 * @param[in] aFrame A reference to the frame that was transmitted. 166 * @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received. 167 * @param[in] aError kErrorNone when the frame was transmitted successfully, 168 * kErrorNoAck when the frame was transmitted but no ACK was received, 169 * kErrorChannelAccessFailure when the tx failed due to activity on the channel, 170 * kErrorAbort when transmission was aborted for other reasons. 171 * 172 */ 173 void ProcessTxDone(const Mac::TxFrame &aFrame, const Mac::RxFrame *aAckFrame, Error aError); 174 #endif 175 176 /** 177 * This method asks the data poll sender to recalculate the poll period. 178 * 179 * This is mainly used to inform the poll sender that a parameter impacting the poll period (e.g., the child's 180 * timeout value which is used to determine the default data poll period) is modified. 181 * 182 */ 183 void RecalculatePollPeriod(void); 184 185 /** 186 * This method sets/clears the attach mode on data poll sender. 187 * 188 * When attach mode is enabled, the data poll sender will send data polls at a faster rate determined by 189 * poll period configuration option `OPENTHREAD_CONFIG_MAC_ATTACH_DATA_POLL_PERIOD`. 190 * 191 * @param[in] aMode The mode value. 192 * 193 */ 194 void SetAttachMode(bool aMode); 195 196 /** 197 * This method asks data poll sender to send the next given number of polls at a faster rate (poll period defined 198 * by `kFastPollPeriod`). This is used by OpenThread stack when it expects a response from the parent/sender. 199 * 200 * If @p aNumFastPolls is zero the default value specified by `kDefaultFastPolls` is used instead. The number of 201 * fast polls is clipped by maximum value specified by `kMaxFastPolls`. 202 * 203 * Note that per `SendFastPolls()` would increase the internal reference count until up to the allowed maximum 204 * value. If there are retransmission mechanism in the caller component, it should be responsible to call 205 * `StopFastPolls()` the same times as `SendFastPolls()` it triggered to decrease the reference count properly, 206 * guaranteeing to exit fast poll mode gracefully. Otherwise, fast poll would continue until all data polls are sent 207 * out. 208 * 209 * @param[in] aNumFastPolls If non-zero, number of fast polls to send, if zero, default value is used instead. 210 * 211 */ 212 void SendFastPolls(uint8_t aNumFastPolls = 0); 213 214 /** 215 * This method asks data poll sender to stop fast polls when the expecting response is received. 216 * 217 */ 218 void StopFastPolls(void); 219 220 /** 221 * This method gets the maximum data polling period in use. 222 * 223 * The maximum data poll period is determined based as the minimum of the user-specified poll interval and the 224 * default poll interval. 225 * 226 * @returns The maximum data polling period in use. 227 * 228 */ 229 uint32_t GetKeepAlivePollPeriod(void) const; 230 231 /** 232 * This method resets the timer for sending keep-alive messages. 233 * 234 */ 235 void ResetKeepAliveTimer(void); 236 237 /** 238 * This method returns the default maximum poll period. 239 * 240 * The default poll period is determined based on the child timeout interval, ensuing the child would send data poll 241 * within the child's timeout. 242 * 243 * @returns The maximum default data polling interval (in msec). 244 * 245 */ 246 uint32_t GetDefaultPollPeriod(void) const; 247 248 /** 249 * This method prepares and returns a data request command frame. 250 * 251 * @param[in] aTxFrames The set of TxFrames for all radio links. 252 * 253 * @returns The data poll frame. 254 * 255 */ 256 Mac::TxFrame *PrepareDataRequest(Mac::TxFrames &aTxFrames); 257 258 private: 259 static constexpr uint8_t kQuickPollsAfterTimeout = 5; // Quick data poll tx in case of back-to-back poll timeouts. 260 static constexpr uint8_t kMaxPollRetxAttempts = OPENTHREAD_CONFIG_FAILED_CHILD_TRANSMISSIONS; 261 static constexpr uint8_t kMaxCslPollRetxAttempts = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT; 262 263 enum PollPeriodSelector : uint8_t 264 { 265 kUsePreviousPollPeriod, 266 kRecalculatePollPeriod, 267 }; 268 269 // Poll period under different conditions (in milliseconds). 270 static constexpr uint32_t kAttachDataPollPeriod = OPENTHREAD_CONFIG_MAC_ATTACH_DATA_POLL_PERIOD; 271 static constexpr uint32_t kRetxPollPeriod = OPENTHREAD_CONFIG_MAC_RETX_POLL_PERIOD; 272 static constexpr uint32_t kFastPollPeriod = 188; 273 static constexpr uint32_t kMinPollPeriod = OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD; 274 static constexpr uint32_t kMaxExternalPeriod = ((1 << 26) - 1); //< ~18.6 hours. 275 276 void ScheduleNextPoll(PollPeriodSelector aPollPeriodSelector); 277 uint32_t CalculatePollPeriod(void) const; 278 const Neighbor &GetParent(void) const; 279 static void HandlePollTimer(Timer &aTimer); 280 #if OPENTHREAD_CONFIG_MULTI_RADIO 281 Error GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const; 282 #else 283 Error GetPollDestinationAddress(Mac::Address &aDest) const; 284 #endif 285 286 TimeMilli mTimerStartTime; 287 uint32_t mPollPeriod; 288 uint32_t mExternalPollPeriod : 26; //< In milliseconds. 289 uint8_t mFastPollsUsers : 6; //< Number of callers which request fast polls. 290 291 TimerMilli mTimer; 292 293 bool mEnabled : 1; //< Indicates whether data polling is enabled/started. 294 bool mAttachMode : 1; //< Indicates whether in attach mode (to use attach poll period). 295 bool mRetxMode : 1; //< Indicates whether last poll tx failed at mac/radio layer (poll retx mode). 296 uint8_t mPollTimeoutCounter : 4; //< Poll timeouts counter (0 to `kQuickPollsAfterTimout`). 297 uint8_t mPollTxFailureCounter : 4; //< Poll tx failure counter (0 to `kMaxPollRetxAttempts`). 298 uint8_t mRemainingFastPolls : 4; //< Number of remaining fast polls when in transient fast polling mode. 299 }; 300 301 /** 302 * @} 303 * 304 */ 305 306 } // namespace ot 307 308 #endif // DATA_POLL_MANAGER_HPP_ 309