• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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