[mac] introduce ScanResult to encapsulate scan results (#12453)

This commit introduces the `ScanResult` class, which inherits from
`otActiveScanResult`. This new class provides C++ idiomatic getter
methods that return core OpenThread types (e.g., `ExtAddress`,
`ExtendedPanId`, `NetworkName`) instead of raw C structures.

The logic for parsing a received Beacon frame and populating the
result fields is moved into `ScanResult::PopulateFromBeacon()`.
This centralizes the parsing logic and allows it to be reused
across different modules.

Consequently, `Mac`, `DiscoverScanner`, `Seeker`, and
`PanIdQueryServer` are updated to utilize `ScanResult`. The `Mac`
class is also updated to use the `Callback` template for the active
scan handler, replacing the previous raw function pointer and context.
This commit is contained in:
Abtin Keshavarzian
2026-02-17 15:20:37 -06:00
committed by GitHub
parent 75db779969
commit 416bb890a5
16 changed files with 379 additions and 184 deletions
+2
View File
@@ -541,6 +541,8 @@ openthread_core_files = [
"mac/mac_links.hpp",
"mac/mac_types.cpp",
"mac/mac_types.hpp",
"mac/scan_result.cpp",
"mac/scan_result.hpp",
"mac/sub_mac.cpp",
"mac/sub_mac.hpp",
"mac/sub_mac_callbacks.cpp",
+1
View File
@@ -158,6 +158,7 @@ set(COMMON_SOURCES
mac/mac_header_ie.cpp
mac/mac_links.cpp
mac/mac_types.cpp
mac/scan_result.cpp
mac/sub_mac.cpp
mac/sub_mac_callbacks.cpp
mac/sub_mac_csl_receiver.cpp
+14 -69
View File
@@ -93,8 +93,7 @@ Mac::Mac(Instance &aInstance)
, mWakeupListenInterval(kDefaultWedListenInterval)
, mWakeupListenDuration(kDefaultWedListenDuration)
#endif
, mActiveScanHandler(nullptr) // Initialize `mActiveScanHandler` and `mEnergyScanHandler` union
, mScanHandlerContext(nullptr)
, mActiveScanCallback()
, mLinks(aInstance)
, mOperationTask(aInstance)
, mTimer(aInstance)
@@ -141,15 +140,14 @@ void Mac::SetEnabled(bool aEnable)
}
}
Error Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext)
Error Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ScanResult::Handler aHandler, void *aContext)
{
Error error = kErrorNone;
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = kErrorBusy);
mActiveScanHandler = aHandler;
mScanHandlerContext = aContext;
mActiveScanCallback.Set(aHandler, aContext);
if (aScanDuration == 0)
{
@@ -169,8 +167,7 @@ Error Mac::EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScan
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = kErrorBusy);
mEnergyScanHandler = aHandler;
mScanHandlerContext = aContext;
mEnergyScanCallback.Set(aHandler, aContext);
Scan(kOperationEnergyScan, aScanChannels, aScanDuration);
@@ -225,57 +222,6 @@ bool Mac::IsInTransmitState(void) const
return retval;
}
Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult)
{
Error error = kErrorNone;
Address address;
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
const BeaconPayload *beaconPayload = nullptr;
const Beacon *beacon = nullptr;
uint16_t payloadLength;
#endif
ClearAllBytes(aResult);
VerifyOrExit(aBeaconFrame != nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aBeaconFrame->GetType() == Frame::kTypeBeacon, error = kErrorParse);
SuccessOrExit(error = aBeaconFrame->GetSrcAddr(address));
VerifyOrExit(address.IsExtended(), error = kErrorParse);
aResult.mExtAddress = address.GetExtended();
if (kErrorNone != aBeaconFrame->GetSrcPanId(aResult.mPanId))
{
IgnoreError(aBeaconFrame->GetDstPanId(aResult.mPanId));
}
aResult.mChannel = aBeaconFrame->GetChannel();
aResult.mRssi = aBeaconFrame->GetRssi();
aResult.mLqi = aBeaconFrame->GetLqi();
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
payloadLength = aBeaconFrame->GetPayloadLength();
beacon = reinterpret_cast<const Beacon *>(aBeaconFrame->GetPayload());
beaconPayload = reinterpret_cast<const BeaconPayload *>(beacon->GetPayload());
if ((payloadLength >= (sizeof(*beacon) + sizeof(*beaconPayload))) && beacon->IsValid() && beaconPayload->IsValid())
{
aResult.mVersion = beaconPayload->GetProtocolVersion();
aResult.mIsJoinable = beaconPayload->IsJoiningPermitted();
aResult.mIsNative = beaconPayload->IsNative();
IgnoreError(AsCoreType(&aResult.mNetworkName).Set(beaconPayload->GetNetworkName()));
VerifyOrExit(IsValidUtf8String(aResult.mNetworkName.m8), error = kErrorParse);
aResult.mExtendedPanId = beaconPayload->GetExtendedPanId();
}
#endif
LogBeacon("Received");
exit:
return error;
}
Error Mac::UpdateScanChannel(void)
{
Error error;
@@ -308,18 +254,20 @@ void Mac::PerformActiveScan(void)
void Mac::ReportActiveScanResult(const RxFrame *aBeaconFrame)
{
VerifyOrExit(mActiveScanHandler != nullptr);
VerifyOrExit(mActiveScanCallback.IsSet());
if (aBeaconFrame == nullptr)
{
mActiveScanHandler(nullptr, mScanHandlerContext);
mActiveScanCallback.Invoke(nullptr);
}
else
{
ActiveScanResult result;
ScanResult result;
SuccessOrExit(ConvertBeaconToActiveScanResult(aBeaconFrame, result));
mActiveScanHandler(&result, mScanHandlerContext);
SuccessOrExit(result.PopulateFromBeacon(aBeaconFrame));
LogBeacon("Received");
mActiveScanCallback.Invoke(&result);
}
exit:
@@ -356,10 +304,7 @@ exit:
{
FinishOperation();
if (mEnergyScanHandler != nullptr)
{
mEnergyScanHandler(nullptr, mScanHandlerContext);
}
mEnergyScanCallback.InvokeIfSet(nullptr);
PerformNextOperation();
}
@@ -369,12 +314,12 @@ void Mac::ReportEnergyScanResult(int8_t aRssi)
{
EnergyScanResult result;
VerifyOrExit((mEnergyScanHandler != nullptr) && (aRssi != Radio::kInvalidRssi));
VerifyOrExit(mEnergyScanCallback.IsSet() && (aRssi != Radio::kInvalidRssi));
result.mChannel = mScanChannel;
result.mMaxRssi = aRssi;
mEnergyScanHandler(&result, mScanHandlerContext);
mEnergyScanCallback.Invoke(&result);
exit:
return;
+4 -16
View File
@@ -51,6 +51,7 @@
#include "mac/mac_frame.hpp"
#include "mac/mac_links.hpp"
#include "mac/mac_types.hpp"
#include "mac/scan_result.hpp"
#include "mac/sub_mac.hpp"
#include "radio/trel_link.hpp"
#include "thread/key_manager.hpp"
@@ -98,16 +99,6 @@ constexpr uint16_t kMinCslIePeriod = OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD;
constexpr uint32_t kDefaultWedListenInterval = OPENTHREAD_CONFIG_WED_LISTEN_INTERVAL;
constexpr uint32_t kDefaultWedListenDuration = OPENTHREAD_CONFIG_WED_LISTEN_DURATION;
/**
* Defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan.
*/
typedef otHandleActiveScanResult ActiveScanHandler;
/**
* Defines an Active Scan result.
*/
typedef otActiveScanResult ActiveScanResult;
/**
* Defines the function pointer which is called during an Energy Scan when the scan result for a channel is
* ready or when the scan completes.
@@ -151,7 +142,7 @@ public:
* @retval kErrorNone Successfully scheduled the Active Scan request.
* @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled).
*/
Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ScanResult::Handler aHandler, void *aContext);
/**
* Starts an IEEE 802.15.4 Energy Scan.
@@ -847,7 +838,6 @@ private:
Error UpdateScanChannel(void);
void PerformActiveScan(void);
void ReportActiveScanResult(const RxFrame *aBeaconFrame);
Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
void PerformEnergyScan(void);
void ReportEnergyScanResult(int8_t aRssi);
@@ -926,12 +916,10 @@ private:
#endif
union
{
ActiveScanHandler mActiveScanHandler;
EnergyScanHandler mEnergyScanHandler;
ScanResult::ScanCallback mActiveScanCallback;
Callback<EnergyScanHandler> mEnergyScanCallback;
};
void *mScanHandlerContext;
Links mLinks;
OperationTask mOperationTask;
MacTimer mTimer;
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2026, 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 implementation of methods in `ScanResult`.
*/
#include "scan_result.hpp"
namespace ot {
Error ScanResult::PopulateFromBeacon(const Mac::RxFrame *aBeaconFrame)
{
Error error = kErrorNone;
Mac::Address address;
Clear();
VerifyOrExit(aBeaconFrame != nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aBeaconFrame->GetType() == Mac::Frame::kTypeBeacon, error = kErrorParse);
SuccessOrExit(error = aBeaconFrame->GetSrcAddr(address));
VerifyOrExit(address.IsExtended(), error = kErrorParse);
mExtAddress = address.GetExtended();
if (aBeaconFrame->GetSrcPanId(mPanId) != kErrorNone)
{
IgnoreError(aBeaconFrame->GetDstPanId(mPanId));
}
mChannel = aBeaconFrame->GetChannel();
mRssi = aBeaconFrame->GetRssi();
mLqi = aBeaconFrame->GetLqi();
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
{
const Mac::Beacon *beacon;
const Mac::BeaconPayload *beaconPayload;
VerifyOrExit(aBeaconFrame->GetPayloadLength() >= sizeof(Mac::Beacon) + sizeof(Mac::BeaconPayload));
beacon = reinterpret_cast<const Mac::Beacon *>(aBeaconFrame->GetPayload());
VerifyOrExit(beacon->IsValid());
beaconPayload = reinterpret_cast<const Mac::BeaconPayload *>(beacon->GetPayload());
VerifyOrExit(beaconPayload->IsValid());
mVersion = beaconPayload->GetProtocolVersion();
mIsJoinable = beaconPayload->IsJoiningPermitted();
mIsNative = beaconPayload->IsNative();
mExtendedPanId = beaconPayload->GetExtendedPanId();
IgnoreError(AsCoreType(&mNetworkName).Set(beaconPayload->GetNetworkName()));
VerifyOrExit(IsValidUtf8String(mNetworkName.m8), error = kErrorParse);
}
#endif
exit:
return error;
}
} // namespace ot
+201
View File
@@ -0,0 +1,201 @@
/*
* Copyright (c) 2026, 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 scan result (discover scan or MAC active scan).
*/
#ifndef OT_CORE_MAC_SCAN_RESULT_HPP_
#define OT_CORE_MAC_SCAN_RESULT_HPP_
#include "openthread-core-config.h"
#include <openthread/link.h>
#include "common/as_core_type.hpp"
#include "common/callback.hpp"
#include "common/clearable.hpp"
#include "common/error.hpp"
#include "mac/mac_frame.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/extended_panid.hpp"
#include "meshcop/network_name.hpp"
#include "meshcop/steering_data.hpp"
namespace ot {
namespace Mac {
class Mac;
}
namespace Mle {
class DiscoverScanner;
}
/**
* Represents a discover or active scan result.
*/
class ScanResult : public otActiveScanResult, public Clearable<ScanResult>
{
friend class ot::Mac::Mac;
friend class ot::Mle::DiscoverScanner;
public:
/**
* Represents the function pointer callback to notify scan result.
*/
typedef otHandleActiveScanResult Handler;
/**
* Gets the IEEE 802.15.4 Extended Address.
*
* @returns A constant reference to the IEEE 802.15.4 Extended Address.
*/
const Mac::ExtAddress &GetExtAddress(void) const { return AsCoreType(&mExtAddress); }
/**
* Gets the Thread Network Name.
*
* @returns A constant reference to the Thread Network Name.
*/
const MeshCoP::NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); }
/**
* Gets the Thread Extended PAN ID.
*
* @returns A constant reference to the Thread Extended PAN ID.
*/
const MeshCoP::ExtendedPanId &GetExtendedPanId(void) const { return AsCoreType(&mExtendedPanId); }
/**
* Gets the Steering Data.
*
* @returns A constant reference to the Steering Data.
*/
const MeshCoP::SteeringData &GetSteeringData(void) const { return AsCoreType(&mSteeringData); }
/**
* Gets the IEEE 802.15.4 PAN ID.
*
* @returns The IEEE 802.15.4 PAN ID.
*/
Mac::PanId GetPanId(void) const { return mPanId; }
/**
* Gets the Joiner UDP Port.
*
* @returns The Joiner UDP Port.
*/
uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
/**
* Gets the IEEE 802.15.4 Channel.
*
* @returns The IEEE 802.15.4 Channel.
*/
uint8_t GetChannel(void) const { return mChannel; }
/**
* Gets the RSSI (dBm).
*
* @returns The RSSI.
*/
int8_t GetRssi(void) const { return mRssi; }
/**
* Gets the LQI.
*
* @returns The LQI.
*/
uint8_t GetLqi(void) const { return mLqi; }
/**
* Gets the Version.
*
* @returns The Version.
*/
uint8_t GetVersion(void) const { return mVersion; }
/**
* Indicates whether the Native Commissioner flag is set.
*
* @retval TRUE If the Native Commissioner flag is set.
* @retval FALSE If the Native Commissioner flag is not set.
*/
bool IsNative(void) const { return mIsNative; }
/**
* Indicates whether the result is from MLE Discovery.
*
* @retval TRUE If the result is from MLE Discovery.
* @retval FALSE If the result is not from MLE Discovery.
*/
bool IsDiscover(void) const { return mDiscover; }
/**
* Indicates whether the Joining Permitted flag is set.
*
* @retval TRUE If the Joining Permitted flag is set.
* @retval FALSE If the Joining Permitted flag is not set.
*/
bool IsJoinable(void) const { return mIsJoinable; }
private:
typedef Callback<Handler> ScanCallback;
Error PopulateFromBeacon(const Mac::RxFrame *aBeaconFrame);
};
/**
* Declares a Scan handler method in a given class `Type`.
*
* This macro simplifies the definition of scan handler callback. It defines a `static` handler method which can be
* used as a `Handler `callback function pointer. The `static` handler acts as a wrapper, casting the `aContext`
* pointer back to a `Type` object and invoking its member method with the same `MethodName`.
*
* The `Type` class MUST implement the following member method which will be invoked by the `static` handler:
*
* void MethodName(const ScanResult *aScanResult);
*
* @param[in] Type The class `Type` in which scan result handler is declared.
* @param[in] MethodName The handler method name.
*/
#define DeclareScanResultHandlerIn(Type, MethodName) \
static void MethodName(otActiveScanResult *aScanResult, void *aContext) \
{ \
static_cast<Type *>(aContext)->MethodName(AsCoreTypePtr(aScanResult)); \
} \
\
void MethodName(const ScanResult *aScanResult)
DefineCoreType(otActiveScanResult, ScanResult);
} // namespace ot
#endif // OT_CORE_MAC_SCAN_RESULT_HPP_
+7 -10
View File
@@ -202,15 +202,14 @@ exit:
return;
}
Seeker::Verdict Joiner::EvaluateScanResult(void *aContext, const Seeker::ScanResult *aResult)
Seeker::Verdict Joiner::EvaluateScanResult(void *aContext, const otSeekerScanResult *aResult)
{
return static_cast<Joiner *>(aContext)->EvaluateScanResult(aResult);
return static_cast<Joiner *>(aContext)->EvaluateScanResult(AsCoreTypePtr(aResult));
}
Seeker::Verdict Joiner::EvaluateScanResult(const Seeker::ScanResult *aResult)
Seeker::Verdict Joiner::EvaluateScanResult(const ScanResult *aResult)
{
Seeker::Verdict verdict = Seeker::kIgnore;
const SteeringData *steeringData;
Seeker::Verdict verdict = Seeker::kIgnore;
if (aResult == nullptr)
{
@@ -218,13 +217,11 @@ Seeker::Verdict Joiner::EvaluateScanResult(const Seeker::ScanResult *aResult)
ExitNow();
}
steeringData = AsCoreTypePtr(&aResult->mSteeringData);
// We prefer networks with an exact match of Joiner ID or
// Discerner in the Steering Data compared to ones that allow all
// Joiners.
if (steeringData->PermitsAllJoiners())
if (aResult->GetSteeringData().PermitsAllJoiners())
{
verdict = Seeker::kAccept;
ExitNow();
@@ -232,11 +229,11 @@ Seeker::Verdict Joiner::EvaluateScanResult(const Seeker::ScanResult *aResult)
if (!mDiscerner.IsEmpty())
{
VerifyOrExit(steeringData->Contains(mDiscerner));
VerifyOrExit(aResult->GetSteeringData().Contains(mDiscerner));
}
else
{
VerifyOrExit(steeringData->Contains(mId));
VerifyOrExit(aResult->GetSteeringData().Contains(mId));
}
verdict = Seeker::kAcceptPreferred;
+2 -2
View File
@@ -195,8 +195,8 @@ private:
void FreeJoinerFinalizeMessage(void);
void SendJoinerFinalize(void);
void SendJoinerEntrustResponse(const Coap::Msg &aMsg);
static Seeker::Verdict EvaluateScanResult(void *aContext, const Seeker::ScanResult *aResult);
Seeker::Verdict EvaluateScanResult(const Seeker::ScanResult *aResult);
static Seeker::Verdict EvaluateScanResult(void *aContext, const otSeekerScanResult *aResult);
Seeker::Verdict EvaluateScanResult(const ScanResult *aResult);
void HandleScanCompleted(void);
static void HandleSecureCoapClientConnect(Dtls::Session::ConnectEvent aEvent, void *aContext);
void HandleSecureCoapClientConnect(Dtls::Session::ConnectEvent aEvent);
+15 -21
View File
@@ -110,12 +110,7 @@ exit:
return error;
}
void Seeker::HandleDiscoverResult(ScanResult *aResult, void *aContext)
{
static_cast<Seeker *>(aContext)->HandleDiscoverResult(aResult);
}
void Seeker::HandleDiscoverResult(ScanResult *aResult)
void Seeker::HandleDiscoverResult(const ScanResult *aResult)
{
bool preferred = false;
@@ -128,8 +123,8 @@ void Seeker::HandleDiscoverResult(ScanResult *aResult)
ExitNow();
}
VerifyOrExit(aResult->mJoinerUdpPort > 0);
VerifyOrExit(AsCoreType(&aResult->mSteeringData).IsValid());
VerifyOrExit(aResult->GetJoinerUdpPort() > 0);
VerifyOrExit(aResult->GetSteeringData().IsValid());
switch (mScanEvaluator.Invoke(aResult))
{
@@ -152,20 +147,19 @@ exit:
void Seeker::SaveCandidate(const ScanResult &aResult, bool aPreferred)
{
Error error = kErrorNone;
const MeshCoP::ExtendedPanId &extPanId = AsCoreType(&aResult.mExtendedPanId);
bool shouldPushAsNew = false;
CandidateEntry entry;
Error error = kErrorNone;
bool shouldPushAsNew = false;
CandidateEntry entry;
entry.MarkAsEmpty();
if (mCandidates.FindMatching(entry, extPanId, AsCoreType(&aResult.mExtAddress)) == kErrorNone)
if (mCandidates.FindMatching(entry, aResult.GetExtendedPanId(), aResult.GetExtAddress()) == kErrorNone)
{
entry.Log(Candidate::kReplace);
}
else
{
uint16_t count = CountAndSelectLeastFavoredCandidateFor(extPanId, entry);
uint16_t count = CountAndSelectLeastFavoredCandidateFor(aResult.GetExtendedPanId(), entry);
if ((count == kMaxCandidatesPerNetwork) || ((count > 0) && mCandidates.IsFull()))
{
@@ -412,12 +406,12 @@ exit:
void Seeker::Candidate::SetFrom(const ScanResult &aResult, bool aPreferred)
{
mExtPanId = AsCoreType(&aResult.mExtendedPanId);
mExtAddr = AsCoreType(&aResult.mExtAddress);
mPanId = aResult.mPanId;
mJoinerUdpPort = aResult.mJoinerUdpPort;
mChannel = aResult.mChannel;
mRssi = aResult.mRssi;
mExtPanId = aResult.GetExtendedPanId();
mExtAddr = aResult.GetExtAddress();
mPanId = aResult.GetPanId();
mJoinerUdpPort = aResult.GetJoinerUdpPort();
mChannel = aResult.GetChannel();
mRssi = aResult.GetRssi();
mPreferred = aPreferred;
mConnAttempted = false;
}
@@ -429,7 +423,7 @@ bool Seeker::Candidate::IsFavoredOver(const Candidate &aOther) const
bool Seeker::Candidate::IsFavoredOver(const ScanResult &aResult, bool aPreferred) const
{
return IsFavoredOver(aResult.mRssi, aPreferred);
return IsFavoredOver(aResult.GetRssi(), aPreferred);
}
bool Seeker::Candidate::IsFavoredOver(int8_t aRssi, bool aPreferred) const
+9 -11
View File
@@ -70,8 +70,6 @@ class Seeker : public InstanceLocator, private NonCopyable
friend class ot::UnitTester;
public:
typedef otSeekerScanResult ScanResult; ///< Discover Scan result.
typedef otSeekerVerdict Verdict; ///< A verdict returned from `ScanEvaluator` evaluating a Discover Scan result.
static constexpr Verdict kAccept = OT_SEEKER_ACCEPT; ///< Scan result is acceptable.
@@ -229,17 +227,17 @@ private:
void ReplaceWithIfFavored(const CandidateEntry &aEntry);
};
State GetState(void) const { return mState; }
void SetState(State aState) { mState = aState; }
static void HandleDiscoverResult(ScanResult *aResult, void *aContext);
void HandleDiscoverResult(ScanResult *aResult);
void SaveCandidate(const ScanResult &aResult, bool aPreferred);
Error EvictCandidate(CandidateEntry &aEntry);
Error SelectNextCandidate(CandidateEntry &aEntry);
uint16_t CountAndSelectLeastFavoredCandidateFor(const MeshCoP::ExtendedPanId &aExtPanId,
CandidateEntry &aEntry) const;
State GetState(void) const { return mState; }
void SetState(State aState) { mState = aState; }
void SaveCandidate(const ScanResult &aResult, bool aPreferred);
Error EvictCandidate(CandidateEntry &aEntry);
Error SelectNextCandidate(CandidateEntry &aEntry);
uint16_t CountAndSelectLeastFavoredCandidateFor(const MeshCoP::ExtendedPanId &aExtPanId,
CandidateEntry &aEntry) const;
Error SelectMostFavoredCandidateFor(const MeshCoP::ExtendedPanId &aExtPanId, CandidateEntry &aFavoredEntry) const;
DeclareScanResultHandlerIn(Seeker, HandleDiscoverResult);
State mState;
uint16_t mUdpPort;
Callback<ScanEvaluator> mScanEvaluator;
+3 -3
View File
@@ -58,7 +58,7 @@ Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
bool aJoiner,
bool aEnableFiltering,
const FilterIndexes *aFilterIndexes,
Handler aCallback,
ScanResult::Handler aHandler,
void *aContext)
{
Error error = kErrorNone;
@@ -88,7 +88,7 @@ Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
}
}
mCallback.Set(aCallback, aContext);
mCallback.Set(aHandler, aContext);
mShouldRestorePanId = false;
mScanChannels = Get<Mac::Mac>().GetSupportedChannelMask();
@@ -332,7 +332,7 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
aRxInfo.mMessage.SetOffset(offsetRange.GetOffset());
IgnoreError(aRxInfo.mMessage.SetLength(offsetRange.GetEndOffset()));
ClearAllBytes(result);
result.Clear();
result.mDiscover = true;
result.mPanId = aRxInfo.mMessage.GetPanId();
result.mChannel = aRxInfo.mMessage.GetChannel();
+12 -25
View File
@@ -44,6 +44,7 @@
#include "mac/channel_mask.hpp"
#include "mac/mac.hpp"
#include "mac/mac_types.hpp"
#include "mac/scan_result.hpp"
#include "meshcop/meshcop.hpp"
#include "thread/mle.hpp"
@@ -68,20 +69,6 @@ public:
*/
static constexpr uint32_t kDefaultScanDuration = Mac::kScanDurationDefault;
/**
* Represents Discover Scan result.
*/
typedef otActiveScanResult ScanResult;
/**
* 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 `nullptr`.
*/
typedef otHandleActiveScanResult Handler;
/**
* Represents the filter indexes, i.e., hash bit index values for the bloom filter (calculated from a
* Joiner ID).
@@ -109,7 +96,7 @@ public:
* @param[in] aFilterIndexes A pointer to `FilterIndexes` to use for filtering (when enabled).
* If set to `nullptr`, filter indexes are derived from hash of factory-assigned
* EUI64.
* @param[in] aCallback A pointer to a function that is called on receiving an MLE Discovery Response.
* @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 kErrorNone Successfully started a Thread Discovery Scan.
@@ -122,7 +109,7 @@ public:
bool aJoiner,
bool aEnableFiltering,
const FilterIndexes *aFilterIndexes,
Handler aCallback,
ScanResult::Handler aHandler,
void *aContext);
/**
@@ -176,15 +163,15 @@ private:
using ScanTimer = TimerMilliIn<DiscoverScanner, &DiscoverScanner::HandleTimer>;
using ScanDoneTask = TaskletIn<DiscoverScanner, &DiscoverScanner::HandleScanDoneTask>;
Callback<Handler> mCallback;
ScanDoneTask mScanDoneTask;
ScanTimer mTimer;
FilterIndexes mFilterIndexes;
Mac::ChannelMask mScanChannels;
State mState;
uint8_t mScanChannel;
bool mEnableFiltering : 1;
bool mShouldRestorePanId : 1;
ScanResult::ScanCallback mCallback;
ScanDoneTask mScanDoneTask;
ScanTimer mTimer;
FilterIndexes mFilterIndexes;
Mac::ChannelMask mScanChannels;
State mState;
uint8_t mScanChannel;
bool mEnableFiltering : 1;
bool mShouldRestorePanId : 1;
#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE
uint8_t mAdvDataLength;
uint8_t mAdvData[kMaxAdvDataLength];
+1 -6
View File
@@ -72,12 +72,7 @@ exit:
return;
}
void PanIdQueryServer::HandleScanResult(Mac::ActiveScanResult *aScanResult, void *aContext)
{
static_cast<PanIdQueryServer *>(aContext)->HandleScanResult(aScanResult);
}
void PanIdQueryServer::HandleScanResult(Mac::ActiveScanResult *aScanResult)
void PanIdQueryServer::HandleScanResult(const ScanResult *aScanResult)
{
if (aScanResult != nullptr)
{
+2 -4
View File
@@ -64,13 +64,11 @@ private:
template <Uri kUri> void HandleTmf(Coap::Msg &aMsg);
static void HandleScanResult(Mac::ActiveScanResult *aScanResult, void *aContext);
void HandleScanResult(Mac::ActiveScanResult *aScanResult);
void HandleTimer(void);
DeclareScanResultHandlerIn(PanIdQueryServer, HandleScanResult);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleTimer(void);
void SendConflict(void);
using DelayTimer = TimerMilliIn<PanIdQueryServer, &PanIdQueryServer::HandleTimer>;
+17 -16
View File
@@ -46,8 +46,8 @@ struct DiscoverContext
mScanResults.Clear();
}
bool mDiscoverDone;
Array<Mle::DiscoverScanner::ScanResult, kMaxResults> mScanResults;
bool mDiscoverDone;
Array<ScanResult, kMaxResults> mScanResults;
};
struct RequestCallbackContext : public Clearable<RequestCallbackContext>
@@ -59,19 +59,20 @@ struct RequestCallbackContext : public Clearable<RequestCallbackContext>
void HandleDiscoverResult(otActiveScanResult *aResult, void *aContext)
{
DiscoverContext *context = static_cast<DiscoverContext *>(aContext);
ScanResult *result = AsCoreTypePtr(aResult);
VerifyOrQuit(aContext != nullptr);
Log(" HandleDiscoverResult() called%s", aResult == nullptr ? " (done)" : "");
Log(" HandleDiscoverResult() called%s", result == nullptr ? " (done)" : "");
if (aResult == nullptr)
if (result == nullptr)
{
context->mDiscoverDone = true;
}
else
{
VerifyOrQuit(!context->mDiscoverDone);
SuccessOrQuit(context->mScanResults.PushBack(*aResult));
SuccessOrQuit(context->mScanResults.PushBack(*result));
}
}
@@ -95,12 +96,12 @@ void HandleDiscoverRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aCon
void TestDiscoverScanRequestCallback(void)
{
Core nexus;
Node &leader = nexus.CreateNode();
Node &scanner = nexus.CreateNode();
DiscoverContext resultContext;
RequestCallbackContext requestContext;
Mle::DiscoverScanner::ScanResult *result;
Core nexus;
Node &leader = nexus.CreateNode();
Node &scanner = nexus.CreateNode();
DiscoverContext resultContext;
RequestCallbackContext requestContext;
ScanResult *result;
Log("------------------------------------------------------------------------------------------------------");
Log("TestDiscoverScanRequestCallback");
@@ -148,11 +149,11 @@ void TestDiscoverScanRequestCallback(void)
result = &resultContext.mScanResults[0];
VerifyOrQuit(AsCoreType(&result->mExtAddress) == leader.Get<Mac::Mac>().GetExtAddress());
VerifyOrQuit(AsCoreType(&result->mExtendedPanId) == leader.Get<MeshCoP::NetworkIdentity>().GetExtPanId());
VerifyOrQuit(result->mPanId == leader.Get<Mac::Mac>().GetPanId());
VerifyOrQuit(result->mChannel == leader.Get<Mac::Mac>().GetPanChannel());
VerifyOrQuit(result->mDiscover);
VerifyOrQuit(result->GetExtAddress() == leader.Get<Mac::Mac>().GetExtAddress());
VerifyOrQuit(result->GetExtendedPanId() == leader.Get<MeshCoP::NetworkIdentity>().GetExtPanId());
VerifyOrQuit(result->GetPanId() == leader.Get<Mac::Mac>().GetPanId());
VerifyOrQuit(result->GetChannel() == leader.Get<Mac::Mac>().GetPanChannel());
VerifyOrQuit(result->IsDiscover());
}
} // namespace Nexus
-1
View File
@@ -39,7 +39,6 @@ class UnitTester
{
public:
using Seeker = MeshCoP::Seeker;
using ScanResult = MeshCoP::Seeker::ScanResult;
using CandidateEntry = MeshCoP::Seeker::CandidateEntry;
static void CreateScanResult(ScanResult &aResult, uint64_t aExtPanId, uint64_t aExtAddr, int8_t aRssi)