/* * Copyright (c) 2016-2018, The OpenThread Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file * This file includes definition for AnnounceSender. */ #ifndef ANNOUNCE_SENDER_HPP_ #define ANNOUNCE_SENDER_HPP_ #include "openthread-core-config.h" #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "common/notifier.hpp" #include "common/timer.hpp" #include "common/trickle_timer.hpp" #include "mac/mac.hpp" namespace ot { /** * Implements the base class for an `AnnounceSender` and `AnnounceBeginSever`. * * Provides APIs to schedule periodic transmission of MLE Announcement messages for a given number * transmissions per channel. */ class AnnounceSenderBase : public InstanceLocator, private NonCopyable { protected: /** * This constant defines the special channel value to start from the first channel in the channel mask. */ static constexpr uint8_t kChannelIteratorFirst = Mac::ChannelMask::kChannelIteratorFirst; /** * Initializes the object. * * @param[in] aInstance A reference to the OpenThread instance. * @param[in] aHandler A timer handler provided by sub-class. */ AnnounceSenderBase(Instance &aInstance, Timer::Handler aHandler); /** * Schedules the MLE Announce transmissions. * * Requests @p aCount additional MLE transmission cycles to be scheduled. Each cycle covers all the * channels in the specified channel mask from `GetChannelMask()`, with `GetPeriod()` as the time interval between * any two successive MLE Announcement transmissions (possibly) on different channels from the mask. The * `GetJitter()` value is used to add a random interval from `[-jitter, jitter]` to each period interval. * * If a "starting channel" is specified using `SetStartingChannel()`, then the cycle starts with MLE Announce * transmission on the given starting channel. Otherwise the cycle starts with the first channel (with smallest * channel number) in the mask. * * If a previously requested MLE Announce transmission is still ongoing, a subsequent call to this method adds * the @p aCount cycles to the schedule. * * If there is no active MLE Announce transmission, after call to `SendAnnounce()`, the first MLE Announce * transmission happens within a short random interval selected from range `[0, jitter]`. * * @param[in] aCount The number of cycles to schedule. */ void SendAnnounce(uint8_t aCount); /** * Stops the ongoing MLE Announce transmissions. */ void Stop(void); /** * Indicates whether a previously scheduled MLE Announce transmission is currently in progress or is * finished. * * @returns TRUE if the MLE Announce transmission is in progress, FALSE otherwise. */ bool IsRunning(void) const { return mTimer.IsRunning(); } /** * Gets the period interval. * * @returns The period interval (in milliseconds). */ uint32_t GetPeriod(void) const { return mPeriod; } /** * Sets the period interval. * * The period along with jitter value from (`Get/SetJitter()`) determines the interval between two successive MLE * Announcement transmissions (possibly) on different channels from the specified channel mask. * * @param[in] aPeriod The period interval (in milliseconds). */ void SetPeriod(uint32_t aPeriod) { mPeriod = aPeriod; } /** * Gets the current jitter interval. * * @returns The jitter interval (in milliseconds). */ uint16_t GetJitter(void) const { return mJitter; } /** * Sets the jitter interval. * * @param[in] aJitter The jitter interval (in milliseconds). */ void SetJitter(uint16_t aJitter) { mJitter = aJitter; } /** * Gets the channel mask. * * @returns The channel mask. */ const Mac::ChannelMask GetChannelMask(void) const { return mChannelMask; } /** * Sets the channel mask. * * @param[in] aChannelMask The channel mask. */ void SetChannelMask(Mac::ChannelMask aChannelMask); /** * Gets the starting channel, i.e., the first channel in a TX cycle to send MLE Announcement on. * * @returns The current starting channel. */ uint8_t GetStartingChannel(void) const { return mStartingChannel; } /** * Sets the starting channel, i.e., the first channel in a TX cycle to send MLE Announcement on. * * @p aStartingChannel MUST be present in the current channel mask (from `GetChannelMask()`), otherwise it is * ignored and an MLE transmission cycle starts with the first channel (with smallest channel number) in the channel * mask. * * @param[in] aStartingChannel The starting channel. */ void SetStartingChannel(uint8_t aStartingChannel); /** * Is the timer handler and must be invoked by sub-class when the timer expires from the `aHandler` * callback function provided in the constructor. */ void HandleTimer(void); private: void SelectStartingChannel(void); Mac::ChannelMask mChannelMask; uint32_t mPeriod; uint16_t mJitter; uint8_t mCount; uint8_t mChannel; uint8_t mStartingChannel; TimerMilli mTimer; }; #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE /** * Implements an AnnounceSender. */ class AnnounceSender : public AnnounceSenderBase { friend class ot::Notifier; public: /** * Initializes the object. * * @param[in] aInstance A reference to the OpenThread instance. */ explicit AnnounceSender(Instance &aInstance); /** * Notifies the `AnnounceSender` that a MLE Announcement message was received with a current timestamp * to update its internal state (decide whether or not to skip transmission of MLE Announcement in this cycle). */ void UpdateOnReceivedAnnounce(void); private: // Specifies the time interval (in milliseconds) between // `AnnounceSender` transmit cycles. Within a cycle, device // sends MLE Announcements on all channels from Active // Dataset's channel mask. static constexpr uint32_t kInterval = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL; // Specifies the sub-interval (in millisecond) within a cycle // to send MLE announcement messages. We use half of the cycle // interval length for transmission. This ensures that the // transmissions are finished before device needs to make a // decision about the next cycle. This time is divided by the // number of channels to determine the time between two // successive Announce tx (on different channels). static constexpr uint32_t kTxInterval = (kInterval / 2 + 1); // Specifies the number of MLE Announcement messages that the // device must receive within a cycle interval to skip sending the // Announcement itself. This is used as `mTrickleTimer` redundancy // constant in `AnnounceSender`. static constexpr uint16_t kRedundancyConstant = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_REDUNDANCY_CONSTANT; // Jitter interval (in milliseconds) applied to the period // between any two successive MLE Announcement transmissions // (possibly) on different channels. static constexpr uint16_t kMaxJitter = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL; void Stop(void); static void HandleTimer(Timer &aTimer); static void HandleTrickleTimer(TrickleTimer &aTimer); void HandleTrickleTimer(void); void HandleNotifierEvents(Events aEvents); void HandleRoleChanged(void); void HandleActiveDatasetChanged(void); void HandleThreadChannelChanged(void); TrickleTimer mTrickleTimer; }; #endif // OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE /** * @} */ } // namespace ot #endif // ANNOUNCE_SENDER_HPP_