[netdata] simplify parsing of Commissioning Dataset sub-TLVs (#9541)

This commit contains changes related to parsing of Commissioning
Dataset sub-TLVs in `NetworkData::Leader`:
- Adds `FindInCommisioningData<SubTlvType>` to search for a given
  `SubTlvType` in Commissioning Data.
- Adds `FindCommissioningSessionId()`, `FindBorderAgentRloc()`,
  and `FindJoinerUdpPort()` to parse and get get the info
  from Commissioning Dataset.
This commit is contained in:
Abtin Keshavarzian
2023-10-18 16:11:25 -07:00
committed by GitHub
parent 03bfced292
commit 2457ba7c18
13 changed files with 154 additions and 124 deletions
+3 -4
View File
@@ -176,11 +176,10 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
if (Tlv::Find<ThreadCommissionerSessionIdTlv>(aMessage, commissionerSessionId) == kErrorNone)
{
const MeshCoP::CommissionerSessionIdTlv *commissionerSessionIdTlv = As<MeshCoP::CommissionerSessionIdTlv>(
Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kCommissionerSessionId));
uint16_t localSessionId;
VerifyOrExit(commissionerSessionIdTlv != nullptr &&
commissionerSessionIdTlv->GetCommissionerSessionId() == commissionerSessionId,
VerifyOrExit((Get<NetworkData::Leader>().FindCommissioningSessionId(localSessionId) == kErrorNone) &&
(localSessionId == commissionerSessionId),
status = ThreadStatusTlv::kMlrGeneralFailure);
hasCommissionerSessionIdTlv = true;
+7 -14
View File
@@ -167,14 +167,12 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo
// check commissioner session id
if (Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId) == kErrorNone)
{
const CommissionerSessionIdTlv *localId;
uint16_t localSessionId;
isUpdateFromCommissioner = true;
localId = As<CommissionerSessionIdTlv>(
Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kCommissionerSessionId));
VerifyOrExit(localId != nullptr && localId->GetCommissionerSessionId() == sessionId);
SuccessOrExit(Get<NetworkData::Leader>().FindCommissioningSessionId(localSessionId));
VerifyOrExit(localSessionId == sessionId);
}
// verify an MGMT_ACTIVE_SET.req from a Commissioner does not affect connectivity
@@ -240,16 +238,11 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo
// notify commissioner if update is from thread device
if (!isUpdateFromCommissioner)
{
const CommissionerSessionIdTlv *localSessionId;
Ip6::Address destination;
localSessionId = As<CommissionerSessionIdTlv>(
Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kCommissionerSessionId));
VerifyOrExit(localSessionId != nullptr);
SuccessOrExit(
Get<Mle::MleRouter>().GetCommissionerAloc(destination, localSessionId->GetCommissionerSessionId()));
uint16_t localSessionId;
Ip6::Address destination;
SuccessOrExit(Get<NetworkData::Leader>().FindCommissioningSessionId(localSessionId));
SuccessOrExit(Get<Mle::MleRouter>().GetCommissionerAloc(destination, localSessionId));
Get<Leader>().SendDatasetChanged(destination);
}
+14 -10
View File
@@ -75,7 +75,7 @@ void JoinerRouter::Start(void)
{
VerifyOrExit(Get<Mle::MleRouter>().IsFullThreadDevice());
if (Get<NetworkData::Leader>().IsJoiningEnabled())
if (Get<NetworkData::Leader>().IsJoiningAllowed())
{
uint16_t port = GetJoinerUdpPort();
@@ -99,20 +99,24 @@ exit:
return;
}
uint16_t JoinerRouter::GetJoinerUdpPort(void)
uint16_t JoinerRouter::GetJoinerUdpPort(void) const
{
uint16_t rval = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
const JoinerUdpPortTlv *joinerUdpPort;
uint16_t port;
VerifyOrExit(!mIsJoinerPortConfigured, rval = mJoinerUdpPort);
if (mIsJoinerPortConfigured)
{
ExitNow(port = mJoinerUdpPort);
}
joinerUdpPort = As<JoinerUdpPortTlv>(Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kJoinerUdpPort));
VerifyOrExit(joinerUdpPort != nullptr);
if (Get<NetworkData::Leader>().FindJoinerUdpPort(port) == kErrorNone)
{
ExitNow();
}
rval = joinerUdpPort->GetUdpPort();
port = kDefaultJoinerUdpPort;
exit:
return rval;
return port;
}
void JoinerRouter::SetJoinerUdpPort(uint16_t aJoinerUdpPort)
@@ -137,7 +141,7 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
LogInfo("JoinerRouter::HandleUdpReceive");
SuccessOrExit(error = GetBorderAgentRloc(Get<ThreadNetif>(), borderAgentRloc));
SuccessOrExit(error = Get<NetworkData::Leader>().FindBorderAgentRloc(borderAgentRloc));
message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(kUriRelayRx);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+3 -2
View File
@@ -71,10 +71,10 @@ public:
/**
* Returns the Joiner UDP Port.
*
* @returns The Joiner UDP Port number .
* @returns The Joiner UDP Port number.
*
*/
uint16_t GetJoinerUdpPort(void);
uint16_t GetJoinerUdpPort(void) const;
/**
* Sets the Joiner UDP Port.
@@ -85,6 +85,7 @@ public:
void SetJoinerUdpPort(uint16_t aJoinerUdpPort);
private:
static constexpr uint16_t kDefaultJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
static constexpr uint32_t kJoinerEntrustTxDelay = 50; // in msec
struct JoinerEntrustMetadata
+1 -15
View File
@@ -1,3 +1,4 @@
/*
* Copyright (c) 2017, The OpenThread Authors.
* All rights reserved.
@@ -300,21 +301,6 @@ void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId)
aJoinerId.SetLocal(true);
}
Error GetBorderAgentRloc(ThreadNetif &aNetif, uint16_t &aRloc)
{
Error error = kErrorNone;
const BorderAgentLocatorTlv *borderAgentLocator;
borderAgentLocator = As<BorderAgentLocatorTlv>(
aNetif.Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
VerifyOrExit(borderAgentLocator != nullptr, error = kErrorNotFound);
aRloc = borderAgentLocator->GetBorderAgentLocator();
exit:
return error;
}
#if OPENTHREAD_FTD
Error GeneratePskc(const char *aPassPhrase,
const NetworkName &aNetworkName,
-12
View File
@@ -434,18 +434,6 @@ Error GeneratePskc(const char *aPassPhrase,
*/
void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId);
/**
* Gets the border agent RLOC.
*
* @param[in] aNetIf A reference to the thread interface.
* @param[out] aRloc Border agent RLOC.
*
* @retval kErrorNone Successfully got the Border Agent Rloc.
* @retval kErrorNotFound Border agent is not available.
*
*/
Error GetBorderAgentRloc(ThreadNetif &aNetIf, uint16_t &aRloc);
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
/**
* Emits a log message indicating an error during a MeshCoP action.
+1 -2
View File
@@ -150,8 +150,7 @@ template <> void Leader::HandleTmf<kUriLeaderKeepAlive>(Coap::Message &aMessage,
SuccessOrExit(Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId));
borderAgentLocator =
As<BorderAgentLocatorTlv>(Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
borderAgentLocator = Get<NetworkData::Leader>().FindInCommissioningData<BorderAgentLocatorTlv>();
if ((borderAgentLocator == nullptr) || (sessionId != mSessionId))
{
+3 -1
View File
@@ -207,8 +207,10 @@ exit:
void EnergyScanServer::HandleNotifierEvents(Events aEvents)
{
uint16_t borderAgentRloc;
if (aEvents.Contains(kEventThreadNetdataChanged) && (mReportMessage != nullptr) &&
Get<NetworkData::Leader>().GetCommissioningData() == nullptr)
Get<NetworkData::Leader>().FindBorderAgentRloc(borderAgentRloc) != kErrorNone)
{
mReportMessage->Free();
mReportMessage = nullptr;
+1 -1
View File
@@ -534,7 +534,7 @@ Error MeshForwarder::UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &a
}
else if (aloc16 <= Mle::kAloc16CommissionerEnd)
{
SuccessOrExit(error = MeshCoP::GetBorderAgentRloc(Get<ThreadNetif>(), mMeshDest));
SuccessOrExit(error = Get<NetworkData::Leader>().FindBorderAgentRloc(mMeshDest));
}
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+5 -5
View File
@@ -2740,7 +2740,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
else // if steering data is not set out of band, fall back to network data
#endif
{
VerifyOrExit(Get<NetworkData::Leader>().IsJoiningEnabled(), error = kErrorSecurity);
VerifyOrExit(Get<NetworkData::Leader>().IsJoiningAllowed(), error = kErrorSecurity);
}
}
}
@@ -2821,13 +2821,13 @@ Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const M
else
#endif
{
const MeshCoP::Tlv *steeringData;
const MeshCoP::SteeringDataTlv *steeringDataTlv;
steeringData = Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
steeringDataTlv = Get<NetworkData::Leader>().FindInCommissioningData<MeshCoP::SteeringDataTlv>();
if (steeringData != nullptr)
if (steeringDataTlv != nullptr)
{
SuccessOrExit(error = steeringData->AppendTo(*message));
SuccessOrExit(error = steeringDataTlv->AppendTo(*message));
}
}
+51 -25
View File
@@ -453,50 +453,76 @@ exit:
return error;
}
const CommissioningDataTlv *LeaderBase::GetCommissioningData(void) const
const CommissioningDataTlv *LeaderBase::FindCommissioningData(void) const
{
return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
}
const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const
const MeshCoP::Tlv *LeaderBase::FindCommissioningDataSubTlv(uint8_t aType) const
{
const MeshCoP::Tlv *rval = nullptr;
const NetworkDataTlv *commissioningDataTlv;
const MeshCoP::Tlv *subTlv = nullptr;
const NetworkDataTlv *dataTlv = FindCommissioningData();
commissioningDataTlv = GetCommissioningData();
VerifyOrExit(commissioningDataTlv != nullptr);
rval = As<MeshCoP::Tlv>(Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType));
VerifyOrExit(dataTlv != nullptr);
subTlv = As<MeshCoP::Tlv>(Tlv::FindTlv(dataTlv->GetValue(), dataTlv->GetLength(), aType));
exit:
return rval;
return subTlv;
}
bool LeaderBase::IsJoiningEnabled(void) const
Error LeaderBase::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const
{
const MeshCoP::Tlv *steeringData;
bool rval = false;
Error error = kErrorNone;
const MeshCoP::Tlv *subTlv = FindCommissioningDataSubTlv(aType);
VerifyOrExit(GetCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator) != nullptr);
VerifyOrExit(subTlv != nullptr, error = kErrorNotFound);
VerifyOrExit(subTlv->GetLength() >= sizeof(uint16_t), error = kErrorParse);
aValue = Encoding::BigEndian::ReadUint16(subTlv->GetValue());
steeringData = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
VerifyOrExit(steeringData != nullptr);
exit:
return error;
}
for (int i = 0; i < steeringData->GetLength(); i++)
Error LeaderBase::FindBorderAgentRloc(uint16_t &aRloc16) const
{
return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kBorderAgentLocator, aRloc16);
}
Error LeaderBase::FindCommissioningSessionId(uint16_t &aSessionId) const
{
return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kCommissionerSessionId, aSessionId);
}
Error LeaderBase::FindJoinerUdpPort(uint16_t &aPort) const
{
return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kJoinerUdpPort, aPort);
}
bool LeaderBase::IsJoiningAllowed(void) const
{
bool isAllowed = false;
const MeshCoP::SteeringDataTlv *steeringDataTlv;
VerifyOrExit(FindInCommissioningData<MeshCoP::BorderAgentLocatorTlv>() != nullptr);
steeringDataTlv = FindInCommissioningData<MeshCoP::SteeringDataTlv>();
VerifyOrExit(steeringDataTlv != nullptr);
for (int i = 0; i < steeringDataTlv->GetLength(); i++)
{
if (steeringData->GetValue()[i] != 0)
if (steeringDataTlv->GetValue()[i] != 0)
{
ExitNow(rval = true);
ExitNow(isAllowed = true);
}
}
exit:
return rval;
return isAllowed;
}
void LeaderBase::RemoveCommissioningData(void)
{
CommissioningDataTlv *tlv = GetCommissioningData();
CommissioningDataTlv *tlv = FindCommissioningData();
VerifyOrExit(tlv != nullptr);
RemoveTlv(tlv);
@@ -507,14 +533,14 @@ exit:
Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
{
Error error = kErrorNone;
const MeshCoP::Tlv *steeringDataTlv;
MeshCoP::SteeringData steeringData;
Error error = kErrorNone;
const MeshCoP::SteeringDataTlv *steeringDataTlv;
MeshCoP::SteeringData steeringData;
steeringDataTlv = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
steeringDataTlv = FindInCommissioningData<MeshCoP::SteeringDataTlv>();
VerifyOrExit(steeringDataTlv != nullptr, error = kErrorInvalidState);
As<MeshCoP::SteeringDataTlv>(steeringDataTlv)->CopyTo(steeringData);
steeringDataTlv->CopyTo(steeringData);
VerifyOrExit(steeringData.Contains(aFilterIndexes), error = kErrorNotFound);
+63 -31
View File
@@ -182,53 +182,77 @@ public:
uint16_t aLength);
/**
* Returns a pointer to the Commissioning Data.
* Searches for given sub-TLV in Commissioning Data TLV.
*
* @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
* @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.
*
*/
CommissioningDataTlv *GetCommissioningData(void) { return AsNonConst(AsConst(this)->GetCommissioningData()); }
/**
* Returns a pointer to the Commissioning Data.
*
* @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
*
*/
const CommissioningDataTlv *GetCommissioningData(void) const;
/**
* Returns a pointer to the Commissioning Data Sub-TLV.
*
* @param[in] aType The TLV type value.
*
* @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
*
*/
MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)
template <typename SubTlvType> const SubTlvType *FindInCommissioningData(void) const
{
return AsNonConst(AsConst(this)->GetCommissioningDataSubTlv(aType));
return As<SubTlvType>(FindCommissioningDataSubTlv(SubTlvType::kType));
}
/**
* Returns a pointer to the Commissioning Data Sub-TLV.
* Searches for given sub-TLV in Commissioning Data TLV.
*
* @param[in] aType The TLV type value.
* @tparam SubTlvType The sub-TLV type to search for.
*
* @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
* @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists.
*
*/
const MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const;
template <typename SubTlvType> SubTlvType *FindInCommissioningData(void)
{
return As<SubTlvType>(FindCommissioningDataSubTlv(SubTlvType::kType));
}
/**
* Indicates whether or not the Commissioning Data TLV indicates Joining is enabled.
* Finds and reads the Commissioning Session ID in Commissioning Data TLV.
*
* Joining is enabled if a Border Agent Locator TLV exist and the Steering Data TLV is non-zero.
* @param[out] aSessionId A reference to return the read session ID.
*
* @returns TRUE if the Commissioning Data TLV says Joining is enabled, FALSE otherwise.
* @retval kErrorNone Successfully read the session ID, @p aSessionId is updated.
* @retval kErrorNotFound Did not find Session ID sub-TLV.
* @retval kErrorParse Failed to parse Commissioning Data TLV (invalid format).
*
*/
bool IsJoiningEnabled(void) const;
Error FindCommissioningSessionId(uint16_t &aSessionId) const;
/**
* Finds and reads the Border Agent RLOC16 in Commissioning Data TLV.
*
* @param[out] aRloc16 A reference to return the read RLOC16.
*
* @retval kErrorNone Successfully read the Border Agent RLOC16, @p aRloc16 is updated.
* @retval kErrorNotFound Did not find Border Agent RLOC16 sub-TLV.
* @retval kErrorParse Failed to parse Commissioning Data TLV (invalid format).
*
*/
Error FindBorderAgentRloc(uint16_t &aRloc16) const;
/**
* Finds and reads the Joiner UDP Port in Commissioning Data TLV.
*
* @param[out] aPort A reference to return the read port number.
*
* @retval kErrorNone Successfully read the Joiner UDP port, @p aPort is updated.
* @retval kErrorNotFound Did not find Joiner UDP Port sub-TLV.
* @retval kErrorParse Failed to parse Commissioning Data TLV (invalid format).
*
*/
Error FindJoinerUdpPort(uint16_t &aPort) const;
/**
* Indicates whether or not the Commissioning Data TLV indicates Joining is allowed.
*
* Joining is allowed if a Border Agent Locator TLV exist and the Steering Data TLV is non-zero.
*
* @retval TRUE If joining is allowed.
* @retval FALSE If joining is not allowed.
*
*/
bool IsJoiningAllowed(void) const;
/**
* Adds Commissioning Data to the Thread Network Data.
@@ -298,7 +322,9 @@ public:
Error GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const;
protected:
void SignalNetDataChanged(void);
void SignalNetDataChanged(void);
const CommissioningDataTlv *FindCommissioningData(void) const;
CommissioningDataTlv *FindCommissioningData(void) { return AsNonConst(AsConst(this)->FindCommissioningData()); }
uint8_t mStableVersion;
uint8_t mVersion;
@@ -320,6 +346,12 @@ private:
Error DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const;
Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const;
void GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const;
Error ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const;
const MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) const;
MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType)
{
return AsNonConst(AsConst(this)->FindCommissioningDataSubTlv(aType));
}
uint8_t mTlvBuffer[kMaxSize];
uint8_t mMaxLength;
+2 -2
View File
@@ -248,7 +248,7 @@ template <> void Leader::HandleTmf<kUriCommissionerSet>(Coap::Message &aMessage,
VerifyOrExit(hasValidTlv);
// Find Commissioning Data TLV
commDataTlv = GetCommissioningData();
commDataTlv = FindCommissioningData();
if (commDataTlv != nullptr)
{
@@ -312,7 +312,7 @@ void Leader::SendCommissioningGetResponse(const Coap::Message &aRequest,
message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
commDataTlv = GetCommissioningData();
commDataTlv = FindCommissioningData();
if (commDataTlv != nullptr)
{