[network-diag] introduce ChildTlvValue (#12820)

This commit updates `ChildTlv` to follow the `SimpleTlvInfo` pattern,
separating the TLV value structure from its type/length header.

Specifically, it defines `ChildTlvValue` to hold the data fields for
a child's diagnostic information, while `ChildTlv` is redefined as
a `SimpleTlvInfo` using the value structure and the `kChild` type.

This allows the use of generic `Tlv::Append<ChildTlv>()` and
`tlvInfo.Read<ChildTlv>()` methods, which are generally safer and
allow value type reuse.

The `NetworkDiagnostics` and `MeshDiag` are updated to utilize
these new definitions.
This commit is contained in:
Abtin Keshavarzian
2026-04-03 11:20:57 -05:00
committed by GitHub
parent c7b922cd99
commit 7533e43ee7
5 changed files with 48 additions and 48 deletions
+8 -8
View File
@@ -144,14 +144,14 @@ exit:
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
Error Server::AppendChildTableAsChildTlvs(Message &aMessage)
{
Error error = kErrorNone;
ChildTlv childTlv;
Error error = kErrorNone;
ChildTlvValue childTlvValue;
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
{
childTlv.InitFrom(child);
childTlvValue.InitFrom(child);
SuccessOrExit(error = childTlv.AppendTo(aMessage));
SuccessOrExit(error = Tlv::Append<ChildTlv>(aMessage, childTlvValue));
}
error = Tlv::AppendEmpty<ChildTlv>(aMessage);
@@ -736,14 +736,14 @@ exit:
Error Server::AppendChildTableAsChildTlvs(Coap::Message *&aAnswer, AnswerInfo &aInfo)
{
Error error = kErrorNone;
ChildTlv childTlv;
Error error = kErrorNone;
ChildTlvValue childTlvValue;
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
{
childTlv.InitFrom(child);
childTlvValue.InitFrom(child);
SuccessOrExit(error = childTlv.AppendTo(*aAnswer));
SuccessOrExit(error = Tlv::Append<ChildTlv>(*aAnswer, childTlvValue));
SuccessOrExit(error = CheckAnswerLength(aAnswer, aInfo));
}
+2 -5
View File
@@ -136,15 +136,12 @@ void EnhancedRouteTlvEntry::Parse(ParseInfo &aParseInfo) const
#if OPENTHREAD_FTD
//---------------------------------------------------------------------------------------------------------------------
// ChildTlv
// ChildTlvValue
void ChildTlv::InitFrom(const Child &aChild)
void ChildTlvValue::InitFrom(const Child &aChild)
{
Clear();
SetType(kChild);
SetLength(sizeof(*this) - sizeof(Tlv));
mFlags |= aChild.IsRxOnWhenIdle() ? kFlagsRxOnWhenIdle : 0;
mFlags |= aChild.IsFullThreadDevice() ? kFlagsFtd : 0;
mFlags |= (aChild.GetNetworkDataType() == NetworkData::kFullSet) ? kFlagsFullNetdta : 0;
+6 -1
View File
@@ -451,7 +451,7 @@ typedef TlvInfo<Tlv::kTypeList> TypeListTlv;
* Implements Child TLV generation and parsing.
*/
OT_TOOL_PACKED_BEGIN
class ChildTlv : public Tlv, public TlvInfo<Tlv::kChild>, public Clearable<ChildTlv>
class ChildTlvValue : public Clearable<ChildTlvValue>
{
public:
static constexpr uint8_t kFlagsRxOnWhenIdle = 1 << 7; ///< Device mode - Rx-on when idle.
@@ -612,6 +612,11 @@ private:
uint8_t mCslChannel; // CSL channel.
} OT_TOOL_PACKED_END;
/**
* Defines Child TLV constants and types.
*/
typedef SimpleTlvInfo<Tlv::kChild, ChildTlvValue> ChildTlv;
/**
* Implements Child IPv6 Address List Value generation and parsing.
*
+31 -33
View File
@@ -285,21 +285,20 @@ exit:
bool MeshDiag::ProcessChildTableAnswer(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
bool didProcess = false;
ChildTlv childTlv;
ChildEntry entry;
uint16_t offset;
bool didProcess = false;
Tlv::Info tlvInfo;
ChildTlvValue childTlvValue;
ChildEntry entry;
SuccessOrExit(ProcessMessage(aMessage, aMessageInfo, mQueryChildTable.mRouterRloc16));
while (true)
{
SuccessOrExit(Tlv::FindTlv(aMessage, childTlv, offset));
VerifyOrExit(!childTlv.IsExtended());
SuccessOrExit(tlvInfo.FindIn(aMessage, ChildTlv::kType));
didProcess = true;
if (childTlv.GetLength() == 0)
if (tlvInfo.GetLength() == 0)
{
// We reached end of the list.
mState = kStateIdle;
@@ -308,17 +307,16 @@ bool MeshDiag::ProcessChildTableAnswer(Coap::Message &aMessage, const Ip6::Messa
ExitNow();
}
VerifyOrExit(childTlv.GetLength() >= sizeof(ChildTlv) - sizeof(Tlv));
IgnoreError(aMessage.Read(offset, childTlv));
SuccessOrExit(tlvInfo.Read<ChildTlv>(aMessage, childTlvValue));
entry.SetFrom(childTlv);
entry.SetFrom(childTlvValue);
mQueryChildTable.mCallback.InvokeIfSet(kErrorPending, &entry);
// Make sure query operation is not canceled from the
// callback.
VerifyOrExit(mState == kStateQueryChildTable);
aMessage.SetOffset(static_cast<uint16_t>(offset + childTlv.GetSize()));
aMessage.SetOffset(tlvInfo.GetTlvOffsetRange().GetEndOffset());
}
exit:
@@ -581,29 +579,29 @@ exit:
//---------------------------------------------------------------------------------------------------------------------
// MeshDiag::ChildEntry
void MeshDiag::ChildEntry::SetFrom(const ChildTlv &aChildTlv)
void MeshDiag::ChildEntry::SetFrom(const ChildTlvValue &aChildTlvValue)
{
mRxOnWhenIdle = (aChildTlv.GetFlags() & ChildTlv::kFlagsRxOnWhenIdle);
mDeviceTypeFtd = (aChildTlv.GetFlags() & ChildTlv::kFlagsFtd);
mFullNetData = (aChildTlv.GetFlags() & ChildTlv::kFlagsFullNetdta);
mCslSynchronized = (aChildTlv.GetFlags() & ChildTlv::kFlagsCslSync);
mSupportsErrRate = (aChildTlv.GetFlags() & ChildTlv::kFlagsTrackErrRate);
mRloc16 = aChildTlv.GetRloc16();
mExtAddress = aChildTlv.GetExtAddress();
mVersion = aChildTlv.GetVersion();
mTimeout = aChildTlv.GetTimeout();
mAge = aChildTlv.GetAge();
mConnectionTime = aChildTlv.GetConnectionTime();
mSupervisionInterval = aChildTlv.GetSupervisionInterval();
mLinkMargin = aChildTlv.GetLinkMargin();
mAverageRssi = aChildTlv.GetAverageRssi();
mLastRssi = aChildTlv.GetLastRssi();
mFrameErrorRate = aChildTlv.GetFrameErrorRate();
mMessageErrorRate = aChildTlv.GetMessageErrorRate();
mQueuedMessageCount = aChildTlv.GetQueuedMessageCount();
mCslPeriod = aChildTlv.GetCslPeriod();
mCslTimeout = aChildTlv.GetCslTimeout();
mCslChannel = aChildTlv.GetCslChannel();
mRxOnWhenIdle = (aChildTlvValue.GetFlags() & ChildTlvValue::kFlagsRxOnWhenIdle);
mDeviceTypeFtd = (aChildTlvValue.GetFlags() & ChildTlvValue::kFlagsFtd);
mFullNetData = (aChildTlvValue.GetFlags() & ChildTlvValue::kFlagsFullNetdta);
mCslSynchronized = (aChildTlvValue.GetFlags() & ChildTlvValue::kFlagsCslSync);
mSupportsErrRate = (aChildTlvValue.GetFlags() & ChildTlvValue::kFlagsTrackErrRate);
mRloc16 = aChildTlvValue.GetRloc16();
mExtAddress = aChildTlvValue.GetExtAddress();
mVersion = aChildTlvValue.GetVersion();
mTimeout = aChildTlvValue.GetTimeout();
mAge = aChildTlvValue.GetAge();
mConnectionTime = aChildTlvValue.GetConnectionTime();
mSupervisionInterval = aChildTlvValue.GetSupervisionInterval();
mLinkMargin = aChildTlvValue.GetLinkMargin();
mAverageRssi = aChildTlvValue.GetAverageRssi();
mLastRssi = aChildTlvValue.GetLastRssi();
mFrameErrorRate = aChildTlvValue.GetFrameErrorRate();
mMessageErrorRate = aChildTlvValue.GetMessageErrorRate();
mQueuedMessageCount = aChildTlvValue.GetQueuedMessageCount();
mCslPeriod = aChildTlvValue.GetCslPeriod();
mCslTimeout = aChildTlvValue.GetCslTimeout();
mCslChannel = aChildTlvValue.GetCslChannel();
}
//---------------------------------------------------------------------------------------------------------------------
+1 -1
View File
@@ -286,7 +286,7 @@ private:
friend class MeshDiag;
private:
void SetFrom(const NetworkDiagnostic::ChildTlv &aChildTlv);
void SetFrom(const NetworkDiagnostic::ChildTlvValue &aChildTlvValue);
};
class RouterNeighborEntry : public otMeshDiagRouterNeighborEntry