Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[diag] add prefix tlv definition and parsing into diagnostic data #311

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions include/commissioner/network_diag_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,64 @@ struct MacCounters
uint32_t mIfOutDiscards = 0;
};

/**
* @brief Has Route Entry
*/
struct HasRouteEntry
{
uint16_t mRloc16 = 0;
uint8_t mRouterPreference = 0;
bool mIsNat64 = false;
};

/**
* @brief Border Router Entry
*/
struct BorderRouterEntry
{
uint16_t mRloc16 = 0;
uint8_t mPrefixPreference = 0;
bool mIsPreferred = false;
bool mIsSlaac = false;
bool mIsDhcp = false;
bool mIsConfigure = false;
bool mIsDefaultRoute = false;
bool mIsOnMesh = false;
bool mIsNdDns = false;
bool mIsDp = false;
};

/**
* @brief 6LoWPAN Context
*/
struct SixLowPanContext
{
uint8_t mIsCompress = false;
uint8_t mContextId = 0;
uint8_t mContextLength = 0;
};

/**
* @brief Prefix
*/
struct PrefixEntry
{
uint8_t mDomainId = 0;
uint8_t mPrefixLength = 0;
ByteArray mPrefix;
std::vector<HasRouteEntry> mHasRouteList;
std::vector<BorderRouterEntry> mBorderRouterList;
SixLowPanContext mSixLowPanContext;
};

/**
* @brief Network Data TLV
*/
struct NetworkDataTlv
{
std::vector<PrefixEntry> mPrefixList;
};

