[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:
Abtin Keshavarzian
2022-04-12 12:36:22 -07:00
committed by GitHub
parent 0c754bb09d
commit d51eb07c62
4 changed files with 416 additions and 10 deletions
+258 -10
View File
@@ -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);