1 /*
2  *  Copyright (c) 2016, 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 the trickle timer logic.
32  */
33 
34 #ifndef TRICKLE_TIMER_HPP_
35 #define TRICKLE_TIMER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/numeric_limits.hpp"
40 #include "common/timer.hpp"
41 
42 namespace ot {
43 
44 /**
45  * @addtogroup core-timer-trickle
46  *
47  * @brief
48  *   This module includes definitions for the trickle timer logic.
49  *
50  * @{
51  *
52  */
53 
54 /**
55  * Implements a trickle timer.
56  *
57  */
58 class TrickleTimer : public TimerMilli
59 {
60     friend class TrickleTimerTester;
61 
62 public:
63     /**
64      * Defines the modes of operation for the `TrickleTimer`.
65      *
66      */
67     enum Mode : uint8_t
68     {
69         kModeTrickle,    ///< Operate as the normal trickle logic (as per RFC 6206).
70         kModePlainTimer, ///< Operate as a plain periodic timer with random interval selected within min/max intervals.
71     };
72 
73     /**
74      * Special value for redundancy constant (aka `k`) to indicate infinity (when used, it disables trickle timer's
75      * suppression behavior, invoking the handler callback independent of number of "consistent" events).
76      *
77      */
78     static constexpr uint16_t kInfiniteRedundancyConstant = NumericLimits<uint16_t>::kMax;
79 
80     /**
81      * Pointer is called when the timer expires (i.e., transmission should happen).
82      *
83      * @param[in]  aTimer  A reference to the trickle timer.
84      *
85      */
86     typedef void (&Handler)(TrickleTimer &aTimer);
87 
88     /**
89      * Initializes a `TrickleTimer` instance.
90      *
91      * @param[in]  aInstance   A reference to the OpenThread instance.
92      * @param[in]  aHandler    A handler which is called when transmission should occur.
93      *
94      */
95     TrickleTimer(Instance &aInstance, Handler aHandler);
96 
97     /**
98      * Indicates whether or not the trickle timer instance is running.
99      *
100      * @retval TRUE   If the trickle timer is running.
101      * @retval FALSE  If the trickle timer is not running.
102      *
103      */
IsRunning(void) const104     bool IsRunning(void) const { return TimerMilli::IsRunning(); }
105 
106     /**
107      * Gets the current operation mode of the trickle timer.
108      *
109      * @returns The current operation mode of the timer.
110      *
111      */
GetMode(void) const112     Mode GetMode(void) const { return mMode; }
113 
114     /**
115      * Gets the interval min value of the trickle timer.
116      *
117      * @returns The interval min value in milliseconds.
118      *
119      */
GetIntervalMin(void) const120     uint32_t GetIntervalMin(void) const { return mIntervalMin; }
121 
122     /**
123      * Sets the interval min value of the trickle timer while timer is running.
124      *
125      * If @p aIntervalMin is smaller than the current `GetIntervalMax()` the interval max value is also updated to
126      * the new @p aIntervalMin (as if `SetIntervalMax(aIntervalMin)` was called).
127      *
128      * @param[in]  aIntervalMin   The minimum interval in milliseconds.
129      *
130      */
131     void SetIntervalMin(uint32_t aIntervalMin);
132 
133     /**
134      * Gets the interval max value of the trickle timer.
135      *
136      * @returns The interval max value in milliseconds.
137      *
138      */
GetIntervalMax(void) const139     uint32_t GetIntervalMax(void) const { return mIntervalMax; }
140 
141     /**
142      * Sets the interval max value of the trickle timer while timer is running.
143      *
144      * If the given @p aIntervalMax is smaller than the current `GetIntervalMin()`, the interval min value will be
145      * used instead.
146      *
147      * @param[in]  aIntervalMax  The maximum interval in milliseconds.
148      *
149      */
150     void SetIntervalMax(uint32_t aIntervalMax);
151 
152     /**
153      * This method starts the trickle timer.
154      *
155      * @param[in]  aMode                The operation mode of timer (trickle or plain periodic mode).
156      * @param[in]  aIntervalMin         The minimum interval for the timer in milliseconds.
157      * @param[in]  aIntervalMax         The maximum interval for the timer in milliseconds.
158      * @param[in]  aRedundancyConstant  The redundancy constant for the timer, also known as `k`. The default value
159      *                                  is set to `kInfiniteRedundancyConstant` which disables the suppression behavior
160      *                                  (i.e., handler is always invoked independent of number of "consistent" events).
161      *
162      */
163     void Start(Mode     aMode,
164                uint32_t aIntervalMin,
165                uint32_t aIntervalMax,
166                uint16_t aRedundancyConstant = kInfiniteRedundancyConstant);
167 
168     /**
169      * Stops the trickle timer.
170      *
171      */
Stop(void)172     void Stop(void) { TimerMilli::Stop(); }
173 
174     /**
175      * Indicates to the trickle timer a 'consistent' event.
176      *
177      * The 'consistent' events are used to control suppression behavior. The trickle timer keeps track of the number of
178      * 'consistent' events in each interval. The timer handler is invoked only if the number of `consistent` events
179      * received in the interval is less than the redundancy constant.
180      *
181      */
182     void IndicateConsistent(void);
183 
184     /**
185      * Indicates to the trickle timer an 'inconsistent' event.
186      *
187      * Receiving an 'inconsistent' event causes the trickle timer to reset (i.e., start with interval set to the min
188      * value) unless the current interval being used is already equal to the min interval.
189      *
190      */
191     void IndicateInconsistent(void);
192 
193 private:
194     enum Phase : uint8_t
195     {
196         kBeforeRandomTime, // Trickle timer is before random time `t` in the current interval.
197         kAfterRandomTime,  // Trickle timer is after random time `t` in the current interval.
198     };
199 
200     void        StartNewInterval(void);
201     static void HandleTimer(Timer &aTimer);
202     void        HandleTimer(void);
203     void        HandleEndOfTimeInInterval(void);
204     void        HandleEndOfInterval(void);
205     TimeMilli   GetStartTimeOfCurrentInterval(void) const;
206 
207     // Shadow base class `TimerMilli` methods to ensure they are hidden.
StartAt(void)208     void StartAt(void) {}
FireAt(void)209     void FireAt(void) {}
FireAtIfEarlier(void)210     void FireAtIfEarlier(void) {}
GetFireTime(void)211     void GetFireTime(void) {}
212 
213     uint32_t mIntervalMin;        // Minimum interval (aka `Imin`).
214     uint32_t mIntervalMax;        // Maximum interval (aka `Imax`).
215     uint32_t mInterval;           // Current interval (aka `I`).
216     uint32_t mTimeInInterval;     // Time in interval (aka `t`).
217     uint16_t mRedundancyConstant; // Redundancy constant (aka 'k').
218     uint16_t mCounter;            // A counter for number of "consistent" transmissions (aka 'c').
219     Handler  mHandler;            // Handler callback.
220     Mode     mMode;               // Trickle timer operation mode.
221     Phase    mPhase;              // Trickle timer phase (before or after time `t` in the current interval).
222 };
223 
224 /**
225  * @}
226  *
227  */
228 
229 } // namespace ot
230 
231 #endif // TRICKLE_TIMER_HPP_
232