mirror of
https://github.com/espressif/openthread.git
synced 2026-07-21 19:44:08 +00:00
[network-diag] introduce TlvTypeListIterator (#12672)
This commit introduces a new `TlvTypeListIterator` helper class in the network diagnostic `Server` to simplify the parsing of Type List TLVs. This iterator handles deduplication of requested TLV types using a `BitSet` and centralizes the offset management and iteration logic. The iterator is now used in `AppendRequestedTlvs()`, `AppendRequestedTlvsForTcat()`, `PrepareAndSendAnswers()`, and `HandleTmf<kUriDiagnosticReset>()`, replacing redundant manual iteration and deduplication code. Additionally, the `TypeListTlv` definition is simplified to a `typedef` of `TlvInfo`, as the dedicated class structure is no longer needed.
This commit is contained in:
committed by
GitHub
parent
e3d03f4f14
commit
ea94a2edf6
@@ -296,28 +296,14 @@ exit:
|
||||
|
||||
Error Server::AppendRequestedTlvs(const Message &aRequest, Message &aResponse)
|
||||
{
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
TlvTypeBitSet processedTlvs;
|
||||
Error error;
|
||||
TlvTypeListIterator iterator;
|
||||
uint8_t tlvType;
|
||||
|
||||
processedTlvs.Clear();
|
||||
SuccessOrExit(error = iterator.InitForTypeListTlv(aRequest));
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kTypeList, offsetRange));
|
||||
|
||||
while (!offsetRange.IsEmpty())
|
||||
while (iterator.ReadNextTlvType(tlvType) == kErrorNone)
|
||||
{
|
||||
uint8_t tlvType;
|
||||
|
||||
SuccessOrExit(error = aRequest.Read(offsetRange, tlvType));
|
||||
offsetRange.AdvanceOffset(sizeof(tlvType));
|
||||
|
||||
if (processedTlvs.Has(tlvType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
processedTlvs.Add(tlvType);
|
||||
|
||||
SuccessOrExit(error = AppendDiagTlv(tlvType, aResponse));
|
||||
}
|
||||
|
||||
@@ -328,25 +314,14 @@ exit:
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
Error Server::AppendRequestedTlvsForTcat(const Message &aRequest, Message &aResponse, OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
TlvTypeBitSet processedTlvs;
|
||||
Error error = kErrorNone;
|
||||
TlvTypeListIterator iterator;
|
||||
uint8_t tlvType;
|
||||
|
||||
processedTlvs.Clear();
|
||||
iterator.Init(aRequest, aOffsetRange);
|
||||
|
||||
while (!aOffsetRange.IsEmpty())
|
||||
while (iterator.ReadNextTlvType(tlvType) == kErrorNone)
|
||||
{
|
||||
uint8_t tlvType;
|
||||
|
||||
SuccessOrExit(error = aRequest.Read(aOffsetRange, tlvType));
|
||||
aOffsetRange.AdvanceOffset(sizeof(uint8_t));
|
||||
|
||||
if (processedTlvs.Has(tlvType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
processedTlvs.Add(tlvType);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
switch (tlvType)
|
||||
{
|
||||
@@ -669,11 +644,12 @@ void Server::FreeAllRelatedAnswers(Coap::Message &aFirstAnswer)
|
||||
|
||||
void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Message &aRequest)
|
||||
{
|
||||
Coap::Message *answer;
|
||||
Error error;
|
||||
AnswerInfo info;
|
||||
OffsetRange offsetRange;
|
||||
AnswerTlv answerTlv;
|
||||
Coap::Message *answer;
|
||||
Error error;
|
||||
AnswerInfo info;
|
||||
uint8_t tlvType;
|
||||
TlvTypeListIterator iterator;
|
||||
AnswerTlv answerTlv;
|
||||
|
||||
if (Tlv::Find<QueryIdTlv>(aRequest, info.mQueryId) == kErrorNone)
|
||||
{
|
||||
@@ -684,15 +660,10 @@ void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Messa
|
||||
|
||||
SuccessOrExit(error = AllocateAnswer(answer, info));
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kTypeList, offsetRange));
|
||||
SuccessOrExit(error = iterator.InitForTypeListTlv(aRequest));
|
||||
|
||||
while (!offsetRange.IsEmpty())
|
||||
while (iterator.ReadNextTlvType(tlvType) == kErrorNone)
|
||||
{
|
||||
uint8_t tlvType;
|
||||
|
||||
SuccessOrExit(error = aRequest.Read(offsetRange, tlvType));
|
||||
offsetRange.AdvanceOffset(sizeof(tlvType));
|
||||
|
||||
switch (tlvType)
|
||||
{
|
||||
case ChildTlv::kType:
|
||||
@@ -924,26 +895,19 @@ exit:
|
||||
|
||||
template <> void Server::HandleTmf<kUriDiagnosticReset>(Coap::Msg &aMsg)
|
||||
{
|
||||
uint16_t offset = 0;
|
||||
uint8_t type;
|
||||
Tlv tlv;
|
||||
TlvTypeListIterator iterator;
|
||||
uint8_t tlvType;
|
||||
|
||||
VerifyOrExit(aMsg.IsConfirmable());
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriDiagnosticReset>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
|
||||
SuccessOrExit(aMsg.mMessage.Read(aMsg.mMessage.GetOffset(), tlv));
|
||||
SuccessOrExit(iterator.InitForTypeListTlv(aMsg.mMessage));
|
||||
|
||||
VerifyOrExit(tlv.GetType() == Tlv::kTypeList);
|
||||
|
||||
offset = aMsg.mMessage.GetOffset() + sizeof(Tlv);
|
||||
|
||||
for (uint8_t i = 0; i < tlv.GetLength(); i++)
|
||||
while (iterator.ReadNextTlvType(tlvType) == kErrorNone)
|
||||
{
|
||||
SuccessOrExit(aMsg.mMessage.Read(offset + i, type));
|
||||
|
||||
switch (type)
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kMacCounters:
|
||||
Get<Mac::Mac>().ResetCounters();
|
||||
@@ -968,6 +932,51 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Server::TlvTypeListIterator
|
||||
|
||||
void Server::TlvTypeListIterator::Init(const Message &aMessage, const OffsetRange &aOffsetRange)
|
||||
{
|
||||
mMessage = &aMessage;
|
||||
mOffsetRange = aOffsetRange;
|
||||
mProcessedTlvs.Clear();
|
||||
}
|
||||
|
||||
Error Server::TlvTypeListIterator::InitForTypeListTlv(const Message &aMessage)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kTypeList, mOffsetRange));
|
||||
mMessage = &aMessage;
|
||||
mProcessedTlvs.Clear();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Server::TlvTypeListIterator::ReadNextTlvType(uint8_t &aTlvType)
|
||||
{
|
||||
Error error;
|
||||
|
||||
while (!mOffsetRange.IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = mMessage->Read(mOffsetRange, aTlvType));
|
||||
mOffsetRange.AdvanceOffset(sizeof(uint8_t));
|
||||
|
||||
if (!mProcessedTlvs.Has(aTlvType))
|
||||
{
|
||||
mProcessedTlvs.Add(aTlvType);
|
||||
error = kErrorNone;
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
error = kErrorNotFound;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -122,7 +122,22 @@ private:
|
||||
static constexpr uint16_t kMaxChildEntries = 398;
|
||||
static constexpr uint16_t kAnswerMessageLengthThreshold = 800;
|
||||
|
||||
typedef BitSet<NumericLimits<uint8_t>::kMax + 1> TlvTypeBitSet; // A bitset to store TLV types.
|
||||
class TlvTypeListIterator
|
||||
{
|
||||
// Iterates through a list of TLV types in a message (e.g., in a
|
||||
// `TypeListTlv`), reading them one by one and skipping over any
|
||||
// duplicate TLV type in the list.
|
||||
|
||||
public:
|
||||
void Init(const Message &aMessage, const OffsetRange &aOffsetRange);
|
||||
Error InitForTypeListTlv(const Message &aMessage);
|
||||
Error ReadNextTlvType(uint8_t &aTlvType);
|
||||
|
||||
private:
|
||||
const Message *mMessage;
|
||||
OffsetRange mOffsetRange;
|
||||
BitSet<NumericLimits<uint8_t>::kMax + 1> mProcessedTlvs;
|
||||
};
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
struct AnswerInfo
|
||||
|
||||
@@ -630,21 +630,9 @@ private:
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Implements IPv6 Address List TLV generation and parsing.
|
||||
* Defines Type List TLV constants and types.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class TypeListTlv : public Tlv, public TlvInfo<Tlv::kTypeList>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the TLV.
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetType(kTypeList);
|
||||
SetLength(sizeof(*this) - sizeof(Tlv));
|
||||
}
|
||||
} OT_TOOL_PACKED_END;
|
||||
typedef TlvInfo<Tlv::kTypeList> TypeListTlv;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
|
||||
Reference in New Issue
Block a user