[discover-scanner] adding Mle::DiscoverScanner (#5075)

This commit adds new class `DiscoverScanner` which implements the MLE
Discover Scan process (moving and simplifying all the code related to
this from `Mle` and `MeshForwarder` into same file/class).
This commit is contained in:
Abtin Keshavarzian
2020-06-17 10:38:03 -07:00
committed by Jonathan Hui
parent e653478c50
commit 54ad5a3960
15 changed files with 557 additions and 341 deletions
+1
View File
@@ -241,6 +241,7 @@ LOCAL_SRC_FILES := \
src/core/thread/announce_begin_server.cpp \
src/core/thread/announce_sender.cpp \
src/core/thread/child_table.cpp \
src/core/thread/discover_scanner.cpp \
src/core/thread/dua_manager.cpp \
src/core/thread/energy_scan_server.cpp \
src/core/thread/indirect_sender.cpp \
+1
View File
@@ -136,6 +136,7 @@ static_library("lib-ot-core") {
"src/core/thread/announce_begin_server.cpp",
"src/core/thread/announce_sender.cpp",
"src/core/thread/child_table.cpp",
"src/core/thread/discover_scanner.cpp",
"src/core/thread/dua_manager.cpp",
"src/core/thread/energy_scan_server.cpp",
"src/core/thread/indirect_sender.cpp",
+1
View File
@@ -172,6 +172,7 @@ set(COMMON_SOURCES
thread/announce_begin_server.cpp
thread/announce_sender.cpp
thread/child_table.cpp
thread/discover_scanner.cpp
thread/dua_manager.cpp
thread/energy_scan_server.cpp
thread/indirect_sender.cpp
+2
View File
@@ -214,6 +214,7 @@ SOURCES_COMMON = \
thread/announce_begin_server.cpp \
thread/announce_sender.cpp \
thread/child_table.cpp \
thread/discover_scanner.cpp \
thread/dua_manager.cpp \
thread/energy_scan_server.cpp \
thread/indirect_sender.cpp \
@@ -423,6 +424,7 @@ HEADERS_COMMON = \
thread/announce_begin_server.hpp \
thread/announce_sender.hpp \
thread/child_table.hpp \
thread/discover_scanner.hpp \
thread/dua_manager.hpp \
thread/energy_scan_server.hpp \
thread/indirect_sender.hpp \
+3 -3
View File
@@ -457,15 +457,15 @@ otError otThreadDiscover(otInstance * aInstance,
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Mle::MleRouter>().Discover(static_cast<Mac::ChannelMask>(aScanChannels), aPanId, aJoiner,
aEnableEui64Filtering, aCallback, aCallbackContext);
return instance.Get<Mle::DiscoverScanner>().Discover(static_cast<Mac::ChannelMask>(aScanChannels), aPanId, aJoiner,
aEnableEui64Filtering, aCallback, aCallbackContext);
}
bool otThreadIsDiscoverInProgress(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Mle::MleRouter>().IsDiscoverInProgress();
return instance.Get<Mle::DiscoverScanner>().IsInProgress();
}
const otIpCounters *otThreadGetIp6Counters(otInstance *aInstance)
+5
View File
@@ -438,6 +438,11 @@ template <> inline Mle::MleRouter &Instance::Get(void)
return mThreadNetif.mMleRouter;
}
template <> inline Mle::DiscoverScanner &Instance::Get(void)
{
return mThreadNetif.mDiscoverScanner;
}
#if OPENTHREAD_FTD
template <> inline ChildTable &Instance::Get(void)
{
+3 -3
View File
@@ -122,9 +122,9 @@ otError Joiner::Start(const char * aPskd,
SuccessOrExit(error = PrepareJoinerFinalizeMessage(aProvisioningUrl, aVendorName, aVendorModel, aVendorSwVersion,
aVendorData));
SuccessOrExit(error = Get<Mle::MleRouter>().Discover(Mac::ChannelMask(0), Get<Mac::Mac>().GetPanId(),
/* aJoiner */ true, /* aEnableFiltering */ true,
HandleDiscoverResult, this));
SuccessOrExit(error = Get<Mle::DiscoverScanner>().Discover(Mac::ChannelMask(0), Get<Mac::Mac>().GetPanId(),
/* aJoiner */ true, /* aEnableFiltering */ true,
HandleDiscoverResult, this));
mCallback = aCallback;
mContext = aContext;
+351
View File
@@ -0,0 +1,351 @@
/*
* Copyright (c) 2016-2020, 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 MLE Discover Scan process.
*/
#include "discover_scanner.hpp"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#include "thread/mesh_forwarder.hpp"
#include "thread/mle.hpp"
#include "thread/mle_router.hpp"
namespace ot {
namespace Mle {
DiscoverScanner::DiscoverScanner(Instance &aInstance)
: InstanceLocator(aInstance)
, mHandler(NULL)
, mHandlerContext(NULL)
, mTimer(aInstance, DiscoverScanner::HandleTimer, this)
, mFilterIndexes()
, mScanChannels()
, mState(kStateIdle)
, mScanChannel(0)
, mEnableFiltering(false)
, mShouldRestorePanId(false)
{
}
otError DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
uint16_t aPanId,
bool aJoiner,
bool aEnableFiltering,
Handler aCallback,
void * aContext)
{
otError error = OT_ERROR_NONE;
Message * message = NULL;
Ip6::Address destination;
MeshCoP::DiscoveryRequestTlv discoveryRequest;
VerifyOrExit(mState == kStateIdle, error = OT_ERROR_BUSY);
mEnableFiltering = aEnableFiltering;
if (mEnableFiltering)
{
Mac::ExtAddress extAddress;
Get<Radio>().GetIeeeEui64(extAddress);
MeshCoP::ComputeJoinerId(extAddress, extAddress);
MeshCoP::SteeringData::CalculateHashBitIndexes(extAddress, mFilterIndexes);
}
mHandler = aCallback;
mHandlerContext = aContext;
mShouldRestorePanId = false;
mScanChannels = Get<Mac::Mac>().GetSupportedChannelMask();
if (!aScanChannels.IsEmpty())
{
mScanChannels.Intersect(aScanChannels);
}
VerifyOrExit((message = Get<Mle>().NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
message->SetSubType(Message::kSubTypeMleDiscoverRequest);
message->SetPanId(aPanId);
SuccessOrExit(error = Get<Mle>().AppendHeader(*message, Header::kCommandDiscoveryRequest));
// Append MLE Discovery TLV with a single sub-TLV (MeshCoP Discovery Request).
discoveryRequest.Init();
discoveryRequest.SetVersion(kThreadVersion);
discoveryRequest.SetJoiner(aJoiner);
SuccessOrExit(error = Tlv::AppendTlv(*message, Tlv::kDiscovery, &discoveryRequest, sizeof(discoveryRequest)));
destination.SetToLinkLocalAllRoutersMulticast();
SuccessOrExit(error = Get<Mle>().SendMessage(*message, destination));
if ((aPanId == Mac::kPanIdBroadcast) && (Get<Mac::Mac>().GetPanId() == Mac::kPanIdBroadcast))
{
// In case a specific PAN ID of a Thread Network to be
// discovered is not known, Discovery Request messages MUST
// have the Destination PAN ID in the IEEE 802.15.4 MAC
// header set to be the Broadcast PAN ID (0xffff) and the
// Source PAN ID set to a randomly generated value.
Get<Mac::Mac>().SetPanId(Mac::GenerateRandomPanId());
mShouldRestorePanId = true;
}
mScanChannel = Mac::ChannelMask::kChannelIteratorFirst;
mState = (mScanChannels.GetNextChannel(mScanChannel) == OT_ERROR_NONE) ? kStateScanning : kStateScanDone;
otLogInfoMle("Send Discovery Request (%s)", destination.ToString().AsCString());
exit:
if (error != OT_ERROR_NONE && message != NULL)
{
message->Free();
}
return error;
}
otError DiscoverScanner::PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame)
{
otError error = OT_ERROR_NONE;
switch (mState)
{
case kStateIdle:
case kStateScanDone:
// If scan is finished (no more channels to scan), abort the
// Discovery Request frame tx. The handler callback is invoked &
// state is cleared from `HandleDiscoveryRequestFrameTxDone()`.
error = OT_ERROR_ABORT;
break;
case kStateScanning:
aFrame.SetChannel(mScanChannel);
IgnoreError(Get<Mac::Mac>().SetTemporaryChannel(mScanChannel));
break;
}
return error;
}
void DiscoverScanner::HandleDiscoveryRequestFrameTxDone(Message &aMessage)
{
switch (mState)
{
case kStateIdle:
break;
case kStateScanning:
// Mark the Discovery Request message for direct tx to ensure it
// is not dequeued and freed by `MeshForwarder` and is ready for
// the next scan channel. Also pause message tx on `MeshForwarder`
// while listening to receive Discovery Responses.
aMessage.SetDirectTransmission();
Get<MeshForwarder>().PauseMessageTransmissions();
mTimer.Start(kDefaultScanDuration);
break;
case kStateScanDone:
HandleDiscoverComplete();
break;
}
}
void DiscoverScanner::HandleDiscoverComplete(void)
{
switch (mState)
{
case kStateIdle:
break;
case kStateScanning:
mTimer.Stop();
Get<MeshForwarder>().ResumeMessageTransmissions();
// Fall through
case kStateScanDone:
Get<Mac::Mac>().ClearTemporaryChannel();
if (mShouldRestorePanId)
{
Get<Mac::Mac>().SetPanId(Mac::kPanIdBroadcast);
mShouldRestorePanId = false;
}
mState = kStateIdle;
if (mHandler)
{
mHandler(NULL, mHandlerContext);
}
break;
}
}
void DiscoverScanner::HandleTimer(Timer &aTimer)
{
aTimer.GetOwner<DiscoverScanner>().HandleTimer();
}
void DiscoverScanner::HandleTimer(void)
{
VerifyOrExit(mState == kStateScanning, OT_NOOP);
// Move to next scan channel and resume message transmissions on
// `MeshForwarder` so that the queued MLE Discovery Request message
// is prepared again for the next scan channel. If no more channel
// to scan, change the state to `kStateScanDone` which ensures the
// frame tx is aborted from `PrepareDiscoveryRequestFrame()` and
// then wraps up the scan (invoking handler callback).
if (mScanChannels.GetNextChannel(mScanChannel) != OT_ERROR_NONE)
{
mState = kStateScanDone;
}
Get<MeshForwarder>().ResumeMessageTransmissions();
exit:
return;
}
void DiscoverScanner::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
{
otError error = OT_ERROR_NONE;
const otThreadLinkInfo * linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
Tlv tlv;
MeshCoP::Tlv meshcopTlv;
MeshCoP::DiscoveryResponseTlv discoveryResponse;
MeshCoP::NetworkNameTlv networkName;
ScanResult result;
uint16_t offset;
uint16_t end;
bool didCheckSteeringData = false;
otLogInfoMle("Receive Discovery Response (%s)", aMessageInfo.GetPeerAddr().ToString().AsCString());
VerifyOrExit(mState == kStateScanning, error = OT_ERROR_DROP);
// Find MLE Discovery TLV
VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == OT_ERROR_NONE, error = OT_ERROR_PARSE);
aMessage.Read(offset, sizeof(tlv), &tlv);
offset += sizeof(tlv);
end = offset + tlv.GetLength();
memset(&result, 0, sizeof(result));
result.mPanId = linkInfo->mPanId;
result.mChannel = linkInfo->mChannel;
result.mRssi = linkInfo->mRss;
result.mLqi = linkInfo->mLqi;
aMessageInfo.GetPeerAddr().ToExtAddress(*static_cast<Mac::ExtAddress *>(&result.mExtAddress));
// Process MeshCoP TLVs
while (offset < end)
{
aMessage.Read(offset, sizeof(meshcopTlv), &meshcopTlv);
switch (meshcopTlv.GetType())
{
case MeshCoP::Tlv::kDiscoveryResponse:
aMessage.Read(offset, sizeof(discoveryResponse), &discoveryResponse);
VerifyOrExit(discoveryResponse.IsValid(), error = OT_ERROR_PARSE);
result.mVersion = discoveryResponse.GetVersion();
result.mIsNative = discoveryResponse.IsNativeCommissioner();
break;
case MeshCoP::Tlv::kExtendedPanId:
SuccessOrExit(error = Tlv::ReadTlv(aMessage, offset, &result.mExtendedPanId, sizeof(Mac::ExtendedPanId)));
break;
case MeshCoP::Tlv::kNetworkName:
aMessage.Read(offset, sizeof(networkName), &networkName);
IgnoreError(static_cast<Mac::NetworkName &>(result.mNetworkName).Set(networkName.GetNetworkName()));
break;
case MeshCoP::Tlv::kSteeringData:
if (meshcopTlv.GetLength() > 0)
{
MeshCoP::SteeringData &steeringData = static_cast<MeshCoP::SteeringData &>(result.mSteeringData);
uint8_t dataLength = MeshCoP::SteeringData::kMaxLength;
if (meshcopTlv.GetLength() < dataLength)
{
dataLength = meshcopTlv.GetLength();
}
steeringData.Init(dataLength);
SuccessOrExit(error = Tlv::ReadTlv(aMessage, offset, steeringData.GetData(), dataLength));
if (mEnableFiltering)
{
VerifyOrExit(steeringData.Contains(mFilterIndexes), OT_NOOP);
}
didCheckSteeringData = true;
}
break;
case MeshCoP::Tlv::kJoinerUdpPort:
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, offset, result.mJoinerUdpPort));
break;
default:
break;
}
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
}
VerifyOrExit(!mEnableFiltering || didCheckSteeringData, OT_NOOP);
if (mHandler)
{
mHandler(&result, mHandlerContext);
}
exit:
if (error != OT_ERROR_NONE)
{
otLogWarnMle("Failed to process Discovery Response: %s", otThreadErrorToString(error));
}
}
} // namespace Mle
} // namespace ot
+157
View File
@@ -0,0 +1,157 @@
/*
* Copyright (c) 2016-2020, 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 definitions for MLE Discover Scan process.
*/
#ifndef DISCOVER_SCANNER_HPP_
#define DISCOVER_SCANNER_HPP_
#include "openthread-core-config.h"
#include "common/locator.hpp"
#include "common/timer.hpp"
#include "mac/channel_mask.hpp"
#include "mac/mac.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop.hpp"
#include "thread/mle.hpp"
namespace ot {
class MeshForwarder;
namespace Mle {
/**
* This class implements MLE Discover Scan.
*
*/
class DiscoverScanner : public InstanceLocator
{
friend class ot::Instance;
friend class ot::MeshForwarder;
friend class Mle;
public:
enum
{
kDefaultScanDuration = Mac::kScanDurationDefault, ///< Default scan duration (per channel), in milliseconds.
};
/**
* This type represents Discover Scan result.
*
*/
typedef otActiveScanResult ScanResult;
/**
* This type represents the handler function pointer called with any Discover Scan result or when the scan
* completes.
*
* The handler function format is `void (*oHandler)(ScanResult *aResult, void *aContext);`. End of scan is
* indicated by `aResult` pointer being set to NULL.
*
*/
typedef otHandleActiveScanResult Handler;
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit DiscoverScanner(Instance &aInstance);
/**
* This method starts a Thread Discovery Scan.
*
* @param[in] aScanChannels Channel mask listing channels to scan (if empty, use all supported channels).
* @param[in] aPanId The PAN ID filter (set to Broadcast PAN to disable filter).
* @param[in] aJoiner Value of the Joiner Flag in the Discovery Request TLV.
* @param[in] aEnableFiltering Enable filtering MLE Discovery Responses that don't match our factory EUI64.
* @param[in] aHandler A pointer to a function that is called on receiving an MLE Discovery Response.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully started a Thread Discovery Scan.
* @retval OT_ERROR_NO_BUFS Could not allocate message for Discovery Request.
* @retval OT_ERROR_BUSY Thread Discovery Scan is already in progress.
*
*/
otError Discover(const Mac::ChannelMask &aScanChannels,
Mac::PanId aPanId,
bool aJoiner,
bool aEnableFiltering,
Handler aHandler,
void * aContext);
/**
* This method indicates whether or not an MLE Thread Discovery Scan is currently in progress.
*
* @returns true if an MLE Thread Discovery Scan is in progress, false otherwise.
*
*/
bool IsInProgress(void) const { return (mState != kStateIdle); }
private:
enum State
{
kStateIdle,
kStateScanning,
kStateScanDone,
};
// Methods used by `MeshForwarder`
otError PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame);
void HandleDiscoveryRequestFrameTxDone(Message &aMessage);
void Stop(void) { HandleDiscoverComplete(); }
// Methods used from `Mle`
void HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const;
void HandleDiscoverComplete(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
Handler mHandler;
void * mHandlerContext;
TimerMilli mTimer;
MeshCoP::SteeringData::HashBitIndexes mFilterIndexes;
Mac::ChannelMask mScanChannels;
State mState;
uint8_t mScanChannel;
bool mEnableFiltering : 1;
bool mShouldRestorePanId : 1;
};
} // namespace Mle
} // namespace ot
#endif // DISCOVER_SCANNER_HPP_
+15 -98
View File
@@ -57,20 +57,16 @@ namespace ot {
MeshForwarder::MeshForwarder(Instance &aInstance)
: InstanceLocator(aInstance)
, mDiscoverTimer(aInstance, MeshForwarder::HandleDiscoverTimer, this)
, mUpdateTimer(aInstance, MeshForwarder::HandleUpdateTimer, this)
, mMessageNextOffset(0)
, mSendMessage(NULL)
, mMeshSource()
, mMeshDest()
, mAddMeshHeader(false)
, mEnabled(false)
, mTxPaused(false)
, mSendBusy(false)
, mScheduleTransmissionTask(aInstance, ScheduleTransmissionTask, this)
, mEnabled(false)
, mScanChannels(0)
, mScanChannel(0)
, mRestorePanId(Mac::kPanIdBroadcast)
, mScanning(false)
#if OPENTHREAD_FTD
, mIndirectSender(aInstance)
#endif
@@ -106,11 +102,7 @@ void MeshForwarder::Stop(void)
mDataPollSender.StopPolling();
mUpdateTimer.Stop();
if (mScanning)
{
HandleDiscoverComplete();
}
Get<Mle::DiscoverScanner>().Stop();
while ((message = mSendQueue.GetHead()) != NULL)
{
@@ -163,6 +155,15 @@ void MeshForwarder::RemoveMessage(Message &aMessage)
aMessage.Free();
}
void MeshForwarder::ResumeMessageTransmissions(void)
{
if (mTxPaused)
{
mTxPaused = false;
mScheduleTransmissionTask.Post();
}
}
void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
{
aTasklet.GetOwner<MeshForwarder>().ScheduleTransmissionTask();
@@ -170,7 +171,7 @@ void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
void MeshForwarder::ScheduleTransmissionTask(void)
{
VerifyOrExit(!mSendBusy, OT_NOOP);
VerifyOrExit(!mSendBusy && !mTxPaused, OT_NOOP);
mSendMessage = GetDirectTransmission();
VerifyOrExit(mSendMessage != NULL, OT_NOOP);
@@ -186,27 +187,6 @@ exit:
return;
}
otError MeshForwarder::PrepareDiscoverRequest(void)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(!mScanning, OT_NOOP);
mScanChannel = Mac::ChannelMask::kChannelIteratorFirst;
mRestorePanId = Get<Mac::Mac>().GetPanId();
mScanning = true;
if (mScanChannels.GetNextChannel(mScanChannel) != OT_ERROR_NONE)
{
HandleDiscoverComplete();
ExitNow(error = OT_ERROR_DROP);
}
exit:
return error;
}
Message *MeshForwarder::GetDirectTransmission(void)
{
Message *curMessage, *nextMessage;
@@ -226,12 +206,6 @@ Message *MeshForwarder::GetDirectTransmission(void)
{
case Message::kTypeIp6:
error = UpdateIp6Route(*curMessage);
if (curMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
{
error = PrepareDiscoverRequest();
}
break;
#if OPENTHREAD_FTD
@@ -436,18 +410,7 @@ otError MeshForwarder::HandleFrameRequest(Mac::TxFrame &aFrame)
case Message::kTypeIp6:
if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
{
SuccessOrExit(error = Get<Mac::Mac>().SetTemporaryChannel(mScanChannel));
aFrame.SetChannel(mScanChannel);
// In case a specific PAN ID of a Thread Network to be discovered is not known, Discovery
// Request messages MUST have the Destination PAN ID in the IEEE 802.15.4 MAC header set
// to be the Broadcast PAN ID (0xFFFF) and the Source PAN ID set to a randomly generated
// value.
if (mSendMessage->GetPanId() == Mac::kPanIdBroadcast && Get<Mac::Mac>().GetPanId() == Mac::kPanIdBroadcast)
{
Get<Mac::Mac>().SetPanId(Mac::GenerateRandomPanId());
}
SuccessOrExit(error = Get<Mle::DiscoverScanner>().PrepareDiscoveryRequestFrame(aFrame));
}
mMessageNextOffset =
@@ -887,9 +850,7 @@ void MeshForwarder::HandleSentFrame(Mac::TxFrame &aFrame, otError aError)
if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
{
mSendBusy = true;
mDiscoverTimer.Start(static_cast<uint16_t>(Mac::kScanDurationDefault));
ExitNow();
Get<Mle::DiscoverScanner>().HandleDiscoveryRequestFrameTxDone(*mSendMessage);
}
if (!mSendMessage->GetDirectTransmission() && !mSendMessage->IsChildPending())
@@ -920,50 +881,6 @@ exit:
}
}
void MeshForwarder::SetDiscoverParameters(const Mac::ChannelMask &aScanChannels)
{
uint32_t mask;
uint32_t supportedMask = Get<Mac::Mac>().GetSupportedChannelMask().GetMask();
mask = aScanChannels.IsEmpty() ? supportedMask : aScanChannels.GetMask();
mScanChannels.SetMask(mask & supportedMask);
}
void MeshForwarder::HandleDiscoverTimer(Timer &aTimer)
{
aTimer.GetOwner<MeshForwarder>().HandleDiscoverTimer();
}
void MeshForwarder::HandleDiscoverTimer(void)
{
if (mScanChannels.GetNextChannel(mScanChannel) != OT_ERROR_NONE)
{
mSendQueue.Dequeue(*mSendMessage);
mSendMessage->Free();
mSendMessage = NULL;
HandleDiscoverComplete();
ExitNow();
}
mSendMessage->SetDirectTransmission();
exit:
mSendBusy = false;
mScheduleTransmissionTask.Post();
}
void MeshForwarder::HandleDiscoverComplete(void)
{
OT_ASSERT(mScanning);
Get<Mac::Mac>().ClearTemporaryChannel();
Get<Mac::Mac>().SetPanId(mRestorePanId);
mScanning = false;
Get<Mle::MleRouter>().HandleDiscoverComplete();
mDiscoverTimer.Stop();
}
void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
{
otThreadLinkInfo linkInfo;
+12 -12
View File
@@ -50,6 +50,10 @@
namespace ot {
namespace Mle {
class DiscoverScanner;
}
enum
{
kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT,
@@ -171,6 +175,7 @@ class MeshForwarder : public InstanceLocator
friend class Instance;
friend class DataPollSender;
friend class IndirectSender;
friend class Mle::DiscoverScanner;
public:
/**
@@ -312,7 +317,6 @@ public:
*/
const PriorityQueue &GetResolvingQueue(void) const { return mResolvingQueue; }
#endif
private:
enum
{
@@ -368,7 +372,6 @@ private:
void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
Message *GetDirectTransmission(void);
otError PrepareDiscoverRequest(void);
void HandleMesh(uint8_t * aFrame,
uint16_t aFrameLength,
const Mac::Address & aMacSource,
@@ -438,6 +441,9 @@ private:
otError GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest);
void PauseMessageTransmissions(void) { mTxPaused = true; }
void ResumeMessageTransmissions(void);
void LogMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, otError aError);
void LogFrame(const char *aActionText, const Mac::Frame &aFrame, otError aError);
void LogFragmentFrameDrop(otError aError,
@@ -500,7 +506,6 @@ private:
otLogLevel aLogLevel);
#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
TimerMilli mDiscoverTimer;
TimerMilli mUpdateTimer;
PriorityQueue mSendQueue;
@@ -514,17 +519,12 @@ private:
Mac::Address mMacDest;
uint16_t mMeshSource;
uint16_t mMeshDest;
bool mAddMeshHeader;
bool mSendBusy;
bool mAddMeshHeader : 1;
bool mEnabled : 1;
bool mTxPaused : 1;
bool mSendBusy : 1;
Tasklet mScheduleTransmissionTask;
bool mEnabled;
Mac::ChannelMask mScanChannels;
uint8_t mScanChannel;
uint16_t mRestorePanId;
bool mScanning;
otIpCounters mIpCounters;
+1 -173
View File
@@ -91,10 +91,6 @@ Mle::Mle(Instance &aInstance)
, mReceivedResponseFromParent(false)
, mSocket(aInstance.Get<Ip6::Udp>())
, mTimeout(kMleEndDeviceTimeout)
, mDiscoverHandler(NULL)
, mDiscoverContext(NULL)
, mDiscoverInProgress(false)
, mDiscoverEnableFiltering(false)
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
, mPreviousParentRloc(Mac::kShortAddrInvalid)
#endif
@@ -511,73 +507,6 @@ exit:
return error;
}
otError Mle::Discover(const Mac::ChannelMask &aScanChannels,
uint16_t aPanId,
bool aJoiner,
bool aEnableFiltering,
DiscoverHandler aCallback,
void * aContext)
{
otError error = OT_ERROR_NONE;
Message * message = NULL;
Ip6::Address destination;
MeshCoP::DiscoveryRequestTlv discoveryRequest;
VerifyOrExit(!mDiscoverInProgress, error = OT_ERROR_BUSY);
mDiscoverEnableFiltering = aEnableFiltering;
if (mDiscoverEnableFiltering)
{
Mac::ExtAddress extAddress;
Get<Radio>().GetIeeeEui64(extAddress);
MeshCoP::ComputeJoinerId(extAddress, extAddress);
MeshCoP::SteeringData::CalculateHashBitIndexes(extAddress, mDiscoverFilterIndexes);
}
mDiscoverHandler = aCallback;
mDiscoverContext = aContext;
Get<MeshForwarder>().SetDiscoverParameters(aScanChannels);
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
message->SetSubType(Message::kSubTypeMleDiscoverRequest);
message->SetPanId(aPanId);
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDiscoveryRequest));
// Append MLE Discovery TLV with a single sub-TLV (MeshCoP Discovery Request).
discoveryRequest.Init();
discoveryRequest.SetVersion(kThreadVersion);
discoveryRequest.SetJoiner(aJoiner);
SuccessOrExit(error = Tlv::AppendTlv(*message, Tlv::kDiscovery, &discoveryRequest, sizeof(discoveryRequest)));
destination.SetToLinkLocalAllRoutersMulticast();
SuccessOrExit(error = SendMessage(*message, destination));
mDiscoverInProgress = true;
LogMleMessage("Send Discovery Request", destination);
exit:
if (error != OT_ERROR_NONE && message != NULL)
{
message->Free();
}
return error;
}
void Mle::HandleDiscoverComplete(void)
{
mDiscoverInProgress = false;
mDiscoverEnableFiltering = false;
mDiscoverHandler(NULL, mDiscoverContext);
}
otError Mle::BecomeDetached(void)
{
otError error = OT_ERROR_NONE;
@@ -2625,7 +2554,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
#endif
case Header::kCommandDiscoveryResponse:
HandleDiscoveryResponse(aMessage, aMessageInfo);
Get<DiscoverScanner>().HandleDiscoveryResponse(aMessage, aMessageInfo);
break;
default:
@@ -3840,107 +3769,6 @@ void Mle::ProcessAnnounce(void)
IgnoreError(Start(/* aAnnounceAttach */ true));
}
void Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
const otThreadLinkInfo * linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
Tlv tlv;
MeshCoP::Tlv meshcopTlv;
MeshCoP::DiscoveryResponseTlv discoveryResponse;
MeshCoP::NetworkNameTlv networkName;
otActiveScanResult result;
uint16_t offset;
uint16_t end;
bool didCheckSteeringData = false;
LogMleMessage("Receive Discovery Response", aMessageInfo.GetPeerAddr());
VerifyOrExit(mDiscoverInProgress, error = OT_ERROR_DROP);
// find MLE Discovery TLV
VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == OT_ERROR_NONE, error = OT_ERROR_PARSE);
aMessage.Read(offset, sizeof(tlv), &tlv);
offset += sizeof(tlv);
end = offset + tlv.GetLength();
memset(&result, 0, sizeof(result));
result.mPanId = linkInfo->mPanId;
result.mChannel = linkInfo->mChannel;
result.mRssi = linkInfo->mRss;
result.mLqi = linkInfo->mLqi;
aMessageInfo.GetPeerAddr().ToExtAddress(*static_cast<Mac::ExtAddress *>(&result.mExtAddress));
// process MeshCoP TLVs
while (offset < end)
{
aMessage.Read(offset, sizeof(meshcopTlv), &meshcopTlv);
switch (meshcopTlv.GetType())
{
case MeshCoP::Tlv::kDiscoveryResponse:
aMessage.Read(offset, sizeof(discoveryResponse), &discoveryResponse);
VerifyOrExit(discoveryResponse.IsValid(), error = OT_ERROR_PARSE);
result.mVersion = discoveryResponse.GetVersion();
result.mIsNative = discoveryResponse.IsNativeCommissioner();
break;
case MeshCoP::Tlv::kExtendedPanId:
SuccessOrExit(error = Tlv::ReadTlv(aMessage, offset, &result.mExtendedPanId, sizeof(Mac::ExtendedPanId)));
break;
case MeshCoP::Tlv::kNetworkName:
aMessage.Read(offset, sizeof(networkName), &networkName);
IgnoreError(static_cast<Mac::NetworkName &>(result.mNetworkName).Set(networkName.GetNetworkName()));
break;
case MeshCoP::Tlv::kSteeringData:
if (meshcopTlv.GetLength() > 0)
{
MeshCoP::SteeringData &steeringData = static_cast<MeshCoP::SteeringData &>(result.mSteeringData);
uint8_t dataLength = MeshCoP::SteeringData::kMaxLength;
if (meshcopTlv.GetLength() < dataLength)
{
dataLength = meshcopTlv.GetLength();
}
steeringData.Init(dataLength);
SuccessOrExit(error = Tlv::ReadTlv(aMessage, offset, steeringData.GetData(), dataLength));
if (mDiscoverEnableFiltering)
{
VerifyOrExit(steeringData.Contains(mDiscoverFilterIndexes), OT_NOOP);
}
didCheckSteeringData = true;
}
break;
case MeshCoP::Tlv::kJoinerUdpPort:
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, offset, result.mJoinerUdpPort));
break;
default:
break;
}
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
}
VerifyOrExit(!mDiscoverEnableFiltering || didCheckSteeringData, OT_NOOP);
mDiscoverHandler(&result, mDiscoverContext);
exit:
if (error != OT_ERROR_NONE)
{
otLogWarnMle("Failed to process Discovery Response: %s", otThreadErrorToString(error));
}
}
Neighbor *Mle::GetNeighbor(uint16_t aAddress)
{
Neighbor *rval = NULL;
+2 -52
View File
@@ -307,6 +307,8 @@ private:
*/
class Mle : public InstanceLocator, public Notifier::Receiver
{
friend class DiscoverScanner;
public:
/**
* This constructor initializes the MLE object.
@@ -371,51 +373,6 @@ public:
*/
otError Store(void);
/**
* This function pointer is called on receiving an MLE Discovery Response message.
*
* @param[in] aResult A valid pointer to the Discovery Response information or NULL when the Discovery completes.
* @param[in] aContext A pointer to application-specific context.
*
*/
typedef void (*DiscoverHandler)(otActiveScanResult *aResult, void *aContext);
/**
* This method initiates a Thread Discovery.
*
* @param[in] aScanChannels A bit vector indicating which channels to scan.
* @param[in] aPanId The PAN ID filter (set to Broadcast PAN to disable filter).
* @param[in] aJoiner Value of the Joiner Flag in the Discovery Request TLV.
* @param[in] aEnableFiltering Enable filtering out MLE discovery responses that don't match our factory
* assigned EUI64.
* @param[in] aHandler A pointer to a function that is called on receiving an MLE Discovery Response.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully started a Thread Discovery.
* @retval OT_ERROR_BUSY Thread Discovery is already in progress.
*
*/
otError Discover(const Mac::ChannelMask &aScanChannels,
uint16_t aPanId,
bool aJoiner,
bool aEnableFiltering,
DiscoverHandler aCallback,
void * aContext);
/**
* This method indicates whether or not an MLE Thread Discovery is currently in progress.
*
* @returns true if an MLE Thread Discovery is in progress, false otherwise.
*
*/
bool IsDiscoverInProgress(void) const { return mDiscoverInProgress; }
/**
* This method is called by the MeshForwarder to indicate that discovery is complete.
*
*/
void HandleDiscoverComplete(void);
/**
* This method generates an MLE Announce message.
*
@@ -1720,7 +1677,6 @@ private:
void HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor);
void HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence);
void HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessAnnounce(void);
bool HasUnregisteredAddress(void);
@@ -1788,12 +1744,6 @@ private:
Ip6::UdpSocket mSocket;
uint32_t mTimeout;
DiscoverHandler mDiscoverHandler;
void * mDiscoverContext;
MeshCoP::SteeringData::HashBitIndexes mDiscoverFilterIndexes;
bool mDiscoverInProgress;
bool mDiscoverEnableFiltering;
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
uint16_t mPreviousParentRloc;
#endif
+1
View File
@@ -72,6 +72,7 @@ ThreadNetif::ThreadNetif(Instance &aInstance)
, mMac(aInstance)
, mMeshForwarder(aInstance)
, mMleRouter(aInstance)
, mDiscoverScanner(aInstance)
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
, mNetworkDataLocal(aInstance)
#endif
+2
View File
@@ -75,6 +75,7 @@
#include "net/sntp_client.hpp"
#include "thread/address_resolver.hpp"
#include "thread/announce_begin_server.hpp"
#include "thread/discover_scanner.hpp"
#include "thread/energy_scan_server.hpp"
#include "thread/key_manager.hpp"
#include "thread/mesh_forwarder.hpp"
@@ -210,6 +211,7 @@ private:
Mac::Mac mMac;
MeshForwarder mMeshForwarder;
Mle::MleRouter mMleRouter;
Mle::DiscoverScanner mDiscoverScanner;
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
NetworkData::Local mNetworkDataLocal;
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE