mirror of
https://github.com/espressif/openthread.git
synced 2026-08-18 00:19:52 +00:00
[announce-sender] use trickle to limit number of announce tx (#6401)
This commit updates and enhances the `AnnounceSender` feature. When this feature is enabled, routers and REEDs periodically send MLE Announcements (on all channels from the channel mask in the current Active Operational Dataset). This commit updates the implementation to use `TrickleTimer` such that a device monitors the number of received Announce messages within a cycle and if the number is above a redundancy threshold, the device skips sending Announcement in that cycle itself. This helps limit the number of Announcement tx in cycle in a dense network. The same mechanism is used by both routers and REEDs.
This commit is contained in:
@@ -40,9 +40,7 @@
|
||||
*
|
||||
* Define as 1 to enable `AnnounceSender` which will periodically send MLE Announce message on all channels.
|
||||
*
|
||||
* The list of channels is determined from the Operational Dataset's ChannelMask. The period intervals are determined
|
||||
* by `OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER` and `OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED`
|
||||
* configuration options.
|
||||
* The list of channels is determined from the Operational Dataset's ChannelMask.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
|
||||
@@ -50,9 +48,9 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER
|
||||
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL
|
||||
*
|
||||
* Specifies the time interval (in milliseconds) between `AnnounceSender` transmit cycles on a device in Router role.
|
||||
* Specifies the time interval (in milliseconds) between `AnnounceSender` transmit cycles.
|
||||
*
|
||||
* In a cycle, the `AnnounceSender` sends MLE Announcement on all channels in Active Operational Dataset's ChannelMask.
|
||||
* The transmissions on different channels happen uniformly over the given interval (i.e., if there are 16 channels,
|
||||
@@ -62,22 +60,34 @@
|
||||
* Applicable only if `AnnounceSender` feature is enabled (see `OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE`).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER
|
||||
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER 688000 // 668 seconds = 11 min and 28 sec.
|
||||
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL
|
||||
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL 688000 // 688 seconds = 11 min and 28 sec.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED
|
||||
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_REDUNDANCY_CONSTANT
|
||||
*
|
||||
* Specifies the time interval (in milliseconds) between `AnnounceSender` transmit cycles on a device in REED role.
|
||||
* Specifies the number of MLE Announcement messages that the device must receive within a cycle interval to skip
|
||||
* sending the Announcement itself.
|
||||
*
|
||||
* This is similar to `OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER` but used when device is in REED role.
|
||||
* This is used as the trickle timer redundancy constant in `AnnounceSender`.
|
||||
*
|
||||
* Applicable only if `AnnounceSender` feature is enabled (see `OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE`).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED
|
||||
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED (668000 * 3)
|
||||
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_REDUNDANCY_CONSTANT
|
||||
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_REDUNDANCY_CONSTANT 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL
|
||||
*
|
||||
* Specifies the jitter interval (in milliseconds) used by `AnnounceSender`. A random jitter interval is applied to
|
||||
* the period between any two successive MLE Announcement transmissions (possibly) on different channels.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL
|
||||
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL 500
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_ANNOUNCE_SENDER_H_
|
||||
|
||||
@@ -496,4 +496,12 @@
|
||||
"OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRESSES"
|
||||
#endif
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER
|
||||
#error "OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER was replaced by OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL"
|
||||
#endif
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED
|
||||
#error "OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED was replaced by OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CORE_CONFIG_CHECK_H_
|
||||
|
||||
@@ -56,7 +56,10 @@ AnnounceBeginServer::AnnounceBeginServer(Instance &aInstance)
|
||||
|
||||
void AnnounceBeginServer::SendAnnounce(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod)
|
||||
{
|
||||
AnnounceSenderBase::SendAnnounce(Mac::ChannelMask(aChannelMask), aCount, aPeriod, kDefaultJitter);
|
||||
SetChannelMask(Mac::ChannelMask(aChannelMask));
|
||||
SetPeriod(aPeriod);
|
||||
SetJitter(kDefaultJitter);
|
||||
AnnounceSenderBase::SendAnnounce(aCount);
|
||||
}
|
||||
|
||||
void AnnounceBeginServer::HandleRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
|
||||
@@ -64,8 +64,6 @@ public:
|
||||
* @param[in] aCount The number of transmissions per channel.
|
||||
* @param[in] aPeriod The time between transmissions (milliseconds).
|
||||
*
|
||||
* @retval kErrorNone Successfully started the transmission process.
|
||||
*
|
||||
*/
|
||||
void SendAnnounce(uint32_t aChannelMask, uint8_t aCount = kDefaultCount, uint16_t aPeriod = kDefaultPeriod);
|
||||
|
||||
|
||||
@@ -46,34 +46,76 @@
|
||||
|
||||
namespace ot {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// AnnounceSenderBase
|
||||
|
||||
AnnounceSenderBase::AnnounceSenderBase(Instance &aInstance, Timer::Handler aHandler)
|
||||
: InstanceLocator(aInstance)
|
||||
, mPeriod(0)
|
||||
, mJitter(0)
|
||||
, mCount(0)
|
||||
, mChannel(0)
|
||||
, mStartingChannel(kChannelIteratorFirst)
|
||||
, mTimer(aInstance, aHandler)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnounceSenderBase::SendAnnounce(Mac::ChannelMask aChannelMask, uint8_t aCount, uint32_t aPeriod, uint16_t aJitter)
|
||||
void AnnounceSenderBase::SendAnnounce(uint8_t aCount)
|
||||
{
|
||||
VerifyOrExit(aPeriod != 0);
|
||||
VerifyOrExit(aJitter < aPeriod);
|
||||
if (IsRunning())
|
||||
{
|
||||
mCount += aCount;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
aChannelMask.Intersect(Get<Mac::Mac>().GetSupportedChannelMask());
|
||||
VerifyOrExit(!aChannelMask.IsEmpty());
|
||||
VerifyOrExit((mPeriod != 0) && !mChannelMask.IsEmpty());
|
||||
|
||||
SelectStartingChannel();
|
||||
|
||||
mCount = aCount;
|
||||
mChannel = mStartingChannel;
|
||||
|
||||
mTimer.Start(Random::NonCrypto::GetUint32InRange(0, mJitter + 1));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void AnnounceSenderBase::Stop(void)
|
||||
{
|
||||
mTimer.Stop();
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
void AnnounceSenderBase::SetChannelMask(Mac::ChannelMask aChannelMask)
|
||||
{
|
||||
mChannelMask = aChannelMask;
|
||||
mCount = aCount;
|
||||
mPeriod = aPeriod;
|
||||
mJitter = aJitter;
|
||||
mChannel = Mac::ChannelMask::kChannelIteratorFirst;
|
||||
mChannelMask.Intersect(Get<Mac::Mac>().GetSupportedChannelMask());
|
||||
|
||||
mTimer.Start(Random::NonCrypto::AddJitter(mPeriod, mJitter));
|
||||
VerifyOrExit(!mChannelMask.IsEmpty(), Stop());
|
||||
SelectStartingChannel();
|
||||
|
||||
otLogInfoMle("Starting periodic MLE Announcements tx, mask %s, count %u, period %u, jitter %u",
|
||||
aChannelMask.ToString().AsCString(), aCount, aPeriod, aJitter);
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void AnnounceSenderBase::SetStartingChannel(uint8_t aStartingChannel)
|
||||
{
|
||||
mStartingChannel = aStartingChannel;
|
||||
SelectStartingChannel();
|
||||
}
|
||||
|
||||
void AnnounceSenderBase::SelectStartingChannel(void)
|
||||
{
|
||||
// If the starting channel is not set or it is not present
|
||||
// in the channel mask, then start from the first channel
|
||||
// in the mask.
|
||||
|
||||
VerifyOrExit(!mChannelMask.IsEmpty());
|
||||
VerifyOrExit((mStartingChannel == kChannelIteratorFirst) || !mChannelMask.ContainsChannel(mStartingChannel));
|
||||
|
||||
mStartingChannel = kChannelIteratorFirst;
|
||||
IgnoreError(mChannelMask.GetNextChannel(mStartingChannel));
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -81,25 +123,23 @@ exit:
|
||||
|
||||
void AnnounceSenderBase::HandleTimer(void)
|
||||
{
|
||||
Error error;
|
||||
Get<Mle::MleRouter>().SendAnnounce(mChannel, false);
|
||||
|
||||
error = mChannelMask.GetNextChannel(mChannel);
|
||||
// Go to the next channel in the mask. If we have reached the end
|
||||
// of the channel mask, we start over from the first channel in
|
||||
// the mask. Once we get back to `mStartingChannel` we have
|
||||
// finished one full cycle and can decrement `mCount`.
|
||||
|
||||
if (error == kErrorNotFound)
|
||||
while (mChannelMask.GetNextChannel(mChannel) != kErrorNone)
|
||||
{
|
||||
if (mCount != 0)
|
||||
{
|
||||
mCount--;
|
||||
VerifyOrExit(mCount != 0);
|
||||
}
|
||||
|
||||
mChannel = Mac::ChannelMask::kChannelIteratorFirst;
|
||||
error = mChannelMask.GetNextChannel(mChannel);
|
||||
mChannel = kChannelIteratorFirst;
|
||||
}
|
||||
|
||||
OT_ASSERT(error == kErrorNone);
|
||||
|
||||
Get<Mle::MleRouter>().SendAnnounce(mChannel, false);
|
||||
if ((mChannel == mStartingChannel) && (mCount != 0))
|
||||
{
|
||||
mCount--;
|
||||
VerifyOrExit(mCount != 0);
|
||||
}
|
||||
|
||||
mTimer.Start(Random::NonCrypto::AddJitter(mPeriod, mJitter));
|
||||
|
||||
@@ -107,11 +147,28 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// AnnounceSender
|
||||
|
||||
#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
|
||||
|
||||
AnnounceSender::AnnounceSender(Instance &aInstance)
|
||||
: AnnounceSenderBase(aInstance, AnnounceSender::HandleTimer)
|
||||
, mTrickleTimer(aInstance, AnnounceSender::HandleTrickleTimer)
|
||||
{
|
||||
SetJitter(kMaxJitter);
|
||||
}
|
||||
|
||||
void AnnounceSender::UpdateOnReceivedAnnounce(void)
|
||||
{
|
||||
mTrickleTimer.IndicateConsistent();
|
||||
}
|
||||
|
||||
void AnnounceSender::Stop(void)
|
||||
{
|
||||
AnnounceSenderBase::Stop();
|
||||
mTrickleTimer.Stop();
|
||||
otLogInfoMle("[announce-sender] Stopped");
|
||||
}
|
||||
|
||||
void AnnounceSender::HandleTimer(Timer &aTimer)
|
||||
@@ -119,25 +176,54 @@ void AnnounceSender::HandleTimer(Timer &aTimer)
|
||||
aTimer.Get<AnnounceSender>().AnnounceSenderBase::HandleTimer();
|
||||
}
|
||||
|
||||
void AnnounceSender::CheckState(void)
|
||||
void AnnounceSender::HandleTrickleTimer(TrickleTimer &aTimer)
|
||||
{
|
||||
Mle::MleRouter & mle = Get<Mle::MleRouter>();
|
||||
uint32_t interval = kRouterTxInterval;
|
||||
uint32_t period;
|
||||
Mac::ChannelMask channelMask;
|
||||
aTimer.Get<AnnounceSender>().HandleTrickleTimer();
|
||||
}
|
||||
|
||||
switch (mle.GetRole())
|
||||
void AnnounceSender::HandleTrickleTimer(void)
|
||||
{
|
||||
// The trickle timer handler is called when
|
||||
// we do not receive enough Announce messages
|
||||
// within the current interval and therefore
|
||||
// the device itself needs to send Announce.
|
||||
// We then request one more cycle of Announce
|
||||
// message transmissions.
|
||||
|
||||
SendAnnounce(1);
|
||||
otLogInfoMle("[announce-sender] Schedule tx for one cycle");
|
||||
}
|
||||
|
||||
void AnnounceSender::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
if (aEvents.Contains(kEventThreadRoleChanged))
|
||||
{
|
||||
HandleRoleChanged();
|
||||
}
|
||||
|
||||
if (aEvents.Contains(kEventActiveDatasetChanged))
|
||||
{
|
||||
HandleActiveDatasetChanged();
|
||||
}
|
||||
|
||||
if (aEvents.Contains(kEventThreadChannelChanged))
|
||||
{
|
||||
HandleThreadChannelChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AnnounceSender::HandleRoleChanged(void)
|
||||
{
|
||||
switch (Get<Mle::Mle>().GetRole())
|
||||
{
|
||||
case Mle::kRoleRouter:
|
||||
case Mle::kRoleLeader:
|
||||
interval = kRouterTxInterval;
|
||||
case Mle::kRoleRouter:
|
||||
break;
|
||||
|
||||
case Mle::kRoleChild:
|
||||
#if OPENTHREAD_FTD
|
||||
if (mle.IsRouterEligible() && mle.IsRxOnWhenIdle())
|
||||
if (Get<Mle::MleRouter>().IsRouterEligible() && Get<Mle::Mle>().IsRxOnWhenIdle())
|
||||
{
|
||||
interval = kReedTxInterval;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -150,35 +236,44 @@ void AnnounceSender::CheckState(void)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) == kErrorNone, Stop());
|
||||
// Start the trickle timer with same min and max interval as the
|
||||
// desired Announce Tx cycle interval.
|
||||
|
||||
period = interval / channelMask.GetNumberOfChannels();
|
||||
|
||||
if (period < kMinTxPeriod)
|
||||
{
|
||||
period = kMinTxPeriod;
|
||||
}
|
||||
|
||||
VerifyOrExit(!IsRunning() || (period != GetPeriod()) || (GetChannelMask() != channelMask));
|
||||
|
||||
SendAnnounce(channelMask, 0, period, kMaxJitter);
|
||||
mTrickleTimer.Start(TrickleTimer::kModeTrickle, kInterval, kInterval, kRedundancyConstant);
|
||||
otLogInfoMle("[announce-sender] Started");
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void AnnounceSender::Stop(void)
|
||||
void AnnounceSender::HandleActiveDatasetChanged(void)
|
||||
{
|
||||
AnnounceSenderBase::Stop();
|
||||
otLogInfoMle("Stopping periodic MLE Announcements tx");
|
||||
Mac::ChannelMask channelMask;
|
||||
|
||||
SuccessOrExit(Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask));
|
||||
VerifyOrExit(!channelMask.IsEmpty());
|
||||
|
||||
VerifyOrExit(channelMask != GetChannelMask());
|
||||
|
||||
SetChannelMask(channelMask);
|
||||
SetPeriod(kTxInterval / channelMask.GetNumberOfChannels());
|
||||
otLogInfoMle("[announce-sender] ChannelMask:%s, period:%u", GetChannelMask().ToString().AsCString(), GetPeriod());
|
||||
|
||||
// When channel mask is changed, we also check and update the PAN
|
||||
// channel. This handles the case where `ThreadChannelChanged` event
|
||||
// may be received and processed before `ActiveDatasetChanged`
|
||||
// event.
|
||||
|
||||
HandleThreadChannelChanged();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void AnnounceSender::HandleNotifierEvents(Events aEvents)
|
||||
void AnnounceSender::HandleThreadChannelChanged(void)
|
||||
{
|
||||
if (aEvents.Contains(kEventThreadRoleChanged))
|
||||
{
|
||||
CheckState();
|
||||
}
|
||||
SetStartingChannel(Get<Mac::Mac>().GetPanChannel());
|
||||
otLogInfoMle("[announce-sender] StartingChannel:%d", GetStartingChannel());
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "common/notifier.hpp"
|
||||
#include "common/timer.hpp"
|
||||
#include "common/trickle_timer.hpp"
|
||||
#include "mac/mac.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -53,6 +54,15 @@ namespace ot {
|
||||
class AnnounceSenderBase : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
protected:
|
||||
enum : uint8_t
|
||||
{
|
||||
/**
|
||||
* This constant defines the special channel value to start from the first channel in the channel mask.
|
||||
*
|
||||
*/
|
||||
kChannelIteratorFirst = Mac::ChannelMask::kChannelIteratorFirst,
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
@@ -65,28 +75,34 @@ protected:
|
||||
/**
|
||||
* This method schedules the MLE Announce transmissions.
|
||||
*
|
||||
* This method schedules `aCount` MLE Announcement transmission cycles. Each cycle covers all the channel in
|
||||
* the `aChannelMask`, with `aPeriod` time interval between any two successive MLE Announcement transmissions
|
||||
* (possibly) on different channels from the given mask. The `aJitter` can be used to add a random jitter
|
||||
* of `[-aJitter, aJitter]` to `aPeriod` interval. A zero value for `aCount` indicates non-stop MLE Announcement
|
||||
* transmission cycles.
|
||||
* This method 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.
|
||||
*
|
||||
* @param[in] aChannelMask The channel mask providing the list of channels to use for transmission.
|
||||
* @param[in] aCount The number of transmissions per channel. Zero indicates non-stop transmissions.
|
||||
* @param[in] aPeriod The time between two successive MLE Announce transmissions (in milliseconds).
|
||||
* @param[in] aJitter Maximum random jitter added to @aPeriod per transmission (in milliseconds).
|
||||
* 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(Mac::ChannelMask aChannelMask, uint8_t aCount, uint32_t aPeriod, uint16_t aJitter);
|
||||
void SendAnnounce(uint8_t aCount);
|
||||
|
||||
/**
|
||||
* This method stops the ongoing MLE Announce transmissions.
|
||||
*
|
||||
*/
|
||||
void Stop(void) { mTimer.Stop(); }
|
||||
void Stop(void);
|
||||
|
||||
/**
|
||||
* This method indicates whether the latest scheduled MLE Announce transmission is currently in progress or is
|
||||
* This method 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.
|
||||
@@ -95,23 +111,76 @@ protected:
|
||||
bool IsRunning(void) const { return mTimer.IsRunning(); }
|
||||
|
||||
/**
|
||||
* This method gets the period for the latest scheduled MLE Announce transmission (the one in progress or the last
|
||||
* finished one).
|
||||
* This method gets the period interval.
|
||||
*
|
||||
* @returns The period interval (in milliseconds) between two successive MLE Announcement transmissions.
|
||||
* @returns The period interval (in milliseconds).
|
||||
*
|
||||
*/
|
||||
uint32_t GetPeriod(void) const { return mPeriod; }
|
||||
|
||||
/**
|
||||
* This method gets the channel mask for the latest scheduled MLE Announce transmission (the one in progress or the
|
||||
* last finished one).
|
||||
* This method sets the period interval.
|
||||
*
|
||||
* @returns A constant reference to channel mask
|
||||
* 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; }
|
||||
|
||||
/**
|
||||
* This method gets the current jitter interval.
|
||||
*
|
||||
* @returns The jitter interval (in milliseconds).
|
||||
*
|
||||
*/
|
||||
uint16_t GetJitter(void) const { return mJitter; }
|
||||
|
||||
/**
|
||||
* This method sets the jitter interval.
|
||||
*
|
||||
* @param[in] aJitter The jitter interval (in milliseconds).
|
||||
*
|
||||
*/
|
||||
void SetJitter(uint16_t aJitter) { mJitter = aJitter; }
|
||||
|
||||
/**
|
||||
* This method gets the channel mask.
|
||||
*
|
||||
* @returns The channel mask.
|
||||
*
|
||||
*/
|
||||
const Mac::ChannelMask GetChannelMask(void) const { return mChannelMask; }
|
||||
|
||||
/**
|
||||
* This method sets the channel mask.
|
||||
*
|
||||
* @param[in] aChannelMask The channel mask.
|
||||
*
|
||||
*/
|
||||
void SetChannelMask(Mac::ChannelMask aChannelMask);
|
||||
|
||||
/**
|
||||
* This method 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; }
|
||||
|
||||
/**
|
||||
* This method 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);
|
||||
|
||||
/**
|
||||
* This method is the timer handler and must be invoked by sub-class when the timer expires from the `aHandler`
|
||||
* callback function provided in the constructor.
|
||||
@@ -120,11 +189,14 @@ protected:
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -147,19 +219,56 @@ public:
|
||||
*/
|
||||
AnnounceSender(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* This method 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:
|
||||
enum
|
||||
enum : uint32_t
|
||||
{
|
||||
kRouterTxInterval = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER,
|
||||
kReedTxInterval = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED,
|
||||
kMinTxPeriod = 1000, // in ms
|
||||
kMaxJitter = 500, // in ms
|
||||
// Specifies the time interval (in milliseconds) between
|
||||
// `AnnounceSender` transmit cycles. With in a cycle, device
|
||||
// sends MLE Announcements on all channels from Active
|
||||
// Dataset's channel mask.
|
||||
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).
|
||||
kTxInterval = (kInterval / 2 + 1),
|
||||
};
|
||||
|
||||
enum : uint16_t
|
||||
{
|
||||
// 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`.
|
||||
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.
|
||||
kMaxJitter = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL,
|
||||
};
|
||||
|
||||
void CheckState(void);
|
||||
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
|
||||
|
||||
@@ -3840,10 +3840,14 @@ void Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessa
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing
|
||||
// timestamps are equal: no behaviour specified by the Thread spec.
|
||||
// If SendAnnounce is executed at this point, there exists a scenario where
|
||||
// multiple devices keep sending MLE Announce messages to one another indefinitely.
|
||||
// Timestamps are equal.
|
||||
|
||||
#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
|
||||
// Notify `AnnounceSender` of the received Announce
|
||||
// message so it can update its state to determine
|
||||
// whether to send Announce or not.
|
||||
Get<AnnounceSender>().UpdateOnReceivedAnnounce();
|
||||
#endif
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
@@ -415,6 +415,14 @@
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_CHANNEL_MANAGER_THRESHOLD_TO_CHANGE_CHANNEL (0xffff * 10 / 100)
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
|
||||
*
|
||||
* Define as 1 to enable `AnnounceSender` which will periodically send MLE Announce message on all channels.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user