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