mirror of
https://github.com/espressif/openthread.git
synced 2026-09-17 22:50:07 +00:00
[netdata] get the list or count of RLOC16s of border routers (#7543)
This commit adds a new method in `NetworkData` to find the list of RLOC16 of all border routers providing external IP connectivity. A border router is considered to provide external IP connectivity if it has added at least one external route entry, or an on-mesh prefix with default-route and on-mesh flags set. It also adds a method to count the number of border routers. The methods allow filtering based on the border router device role, including devices in any role, or in router role only, or in child role only. This commit also updates `test_network_data` unit test to validate the behavior of the newly added methods.
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "common/array.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/instance.hpp"
|
||||
#include "thread/network_data_leader.hpp"
|
||||
@@ -42,7 +43,7 @@ namespace NetworkData {
|
||||
|
||||
void PrintExternalRouteConfig(const ExternalRouteConfig &aConfig)
|
||||
{
|
||||
printf("\nprefix:");
|
||||
printf("\nroute-prefix:");
|
||||
|
||||
for (uint8_t b : aConfig.mPrefix.mPrefix.mFields.m8)
|
||||
{
|
||||
@@ -53,6 +54,19 @@ void PrintExternalRouteConfig(const ExternalRouteConfig &aConfig)
|
||||
aConfig.mRloc16, aConfig.mPreference, aConfig.mNat64, aConfig.mStable, aConfig.mNextHopIsThisDevice);
|
||||
}
|
||||
|
||||
void PrintOnMeshPrefixConfig(const OnMeshPrefixConfig &aConfig)
|
||||
{
|
||||
printf("\non-mesh-prefix:");
|
||||
|
||||
for (uint8_t b : aConfig.mPrefix.mPrefix.mFields.m8)
|
||||
{
|
||||
printf("%02x", b);
|
||||
}
|
||||
|
||||
printf(", length:%d, rloc16:%04x, preference:%d, stable:%d, def-route:%d", aConfig.mPrefix.mLength, aConfig.mRloc16,
|
||||
aConfig.mPreference, aConfig.mStable, aConfig.mDefaultRoute);
|
||||
}
|
||||
|
||||
// Returns true if the two given ExternalRouteConfig match (intentionally ignoring mNextHopIsThisDevice).
|
||||
bool CompareExternalRouteConfig(const otExternalRouteConfig &aConfig1, const otExternalRouteConfig &aConfig2)
|
||||
{
|
||||
@@ -62,11 +76,42 @@ bool CompareExternalRouteConfig(const otExternalRouteConfig &aConfig1, const otE
|
||||
(aConfig1.mPreference == aConfig2.mPreference) && (aConfig1.mStable == aConfig2.mStable);
|
||||
}
|
||||
|
||||
// Returns true if the two given OnMeshprefix match.
|
||||
bool CompareOnMeshPrefixConfig(const otBorderRouterConfig &aConfig1, const otBorderRouterConfig &aConfig2)
|
||||
{
|
||||
return (memcmp(aConfig1.mPrefix.mPrefix.mFields.m8, aConfig2.mPrefix.mPrefix.mFields.m8,
|
||||
sizeof(aConfig1.mPrefix.mPrefix)) == 0) &&
|
||||
(aConfig1.mPrefix.mLength == aConfig2.mPrefix.mLength) && (aConfig1.mRloc16 == aConfig2.mRloc16) &&
|
||||
(aConfig1.mPreference == aConfig2.mPreference) && (aConfig1.mStable == aConfig2.mStable) &&
|
||||
(aConfig1.mDefaultRoute == aConfig2.mDefaultRoute) && (aConfig1.mOnMesh == aConfig2.mOnMesh);
|
||||
}
|
||||
|
||||
template <uint8_t kLength>
|
||||
void VerifyRlocsArray(const uint16_t *aRlocs, uint16_t aRlocsLength, const uint16_t (&aExpectedRlocs)[kLength])
|
||||
{
|
||||
VerifyOrQuit(aRlocsLength == kLength);
|
||||
|
||||
printf("\nRLOCs: { ");
|
||||
|
||||
for (uint8_t index = 0; index < aRlocsLength; index++)
|
||||
{
|
||||
VerifyOrQuit(aRlocs[index] == aExpectedRlocs[index]);
|
||||
printf("0x%04x ", aRlocs[index]);
|
||||
}
|
||||
|
||||
printf("}");
|
||||
}
|
||||
|
||||
void TestNetworkDataIterator(void)
|
||||
{
|
||||
static constexpr uint8_t kMaxRlocsArray = 10;
|
||||
|
||||
ot::Instance * instance;
|
||||
Iterator iter = kIteratorInit;
|
||||
ExternalRouteConfig config;
|
||||
ExternalRouteConfig rconfig;
|
||||
OnMeshPrefixConfig pconfig;
|
||||
uint16_t rlocs[kMaxRlocsArray];
|
||||
uint8_t rlocsLength;
|
||||
|
||||
instance = testInitInstance();
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
@@ -104,6 +149,8 @@ void TestNetworkDataIterator(void)
|
||||
},
|
||||
};
|
||||
|
||||
const uint16_t kRlocs[] = {0xc800, 0x5400};
|
||||
|
||||
NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData));
|
||||
|
||||
iter = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
@@ -113,10 +160,25 @@ void TestNetworkDataIterator(void)
|
||||
|
||||
for (const auto &route : routes)
|
||||
{
|
||||
SuccessOrQuit(netData.GetNextExternalRoute(iter, config));
|
||||
PrintExternalRouteConfig(config);
|
||||
VerifyOrQuit(CompareExternalRouteConfig(config, route));
|
||||
SuccessOrQuit(netData.GetNextExternalRoute(iter, rconfig));
|
||||
PrintExternalRouteConfig(rconfig);
|
||||
VerifyOrQuit(CompareExternalRouteConfig(rconfig, route));
|
||||
}
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocs);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocs));
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocs);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocs));
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength));
|
||||
VerifyOrQuit(rlocsLength == 0);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -124,7 +186,7 @@ void TestNetworkDataIterator(void)
|
||||
0x08, 0x04, 0x0B, 0x02, 0x00, 0x00, 0x03, 0x1E, 0x00, 0x40, 0xFD, 0x00, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00,
|
||||
0x07, 0x02, 0x11, 0x40, 0x00, 0x03, 0x10, 0x00, 0x40, 0x01, 0x03, 0x54, 0x00, 0x00, 0x05, 0x04, 0x54, 0x00,
|
||||
0x31, 0x00, 0x02, 0x0F, 0x00, 0x40, 0xFD, 0x00, 0xAB, 0xBA, 0xCD, 0xDC, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00,
|
||||
0x20, 0x03, 0x0E, 0x00, 0x20, 0xFD, 0x00, 0xAB, 0xBA, 0x01, 0x06, 0x54, 0x00, 0x00, 0x04, 0x00, 0x00,
|
||||
0x20, 0x03, 0x0E, 0x00, 0x20, 0xFD, 0x00, 0xAB, 0xBA, 0x01, 0x06, 0x54, 0x00, 0x00, 0x04, 0x01, 0x00,
|
||||
};
|
||||
|
||||
otExternalRouteConfig routes[] = {
|
||||
@@ -182,7 +244,7 @@ void TestNetworkDataIterator(void)
|
||||
0x00}}},
|
||||
32,
|
||||
},
|
||||
0x0400, // mRloc16
|
||||
0x0401, // mRloc16
|
||||
0, // mPreference
|
||||
false, // mNat64
|
||||
true, // mStable
|
||||
@@ -190,6 +252,10 @@ void TestNetworkDataIterator(void)
|
||||
},
|
||||
};
|
||||
|
||||
const uint16_t kRlocsAnyRole[] = {0x1000, 0x5400, 0x0401};
|
||||
const uint16_t kRlocsRouterRole[] = {0x1000, 0x5400};
|
||||
const uint16_t kRlocsChildRole[] = {0x0401};
|
||||
|
||||
NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData));
|
||||
|
||||
iter = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
@@ -199,10 +265,192 @@ void TestNetworkDataIterator(void)
|
||||
|
||||
for (const auto &route : routes)
|
||||
{
|
||||
SuccessOrQuit(netData.GetNextExternalRoute(iter, config));
|
||||
PrintExternalRouteConfig(config);
|
||||
VerifyOrQuit(CompareExternalRouteConfig(config, route));
|
||||
SuccessOrQuit(netData.GetNextExternalRoute(iter, rconfig));
|
||||
PrintExternalRouteConfig(rconfig);
|
||||
VerifyOrQuit(CompareExternalRouteConfig(rconfig, route));
|
||||
}
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocsAnyRole));
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsRouterRole);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocsRouterRole));
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsChildRole);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == GetArrayLength(kRlocsChildRole));
|
||||
|
||||
// Test failure case when given array is smaller than number of RLOCs.
|
||||
rlocsLength = GetArrayLength(kRlocsAnyRole) - 1;
|
||||
VerifyOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength) == kErrorNoBufs);
|
||||
VerifyOrQuit(rlocsLength == GetArrayLength(kRlocsAnyRole) - 1);
|
||||
for (uint8_t index = 0; index < rlocsLength; index++)
|
||||
{
|
||||
VerifyOrQuit(rlocs[index] == kRlocsAnyRole[index]);
|
||||
}
|
||||
|
||||
rlocsLength = GetArrayLength(kRlocsAnyRole);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole);
|
||||
}
|
||||
|
||||
{
|
||||
const uint8_t kNetworkData[] = {
|
||||
0x08, 0x04, 0x0b, 0x02, 0x36, 0xcc, 0x03, 0x1c, 0x00, 0x40, 0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe,
|
||||
0x00, 0x00, 0x05, 0x0c, 0x28, 0x00, 0x33, 0x00, 0x28, 0x01, 0x33, 0x00, 0x4c, 0x00, 0x31, 0x00,
|
||||
0x07, 0x02, 0x11, 0x40, 0x03, 0x14, 0x00, 0x40, 0xfd, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x04, 0x28, 0x00, 0x73, 0x00, 0x07, 0x02, 0x12, 0x40, 0x03, 0x12, 0x00, 0x40, 0xfd, 0x00,
|
||||
0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0xec, 0x00, 0x00, 0x28, 0x01, 0xc0,
|
||||
};
|
||||
|
||||
otExternalRouteConfig routes[] = {
|
||||
{
|
||||
{
|
||||
{{{0xfd, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}},
|
||||
64,
|
||||
},
|
||||
0xec00, // mRloc16
|
||||
0, // mPreference
|
||||
false, // mNat64
|
||||
true, // mStable
|
||||
false, // mNextHopIsThisDevice
|
||||
},
|
||||
{
|
||||
{
|
||||
{{{0xfd, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}},
|
||||
64,
|
||||
},
|
||||
0x2801, // mRloc16
|
||||
-1, // mPreference
|
||||
false, // mNat64
|
||||
true, // mStable
|
||||
false, // mNextHopIsThisDevice
|
||||
},
|
||||
};
|
||||
|
||||
otBorderRouterConfig prefixes[] = {
|
||||
{
|
||||
{
|
||||
{{{0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}},
|
||||
64,
|
||||
},
|
||||
0, // mPreference
|
||||
true, // mPreferred
|
||||
true, // mSlaac
|
||||
false, // mDhcp
|
||||
true, // mConfigure
|
||||
true, // mDefaultRoute
|
||||
true, // mOnMesh
|
||||
true, // mStable
|
||||
false, // mNdDns
|
||||
false, // mDp
|
||||
0x2800, // mRloc16
|
||||
},
|
||||
{
|
||||
{
|
||||
{{{0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}},
|
||||
64,
|
||||
},
|
||||
0, // mPreference
|
||||
true, // mPreferred
|
||||
true, // mSlaac
|
||||
false, // mDhcp
|
||||
true, // mConfigure
|
||||
true, // mDefaultRoute
|
||||
true, // mOnMesh
|
||||
true, // mStable
|
||||
false, // mNdDns
|
||||
false, // mDp
|
||||
0x2801, // mRloc16
|
||||
},
|
||||
{
|
||||
{
|
||||
{{{0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}},
|
||||
64,
|
||||
},
|
||||
0, // mPreference
|
||||
true, // mPreferred
|
||||
true, // mSlaac
|
||||
false, // mDhcp
|
||||
true, // mConfigure
|
||||
false, // mDefaultRoute
|
||||
true, // mOnMesh
|
||||
true, // mStable
|
||||
false, // mNdDns
|
||||
false, // mDp
|
||||
0x4c00, // mRloc16
|
||||
},
|
||||
{
|
||||
{
|
||||
{{{0xfd, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}},
|
||||
64,
|
||||
},
|
||||
1, // mPreference
|
||||
true, // mPreferred
|
||||
true, // mSlaac
|
||||
false, // mDhcp
|
||||
true, // mConfigure
|
||||
true, // mDefaultRoute
|
||||
true, // mOnMesh
|
||||
true, // mStable
|
||||
false, // mNdDns
|
||||
false, // mDp
|
||||
0x2800, // mRloc16
|
||||
},
|
||||
};
|
||||
|
||||
const uint16_t kRlocsAnyRole[] = {0xec00, 0x2801, 0x2800};
|
||||
const uint16_t kRlocsRouterRole[] = {0xec00, 0x2800};
|
||||
const uint16_t kRlocsChildRole[] = {0x2801};
|
||||
|
||||
NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData));
|
||||
|
||||
printf("\nTest #3: Network data 3");
|
||||
printf("\n-------------------------------------------------");
|
||||
|
||||
iter = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
|
||||
for (const auto &route : routes)
|
||||
{
|
||||
SuccessOrQuit(netData.GetNextExternalRoute(iter, rconfig));
|
||||
PrintExternalRouteConfig(rconfig);
|
||||
VerifyOrQuit(CompareExternalRouteConfig(rconfig, route));
|
||||
}
|
||||
|
||||
iter = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
|
||||
for (const auto &prefix : prefixes)
|
||||
{
|
||||
SuccessOrQuit(netData.GetNextOnMeshPrefix(iter, pconfig));
|
||||
PrintOnMeshPrefixConfig(pconfig);
|
||||
VerifyOrQuit(CompareOnMeshPrefixConfig(pconfig, prefix));
|
||||
}
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocsAnyRole));
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsRouterRole);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocsRouterRole));
|
||||
|
||||
rlocsLength = GetArrayLength(rlocs);
|
||||
SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength));
|
||||
VerifyRlocsArray(rlocs, rlocsLength, kRlocsChildRole);
|
||||
VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == GetArrayLength(kRlocsChildRole));
|
||||
}
|
||||
|
||||
testFreeInstance(instance);
|
||||
|
||||
Reference in New Issue
Block a user