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  * This class implements a trickle timer.
56  *
57  */
58 class TrickleTimer : public TimerMilli
59 {
60 public:
61     /**
62      * This enumeration defines the modes of operation for the `TrickleTimer`.
63      *
64      */
65     enum Mode : uint8_t
66     {
67         kModeTrickle,    ///< Operate as the normal trickle logic (as per RFC 6206).
68         kModePlainTimer, ///< Operate as a plain periodic timer with random interval selected within min/max intervals.
69     };
70 
71     /**
72      * Special value for redundancy constant (aka `k`) to indicate infinity (when used, it disables trickle timer's
73      * suppression behavior, invoking the handler callback independent of number of "consistent" events).
74      *
75      */
76     static constexpr uint16_t kInfiniteRedundancyConstant = NumericLimits<uint16_t>::kMax;
77 
78     /**
79      * This function pointer is called when the timer expires (i.e., transmission should happen).
80      *
81      * @param[in]  aTimer  A reference to the trickle timer.
82      *
83      */
84     typedef void (&Handler)(TrickleTimer &aTimer);
85 
86     /**
87      * This constructor initializes a `TrickleTimer` instance.
88      *
89      * @param[in]  aInstance   A reference to the OpenThread instance.
90      * @param[in]  aHandler    A handler which is called when transmission should occur.
91      *
92      */
93     TrickleTimer(Instance &aInstance, Handler aHandler);
94 
95     /**
96      * This method indicates whether or not the trickle timer instance is running.
97      *
98      * @retval TRUE   If the trickle timer is running.
99      * @retval FALSE  If the trickle timer is not running.
100      *
101      */
IsRunning(void) const102     bool IsRunning(void) const { return TimerMilli::IsRunning(); }
103 
104     /**
105      * This method gets the current operation mode of the trickle timer.
106      *
107      * @returns The current operation mode of the timer.
108      *
109      */
GetMode(void) const110     Mode GetMode(void) const { return mMode; }
111 
112     /**
113      * This method starts the trickle timer.
114      *
115      * @param[in]  aMode                The operation mode of timer (trickle or plain periodic mode).
116      * @param[in]  aIntervalMin         The minimum interval for the timer in milliseconds.
117      * @param[in]  aIntervalMax         The maximum interval for the timer in milliseconds.
118      * @param[in]  aRedundancyConstant  The redundancy constant for the timer, also known as `k`. The default value
119      *                                  is set to `kInfiniteRedundancyConstant` which disables the suppression behavior
120      *                                  (i.e., handler is always invoked independent of number of "consistent" events).
121      *
122      */
123     void Start(Mode     aMode,
124                uint32_t aIntervalMin,
125                uint32_t aIntervalMax,
126                uint16_t aRedundancyConstant = kInfiniteRedundancyConstant);
127 
128     /**
129      * This method stops the trickle timer.
130      *
131      */
Stop(void)132     void Stop(void) { TimerMilli::Stop(); }
133 
134     /**
135      * This method indicates to the trickle timer a 'consistent' event.
136      *
137      * The 'consistent' events are used to control suppression behavior. The trickle timer keeps track of the number of
138      * 'consistent' events in each interval. The timer handler is invoked only if the number of `consistent` events
139      * received in the interval is less than the redundancy constant.
140      *
141      */
142     void IndicateConsistent(void);
143 
144     /**
145      * This method indicates to the trickle timer an 'inconsistent' event.
146      *
147      * Receiving an 'inconsistent' event causes the trickle timer to reset (i.e., start with interval set to the min
148      * value) unless the current interval being used is already equal to the min interval.
149      *
150      */
151     void IndicateInconsistent(void);
152 
153 private:
154     enum Phase : uint8_t
155     {
156         kBeforeRandomTime, // Trickle timer is before random time `t` in the current interval.
157         kAfterRandomTime,  // Trickle timer is after random time `t` in the current interval.
158     };
159 
160     void        StartNewInterval(void);
161     static void HandleTimer(Timer &aTimer);
162     void        HandleTimer(void);
163     void        HandleEndOfTimeInInterval(void);
164     void        HandleEndOfInterval(void);
165 
166     // Shadow base class `TimerMilli` methods to ensure they are hidden.
StartAt(void)167     void StartAt(void) {}
FireAt(void)168     void FireAt(void) {}
FireAtIfEarlier(void)169     void FireAtIfEarlier(void) {}
GetFireTime(void)170     void GetFireTime(void) {}
171 
172     uint32_t mIntervalMin;        // Minimum interval (aka `Imin`).
173     uint32_t mIntervalMax;        // Maximum interval (aka `Imax`).
174     uint32_t mInterval;           // Current interval (aka `I`).
175     uint32_t mTimeInInterval;     // Time in interval (aka `t`).
176     uint16_t mRedundancyConstant; // Redundancy constant (aka 'k').
177     uint16_t mCounter;            // A counter for number of "consistent" transmissions (aka 'c').
178     Handler  mHandler;            // Handler callback.
179     Mode     mMode;               // Trickle timer operation mode.
180     Phase    mPhase;              // Trickle timer phase (before or after time `t` in the current interval).
181 };
182 
183 /**
184  * @}
185  *
186  */
187 
188 } // namespace ot
189 
190 #endif // TRICKLE_TIMER_HPP_
191