/* * Copyright (c) 2017, The OpenThread Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file * This file includes definitions for data poll (mac data request command) sender. */ #ifndef DATA_POLL_MANAGER_HPP_ #define DATA_POLL_MANAGER_HPP_ #include "openthread-core-config.h" #include "common/code_utils.hpp" #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "common/timer.hpp" #include "mac/mac.hpp" #include "mac/mac_frame.hpp" #include "thread/neighbor.hpp" namespace ot { /** * @addtogroup core-data-poll-sender * * @brief * This module includes definitions for data poll sender. * * @{ */ /** * Implements the data poll (mac data request command) sender. * */ class DataPollSender : public InstanceLocator, private NonCopyable { public: static constexpr uint8_t kDefaultFastPolls = 8; ///< Default number of fast poll tx (@sa StartFastPolls). static constexpr uint8_t kMaxFastPolls = 15; ///< Maximum number of fast poll tx allowed. static constexpr uint8_t kMaxFastPollsUsers = 63; ///< Maximum number of the users of fast poll tx allowed. /** * Initializes the data poll sender object. * * @param[in] aInstance A reference to the OpenThread instance. * */ explicit DataPollSender(Instance &aInstance); /** * Instructs the data poll sender to start sending periodic data polls. * */ void StartPolling(void); /** * Instructs the data poll sender to stop sending periodic data polls. * */ void StopPolling(void); /** * Enqueues a data poll (an IEEE 802.15.4 Data Request) message. * * @retval kErrorNone Successfully enqueued a data poll message * @retval kErrorAlready A data poll message is already enqueued. * @retval kErrorInvalidState Device is not in rx-off-when-idle mode. * @retval kErrorNoBufs Insufficient message buffers available. * */ Error SendDataPoll(void); /** * Sets/clears a user-specified/external data poll period. * * Value of zero for `aPeriod` clears the user-specified poll period. * * If the user provides a non-zero poll period, the user value specifies the maximum period between data * request transmissions. Note that OpenThread may send data request transmissions more frequently when expecting * a control-message from a parent or in case of data poll transmission failures or timeouts, or when the specified * value is larger than the child timeout. * * A non-zero `aPeriod` should be larger than or equal to `OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD` (10ms) or * this method returns `kErrorInvalidArgs`. If a non-zero `aPeriod` is larger than maximum value of * `0x3FFFFFF ((1 << 26) - 1)`, it would be clipped to this value. * * @param[in] aPeriod The data poll period in milliseconds. * * @retval kErrorNone Successfully set/cleared user-specified poll period. * @retval kErrorInvalidArgs If aPeriod is invalid. * */ Error SetExternalPollPeriod(uint32_t aPeriod); /** * Gets the current user-specified/external data poll period. * * @returns The data poll period in milliseconds. * */ uint32_t GetExternalPollPeriod(void) const { return mExternalPollPeriod; } /** * Informs the data poll sender of success/error status of a previously requested poll frame * transmission. * * In case of transmit failure, the data poll sender may choose to send the next data poll more quickly (up to * some fixed number of attempts). * * @param[in] aFrame The data poll frame. * @param[in] aError Error status of a data poll message transmission. * */ void HandlePollSent(Mac::TxFrame &aFrame, Error aError); /** * Informs the data poll sender that a data poll timeout happened, i.e., when the ack in response to * a data request command indicated that a frame was pending, but no frame was received after timeout interval. * * Data poll sender may choose to transmit another data poll immediately (up to some fixed number of attempts). * */ void HandlePollTimeout(void); /** * Informs the data poll sender to process a received MAC frame. * * @param[in] aFrame A reference to the received frame to process. * */ void ProcessRxFrame(const Mac::RxFrame &aFrame); #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 /** * Informs the data poll sender to process a transmitted MAC frame. * * @param[in] aFrame A reference to the frame that was transmitted. * @param[in] aAckFrame A pointer to the ACK frame, `nullptr` if no ACK was received. * @param[in] aError kErrorNone when the frame was transmitted successfully, * kErrorNoAck when the frame was transmitted but no ACK was received, * kErrorChannelAccessFailure when the tx failed due to activity on the channel, * kErrorAbort when transmission was aborted for other reasons. * */ void ProcessTxDone(const Mac::TxFrame &aFrame, const Mac::RxFrame *aAckFrame, Error aError); #endif /** * Asks the data poll sender to recalculate the poll period. * * This is mainly used to inform the poll sender that a parameter impacting the poll period (e.g., the child's * timeout value which is used to determine the default data poll period) is modified. * */ void RecalculatePollPeriod(void); /** * Sets/clears the attach mode on data poll sender. * * When attach mode is enabled, the data poll sender will send data polls at a faster rate determined by * poll period configuration option `OPENTHREAD_CONFIG_MAC_ATTACH_DATA_POLL_PERIOD`. * * @param[in] aMode The mode value. * */ void SetAttachMode(bool aMode); /** * Asks data poll sender to send the next given number of polls at a faster rate (poll period defined * by `kFastPollPeriod`). This is used by OpenThread stack when it expects a response from the parent/sender. * * If @p aNumFastPolls is zero the default value specified by `kDefaultFastPolls` is used instead. The number of * fast polls is clipped by maximum value specified by `kMaxFastPolls`. * * Note that per `SendFastPolls()` would increase the internal reference count until up to the allowed maximum * value. If there are retransmission mechanism in the caller component, it should be responsible to call * `StopFastPolls()` the same times as `SendFastPolls()` it triggered to decrease the reference count properly, * guaranteeing to exit fast poll mode gracefully. Otherwise, fast poll would continue until all data polls are sent * out. * * @param[in] aNumFastPolls If non-zero, number of fast polls to send, if zero, default value is used instead. * */ void SendFastPolls(uint8_t aNumFastPolls = 0); /** * Asks data poll sender to stop fast polls when the expecting response is received. * */ void StopFastPolls(void); /** * Gets the maximum data polling period in use. * * The maximum data poll period is determined based as the minimum of the user-specified poll interval and the * default poll interval. * * @returns The maximum data polling period in use. * */ uint32_t GetKeepAlivePollPeriod(void) const; /** * Resets the timer for sending keep-alive messages. * */ void ResetKeepAliveTimer(void); /** * Returns the default maximum poll period. * * The default poll period is determined based on the child timeout interval, ensuing the child would send data poll * within the child's timeout. * * @returns The maximum default data polling interval (in msec). * */ uint32_t GetDefaultPollPeriod(void) const; /** * Prepares and returns a data request command frame. * * @param[in] aTxFrames The set of TxFrames for all radio links. * * @returns The data poll frame. * */ Mac::TxFrame *PrepareDataRequest(Mac::TxFrames &aTxFrames); private: static constexpr uint8_t kQuickPollsAfterTimeout = 5; // Quick data poll tx in case of back-to-back poll timeouts. static constexpr uint8_t kMaxPollRetxAttempts = OPENTHREAD_CONFIG_FAILED_CHILD_TRANSMISSIONS; static constexpr uint8_t kMaxCslPollRetxAttempts = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT; enum PollPeriodSelector : uint8_t { kUsePreviousPollPeriod, kRecalculatePollPeriod, }; // Poll period under different conditions (in milliseconds). static constexpr uint32_t kAttachDataPollPeriod = OPENTHREAD_CONFIG_MAC_ATTACH_DATA_POLL_PERIOD; static constexpr uint32_t kRetxPollPeriod = OPENTHREAD_CONFIG_MAC_RETX_POLL_PERIOD; static constexpr uint32_t kFastPollPeriod = 188; static constexpr uint32_t kMinPollPeriod = OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD; static constexpr uint32_t kMaxExternalPeriod = ((1 << 26) - 1); // ~18.6 hours. void ScheduleNextPoll(PollPeriodSelector aPollPeriodSelector); uint32_t CalculatePollPeriod(void) const; const Neighbor &GetParent(void) const; void HandlePollTimer(void) { IgnoreError(SendDataPoll()); } #if OPENTHREAD_CONFIG_MULTI_RADIO Error GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const; #else Error GetPollDestinationAddress(Mac::Address &aDest) const; #endif using PollTimer = TimerMilliIn; TimeMilli mTimerStartTime; uint32_t mPollPeriod; uint32_t mExternalPollPeriod : 26; // In milliseconds. uint8_t mFastPollsUsers : 6; // Number of callers which request fast polls. PollTimer mTimer; bool mEnabled : 1; // Indicates whether data polling is enabled/started. bool mAttachMode : 1; // Indicates whether in attach mode (to use attach poll period). bool mRetxMode : 1; // Indicates whether last poll tx failed at mac/radio layer (poll retx mode). uint8_t mPollTimeoutCounter : 4; // Poll timeouts counter (0 to `kQuickPollsAfterTimeout`). uint8_t mPollTxFailureCounter : 4; // Poll tx failure counter (0 to `kMaxPollRetxAttempts`). uint8_t mRemainingFastPolls : 4; // Number of remaining fast polls when in transient fast polling mode. }; /** * @} * */ } // namespace ot #endif // DATA_POLL_MANAGER_HPP_