mirror of
https://github.com/espressif/openthread.git
synced 2026-09-12 04:00:10 +00:00
[netdata] support Extended TLVs in Commissioning Data sub-TLVs (#13594)
This commit enhances `NetworkData::Leader` handling of Commissioning Data sub-TLVs to support MeshCoP regular and Extended TLVs: - Define `CommissioningDataSubTlvInfo` and `FindCommissioningDataSubTlv()` to retrieve sub-TLVs, their value pointers, and lengths, correctly handling both standard and extended TLVs. - Updates `ReadCommissioningDataUint16SubTlv`, `FindSteeringData`, and `ProcessCommissionerGetRequest` to use `CommissioningDataSubTlvInfo`. - Removes the `FindInCommissioningData<SubTlvType>` template to prevent potential unsafe use. - Introduces `Leader::UpdateBorderAgentRloc()` to safely update the Border Agent Locator sub-TLV in-place and increment the Network Data version (if the RLOC changed). - Introduces `Leader::HasBorderAgentRloc()` to check for the presence of a valid Border Agent Locator sub-TLV without requiring dummy out-parameters at call sites.
This commit is contained in:
@@ -535,10 +535,10 @@ Error Manager::EvictActiveCommissioner(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t sessionId;
|
||||
uint16_t baRloc16;
|
||||
OwnedPtr<Coap::Message> message;
|
||||
|
||||
SuccessOrExit(error = Get<NetworkData::Leader>().FindBorderAgentRloc(baRloc16));
|
||||
VerifyOrExit(Get<NetworkData::Leader>().HasBorderAgentRloc(), error = kErrorNotFound);
|
||||
|
||||
SuccessOrExit(error = Get<NetworkData::Leader>().FindCommissioningSessionId(sessionId));
|
||||
|
||||
message.Reset(Get<Tmf::Agent>().AllocateAndInitPriorityConfirmablePostMessage(kUriLeaderKeepAlive));
|
||||
|
||||
@@ -571,7 +571,7 @@ void Admitter::CommissionerPetitioner::SendPetitionIfNoOtherCommissioner(void)
|
||||
|
||||
OT_ASSERT(mState == kToPetition || mState == kRejected);
|
||||
|
||||
if (Get<NetworkData::Leader>().FindInCommissioningData<BorderAgentLocatorTlv>() != nullptr)
|
||||
if (Get<NetworkData::Leader>().HasBorderAgentRloc())
|
||||
{
|
||||
SetState(kRejected);
|
||||
ExitNow();
|
||||
|
||||
@@ -112,10 +112,9 @@ exit:
|
||||
|
||||
template <> void Leader::HandleTmf<kUriLeaderKeepAlive>(Coap::Msg &aMsg)
|
||||
{
|
||||
uint8_t state;
|
||||
uint16_t sessionId;
|
||||
BorderAgentLocatorTlv *borderAgentLocator;
|
||||
StateTlv::State responseState;
|
||||
uint8_t state;
|
||||
uint16_t sessionId;
|
||||
StateTlv::State responseState;
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriLeaderKeepAlive>());
|
||||
|
||||
@@ -125,9 +124,7 @@ template <> void Leader::HandleTmf<kUriLeaderKeepAlive>(Coap::Msg &aMsg)
|
||||
|
||||
SuccessOrExit(Tlv::Find<CommissionerSessionIdTlv>(aMsg.mMessage, sessionId));
|
||||
|
||||
borderAgentLocator = Get<NetworkData::Leader>().FindInCommissioningData<BorderAgentLocatorTlv>();
|
||||
|
||||
if ((borderAgentLocator == nullptr) || (sessionId != mSessionId))
|
||||
if (!Get<NetworkData::Leader>().HasBorderAgentRloc() || (sessionId != mSessionId))
|
||||
{
|
||||
responseState = StateTlv::kReject;
|
||||
}
|
||||
@@ -138,13 +135,7 @@ template <> void Leader::HandleTmf<kUriLeaderKeepAlive>(Coap::Msg &aMsg)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t rloc = aMsg.mMessageInfo.GetPeerAddr().GetIid().GetLocator();
|
||||
|
||||
if (borderAgentLocator->GetBorderAgentLocator() != rloc)
|
||||
{
|
||||
borderAgentLocator->SetBorderAgentLocator(rloc);
|
||||
Get<NetworkData::Leader>().IncrementVersion();
|
||||
}
|
||||
Get<NetworkData::Leader>().UpdateBorderAgentRloc(aMsg.mMessageInfo.GetPeerAddr().GetIid().GetLocator());
|
||||
|
||||
responseState = StateTlv::kAccept;
|
||||
mTimer.Start(kLeaderPetitionTimeout);
|
||||
|
||||
@@ -174,10 +174,8 @@ exit:
|
||||
|
||||
void EnergyScanServer::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
uint16_t borderAgentRloc;
|
||||
|
||||
if (aEvents.Contains(kEventThreadNetdataChanged) && (mReportMessage != nullptr) &&
|
||||
Get<NetworkData::Leader>().FindBorderAgentRloc(borderAgentRloc) != kErrorNone)
|
||||
!Get<NetworkData::Leader>().HasBorderAgentRloc())
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
@@ -505,26 +505,36 @@ const CommissioningDataTlv *Leader::FindCommissioningData(void) const
|
||||
return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
|
||||
}
|
||||
|
||||
const MeshCoP::Tlv *Leader::FindCommissioningDataSubTlv(uint8_t aType) const
|
||||
Error Leader::FindCommissioningDataSubTlv(uint8_t aType, CommissioningDataSubTlvInfo &aSubTlvInfo) const
|
||||
{
|
||||
const MeshCoP::Tlv *subTlv = nullptr;
|
||||
Error error = kErrorNotFound;
|
||||
const NetworkDataTlv *dataTlv = FindCommissioningData();
|
||||
const MeshCoP::Tlv *subTlv;
|
||||
|
||||
VerifyOrExit(dataTlv != nullptr);
|
||||
|
||||
subTlv = As<MeshCoP::Tlv>(Tlv::FindTlv(dataTlv->GetValue(), dataTlv->GetLength(), aType));
|
||||
VerifyOrExit(subTlv != nullptr);
|
||||
|
||||
aSubTlvInfo.mTlv = subTlv;
|
||||
aSubTlvInfo.mValue = subTlv->GetValue();
|
||||
aSubTlvInfo.mLength = subTlv->IsExtended() ? As<ExtendedTlv>(subTlv)->GetLength() : subTlv->GetLength();
|
||||
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return subTlv;
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Leader::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
const MeshCoP::Tlv *subTlv = FindCommissioningDataSubTlv(aType);
|
||||
Error error;
|
||||
CommissioningDataSubTlvInfo subTlvInfo;
|
||||
|
||||
VerifyOrExit(subTlv != nullptr, error = kErrorNotFound);
|
||||
VerifyOrExit(subTlv->GetLength() >= sizeof(uint16_t), error = kErrorParse);
|
||||
aValue = BigEndian::ReadUint16(subTlv->GetValue());
|
||||
SuccessOrExit(error = FindCommissioningDataSubTlv(aType, subTlvInfo));
|
||||
|
||||
VerifyOrExit(subTlvInfo.mLength >= sizeof(uint16_t), error = kErrorParse);
|
||||
aValue = BigEndian::ReadUint16(subTlvInfo.mValue);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -583,16 +593,14 @@ Coap::Message *Leader::ProcessCommissionerGetRequest(const Coap::Message &aMessa
|
||||
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
uint8_t type;
|
||||
const MeshCoP::Tlv *subTlv;
|
||||
uint8_t type;
|
||||
CommissioningDataSubTlvInfo subTlvInfo;
|
||||
|
||||
IgnoreError(aMessage.ReadAndAdvance(offsetRange, type));
|
||||
|
||||
subTlv = FindCommissioningDataSubTlv(type);
|
||||
|
||||
if (subTlv != nullptr)
|
||||
if (FindCommissioningDataSubTlv(type, subTlvInfo) == kErrorNone)
|
||||
{
|
||||
SuccessOrExit(error = subTlv->AppendTo(*response));
|
||||
SuccessOrExit(error = subTlvInfo.mTlv->AppendTo(*response));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,6 +626,13 @@ Error Leader::FindBorderAgentRloc(uint16_t &aRloc16) const
|
||||
return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kBorderAgentLocator, aRloc16);
|
||||
}
|
||||
|
||||
bool Leader::HasBorderAgentRloc(void) const
|
||||
{
|
||||
uint16_t rloc16;
|
||||
|
||||
return (FindBorderAgentRloc(rloc16) == kErrorNone);
|
||||
}
|
||||
|
||||
Error Leader::FindCommissioningSessionId(uint16_t &aSessionId) const
|
||||
{
|
||||
return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kCommissionerSessionId, aSessionId);
|
||||
@@ -630,11 +645,14 @@ Error Leader::FindJoinerUdpPort(uint16_t &aPort) const
|
||||
|
||||
Error Leader::FindSteeringData(MeshCoP::SteeringData &aSteeringData) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
const MeshCoP::SteeringDataTlv *steeringDataTlv = FindInCommissioningData<MeshCoP::SteeringDataTlv>();
|
||||
Error error = kErrorNotFound;
|
||||
CommissioningDataSubTlvInfo subTlvInfo;
|
||||
uint16_t steeringDataLength;
|
||||
|
||||
VerifyOrExit(steeringDataTlv != nullptr, error = kErrorNotFound);
|
||||
error = steeringDataTlv->CopyTo(aSteeringData);
|
||||
SuccessOrExit(FindCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData, subTlvInfo));
|
||||
|
||||
steeringDataLength = Min<uint16_t>(subTlvInfo.mLength, MeshCoP::SteeringData::kMaxLength);
|
||||
error = aSteeringData.Init(static_cast<uint8_t>(steeringDataLength), subTlvInfo.mValue);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
@@ -186,30 +186,6 @@ public:
|
||||
*/
|
||||
Coap::Message *ProcessCommissionerGetRequest(const Coap::Message &aMessage) const;
|
||||
|
||||
/**
|
||||
* Searches for given sub-TLV in Commissioning Data TLV.
|
||||
*
|
||||
* @tparam SubTlvType The sub-TLV type to search for.
|
||||
*
|
||||
* @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists.
|
||||
*/
|
||||
template <typename SubTlvType> const SubTlvType *FindInCommissioningData(void) const
|
||||
{
|
||||
return As<SubTlvType>(FindCommissioningDataSubTlv(SubTlvType::kType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for given sub-TLV in Commissioning Data TLV.
|
||||
*
|
||||
* @tparam SubTlvType The sub-TLV type to search for.
|
||||
*
|
||||
* @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists.
|
||||
*/
|
||||
template <typename SubTlvType> SubTlvType *FindInCommissioningData(void)
|
||||
{
|
||||
return As<SubTlvType>(FindCommissioningDataSubTlv(SubTlvType::kType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and reads the Commissioning Session ID in Commissioning Data TLV.
|
||||
*
|
||||
@@ -232,6 +208,14 @@ public:
|
||||
*/
|
||||
Error FindBorderAgentRloc(uint16_t &aRloc16) const;
|
||||
|
||||
/**
|
||||
* Indicates whether the Commissioning Data contains a valid Border Agent Locator sub-TLV.
|
||||
*
|
||||
* @retval TRUE The Commissioning Data contains a valid Border Agent Locator sub-TLV.
|
||||
* @retval FALSE The Commissioning Data does not contain a valid Border Agent Locator sub-TLV.
|
||||
*/
|
||||
bool HasBorderAgentRloc(void) const;
|
||||
|
||||
/**
|
||||
* Finds and reads the Joiner UDP Port in Commissioning Data TLV.
|
||||
*
|
||||
@@ -356,6 +340,18 @@ public:
|
||||
*/
|
||||
void IncrementVersionAndStableVersion(void);
|
||||
|
||||
/**
|
||||
* Updates the Border Agent Locator sub-TLV in the Commissioning Data.
|
||||
*
|
||||
* If the Border Agent Locator sub-TLV is present in the Commissioning Data and its value differs from @p aRloc16,
|
||||
* this method updates its value in-place and increments the Thread Network Data version. If the sub-TLV is not
|
||||
* present, or if its value already matches @p aRloc16, no changes are made and the Network Data version is not
|
||||
* incremented.
|
||||
*
|
||||
* @param[in] aRloc16 The new Border Agent RLOC16 value.
|
||||
*/
|
||||
void UpdateBorderAgentRloc(uint16_t aRloc16);
|
||||
|
||||
/**
|
||||
* Performs anycast ALOC route lookup using the Network Data.
|
||||
*
|
||||
@@ -432,6 +428,13 @@ private:
|
||||
|
||||
typedef bool (&EntryChecker)(const BorderRouterEntry &aEntry);
|
||||
|
||||
struct CommissioningDataSubTlvInfo
|
||||
{
|
||||
const Tlv *mTlv;
|
||||
const uint8_t *mValue;
|
||||
uint16_t mLength;
|
||||
};
|
||||
|
||||
const PrefixTlv *FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const;
|
||||
const PrefixTlv *FindPrefixTlvForContextId(uint8_t aContextId, const ContextTlv *&aContextTlv) const;
|
||||
|
||||
@@ -453,11 +456,7 @@ private:
|
||||
void SignalNetDataChanged(void);
|
||||
const CommissioningDataTlv *FindCommissioningData(void) const;
|
||||
CommissioningDataTlv *FindCommissioningData(void) { return AsNonConst(AsConst(this)->FindCommissioningData()); }
|
||||
const MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) const;
|
||||
MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType)
|
||||
{
|
||||
return AsNonConst(AsConst(this)->FindCommissioningDataSubTlv(aType));
|
||||
}
|
||||
Error FindCommissioningDataSubTlv(uint8_t aType, CommissioningDataSubTlvInfo &aSubTlvInfo) const;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec.
|
||||
|
||||
@@ -99,6 +99,22 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Leader::UpdateBorderAgentRloc(uint16_t aRloc16)
|
||||
{
|
||||
CommissioningDataSubTlvInfo subTlvInfo;
|
||||
|
||||
SuccessOrExit(FindCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator, subTlvInfo));
|
||||
|
||||
VerifyOrExit(subTlvInfo.mLength >= sizeof(uint16_t));
|
||||
VerifyOrExit(BigEndian::ReadUint16(subTlvInfo.mValue) != aRloc16);
|
||||
BigEndian::WriteUint16(aRloc16, AsNonConst(subTlvInfo.mValue));
|
||||
|
||||
IncrementVersion();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error Leader::AnycastLookup(uint16_t aAloc16, uint16_t &aRloc16) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -1285,7 +1301,6 @@ void Leader::HandleNetworkDataRestoredAfterReset(void)
|
||||
const PrefixTlv *prefix;
|
||||
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
|
||||
ChangedFlags flags;
|
||||
uint16_t rloc16;
|
||||
uint16_t sessionId;
|
||||
Rlocs rlocs;
|
||||
|
||||
@@ -1339,7 +1354,7 @@ void Leader::HandleNetworkDataRestoredAfterReset(void)
|
||||
Get<MeshCoP::Leader>().SetSessionId(sessionId);
|
||||
}
|
||||
|
||||
if (FindBorderAgentRloc(rloc16) == kErrorNone)
|
||||
if (HasBorderAgentRloc())
|
||||
{
|
||||
Get<MeshCoP::Leader>().SetEmptyCommissionerData();
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ void TestBorderAdmitterEnrollerInteraction(void)
|
||||
VerifyOrQuit(admitter.Get<Admitter>().IsPrimeAdmitter());
|
||||
VerifyOrQuit(!admitter.Get<Admitter>().IsActiveCommissioner());
|
||||
|
||||
VerifyOrQuit(admitter.Get<NetworkData::Leader>().FindBorderAgentRloc(rloc16) == kErrorNotFound);
|
||||
VerifyOrQuit(!admitter.Get<NetworkData::Leader>().HasBorderAgentRloc());
|
||||
|
||||
nexus.AdvanceTime(10 * Time::kOneSecondInMsec);
|
||||
|
||||
@@ -933,7 +933,7 @@ void TestBorderAdmitterEnrollerInteraction(void)
|
||||
VerifyOrQuit(admitter.Get<Admitter>().IsPrimeAdmitter());
|
||||
VerifyOrQuit(!admitter.Get<Admitter>().IsActiveCommissioner());
|
||||
|
||||
VerifyOrQuit(admitter.Get<NetworkData::Leader>().FindBorderAgentRloc(rloc16) == kErrorNotFound);
|
||||
VerifyOrQuit(!admitter.Get<NetworkData::Leader>().HasBorderAgentRloc());
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Re-establish DTLS session");
|
||||
|
||||
Reference in New Issue
Block a user