[announce-sender] feature to enable periodic tx of MLE Announce (#2693)

This commit adds a new feature/class namely `AnnounceSender` which
enables periodic transmission of MLE Announce messages on all
channels. The feature can be enabled using the config option
`OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER` (disabled by default).

This commit also adds some new helper methods in `Mac::ChannelMask`
to get number of channels in a given mask, and operator overloads
to compare two masks.
This commit is contained in:
Abtin Keshavarzian
2018-05-15 19:32:01 -07:00
committed by Jonathan Hui
parent 38a48b2b09
commit 7f901cf9c7
16 changed files with 547 additions and 55 deletions
+2
View File
@@ -124,6 +124,7 @@
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp" />
<ClCompile Include="..\..\src\core\thread\child_table.cpp" />
<ClCompile Include="..\..\src\core\thread\energy_scan_server.cpp" />
<ClCompile Include="..\..\src\core\thread\data_poll_manager.cpp" />
@@ -206,6 +207,7 @@
<ClInclude Include="..\..\src\core\net\udp6.hpp" />
<ClInclude Include="..\..\src\core\thread\address_resolver.hpp" />
<ClInclude Include="..\..\src\core\thread\announce_begin_server.hpp" />
<ClInclude Include="..\..\src\core\thread\announce_sender.hpp" />
<ClInclude Include="..\..\src\core\thread\energy_scan_server.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_client.hpp" />
@@ -345,6 +345,9 @@
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\common\crc16.cpp">
<Filter>Source Files\common</Filter>
</ClCompile>
@@ -458,6 +461,9 @@
<ClInclude Include="..\..\src\core\thread\announce_begin_server.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\thread\announce_sender.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\thread\child_table.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
@@ -132,6 +132,7 @@
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp" />
<ClCompile Include="..\..\src\core\thread\child_table.cpp" />
<ClCompile Include="..\..\src\core\thread\data_poll_manager.cpp" />
<ClCompile Include="..\..\src\core\thread\energy_scan_server.cpp" />
@@ -243,6 +244,7 @@
<ClInclude Include="..\..\src\core\openthread-core-default-config.h" />
<ClInclude Include="..\..\src\core\thread\address_resolver.hpp" />
<ClInclude Include="..\..\src\core\meshcop\announce_begin_server.hpp" />
<ClInclude Include="..\..\src\core\meshcop\announce_sender.hpp" />
<ClInclude Include="..\..\src\core\thread\child_table.hpp" />
<ClInclude Include="..\..\src\core\thread\data_poll_manager.hpp" />
<ClInclude Include="..\..\src\core\thread\energy_scan_server.hpp" />
@@ -333,6 +333,9 @@
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\meshcop\announce_begin_client.cpp">
<Filter>Source Files\meshcop</Filter>
</ClCompile>
@@ -590,6 +593,9 @@
<ClInclude Include="..\..\src\core\meshcop\announce_begin_server.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\meshcop\announce_sender.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\meshcop\announce_begin_client.hpp">
<Filter>Header Files\meshcop</Filter>
</ClInclude>
+2
View File
@@ -171,6 +171,7 @@ SOURCES_COMMON = \
net/udp6.cpp \
thread/address_resolver.cpp \
thread/announce_begin_server.cpp \
thread/announce_sender.cpp \
thread/child_table.cpp \
thread/data_poll_manager.cpp \
thread/energy_scan_server.cpp \
@@ -292,6 +293,7 @@ HEADERS_COMMON = \
net/udp6.hpp \
thread/address_resolver.hpp \
thread/announce_begin_server.hpp \
thread/announce_sender.hpp \
thread/child_table.hpp \
thread/data_poll_manager.hpp \
thread/energy_scan_server.hpp \
+10
View File
@@ -72,6 +72,9 @@ Instance::Instance(void)
#endif
#if OPENTHREAD_ENABLE_CHANNEL_MANAGER
, mChannelManager(*this)
#endif
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
, mAnnounceSender(*this)
#endif
, mMessagePool(*this)
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
@@ -417,6 +420,13 @@ template <> Utils::ChannelManager &Instance::Get(void)
}
#endif
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
template <> AnnounceSender &Instance::Get(void)
{
return GetAnnounceSender();
}
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
+15
View File
@@ -56,6 +56,7 @@
#include "common/notifier.hpp"
#include "common/settings.hpp"
#include "net/ip6.hpp"
#include "thread/announce_sender.hpp"
#include "thread/link_quality.hpp"
#include "thread/thread_netif.hpp"
#if OPENTHREAD_ENABLE_CHANNEL_MANAGER
@@ -329,6 +330,16 @@ public:
Utils::ChannelManager &GetChannelManager(void) { return mChannelManager; }
#endif
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
/**
* This method returns a reference to AnnounceSender object.
*
* @returns A reference to the AnnounceSender object.
*
*/
AnnounceSender &GetAnnounceSender(void) { return mAnnounceSender; }
#endif
/**
* This method returns a reference to message pool object.
*
@@ -404,6 +415,10 @@ private:
Utils::ChannelManager mChannelManager;
#endif
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
AnnounceSender mAnnounceSender;
#endif
MessagePool mMessagePool;
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
+13
View File
@@ -73,6 +73,19 @@ const uint32_t kMaxBackoffSum = kMinBackoff + (kUnitBackoffPeriod * OT_RADIO_SYM
static_assert(kMinBackoffSum > 0, "The min backoff value should be greater than zero!");
#endif
uint8_t ChannelMask::GetNumberOfChannels(void) const
{
uint8_t num = 0;
uint8_t channel = kChannelIteratorFirst;
while (GetNextChannel(channel) == OT_ERROR_NONE)
{
num++;
}
return num;
}
otError ChannelMask::GetNextChannel(uint8_t &aChannel) const
{
otError error = OT_ERROR_NOT_FOUND;
+28
View File
@@ -204,6 +204,14 @@ public:
*/
void Intersect(const ChannelMask &aOtherMask) { mMask &= aOtherMask.mMask; }
/**
* This method returns the number of channels in the mask.
*
* @returns Number of channels in the mask.
*
*/
uint8_t GetNumberOfChannels(void) const;
/**
* This method gets the next channel in the channel mask.
*
@@ -220,6 +228,26 @@ public:
*/
otError GetNextChannel(uint8_t &aChannel) const;
/**
* This method overloads `==` operator to indicate whether two masks are equal.
*
* @param[in] aAnother A reference to another mask to compare with the current one.
*
* @returns TRUE if the two masks are equal, FALSE otherwise.
*
*/
bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); }
/**
* This method overloads `!=` operator to indicate whether two masks are different.
*
* @param[in] aAnother A reference to another mask to compare with the current one.
*
* @returns TRUE if the two masks are different, FALSE otherwise.
*
*/
bool operator!=(const ChannelMask &aAnother) const { return (mMask != aAnother.mMask); }
/**
* This method converts the channel mask into a human-readable NULL-terminated string.
*
+45
View File
@@ -1353,6 +1353,51 @@
#define OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE 1
#endif
/**
* @def OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
*
* 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.
*
*/
#ifndef OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
#define OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER 0
#endif
/**
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER
*
* Specifies the time interval (in milliseconds) between `AnnounceSender` transmit cycles on a device in Router role.
*
* 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,
* there will be 16 MLE Announcement messages each on one channel with `interval / 16` between two consecutive MLE
* Announcement transmissions).
*
* Applicable only if `AnnounceSender` feature is enabled (see `OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER`).
*
*/
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER 688000 // 668 seconds = 11 min and 28 sec.
#endif
/**
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED
*
* Specifies the time interval (in milliseconds) between `AnnounceSender` transmit cycles on a device in REED role.
*
* This is similar to `OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER` but used when device is in REED role.
*
* Applicable only if `AnnounceSender` feature is enabled (see `OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER`).
*
*/
#ifndef OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED (668000 * 3)
#endif
/**
* @def OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
*
+4 -46
View File
@@ -52,12 +52,7 @@ using ot::Encoding::BigEndian::HostSwap32;
namespace ot {
AnnounceBeginServer::AnnounceBeginServer(Instance &aInstance)
: InstanceLocator(aInstance)
, mChannelMask(0)
, mPeriod(0)
, mCount(0)
, mChannel(0)
, mTimer(aInstance, &AnnounceBeginServer::HandleTimer, this)
: AnnounceSenderBase(aInstance, &AnnounceBeginServer::HandleTimer)
, mAnnounceBegin(OT_URI_PATH_ANNOUNCE_BEGIN, &AnnounceBeginServer::HandleRequest, this)
{
GetNetif().GetCoap().AddResource(mAnnounceBegin);
@@ -70,23 +65,7 @@ otError AnnounceBeginServer::SendAnnounce(uint32_t aChannelMask)
otError AnnounceBeginServer::SendAnnounce(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod)
{
otError error = OT_ERROR_NONE;
mChannelMask = aChannelMask;
mCount = aCount;
mPeriod = aPeriod;
mChannel = OT_RADIO_CHANNEL_MIN;
while ((mChannelMask & (1 << mChannel)) == 0)
{
mChannel++;
VerifyOrExit(mChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_INVALID_ARGS);
}
mTimer.Start(mPeriod);
exit:
return error;
return AnnounceSenderBase::SendAnnounce(Mac::ChannelMask(aChannelMask), aCount, aPeriod, kDefaultJitter);
}
void AnnounceBeginServer::HandleRequest(void * aContext,
@@ -98,6 +77,7 @@ void AnnounceBeginServer::HandleRequest(void * aContext,
*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void AnnounceBeginServer::HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
MeshCoP::ChannelMask0Tlv channelMask;
@@ -130,29 +110,7 @@ exit:
void AnnounceBeginServer::HandleTimer(Timer &aTimer)
{
aTimer.GetOwner<AnnounceBeginServer>().HandleTimer();
}
void AnnounceBeginServer::HandleTimer(void)
{
GetNetif().GetMle().SendAnnounce(mChannel++, false);
while (mCount > 0)
{
if (mChannelMask & (1 << mChannel))
{
mTimer.Start(mPeriod);
break;
}
mChannel++;
if (mChannel > OT_RADIO_CHANNEL_MAX)
{
mChannel = OT_RADIO_CHANNEL_MIN;
mCount--;
}
}
aTimer.GetOwner<AnnounceBeginServer>().AnnounceSenderBase::HandleTimer();
}
} // namespace ot
+3 -9
View File
@@ -42,6 +42,7 @@
#include "common/locator.hpp"
#include "common/timer.hpp"
#include "net/ip6_address.hpp"
#include "thread/announce_sender.hpp"
namespace ot {
@@ -49,7 +50,7 @@ namespace ot {
* This class implements handling Announce Begin Requests.
*
*/
class AnnounceBeginServer : public InstanceLocator
class AnnounceBeginServer : public AnnounceSenderBase
{
public:
/**
@@ -85,6 +86,7 @@ private:
{
kDefaultCount = 3,
kDefaultPeriod = 1000,
kDefaultJitter = 0,
};
static void HandleRequest(void * aContext,
@@ -94,14 +96,6 @@ private:
void HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
uint32_t mChannelMask;
uint16_t mPeriod;
uint8_t mCount;
uint8_t mChannel;
TimerMilli mTimer;
Coap::Resource mAnnounceBegin;
};
+217
View File
@@ -0,0 +1,217 @@
/*
* 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 implements the AnnounceSender.
*/
#define WPP_NAME "announce_sender.tmh"
#include "announce_sender.hpp"
#include <openthread/platform/radio.h>
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/logging.hpp"
#include "common/owner-locator.hpp"
#include "common/random.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
namespace ot {
AnnounceSenderBase::AnnounceSenderBase(Instance &aInstance, Timer::Handler aHandler)
: InstanceLocator(aInstance)
, mChannelMask()
, mPeriod(0)
, mJitter(0)
, mCount(0)
, mChannel(0)
, mTimer(aInstance, aHandler, this)
{
}
otError AnnounceSenderBase::SendAnnounce(Mac::ChannelMask aMask, uint8_t aCount, uint32_t aPeriod, uint16_t aJitter)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(aPeriod != 0, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aJitter < aPeriod, error = OT_ERROR_INVALID_ARGS);
aMask.Intersect(OT_RADIO_SUPPORTED_CHANNELS);
VerifyOrExit(!aMask.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
mChannelMask = aMask;
mCount = aCount;
mPeriod = aPeriod;
mJitter = aJitter;
mChannel = Mac::ChannelMask::kChannelIteratorFirst;
mTimer.Start(Random::AddJitter(mPeriod, mJitter));
exit:
return error;
}
void AnnounceSenderBase::HandleTimer(void)
{
otError error;
error = mChannelMask.GetNextChannel(mChannel);
if (error == OT_ERROR_NOT_FOUND)
{
if (mCount != 0)
{
mCount--;
VerifyOrExit(mCount != 0);
}
mChannel = Mac::ChannelMask::kChannelIteratorFirst;
error = mChannelMask.GetNextChannel(mChannel);
}
assert(error == OT_ERROR_NONE);
GetNetif().GetMle().SendAnnounce(mChannel, false);
mTimer.Start(Random::AddJitter(mPeriod, mJitter));
exit:
return;
}
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
AnnounceSender::AnnounceSender(Instance &aInstance)
: AnnounceSenderBase(aInstance, &AnnounceSender::HandleTimer)
, mNotifierCallback(HandleStateChanged, this)
{
aInstance.GetNotifier().RegisterCallback(mNotifierCallback);
}
void AnnounceSender::HandleTimer(Timer &aTimer)
{
aTimer.GetOwner<AnnounceSender>().AnnounceSenderBase::HandleTimer();
}
otError AnnounceSender::GetActiveDatasetChannelMask(Mac::ChannelMask &aMask) const
{
otError error = OT_ERROR_NONE;
const MeshCoP::ChannelMask0Tlv *channelMaskTlv;
MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp);
SuccessOrExit(error = GetNetif().GetActiveDataset().Get(dataset));
channelMaskTlv = static_cast<const MeshCoP::ChannelMask0Tlv *>(dataset.Get(MeshCoP::Tlv::kChannelMask));
VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND);
aMask.SetMask(channelMaskTlv->GetMask());
exit:
return error;
}
void AnnounceSender::CheckState(void)
{
Mle::MleRouter & mle = GetInstance().Get<Mle::MleRouter>();
uint32_t interval = kRouterTxInterval;
uint32_t period;
Mac::ChannelMask channelMask;
char string[Mac::ChannelMask::kInfoStringSize];
switch (mle.GetRole())
{
case OT_DEVICE_ROLE_ROUTER:
case OT_DEVICE_ROLE_LEADER:
period = kRouterTxInterval;
break;
case OT_DEVICE_ROLE_CHILD:
if (mle.IsRouterRoleEnabled() && (mle.GetDeviceMode() & Mle::ModeTlv::kModeRxOnWhenIdle))
{
period = kReedTxInterval;
break;
}
// fall through
case OT_DEVICE_ROLE_DISABLED:
case OT_DEVICE_ROLE_DETACHED:
Stop();
ExitNow();
}
VerifyOrExit(GetActiveDatasetChannelMask(channelMask) == OT_ERROR_NONE, Stop());
channelMask.Intersect(OT_RADIO_SUPPORTED_CHANNELS);
VerifyOrExit(!channelMask.IsEmpty(), Stop());
period = interval / channelMask.GetNumberOfChannels();
if (period < kMinTxPeriod)
{
period = kMinTxPeriod;
}
VerifyOrExit(!IsRunning() || (period != GetPeriod()) || (GetChannelMask() != channelMask));
SendAnnounce(channelMask, 0, period, kMaxJitter);
otLogInfoMle(GetInstance(), "Starting periodic MLE Announcements tx, period %u, mask %s", period,
channelMask.ToString(string, sizeof(string)));
OT_UNUSED_VARIABLE(string);
exit:
return;
}
void AnnounceSender::Stop(void)
{
AnnounceSenderBase::Stop();
otLogInfoMle(GetInstance(), "Stopping periodic MLE Announcements tx");
}
void AnnounceSender::HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags)
{
aCallback.GetOwner<AnnounceSender>().HandleStateChanged(aFlags);
}
void AnnounceSender::HandleStateChanged(uint32_t aFlags)
{
if ((aFlags & OT_CHANGED_THREAD_ROLE) != 0)
{
CheckState();
}
}
#endif // OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
} // namespace ot
+179
View File
@@ -0,0 +1,179 @@
/*
* 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 <openthread/types.h>
#include "common/locator.hpp"
#include "common/notifier.hpp"
#include "common/timer.hpp"
#include "mac/mac.hpp"
namespace ot {
/**
* This class implements the base class for an `AnnounceSender` and `AnnoucneBeginSever`.
*
* This class provides APIs to schedule periodic transmission of MLE Announcement messages for a given number
* transmissions per channel.
*/
class AnnounceSenderBase : public InstanceLocator
{
protected:
/**
* This constructor 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);
/**
* 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.
*
* @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).
*
* @retval OT_ERROR_NONE Successfully started the transmission process.
* @retval OT_ERROR_INVALID_ARGS @p aChanelMask is empty, or @p aPeriod is zero or smaller than @aJitter.
*
*/
otError SendAnnounce(Mac::ChannelMask aChannelMask, uint8_t aCount, uint32_t aPeriod, uint16_t aJitter);
/**
* This method stops the ongoing MLE Announce transmissions.
*
*/
void Stop(void) { mTimer.Stop(); }
/**
* This method indicates whether the latest 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(); }
/**
* This method gets the period for the latest scheduled MLE Announce transmission (the one in progress or the last
* finished one).
*
* @returns The period interval (in milliseconds) between two successive MLE Announcement transmissions.
*
*/
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).
*
* @returns A constant reference to channel mask
*
*/
const Mac::ChannelMask GetChannelMask(void) const { return mChannelMask; }
/**
* 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.
*
*/
void HandleTimer(void);
private:
Mac::ChannelMask mChannelMask;
uint32_t mPeriod;
uint16_t mJitter;
uint8_t mCount;
uint8_t mChannel;
TimerMilli mTimer;
};
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
/**
* This class implements an AnnounceSender.
*
*/
class AnnounceSender : public AnnounceSenderBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
AnnounceSender(Instance &aInstance);
private:
enum
{
kRouterTxInterval = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_ROUTER,
kReedTxInterval = OPENTHREAD_CONFIG_ANNOUNCE_SENDER_INTERVAL_REED,
kMinTxPeriod = 1000, // in ms
kMaxJitter = 500, // in ms
};
otError GetActiveDatasetChannelMask(Mac::ChannelMask &aMask) const;
void CheckState(void);
void Stop(void);
static void HandleTimer(Timer &aTimer);
static void HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags);
void HandleStateChanged(uint32_t aFlags);
Notifier::Callback mNotifierCallback;
};
#endif // OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
/**
* @}
*/
} // namespace ot
#endif // ANNOUNCE_SENDER_HPP_
+2
View File
@@ -59,6 +59,8 @@ public:
{
}
bool IsRouterRoleEnabled(void) const { return false; }
bool IsSingleton(void) { return false; }
otError BecomeRouter(ThreadStatusTlv::Status) { return OT_ERROR_NOT_CAPABLE; }
+13
View File
@@ -120,6 +120,8 @@ void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels,
{
VerifyOrQuit(!aMask.IsSingleChannel(), "ChannelMask.IsSingleChannel() failed\n");
}
VerifyOrQuit(aLength == aMask.GetNumberOfChannels(), "ChannelMask.GetNumberOfChannels() failed\n");
}
void TestMacChannelMask(void)
@@ -191,6 +193,17 @@ void TestMacChannelMask(void)
VerifyChannelMaskContent(mask2, channles4, sizeof(channles4));
printf("channels4 = %s\n", mask2.ToString(stringBuffer, sizeof(stringBuffer)));
mask1.Clear();
mask2.Clear();
VerifyOrQuit(mask1 == mask2, "ChannelMask.operator== failed\n");
mask1.SetMask(OT_RADIO_SUPPORTED_CHANNELS);
mask2.SetMask(OT_RADIO_SUPPORTED_CHANNELS);
VerifyOrQuit(mask1 == mask2, "ChannelMask.operator== failed\n");
mask1.Clear();
VerifyOrQuit(mask1 != mask2, "ChannelMask.operator== failed\n");
}
} // namespace ot