1 /*
2  *  Copyright (c) 2016-2018, 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 definition for AnnounceSender.
32  */
33 
34 #ifndef ANNOUNCE_SENDER_HPP_
35 #define ANNOUNCE_SENDER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/locator.hpp"
40 #include "common/non_copyable.hpp"
41 #include "common/notifier.hpp"
42 #include "common/timer.hpp"
43 #include "common/trickle_timer.hpp"
44 #include "mac/mac.hpp"
45 
46 namespace ot {
47 
48 /**
49  * This class implements the base class for an `AnnounceSender` and `AnnounceBeginSever`.
50  *
51  * This class provides APIs to schedule periodic transmission of MLE Announcement messages for a given number
52  * transmissions per channel.
53  */
54 class AnnounceSenderBase : public InstanceLocator, private NonCopyable
55 {
56 protected:
57     /**
58      * This constant defines the special channel value to start from the first channel in the channel mask.
59      *
60      */
61     static constexpr uint8_t kChannelIteratorFirst = Mac::ChannelMask::kChannelIteratorFirst;
62 
63     /**
64      * This constructor initializes the object.
65      *
66      * @param[in]  aInstance   A reference to the OpenThread instance.
67      * @param[in]  aHandler    A timer handler provided by sub-class.
68      *
69      */
70     AnnounceSenderBase(Instance &aInstance, Timer::Handler aHandler);
71 
72     /**
73      * This method schedules the MLE Announce transmissions.
74      *
75      * This method requests @p aCount additional MLE transmission cycles to be scheduled. Each cycle covers all the
76      * channels in the specified channel mask from `GetChannelMask()`, with `GetPeriod()` as the time interval between
77      * any two successive MLE Announcement transmissions (possibly) on different channels from the mask. The
78      * `GetJitter()` value is used to add a random interval from `[-jitter, jitter]` to each period interval.
79      *
80      * If a "starting channel" is specified using `SetStartingChannel()`, then the cycle starts with MLE Announce
81      * transmission on the given starting channel. Otherwise the cycle starts with the first channel (with smallest
82      * channel number) in the mask.
83      *
84      * If a previously requested MLE Announce transmission is still ongoing, a subsequent call to this method adds
85      * the @p aCount cycles to the schedule.
86      *
87      * If there is no active MLE Announce transmission, after call to `SendAnnounce()`, the first MLE Announce
88      * transmission happens within a short random interval selected from range `[0, jitter]`.
89      *
90      * @param[in]  aCount     The number of cycles to schedule.
91      *
92      */
93     void SendAnnounce(uint8_t aCount);
94 
95     /**
96      * This method stops the ongoing MLE Announce transmissions.
97      *
98      */
99     void Stop(void);
100 
101     /**
102      * This method indicates whether a previously scheduled MLE Announce transmission is currently in progress or is
103      * finished.
104      *
105      * @returns TRUE if the MLE Announce transmission is in progress, FALSE otherwise.
106      *
107      */
IsRunning(void) const108     bool IsRunning(void) const { return mTimer.IsRunning(); }
109 
110     /**
111      * This method gets the period interval.
112      *
113      * @returns The period interval (in milliseconds).
114      *
115      */
GetPeriod(void) const116     uint32_t GetPeriod(void) const { return mPeriod; }
117 
118     /**
119      * This method sets the period interval.
120      *
121      * The period along with jitter value from (`Get/SetJitter()`) determines the interval between two successive MLE
122      * Announcement transmissions (possibly) on different channels from the specified channel mask.
123      *
124      * @param[in] aPeriod   The period interval (in milliseconds).
125      *
126      */
SetPeriod(uint32_t aPeriod)127     void SetPeriod(uint32_t aPeriod) { mPeriod = aPeriod; }
128 
129     /**
130      * This method gets the current jitter interval.
131      *
132      * @returns The jitter interval (in milliseconds).
133      *
134      */
GetJitter(void) const135     uint16_t GetJitter(void) const { return mJitter; }
136 
137     /**
138      * This method sets the jitter interval.
139      *
140      * @param[in] aJitter  The jitter interval (in milliseconds).
141      *
142      */
SetJitter(uint16_t aJitter)143     void SetJitter(uint16_t aJitter) { mJitter = aJitter; }
144 
145     /**
146      * This method gets the channel mask.
147      *
148      * @returns The channel mask.
149      *
150      */
GetChannelMask(void) const151     const Mac::ChannelMask GetChannelMask(void) const { return mChannelMask; }
152 
153     /**
154      * This method sets the channel mask.
155      *
156      * @param[in] aChannelMask   The channel mask.
157      *
158      */
159     void SetChannelMask(Mac::ChannelMask aChannelMask);
160 
161     /**
162      * This method gets the starting channel, i.e., the first channel in a TX cycle to send MLE Announcement on.
163      *
164      * @returns The current starting channel.
165      *
166      */
GetStartingChannel(void) const167     uint8_t GetStartingChannel(void) const { return mStartingChannel; }
168 
169     /**
170      * This method sets the starting channel, i.e., the first channel in a TX cycle to send MLE Announcement on.
171      *
172      * @p aStartingChannel MUST be present in the current channel mask (from `GetChannelMask()`), otherwise it is
173      * ignored and an MLE transmission cycle starts with the first channel (with smallest channel number) in the channel
174      * mask.
175      *
176      * @param[in] aStartingChannel  The starting channel.
177      *
178      */
179     void SetStartingChannel(uint8_t aStartingChannel);
180 
181     /**
182      * This method is the timer handler and must be invoked by sub-class when the timer expires from the `aHandler`
183      * callback function provided in the constructor.
184      *
185      */
186     void HandleTimer(void);
187 
188 private:
189     void SelectStartingChannel(void);
190 
191     Mac::ChannelMask mChannelMask;
192     uint32_t         mPeriod;
193     uint16_t         mJitter;
194     uint8_t          mCount;
195     uint8_t          mChannel;
196     uint8_t          mStartingChannel;
197     TimerMilli       mTimer;
198 };
199 
200 #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
201 
202 /**
203  * This class implements an AnnounceSender.
204  *
205  */
206 class AnnounceSender : public AnnounceSenderBase
207 {
208     friend class ot::Notifier;
209 
210 public:
211     /**
212      * This constructor initializes the object.
213      *
214      * @param[in]  aInstance   A reference to the OpenThread instance.
215      *
216      */
217     explicit AnnounceSender(Instance &aInstance);
218 
219     /**
220      * This method notifies the `AnnounceSender` that a MLE Announcement message was received with a current timestamp
221      * to update its internal state (decide whether or not to skip transmission of MLE Announcement in this cycle).
222      *
223      */
224     void UpdateOnReceivedAnnounce(void);
225 
226 private:
227     // Specifies the time interval (in milliseconds) between
228     // `AnnounceSender` transmit cycles. Within a cycle, device
229     // sends MLE Announcements on all channels from Active
230     // Dataset's channel mask.
231     static constexpr uint32_t kInterval = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL;
232 
233     // Specifies the sub-interval (in millisecond) within a cycle
234     // to send MLE announcement messages. We use half of the cycle
235     // interval length for transmission. This ensures that the
236     // transmissions are finished before device needs to make a
237     // decision about the next cycle. This time is divided by the
238     // number of channels to determine the time between two
239     // successive Announce tx (on different channels).
240     static constexpr uint32_t kTxInterval = (kInterval / 2 + 1);
241 
242     // Specifies the number of MLE Announcement messages that the
243     // device must receive within a cycle interval to skip sending the
244     // Announcement itself. This is used as `mTrickleTimer` redundancy
245     // constant in `AnnounceSender`.
246     static constexpr uint16_t kRedundancyConstant = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_REDUNDANCY_CONSTANT;
247 
248     // Jitter interval (in milliseconds) applied to the period
249     // between any two successive MLE Announcement transmissions
250     // (possibly) on different channels.
251     static constexpr uint16_t kMaxJitter = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL;
252 
253     void        Stop(void);
254     static void HandleTimer(Timer &aTimer);
255     static void HandleTrickleTimer(TrickleTimer &aTimer);
256     void        HandleTrickleTimer(void);
257     void        HandleNotifierEvents(Events aEvents);
258     void        HandleRoleChanged(void);
259     void        HandleActiveDatasetChanged(void);
260     void        HandleThreadChannelChanged(void);
261 
262     TrickleTimer mTrickleTimer;
263 };
264 
265 #endif // OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
266 
267 /**
268  * @}
269  */
270 
271 } // namespace ot
272 
273 #endif // ANNOUNCE_SENDER_HPP_
274