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