diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index 40085aae1..082576894 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -174,8 +174,6 @@ typedef uint32_t otChannelMaskPage0; #define OT_CHANNEL_25_MASK (1 << 25) ///< Channel 25 #define OT_CHANNEL_26_MASK (1 << 26) ///< Channel 26 -#define OT_CHANNEL_ALL 0xffffffff ///< All channels - /** * This structure represents presence of different components in Active or Pending Operational Dataset. * diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index af8b8aaad..9e8053d58 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -74,8 +74,7 @@ enum kSleepDelay = 300, ///< Max sleep delay when frame is pending (milliseconds). kNonceSize = 13, ///< Size of IEEE 802.15.4 Nonce (bytes). - kScanChannelsAll = OT_CHANNEL_ALL, ///< All channels. - kScanDurationDefault = 300, ///< Default interval between channels (milliseconds). + kScanDurationDefault = 300, ///< Default interval between channels (milliseconds). kMaxCsmaBackoffsDirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT, ///< macMaxCsmaBackoffs for direct transmissions diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index a09b67816..00882ed2a 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -214,6 +214,29 @@ exit: return error; } +otError DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const +{ + otError error; + const MeshCoP::ChannelMaskBaseTlv *channelMaskTlv; + const MeshCoP::ChannelMaskEntry * channelMaskEntry; + Dataset dataset(mLocal.GetType()); + + SuccessOrExit(error = mLocal.Get(dataset)); + + channelMaskTlv = static_cast(dataset.Get(MeshCoP::Tlv::kChannelMask)); + VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND); + + channelMaskEntry = channelMaskTlv->GetMaskEntry(OT_RADIO_CHANNEL_PAGE); + VerifyOrExit(channelMaskEntry != NULL, error = OT_ERROR_NOT_FOUND); + + aChannelMask.SetMask(channelMaskEntry->GetMask() & OT_RADIO_SUPPORTED_CHANNELS); + + VerifyOrExit(!aChannelMask.IsEmpty(), error = OT_ERROR_NOT_FOUND); + +exit: + return error; +} + void DatasetManager::HandleTimer(void) { ThreadNetif &netif = GetNetif(); diff --git a/src/core/meshcop/dataset_manager.hpp b/src/core/meshcop/dataset_manager.hpp index bd9bd4cbf..14684d445 100644 --- a/src/core/meshcop/dataset_manager.hpp +++ b/src/core/meshcop/dataset_manager.hpp @@ -40,6 +40,7 @@ #include "coap/coap.hpp" #include "common/locator.hpp" #include "common/timer.hpp" +#include "mac/channel_mask.hpp" #include "meshcop/dataset.hpp" #include "meshcop/dataset_local.hpp" #include "net/udp6.hpp" @@ -102,6 +103,17 @@ public: */ otError Get(otOperationalDataset &aDataset) const { return mLocal.Get(aDataset); } + /** + * This method retrieves the channel mask from local dataset. + * + * @param[out] aChannelMask A reference to the channel mask. + * + * @retval OT_ERROR_NONE Successfully retrieved the channel mask. + * @retval OT_ERROR_NOT_FOUND There is no valid channel mask stored in local dataset. + * + */ + otError GetChannelMask(Mac::ChannelMask &aChannelMask) const; + /** * This method applies the Active or Pending Dataset to the Thread interface. * diff --git a/src/core/thread/announce_sender.cpp b/src/core/thread/announce_sender.cpp index 7757df28e..6a4b1c237 100644 --- a/src/core/thread/announce_sender.cpp +++ b/src/core/thread/announce_sender.cpp @@ -122,24 +122,6 @@ void AnnounceSender::HandleTimer(Timer &aTimer) aTimer.GetOwner().AnnounceSenderBase::HandleTimer(); } -otError AnnounceSender::GetActiveDatasetChannelMask(Mac::ChannelMask &aMask) const -{ - otError error = OT_ERROR_NONE; - const MeshCoP::ChannelMaskTlv *channelMaskTlv; - MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp); - - SuccessOrExit(error = GetNetif().GetActiveDataset().Get(dataset)); - - channelMaskTlv = static_cast(dataset.Get(MeshCoP::Tlv::kChannelMask)); - VerifyOrExit(channelMaskTlv != NULL && channelMaskTlv->GetChannelPage() == OT_RADIO_CHANNEL_PAGE, - error = OT_ERROR_NOT_FOUND); - - aMask.SetMask(channelMaskTlv->GetMask()); - -exit: - return error; -} - void AnnounceSender::CheckState(void) { Mle::MleRouter & mle = GetInstance().Get(); @@ -169,9 +151,7 @@ void AnnounceSender::CheckState(void) ExitNow(); } - VerifyOrExit(GetActiveDatasetChannelMask(channelMask) == OT_ERROR_NONE, Stop()); - channelMask.Intersect(OT_RADIO_SUPPORTED_CHANNELS); - VerifyOrExit(!channelMask.IsEmpty(), Stop()); + SuccessOrExit(GetNetif().GetActiveDataset().GetChannelMask(channelMask) == OT_ERROR_NONE, Stop()); period = interval / channelMask.GetNumberOfChannels(); diff --git a/src/core/thread/announce_sender.hpp b/src/core/thread/announce_sender.hpp index f7ce1e2c0..ccf859dcd 100644 --- a/src/core/thread/announce_sender.hpp +++ b/src/core/thread/announce_sender.hpp @@ -156,7 +156,6 @@ private: kMaxJitter = 500, // in ms }; - otError GetActiveDatasetChannelMask(Mac::ChannelMask &aMask) const; void CheckState(void); void Stop(void); static void HandleTimer(Timer &aTimer); diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index ff9cf0094..957a436ea 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -203,24 +203,17 @@ otError MeshForwarder::PrepareDiscoverRequest(void) VerifyOrExit(!mScanning); - mScanChannel = OT_RADIO_CHANNEL_MIN; - mScanChannels >>= OT_RADIO_CHANNEL_MIN; + mScanChannel = Mac::ChannelMask::kChannelIteratorFirst; mRestorePanId = netif.GetMac().GetPanId(); SuccessOrExit(error = netif.GetMac().AcquireRadioChannel(&mMacRadioAcquisitionId)); mScanning = true; - while ((mScanChannels & 1) == 0) + if (mScanChannels.GetNextChannel(mScanChannel) != OT_ERROR_NONE) { - mScanChannels >>= 1; - mScanChannel++; - - if (mScanChannel > OT_RADIO_CHANNEL_MAX) - { - HandleDiscoverComplete(); - ExitNow(error = OT_ERROR_DROP); - } + HandleDiscoverComplete(); + ExitNow(error = OT_ERROR_DROP); } exit: @@ -1146,9 +1139,12 @@ exit: } } -void MeshForwarder::SetDiscoverParameters(uint32_t aScanChannels) +void MeshForwarder::SetDiscoverParameters(const Mac::ChannelMask &aScanChannels) { - mScanChannels = (aScanChannels == 0) ? static_cast(Mac::kScanChannelsAll) : aScanChannels; + uint32_t mask; + + mask = aScanChannels.IsEmpty() ? static_cast(OT_RADIO_SUPPORTED_CHANNELS) : aScanChannels.GetMask(); + mScanChannels.SetMask(mask & OT_RADIO_SUPPORTED_CHANNELS); } void MeshForwarder::HandleDiscoverTimer(Timer &aTimer) @@ -1158,21 +1154,15 @@ void MeshForwarder::HandleDiscoverTimer(Timer &aTimer) void MeshForwarder::HandleDiscoverTimer(void) { - do + if (mScanChannels.GetNextChannel(mScanChannel) != OT_ERROR_NONE) { - mScanChannels >>= 1; - mScanChannel++; + mSendQueue.Dequeue(*mSendMessage); + mSendMessage->Free(); + mSendMessage = NULL; - if (mScanChannel > OT_RADIO_CHANNEL_MAX) - { - mSendQueue.Dequeue(*mSendMessage); - mSendMessage->Free(); - mSendMessage = NULL; - - HandleDiscoverComplete(); - ExitNow(); - } - } while ((mScanChannels & 1) == 0); + HandleDiscoverComplete(); + ExitNow(); + } mSendMessage->SetDirectTransmission(); diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 2f3e98626..511c19c57 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -38,6 +38,7 @@ #include "common/locator.hpp" #include "common/tasklet.hpp" +#include "mac/channel_mask.hpp" #include "mac/mac.hpp" #include "net/ip6.hpp" #include "thread/address_resolver.hpp" @@ -137,10 +138,11 @@ public: /** * This method sets the scan parameters for MLE Discovery Request messages. * - * @param[in] aScanChannels A bit vector indicating which channels to scan. + * @param[in] aScanChannels A reference to channel mask indicating which channels to scan. + * If @p aScanChannels is empty, then all channels are used instead. * */ - void SetDiscoverParameters(uint32_t aScanChannels); + void SetDiscoverParameters(const Mac::ChannelMask &aScanChannels); /** * This method frees any indirect messages queued for a specific child. @@ -430,11 +432,11 @@ private: Tasklet mScheduleTransmissionTask; bool mEnabled; - uint32_t mScanChannels; - uint8_t mScanChannel; - uint16_t mMacRadioAcquisitionId; - uint16_t mRestorePanId; - bool mScanning; + Mac::ChannelMask mScanChannels; + uint8_t mScanChannel; + uint16_t mMacRadioAcquisitionId; + uint16_t mRestorePanId; + bool mScanning; otIpCounters mIpCounters; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 58cccbe37..2f99cb308 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -104,7 +104,7 @@ Mle::Mle(Instance &aInstance) , mParentSearchBackoffCancelTime(0) , mParentSearchTimer(aInstance, &Mle::HandleParentSearchTimer, this) #endif - , mAnnounceChannel(OT_RADIO_CHANNEL_MIN) + , mAnnounceChannel(0) , mAlternateChannel(0) , mAlternatePanId(Mac::kPanIdBroadcast) , mAlternateTimestamp(0) @@ -492,12 +492,12 @@ exit: return error; } -otError Mle::Discover(uint32_t aScanChannels, - uint16_t aPanId, - bool aJoiner, - bool aEnableEui64Filtering, - DiscoverHandler aCallback, - void * aContext) +otError Mle::Discover(const Mac::ChannelMask &aScanChannels, + uint16_t aPanId, + bool aJoiner, + bool aEnableEui64Filtering, + DiscoverHandler aCallback, + void * aContext) { otError error = OT_ERROR_NONE; Message * message = NULL; @@ -1673,7 +1673,7 @@ void Mle::HandleAttachTimer(void) { SetAttachState(kAttachStateAnnounce); SendParentRequest(kParentRequestTypeRoutersAndReeds); - mAnnounceChannel = OT_RADIO_CHANNEL_MIN; + mAnnounceChannel = Mac::ChannelMask::kChannelIteratorFirst; delay = mAnnounceDelay; break; } @@ -1709,31 +1709,14 @@ exit: bool Mle::PrepareAnnounceState(void) { - bool shouldAnnounce = false; - uint16_t numChannels = 0; - const MeshCoP::ChannelMaskBaseTlv *channelMaskTlv; - const MeshCoP::ChannelMaskEntry * channelMaskEntry; - MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp); + bool shouldAnnounce = false; + Mac::ChannelMask channelMask; VerifyOrExit((mRole != OT_DEVICE_ROLE_CHILD) && !IsFullThreadDevice() && (mReattachState == kReattachStop)); - SuccessOrExit(GetNetif().GetActiveDataset().Get(dataset)); + SuccessOrExit(GetNetif().GetActiveDataset().GetChannelMask(channelMask)); - channelMaskTlv = static_cast(dataset.Get(MeshCoP::Tlv::kChannelMask)); - VerifyOrExit(channelMaskTlv != NULL); - - channelMaskEntry = channelMaskTlv->GetMaskEntry(OT_RADIO_CHANNEL_PAGE); - VerifyOrExit(channelMaskEntry != NULL); - - for (uint8_t channel = OT_RADIO_CHANNEL_MIN; channel <= OT_RADIO_CHANNEL_MAX; channel++) - { - if (channelMaskEntry->IsChannelSet(channel)) - { - numChannels++; - } - } - - mAnnounceDelay = kAnnounceTimeout / (numChannels + 1); + mAnnounceDelay = kAnnounceTimeout / (channelMask.GetNumberOfChannels() + 1); if (mAnnounceDelay < kMinAnnounceDelay) { @@ -2381,29 +2364,13 @@ exit: otError Mle::SendOrphanAnnounce(void) { - otError error = OT_ERROR_NONE; - const MeshCoP::ChannelMaskBaseTlv *channelMaskTlv; - const MeshCoP::ChannelMaskEntry * channelMaskEntry; - MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp); + otError error; + Mac::ChannelMask channelMask; - SuccessOrExit(error = GetNetif().GetActiveDataset().Get(dataset)); - - channelMaskTlv = static_cast(dataset.Get(MeshCoP::Tlv::kChannelMask)); - VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND); - - channelMaskEntry = channelMaskTlv->GetMaskEntry(OT_RADIO_CHANNEL_PAGE); - VerifyOrExit(channelMaskEntry != NULL, error = OT_ERROR_NOT_FOUND); - - VerifyOrExit(mAnnounceChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_NOT_FOUND); - - while (!channelMaskEntry->IsChannelSet(mAnnounceChannel)) - { - mAnnounceChannel++; - VerifyOrExit(mAnnounceChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_NOT_FOUND); - } + SuccessOrExit(error = GetNetif().GetActiveDataset().GetChannelMask(channelMask)); + SuccessOrExit(error = channelMask.GetNextChannel(mAnnounceChannel)); SendAnnounce(mAnnounceChannel, true); - mAnnounceChannel++; exit: return error; diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 1d6eb0930..c99fa8b32 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -557,12 +557,12 @@ public: * @retval OT_ERROR_BUSY Thread Discovery is already in progress. * */ - otError Discover(uint32_t aScanChannels, - uint16_t aPanId, - bool aJoiner, - bool aEnableEui64Filtering, - DiscoverHandler aCallback, - void * aContext); + otError Discover(const Mac::ChannelMask &aScanChannels, + uint16_t aPanId, + bool aJoiner, + bool aEnableEui64Filtering, + DiscoverHandler aCallback, + void * aContext); /** * This method indicates whether or not an MLE Thread Discovery is currently in progress.