mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[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:
committed by
Jonathan Hui
parent
38a48b2b09
commit
7f901cf9c7
@@ -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>
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user