[network-diag] introduce RouterNeighborTlv (#12827)

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

Specifically, it defines `RouterNeighborTlvValue` to hold the data
fields for a router neighbor's diagnostic information, while
`RouterNeighborTlv` is redefined as a `SimpleTlvInfo` using the value
structure and the `kRouterNeighbor` type.

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

The `NetworkDiagnostic`  and `MeshDiag` module are updated to
utilize these new methods.
This commit is contained in:
Abtin Keshavarzian
2026-04-04 01:17:03 -05:00
committed by GitHub
parent aec6b5d795
commit 9f28df1e30
5 changed files with 38 additions and 37 deletions
+8 -8
View File
@@ -162,15 +162,15 @@ exit:
Error Server::AppendRouterNeighborTlvs(Message &aMessage) Error Server::AppendRouterNeighborTlvs(Message &aMessage)
{ {
Error error = kErrorNone; Error error = kErrorNone;
RouterNeighborTlv neighborTlv; RouterNeighborTlvValue neighborTlvValue;
for (Router &router : Get<RouterTable>()) for (Router &router : Get<RouterTable>())
{ {
if (router.IsStateValid()) if (router.IsStateValid())
{ {
neighborTlv.InitFrom(router); neighborTlvValue.InitFrom(router);
SuccessOrExit(error = neighborTlv.AppendTo(aMessage)); SuccessOrExit(error = Tlv::Append<RouterNeighborTlv>(aMessage, neighborTlvValue));
} }
} }
@@ -755,8 +755,8 @@ exit:
Error Server::AppendRouterNeighborTlvs(Coap::Message *&aAnswer, AnswerInfo &aInfo) Error Server::AppendRouterNeighborTlvs(Coap::Message *&aAnswer, AnswerInfo &aInfo)
{ {
Error error = kErrorNone; Error error = kErrorNone;
RouterNeighborTlv neighborTlv; RouterNeighborTlvValue neighborTlvValue;
for (Router &router : Get<RouterTable>()) for (Router &router : Get<RouterTable>())
{ {
@@ -765,9 +765,9 @@ Error Server::AppendRouterNeighborTlvs(Coap::Message *&aAnswer, AnswerInfo &aInf
continue; continue;
} }
neighborTlv.InitFrom(router); neighborTlvValue.InitFrom(router);
SuccessOrExit(error = neighborTlv.AppendTo(*aAnswer)); SuccessOrExit(error = Tlv::Append<RouterNeighborTlv>(*aAnswer, neighborTlvValue));
SuccessOrExit(error = CheckAnswerLength(aAnswer, aInfo)); SuccessOrExit(error = CheckAnswerLength(aAnswer, aInfo));
} }
+2 -5
View File
@@ -170,15 +170,12 @@ void ChildTlvValue::InitFrom(const Child &aChild)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
// RouterNeighborTlv // RouterNeighborTlvValue
void RouterNeighborTlv::InitFrom(const Router &aRouter) void RouterNeighborTlvValue::InitFrom(const Router &aRouter)
{ {
Clear(); Clear();
SetType(kRouterNeighbor);
SetLength(sizeof(*this) - sizeof(Tlv));
mFlags |= kFlagsTrackErrRate; mFlags |= kFlagsTrackErrRate;
mRloc16 = BigEndian::HostSwap16(aRouter.GetRloc16()); mRloc16 = BigEndian::HostSwap16(aRouter.GetRloc16());
mExtAddress = aRouter.GetExtAddress(); mExtAddress = aRouter.GetExtAddress();
+7 -2
View File
@@ -647,10 +647,10 @@ private:
} OT_TOOL_PACKED_END; } OT_TOOL_PACKED_END;
/** /**
* Implements Router Neighbor TLV generation and parsing. * Implements Router Neighbor TLV Value generation and parsing.
*/ */
OT_TOOL_PACKED_BEGIN OT_TOOL_PACKED_BEGIN
class RouterNeighborTlv : public Tlv, public TlvInfo<Tlv::kRouterNeighbor>, public Clearable<RouterNeighborTlv> class RouterNeighborTlvValue : public Clearable<RouterNeighborTlvValue>
{ {
public: public:
static constexpr uint8_t kFlagsTrackErrRate = 1 << 7; ///< Supports tracking error rates. static constexpr uint8_t kFlagsTrackErrRate = 1 << 7; ///< Supports tracking error rates.
@@ -751,6 +751,11 @@ private:
uint16_t mMessageErrorRate; // (IPv6) msg error rate (0x0000->0%, 0xffff->100%) uint16_t mMessageErrorRate; // (IPv6) msg error rate (0x0000->0%, 0xffff->100%)
} OT_TOOL_PACKED_END; } OT_TOOL_PACKED_END;
/**
* Defines Router Neighbor TLV constants and types.
*/
typedef SimpleTlvInfo<Tlv::kRouterNeighbor, RouterNeighborTlvValue> RouterNeighborTlv;
#endif // OPENTHREAD_FTD #endif // OPENTHREAD_FTD
/** /**
+20 -21
View File
@@ -325,21 +325,20 @@ exit:
bool MeshDiag::ProcessRouterNeighborTableAnswer(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) bool MeshDiag::ProcessRouterNeighborTableAnswer(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{ {
bool didProcess = false; bool didProcess = false;
RouterNeighborTlv neighborTlv; Tlv::Info tlvInfo;
RouterNeighborEntry entry; RouterNeighborTlvValue neighborTlvValue;
uint16_t offset; RouterNeighborEntry entry;
SuccessOrExit(ProcessMessage(aMessage, aMessageInfo, mQueryRouterNeighborTable.mRouterRloc16)); SuccessOrExit(ProcessMessage(aMessage, aMessageInfo, mQueryRouterNeighborTable.mRouterRloc16));
while (true) while (true)
{ {
SuccessOrExit(Tlv::FindTlv(aMessage, neighborTlv, offset)); SuccessOrExit(tlvInfo.FindIn(aMessage, RouterNeighborTlv::kType));
VerifyOrExit(!neighborTlv.IsExtended());
didProcess = true; didProcess = true;
if (neighborTlv.GetLength() == 0) if (tlvInfo.GetLength() == 0)
{ {
// We reached end of the list. // We reached end of the list.
mState = kStateIdle; mState = kStateIdle;
@@ -348,16 +347,16 @@ bool MeshDiag::ProcessRouterNeighborTableAnswer(Coap::Message &aMessage, const I
ExitNow(); ExitNow();
} }
VerifyOrExit(neighborTlv.GetLength() >= sizeof(RouterNeighborTlv) - sizeof(Tlv)); SuccessOrExit(tlvInfo.Read<RouterNeighborTlv>(aMessage, neighborTlvValue));
entry.SetFrom(neighborTlv); entry.SetFrom(neighborTlvValue);
mQueryRouterNeighborTable.mCallback.InvokeIfSet(kErrorPending, &entry); mQueryRouterNeighborTable.mCallback.InvokeIfSet(kErrorPending, &entry);
// Make sure query operation is not canceled from the // Make sure query operation is not canceled from the
// callback. // callback.
VerifyOrExit(mState == kStateQueryRouterNeighborTable); VerifyOrExit(mState == kStateQueryRouterNeighborTable);
aMessage.SetOffset(static_cast<uint16_t>(offset + neighborTlv.GetSize())); aMessage.SetOffset(tlvInfo.GetTlvOffsetRange().GetEndOffset());
} }
exit: exit:
@@ -607,18 +606,18 @@ void MeshDiag::ChildEntry::SetFrom(const ChildTlvValue &aChildTlvValue)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
// MeshDiag::RouterNeighborEntry // MeshDiag::RouterNeighborEntry
void MeshDiag::RouterNeighborEntry::SetFrom(const RouterNeighborTlv &aTlv) void MeshDiag::RouterNeighborEntry::SetFrom(const RouterNeighborTlvValue &aTlvValue)
{ {
mSupportsErrRate = (aTlv.GetFlags() & RouterNeighborTlv::kFlagsTrackErrRate); mSupportsErrRate = (aTlvValue.GetFlags() & RouterNeighborTlvValue::kFlagsTrackErrRate);
mRloc16 = aTlv.GetRloc16(); mRloc16 = aTlvValue.GetRloc16();
mExtAddress = aTlv.GetExtAddress(); mExtAddress = aTlvValue.GetExtAddress();
mVersion = aTlv.GetVersion(); mVersion = aTlvValue.GetVersion();
mConnectionTime = aTlv.GetConnectionTime(); mConnectionTime = aTlvValue.GetConnectionTime();
mLinkMargin = aTlv.GetLinkMargin(); mLinkMargin = aTlvValue.GetLinkMargin();
mAverageRssi = aTlv.GetAverageRssi(); mAverageRssi = aTlvValue.GetAverageRssi();
mLastRssi = aTlv.GetLastRssi(); mLastRssi = aTlvValue.GetLastRssi();
mFrameErrorRate = aTlv.GetFrameErrorRate(); mFrameErrorRate = aTlvValue.GetFrameErrorRate();
mMessageErrorRate = aTlv.GetMessageErrorRate(); mMessageErrorRate = aTlvValue.GetMessageErrorRate();
} }
} // namespace Utils } // namespace Utils
+1 -1
View File
@@ -294,7 +294,7 @@ private:
friend class MeshDiag; friend class MeshDiag;
private: private:
void SetFrom(const NetworkDiagnostic::RouterNeighborTlv &aTlv); void SetFrom(const NetworkDiagnostic::RouterNeighborTlvValue &aTlvValue);
}; };
Error SendQuery(uint16_t aRloc16, const uint8_t *aTlvs, uint8_t aTlvsLength); Error SendQuery(uint16_t aRloc16, const uint8_t *aTlvs, uint8_t aTlvsLength);