/**
* @brief network diagnostic data in TMF
*
Expand All @@ -146,6 +204,7 @@ struct NetDiagData
std::vector<std::string> mAddrs;
std::vector<ChildTableEntry> mChildTable;
std::vector<ChildIpv6AddrInfo> mChildIpv6AddrsInfoList;
NetworkDataTlv mNetworkData;

/**
* Indicates which fields are included in the object.
Expand All @@ -162,6 +221,7 @@ struct NetDiagData
static constexpr uint64_t kEui64Bit = (1ull << 7);
static constexpr uint64_t kMacCountersBit = (1ull << 8);
static constexpr uint64_t kChildIpv6AddrsInfoListBit = (1ull << 9);
static constexpr uint64_t kNetworkDataBit = (1ull << 10);
};

} // namespace commissioner
Expand Down
3 changes: 3 additions & 0 deletions src/java/commissioner.i
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@
%template(ChildIpv6AddrInfoVector) std::vector<ot::commissioner::ChildIpv6AddrInfo>;
%template(ChildTableEntryVector) std::vector<ot::commissioner::ChildTableEntry>;
%template(RouteDataEntryVector) std::vector<ot::commissioner::RouteDataEntry>;
%template(HasRouteEntryVector) std::vector<ot::commissioner::HasRouteEntry>;
%template(BorderRouterEntryVector) std::vector<ot::commissioner::BorderRouterEntry>;
%template(PrefixEntryVector) std::vector<ot::commissioner::PrefixEntry>;

%typemap(jstype) std::string& OUTPUT "String[]"
%typemap(jtype) std::string& OUTPUT "String[]"
Expand Down
150 changes: 150 additions & 0 deletions src/library/commissioner_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2127,6 +2127,11 @@ ByteArray CommissionerImpl::GetNetDiagTlvTypes(uint64_t aDiagDataFlags)
EncodeTlvType(tlvTypes, tlv::Type::kNetworkDiagChildIpv6Address);
}

if (aDiagDataFlags & NetDiagData::kNetworkDataBit)
{
EncodeTlvType(tlvTypes, tlv::Type::kNetworkDiagNetworkData);
}

return tlvTypes;
}

Expand Down Expand Up @@ -2214,12 +2219,157 @@ Error internal::DecodeNetDiagData(NetDiagData &aNetDiagData, const ByteArray &aP
diagData.mPresentFlags |= NetDiagData::kChildIpv6AddrsInfoListBit;
}

if (auto networkData = tlvSet[tlv::Type::kNetworkDiagNetworkData])
{
const ByteArray &value = networkData->GetValue();
SuccessOrExit(error = DecodeNetworkData(diagData.mNetworkData, value));
diagData.mPresentFlags |= NetDiagData::kNetworkDataBit;
}
aNetDiagData = diagData;

exit:
return error;
}

Error internal::DecodeNetworkData(NetworkDataTlv &aNetworkData, const ByteArray &aBuf)
{
Error error;
tlv::TlvSet tlvSet;
tlv::TlvList tlvList;
NetworkDataTlv networkData;

SuccessOrExit(error =
tlv::GetTlvListByType(tlvList, aBuf, tlv::Type::kNetworkDataPrefix, tlv::Scope::kNetworkData));
if (tlvList.size() > 0)
{
for (const auto &tlv : tlvList)
{
SuccessOrExit(error = DecodePrefixList(networkData.mPrefixList, tlv.GetValue()));
}
}

aNetworkData = networkData;

exit:
return error;
}

Error internal::DecodePrefixList(std::vector<PrefixEntry> &aPrefixList, const ByteArray &aBuf)
{
Error error;
size_t length = aBuf.size();
PrefixEntry prefix;
uint8_t offset = 0;
ByteArray subTlv;
tlv::TlvList tlvList;
tlv::TlvSet tlvSet;

VerifyOrExit(length >= kPrefixBytes, error = ERROR_BAD_FORMAT("premature end of Prefix"));
offset += kPrefixBytes;
prefix.mDomainId = aBuf[0];
prefix.mPrefixLength = (aBuf[1] + 7) >> 3;
offset += prefix.mPrefixLength;
VerifyOrExit(length >= offset, error = ERROR_BAD_FORMAT("premature end of Prefix"));
prefix.mPrefix = {aBuf.begin() + kPrefixBytes, aBuf.begin() + kPrefixBytes + offset};

if (length > offset)
{
subTlv = {aBuf.begin() + offset, aBuf.end()};

// Get the context
SuccessOrExit(error = tlv::GetTlvSet(tlvSet, subTlv, tlv::Scope::kNetworkData));
if (auto context = tlvSet[tlv::Type::kNetworkData6LowPanContext])
{
const ByteArray &value = context->GetValue();
SuccessOrExit(error = DecodeContext(prefix.mSixLowPanContext, value));
}

// Get the HasRoute
SuccessOrExit(error = tlv::GetTlvSet(tlvSet, subTlv, tlv::Scope::kNetworkData));
if (auto hasRoute = tlvSet[tlv::Type::kNetworkDataHasRoute])
{
const ByteArray &value = hasRoute->GetValue();
SuccessOrExit(error = DecodeHasRoute(prefix.mHasRouteList, value));
}

// Get the BorderRouter
SuccessOrExit(error = tlv::GetTlvSet(tlvSet, subTlv, tlv::Scope::kNetworkData));
if (auto borderRouter = tlvSet[tlv::Type::kNetworkDataBorderRouter])
{
const ByteArray &value = borderRouter->GetValue();
SuccessOrExit(error = DecodeBorderRouter(prefix.mBorderRouterList, value));
}

// Add the prefix to the list
aPrefixList.emplace_back(prefix);
}
exit:
return error;
}
Error internal::DecodeHasRoute(std::vector<HasRouteEntry> &aHasRouteList, const ByteArray &aBuf)
{
Error error;
size_t length = aBuf.size();
HasRouteEntry hasRoute;
uint8_t offset = 0;
tlv::TlvList tlvList;

VerifyOrExit((length % kHasRouteBytes == 0), error = ERROR_BAD_FORMAT("incorrect size of HasRoute"));
while (offset < length)
{
hasRoute.mRloc16 = utils::Decode<uint16_t>(aBuf.data() + offset, kRloc16Bytes);
offset += kRloc16Bytes;
hasRoute.mIsNat64 = (aBuf[offset] >> 5) & 0x01;
hasRoute.mRouterPreference = (aBuf[offset] >> 6) & 0x03;
offset += 1;
aHasRouteList.emplace_back(hasRoute);
}
exit:
return error;
}

Error internal::DecodeBorderRouter(std::vector<BorderRouterEntry> &aBorderRouterList, const ByteArray &aBuf)
{
Error error;
size_t length = aBuf.size();
BorderRouterEntry borderRouter;
uint8_t offset = 0;
tlv::TlvList tlvList;
VerifyOrExit((length % kBorderRouterBytes == 0), error = ERROR_BAD_FORMAT("incorrect size of BorderRouter"));
while (offset < length)
{
borderRouter.mRloc16 = utils::Decode<uint16_t>(aBuf.data() + offset, kRloc16Bytes);
offset += kRloc16Bytes;
borderRouter.mPrefixPreference = (aBuf[offset] >> 6) & 0x03;
borderRouter.mIsPreferred = (aBuf[offset] >> 5) & 0x01;
borderRouter.mIsSlaac = (aBuf[offset] >> 4) & 0x01;
borderRouter.mIsDhcp = (aBuf[offset] >> 3) & 0x01;
borderRouter.mIsConfigure = (aBuf[offset] >> 2) & 0x01;
borderRouter.mIsDefaultRoute = (aBuf[offset] >> 1) & 0x01;
borderRouter.mIsOnMesh = (aBuf[offset] >> 0) & 0x01;
offset += 1;
borderRouter.mIsNdDns = (aBuf[offset] >> 7) & 0x01;
borderRouter.mIsDp = (aBuf[offset] >> 6) & 0x01;
offset += 1;
aBorderRouterList.emplace_back(borderRouter);
}

exit:
return error;
}

Error internal::DecodeContext(SixLowPanContext &aSixLowPanContext, const ByteArray &aBuf)
{
Error error;
size_t length = aBuf.size();
VerifyOrExit(length == kSixLowPanContextBytes, error = ERROR_BAD_FORMAT("incorrect size of Context"));
aSixLowPanContext.mIsCompress = (aBuf[0] >> 4) & 0x01;
aSixLowPanContext.mContextId = aBuf[0] & 0x0F;
aSixLowPanContext.mContextLength = aBuf[1];
exit:
return error;
}

Error internal::DecodeIpv6AddressList(std::vector<std::string> &aAddrs, const ByteArray &aBuf)
{
Error error;
Expand Down
23 changes: 17 additions & 6 deletions src/library/commissioner_impl_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ namespace ot {

namespace commissioner {

static constexpr uint8_t kChildTableEntryBytes = 3;
static constexpr uint8_t kIpv6AddressBytes = 16;
static constexpr uint8_t kLeaderDataBytes = 8;
static constexpr uint8_t kMacCountersBytes = 36;
static constexpr uint8_t kRloc16Bytes = 2;
static constexpr uint8_t kRouterIdMaskBytes = 8;
static constexpr uint8_t kChildTableEntryBytes = 3;
static constexpr uint8_t kIpv6AddressBytes = 16;
static constexpr uint8_t kLeaderDataBytes = 8;
static constexpr uint8_t kMacCountersBytes = 36;
static constexpr uint8_t kRloc16Bytes = 2;
static constexpr uint8_t kRouterIdMaskBytes = 8;
static constexpr uint8_t kPrefixBytes = 2;
static constexpr uint8_t kHasRouteBytes = 3;
static constexpr uint8_t kBorderRouterBytes = 4;
static constexpr uint8_t kSixLowPanContextBytes = 2;

namespace internal {

Expand All @@ -59,6 +63,13 @@ Error DecodeRoute64(Route64 &aRoute64, const ByteArray &aBuf);
void DecodeRouteDataEntry(RouteDataEntry &aRouteDataEntry, uint8_t aBuf);
ByteArray ExtractRouterIds(const ByteArray &aMask);

Error DecodeNetworkData(NetworkDataTlv &aNetworkData, const ByteArray &aBuf);
Error DecodePrefixList(std::vector<PrefixEntry> &aPrefixList, const ByteArray &aBuf);
Error DecodePrefix(PrefixEntry &aPrefix, const ByteArray &aBuf);
Error DecodeHasRoute(std::vector<HasRouteEntry> &aHasRouteList, const ByteArray &aBuf);
Error DecodeBorderRouter(std::vector<BorderRouterEntry> &aBorderRouterList, const ByteArray &aBuf);
Error DecodeContext(SixLowPanContext &aSixLowPanContext, const ByteArray &aBuf);

} // namespace internal

} // namespace commissioner
Expand Down
34 changes: 32 additions & 2 deletions src/library/commissioner_impl_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ TEST(CommissionerImplTest, ValidInput_DecodeNetDiagData)
"00086ac6c2de12b212df0102c80002010f0512e7000400204300300af1f1f1f1f101f1f1f10608360bb9f7415c30210840fd9238a3395d"
"0001f9043dfeb7b3edf3fd7d604fb88a0000000000fffe00c800fd7d604fb88a0000fe3e5a4c31acb559fe8000000000000068c6c2de12"
"b212df1009601804601d046019041e22c818fdc31ff45feff4e7e580431c60becfabfd110022000000008df846f3ab0c05551e22c802fd"
"c31ff45feff4e75257420f1cbd46f5fd1100220000000034e5d9e28d1952c0";
"c31ff45feff4e75257420f1cbd46f5fd1100220000000034e5d9e28d1952c0077d030e0007fc0109e400108400109c000003140040fd27"
"fd30e5ce0001070212400504e400f1000b0e8001010d09e4000a000500000e100b0881025cf40d029c0003130060fd6b51760904ffff00"
"00000001039c00e00b1982015d0d149c00fd27fd30e5ce00018e250585edd6f1b0e5ec080b090284000b028dbc080100";

error = utils::Hex(buf, tlvsHexString);
EXPECT_EQ(error, ErrorCode::kNone);
Expand All @@ -167,7 +169,7 @@ TEST(CommissionerImplTest, ValidInput_DecodeNetDiagData)
error = utils::Hex(extMacAddrBytes, "6ac6c2de12b212df");

EXPECT_EQ(error, ErrorCode::kNone);
EXPECT_EQ(diagData.mPresentFlags, 639);
EXPECT_EQ(diagData.mPresentFlags, 1663);
EXPECT_EQ(diagData.mExtMacAddr, extMacAddrBytes);
EXPECT_EQ(diagData.mMacAddr, macAddr);
EXPECT_EQ(diagData.mMode.mIsMtd, false);
Expand All @@ -186,6 +188,34 @@ TEST(CommissionerImplTest, ValidInput_DecodeNetDiagData)
EXPECT_EQ(diagData.mChildIpv6AddrsInfoList[1].mChildId, 2);
EXPECT_EQ(diagData.mChildIpv6AddrsInfoList[1].mAddrs[0], "fdc3:1ff4:5fef:f4e7:5257:420f:1cbd:46f5");
EXPECT_EQ(diagData.mChildIpv6AddrsInfoList[1].mAddrs[1], "fd11:22::34e5:d9e2:8d19:52c0");
// Parsing prefix TLV in Network Data
EXPECT_EQ(diagData.mNetworkData.mPrefixList.size(), 3);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mDomainId, 0);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mPrefixLength, 1);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList.size(), 3);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[0].mRloc16, 58368);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[0].mRouterPreference, 0);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[0].mIsNat64, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[1].mRloc16, 33792);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[1].mRouterPreference, 0);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[1].mIsNat64, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[2].mRloc16, 39936);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[2].mRouterPreference, 0);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[0].mHasRouteList[2].mIsNat64, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList.size(), 1);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mRloc16, 58368);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mPrefixPreference, 3);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsPreferred, true);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsSlaac, true);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsDhcp, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsConfigure, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsDefaultRoute, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsOnMesh, true);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsNdDns, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mBorderRouterList[0].mIsDp, false);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mSixLowPanContext.mIsCompress, true);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mSixLowPanContext.mContextId, 2);
EXPECT_EQ(diagData.mNetworkData.mPrefixList[1].mSixLowPanContext.mContextLength, 64);
}

} // namespace commissioner
Expand Down
28 changes: 27 additions & 1 deletion src/library/tlv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,16 @@ TlvPtr Tlv::Deserialize(Error &aError, size_t &aOffset, const ByteArray &aBuf, S
TlvPtr tlv = nullptr;

VerifyOrExit(offset + 2 <= aBuf.size(), error = ERROR_BAD_FORMAT("premature end of TLV"));
type = aBuf[offset++];
// Based on spec 5.18,Network Data TLVs use first 7-bit type and the 8th bit to indicate
// the data to be valid for at least MIN_STABLE_LIFETIME.
if (aScope == Scope::kNetworkData)
{
type = aBuf[offset++] >> 1;
}
else
{
type = aBuf[offset++];
}
length = aBuf[offset++];
if (length == kEscapeLength)
{
Expand Down Expand Up @@ -287,6 +296,23 @@ bool Tlv::IsValid() const
return false;
}
}
else if (mScope == Scope::kNetworkData)
{
switch (mType)
{
// Network Data TLVs
case Type::kNetworkDataHasRoute:
return length >= 3;
case Type::kNetworkDataPrefix:
return length >= 2;
case Type::kNetworkDataBorderRouter:
return length >= 4;
case Type::kNetworkData6LowPanContext:
return length >= 2;
default:
return false;
}
}

switch (mType)
{
Expand Down
Loading
Loading