From 09aa9630aa9b7361907f0e7d364411c5514f7f5a Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 25 Mar 2024 13:18:19 -0700 Subject: [PATCH] [netdata] add `FindRlocs()` to retrieve RLOC16 of entries (#9961) This commit introduces `NetworkData::FindRlocs()` which returns the list of RLCO16 of all border routers and servers in the Network Data matching specified filter conditions. The `BorderRouterFilter` can be used to filter the entry type. It can be set to `kAnyBrOrServer` to include all BRs and servers, or `kBrProvidingExternalIpConn` to restrict the list to BRs providing external IP connectivity. The new `FindRlocs()` replaces `FindBorderRouters()` and `GetNextServer()` methods and helps simplify the code. Unit test `test_network_data` is updated to validate the new method. --- src/core/thread/network_data.cpp | 220 +++++++------------- src/core/thread/network_data.hpp | 40 ++-- src/core/thread/network_data_leader_ftd.cpp | 17 +- src/core/thread/network_data_notifier.cpp | 9 +- src/core/thread/network_data_types.hpp | 33 +++ tests/unit/test_network_data.cpp | 142 ++++++++----- 6 files changed, 218 insertions(+), 243 deletions(-) diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index 30ebe0038..7a1fbc1e9 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -675,177 +675,103 @@ void MutableNetworkData::Remove(void *aRemoveStart, uint8_t aRemoveLength) void MutableNetworkData::RemoveTlv(NetworkDataTlv *aTlv) { Remove(aTlv, aTlv->GetSize()); } -Error NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const +void NetworkData::FindRlocs(BorderRouterFilter aBrFilter, RoleFilter aRoleFilter, Rlocs &aRlocs) const { - Error error; - OnMeshPrefixConfig prefixConfig; - ExternalRouteConfig routeConfig; - ServiceConfig serviceConfig; + Iterator iterator = kIteratorInit; + OnMeshPrefixConfig prefix; + ExternalRouteConfig route; + ServiceConfig service; Config config; - config.mOnMeshPrefix = &prefixConfig; - config.mExternalRoute = &routeConfig; - config.mService = &serviceConfig; - config.mLowpanContext = nullptr; + aRlocs.Clear(); - SuccessOrExit(error = Iterate(aIterator, Mac::kShortAddrBroadcast, config)); + while (true) + { + config.mOnMeshPrefix = &prefix; + config.mExternalRoute = &route; + config.mService = &service; + config.mLowpanContext = nullptr; - if (config.mOnMeshPrefix != nullptr) - { - aRloc16 = config.mOnMeshPrefix->mRloc16; - } - else if (config.mExternalRoute != nullptr) - { - aRloc16 = config.mExternalRoute->mRloc16; - } - else if (config.mService != nullptr) - { - aRloc16 = config.mService->mServerConfig.mRloc16; - } - else - { - OT_ASSERT(false); + SuccessOrExit(Iterate(iterator, Mac::kShortAddrBroadcast, config)); + + if (config.mOnMeshPrefix != nullptr) + { + bool matches = true; + + switch (aBrFilter) + { + case kAnyBrOrServer: + break; + case kBrProvidingExternalIpConn: + matches = prefix.mOnMesh && (prefix.mDefaultRoute || prefix.mDp); + break; + } + + if (matches) + { + AddRloc16ToRlocs(prefix.mRloc16, aRlocs, aRoleFilter); + } + } + else if (config.mExternalRoute != nullptr) + { + AddRloc16ToRlocs(route.mRloc16, aRlocs, aRoleFilter); + } + else if (config.mService != nullptr) + { + switch (aBrFilter) + { + case kAnyBrOrServer: + AddRloc16ToRlocs(service.mServerConfig.mRloc16, aRlocs, aRoleFilter); + break; + case kBrProvidingExternalIpConn: + break; + } + } } exit: - return error; -} - -Error NetworkData::FindBorderRouters(RoleFilter aRoleFilter, uint16_t aRlocs[], uint8_t &aRlocsLength) const -{ - class Rlocs // Wrapper over an array of RLOC16s. - { - public: - Rlocs(RoleFilter aRoleFilter, uint16_t *aRlocs, uint8_t aRlocsMaxLength) - : mRoleFilter(aRoleFilter) - , mRlocs(aRlocs) - , mLength(0) - , mMaxLength(aRlocsMaxLength) - { - } - - uint8_t GetLength(void) const { return mLength; } - - Error AddRloc16(uint16_t aRloc16) - { - // Add `aRloc16` into the array if it matches `RoleFilter` and - // it is not in the array already. If we need to add the `aRloc16` - // but there is no more room in the array, return `kErrorNoBufs`. - - Error error = kErrorNone; - uint8_t index; - - switch (mRoleFilter) - { - case kAnyRole: - break; - - case kRouterRoleOnly: - VerifyOrExit(Mle::IsActiveRouter(aRloc16)); - break; - - case kChildRoleOnly: - VerifyOrExit(!Mle::IsActiveRouter(aRloc16)); - break; - } - - for (index = 0; index < mLength; index++) - { - if (mRlocs[index] == aRloc16) - { - break; - } - } - - if (index == mLength) - { - VerifyOrExit(mLength < mMaxLength, error = kErrorNoBufs); - mRlocs[mLength++] = aRloc16; - } - - exit: - return error; - } - - private: - RoleFilter mRoleFilter; - uint16_t *mRlocs; - uint8_t mLength; - uint8_t mMaxLength; - }; - - Error error = kErrorNone; - Rlocs rlocs(aRoleFilter, aRlocs, aRlocsLength); - Iterator iterator = kIteratorInit; - ExternalRouteConfig route; - OnMeshPrefixConfig prefix; - - while (GetNextExternalRoute(iterator, route) == kErrorNone) - { - SuccessOrExit(error = rlocs.AddRloc16(route.mRloc16)); - } - - iterator = kIteratorInit; - - while (GetNextOnMeshPrefix(iterator, prefix) == kErrorNone) - { - if (!prefix.mDefaultRoute || !prefix.mOnMesh) - { - continue; - } - - SuccessOrExit(error = rlocs.AddRloc16(prefix.mRloc16)); - } - -exit: - aRlocsLength = rlocs.GetLength(); - return error; + return; } uint8_t NetworkData::CountBorderRouters(RoleFilter aRoleFilter) const { - // We use an over-estimate of max number of border routers in the - // Network Data using the facts that network data is limited to 254 - // bytes and that an external route entry uses at minimum 3 bytes - // for RLOC16 and flag, so `ceil(254/3) = 85`. + Rlocs rlocs; - static constexpr uint16_t kMaxRlocs = 85; + FindRlocs(kBrProvidingExternalIpConn, aRoleFilter, rlocs); - uint16_t rlocs[kMaxRlocs]; - uint8_t rlocsLength = kMaxRlocs; - - SuccessOrAssert(FindBorderRouters(aRoleFilter, rlocs, rlocsLength)); - - return rlocsLength; + return rlocs.GetLength(); } bool NetworkData::ContainsBorderRouterWithRloc(uint16_t aRloc16) const { - bool contains = false; - Iterator iterator = kIteratorInit; - ExternalRouteConfig route; - OnMeshPrefixConfig prefix; + Rlocs rlocs; - while (GetNextExternalRoute(iterator, route) == kErrorNone) + FindRlocs(kBrProvidingExternalIpConn, kAnyRole, rlocs); + + return rlocs.Contains(aRloc16); +} + +void NetworkData::AddRloc16ToRlocs(uint16_t aRloc16, Rlocs &aRlocs, RoleFilter aRoleFilter) +{ + switch (aRoleFilter) { - if (route.mRloc16 == aRloc16) - { - ExitNow(contains = true); - } + case kAnyRole: + break; + + case kRouterRoleOnly: + VerifyOrExit(Mle::IsActiveRouter(aRloc16)); + break; + + case kChildRoleOnly: + VerifyOrExit(!Mle::IsActiveRouter(aRloc16)); + break; } - iterator = kIteratorInit; - - while (GetNextOnMeshPrefix(iterator, prefix) == kErrorNone) - { - if ((prefix.mRloc16 == aRloc16) && prefix.mOnMesh && (prefix.mDefaultRoute || prefix.mDp)) - { - ExitNow(contains = true); - } - } + VerifyOrExit(!aRlocs.Contains(aRloc16)); + IgnoreError(aRlocs.PushBack(aRloc16)); exit: - return contains; + return; } Error NetworkData::FindDomainIdFor(const Ip6::Prefix &aPrefix, uint8_t &aDomainId) const diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index 17c515142..7b4569652 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -324,18 +324,6 @@ public: */ bool ContainsEntriesFrom(const NetworkData &aCompare, uint16_t aRloc16) const; - /** - * Provides the next server RLOC16 in the Thread Network Data. - * - * @param[in,out] aIterator A reference to the Network Data iterator. - * @param[out] aRloc16 The RLOC16 value. - * - * @retval kErrorNone Successfully found the next server. - * @retval kErrorNotFound No subsequent server exists in the Thread Network Data. - * - */ - Error GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const; - /** * Finds and returns Domain ID associated with a given prefix in the Thread Network data. * @@ -349,30 +337,30 @@ public: Error FindDomainIdFor(const Ip6::Prefix &aPrefix, uint8_t &aDomainId) const; /** - * Finds and returns the list of RLOCs of border routers providing external IP connectivity. + * Finds border routers and servers in the Network Data matching specified filters, returning their RLOC16s. * - * 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. + * @p aBrFilter can be used to filter the type of BRs. It can be set to `kAnyBrOrServer` to include all BRs and + * servers. `kBrProvidingExternalIpConn` restricts it to BRs providing external IP connectivity where at least one + * the below conditions hold: + * + * - It has added at least one external route entry. + * - It has added at least one prefix entry with default-route and on-mesh flags set. + * - It has added at least one domain prefix (domain and on-mesh flags set). * * Should be used when the RLOC16s are present in the Network Data (when the Network Data contains the * full set and not the stable subset). * - * @param[in] aRoleFilter Indicates which devices to include (any role, router role only, or child only). - * @param[out] aRlocs Array to output the list of RLOCs. - * @param[in,out] aRlocsLength On entry, @p aRlocs array length (max number of elements). - * On exit, number RLOC16 entries added in @p aRlocs. - * - * @retval kErrorNone Successfully found all RLOC16s and updated @p aRlocs and @p aRlocsLength. - * @retval kErrorNoBufs Ran out of space in @p aRlocs array. @p aRlocs and @p aRlocsLength are still updated up - * to the maximum array length. + * @param[in] aBrFilter Indicates BR filter. + * @param[in] aRoleFilter Indicates role filter (any role, router role only, or child only). + * @param[out] aRlocs Array to output the list of RLOC16s. * */ - Error FindBorderRouters(RoleFilter aRoleFilter, uint16_t aRlocs[], uint8_t &aRlocsLength) const; + void FindRlocs(BorderRouterFilter aBrFilter, RoleFilter aRoleFilter, Rlocs &aRlocs) const; /** * Counts the number of border routers providing external IP connectivity. * - * A border router is considered to provide external IP connectivity if at least one of the below conditions hold + * A border router is considered to provide external IP connectivity if at least one of the below conditions hold: * * - It has added at least one external route entry. * - It has added at least one prefix entry with default-route and on-mesh flags set. @@ -591,6 +579,8 @@ private: const ServiceData &aServiceData, ServiceMatchMode aServiceMatchMode); + static void AddRloc16ToRlocs(uint16_t aRloc16, Rlocs &aRlocs, RoleFilter aRoleFilter); + const uint8_t *mTlvs; uint8_t mLength; }; diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index fe423ef4f..1b5d077ec 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -1218,10 +1218,10 @@ void Leader::HandleNetworkDataRestoredAfterReset(void) { const PrefixTlv *prefix; TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd()); - Iterator iterator = kIteratorInit; ChangedFlags flags; uint16_t rloc16; uint16_t sessionId; + Rlocs rlocs; mWaitingForNetDataSync = false; @@ -1232,16 +1232,13 @@ void Leader::HandleNetworkDataRestoredAfterReset(void) // got the chance to send the updated Network Data to other // routers. - while (GetNextServer(iterator, rloc16) == kErrorNone) - { - if (!Get().IsAllocated(Mle::RouterIdFromRloc16(rloc16))) - { - // After we `RemoveRloc()` the Network Data gets changed - // and the `iterator` will not be valid anymore. So we set - // it to `kIteratorInit` to restart the loop. + FindRlocs(kAnyBrOrServer, kAnyRole, rlocs); - RemoveRloc(rloc16, kMatchModeRouterId, flags); - iterator = kIteratorInit; + for (uint16_t rloc : rlocs) + { + if (!Get().IsAllocated(Mle::RouterIdFromRloc16(rloc))) + { + RemoveRloc(rloc, kMatchModeRouterId, flags); } } diff --git a/src/core/thread/network_data_notifier.cpp b/src/core/thread/network_data_notifier.cpp index 750b3799b..e451a73e4 100644 --- a/src/core/thread/network_data_notifier.cpp +++ b/src/core/thread/network_data_notifier.cpp @@ -129,13 +129,14 @@ Error Notifier::RemoveStaleChildEntries(void) // - `kErrorNoBufs` if could not allocate message to send message. // - `kErrorNotFound` if no stale child entries were found. - Error error = kErrorNotFound; - Iterator iterator = kIteratorInit; - uint16_t rloc16; + Error error = kErrorNotFound; + Rlocs rlocs; VerifyOrExit(Get().IsRouterOrLeader()); - while (Get().GetNextServer(iterator, rloc16) == kErrorNone) + Get().FindRlocs(kAnyBrOrServer, kAnyRole, rlocs); + + for (uint16_t rloc16 : rlocs) { if (!Mle::IsActiveRouter(rloc16) && Mle::RouterIdMatch(Get().GetRloc16(), rloc16) && Get().FindChild(rloc16, Child::kInStateValid) == nullptr) diff --git a/src/core/thread/network_data_types.hpp b/src/core/thread/network_data_types.hpp index 1457aa239..af63ff5d7 100644 --- a/src/core/thread/network_data_types.hpp +++ b/src/core/thread/network_data_types.hpp @@ -38,6 +38,7 @@ #include +#include "common/array.hpp" #include "common/as_core_type.hpp" #include "common/clearable.hpp" #include "common/data.hpp" @@ -107,6 +108,38 @@ enum RoleFilter : uint8_t kChildRoleOnly, ///< Include devices that act as Thread child (end-device). }; +/** + * Represents the entry filter used when searching for RLOC16 of border routers or servers in the Network Data. + * + * Regarding `kBrProvidingExternalIpConn`, a border router is considered to provide external IP connectivity if at + * least one of the below conditions hold: + * + * - It has added at least one external route entry. + * - It has added at least one prefix entry with default-route and on-mesh flags set. + * - It has added at least one domain prefix (domain and on-mesh flags set). + * + */ +enum BorderRouterFilter : uint8_t +{ + kAnyBrOrServer, ///< Include any border router or server entry. + kBrProvidingExternalIpConn, ///< Include border routers providing external IP connectivity. +}; + +/** + * Maximum length of `Rlocs` array containing RLOC16 of all border routers and servers in the Network Data. + * + * This limit is derived from the maximum Network Data size (254 bytes) and the minimum size of an external route entry + * (3 bytes including the RLOC16 and flags) as `ceil(254/3) = 85`. + * + */ +static constexpr uint8_t kMaxRlocs = 85; + +/** + * An array containing RLOC16 of all border routers and server in the Network Data. + * + */ +typedef Array Rlocs; + /** * Indicates whether a given `int8_t` preference value is a valid route preference (i.e., one of the * values from `RoutePreference` enumeration). diff --git a/tests/unit/test_network_data.cpp b/tests/unit/test_network_data.cpp index 286870908..4740a2fff 100644 --- a/tests/unit/test_network_data.cpp +++ b/tests/unit/test_network_data.cpp @@ -86,32 +86,32 @@ bool CompareOnMeshPrefixConfig(const otBorderRouterConfig &aConfig1, const otBor (aConfig1.mDefaultRoute == aConfig2.mDefaultRoute) && (aConfig1.mOnMesh == aConfig2.mOnMesh); } -template -void VerifyRlocsArray(const uint16_t *aRlocs, uint16_t aRlocsLength, const uint16_t (&aExpectedRlocs)[kLength]) +template void VerifyRlocsArray(const Rlocs &aRlocs, const uint16_t (&aExpectedRlocs)[kLength]) { - VerifyOrQuit(aRlocsLength == kLength); + VerifyOrQuit(aRlocs.GetLength() == kLength); printf("\nRLOCs: { "); - for (uint16_t index = 0; index < aRlocsLength; index++) + for (uint16_t rloc : aRlocs) { - VerifyOrQuit(aRlocs[index] == aExpectedRlocs[index]); - printf("0x%04x ", aRlocs[index]); + printf("0x%04x ", rloc); } printf("}"); + + for (uint16_t index = 0; index < kLength; index++) + { + VerifyOrQuit(aRlocs.Contains(aExpectedRlocs[index])); + } } void TestNetworkDataIterator(void) { - static constexpr uint8_t kMaxRlocsArray = 10; - Instance *instance; Iterator iter = kIteratorInit; ExternalRouteConfig rconfig; OnMeshPrefixConfig pconfig; - uint16_t rlocs[kMaxRlocsArray]; - uint8_t rlocsLength; + Rlocs rlocs; instance = testInitInstance(); VerifyOrQuit(instance != nullptr); @@ -168,19 +168,25 @@ void TestNetworkDataIterator(void) VerifyOrQuit(CompareExternalRouteConfig(rconfig, route)); } - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocs); + netData.FindRlocs(kAnyBrOrServer, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kRlocs); + + netData.FindRlocs(kAnyBrOrServer, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocs); + + netData.FindRlocs(kAnyBrOrServer, kChildRoleOnly, rlocs); + VerifyOrQuit(rlocs.GetLength() == 0); + + netData.FindRlocs(kBrProvidingExternalIpConn, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kRlocs); VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocs)); - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocs); + netData.FindRlocs(kBrProvidingExternalIpConn, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocs); VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocs)); - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength)); - VerifyOrQuit(rlocsLength == 0); + netData.FindRlocs(kBrProvidingExternalIpConn, kChildRoleOnly, rlocs); + VerifyOrQuit(rlocs.GetLength() == 0); VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == 0); for (uint16_t rloc16 : kRlocs) @@ -284,33 +290,29 @@ void TestNetworkDataIterator(void) VerifyOrQuit(CompareExternalRouteConfig(rconfig, route)); } - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole); + netData.FindRlocs(kAnyBrOrServer, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kRlocsAnyRole); + + netData.FindRlocs(kAnyBrOrServer, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocsRouterRole); + + netData.FindRlocs(kAnyBrOrServer, kChildRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocsChildRole); + + netData.FindRlocs(kBrProvidingExternalIpConn, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kRlocsAnyRole); VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocsAnyRole)); - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocsRouterRole); + netData.FindRlocs(kBrProvidingExternalIpConn, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocsRouterRole); VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocsRouterRole)); - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocsChildRole); + netData.FindRlocs(kBrProvidingExternalIpConn, kChildRoleOnly, rlocs); + VerifyRlocsArray(rlocs, 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); + netData.FindRlocs(kBrProvidingExternalIpConn, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kRlocsAnyRole); for (uint16_t rloc16 : kRlocsAnyRole) { @@ -434,10 +436,13 @@ void TestNetworkDataIterator(void) }, }; - const uint16_t kRlocsAnyRole[] = {0xec00, 0x2801, 0x2800}; - const uint16_t kRlocsRouterRole[] = {0xec00, 0x2800}; - const uint16_t kRlocsChildRole[] = {0x2801}; - const uint16_t kNonExistingRlocs[] = {0x6000, 0x0000, 0x2806, 0x4c00}; + const uint16_t kRlocsAnyRole[] = {0xec00, 0x2801, 0x2800, 0x4c00}; + const uint16_t kRlocsRouterRole[] = {0xec00, 0x2800, 0x4c00}; + const uint16_t kRlocsChildRole[] = {0x2801}; + const uint16_t kBrRlocsAnyRole[] = {0xec00, 0x2801, 0x2800}; + const uint16_t kBrRlocsRouterRole[] = {0xec00, 0x2800}; + const uint16_t kBrRlocsChildRole[] = {0x2801}; + const uint16_t kNonExistingRlocs[] = {0x6000, 0x0000, 0x2806, 0x4c00}; NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData)); @@ -462,22 +467,28 @@ void TestNetworkDataIterator(void) VerifyOrQuit(CompareOnMeshPrefixConfig(pconfig, prefix)); } - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole); - VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocsAnyRole)); + netData.FindRlocs(kAnyBrOrServer, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kRlocsAnyRole); - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocsRouterRole); - VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocsRouterRole)); + netData.FindRlocs(kAnyBrOrServer, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocsRouterRole); - rlocsLength = GetArrayLength(rlocs); - SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength)); - VerifyRlocsArray(rlocs, rlocsLength, kRlocsChildRole); - VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == GetArrayLength(kRlocsChildRole)); + netData.FindRlocs(kAnyBrOrServer, kChildRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kRlocsChildRole); - for (uint16_t rloc16 : kRlocsAnyRole) + netData.FindRlocs(kBrProvidingExternalIpConn, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kBrRlocsAnyRole); + VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kBrRlocsAnyRole)); + + netData.FindRlocs(kBrProvidingExternalIpConn, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kBrRlocsRouterRole); + VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kBrRlocsRouterRole)); + + netData.FindRlocs(kBrProvidingExternalIpConn, kChildRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kBrRlocsChildRole); + VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == GetArrayLength(kBrRlocsChildRole)); + + for (uint16_t rloc16 : kBrRlocsAnyRole) { VerifyOrQuit(netData.ContainsBorderRouterWithRloc(rloc16)); } @@ -681,17 +692,34 @@ void TestNetworkDataDsnSrpServices(void) {"fdde:ad00:beef:0:0:ff:fe00:6c00", 0xcd12, Service::DnsSrpUnicast::kFromServerData, 0x6c00}, }; + const uint16_t kExpectedRlocs[] = {0x6c00, 0x2800, 0x4c00, 0x0000}; + const uint8_t kPreferredAnycastEntryIndex = 2; Service::Manager &manager = instance->Get(); Service::Manager::Iterator iterator; Service::DnsSrpAnycast::Info anycastInfo; Service::DnsSrpUnicast::Info unicastInfo; + Rlocs rlocs; reinterpret_cast(instance->Get()).Populate(kNetworkData, sizeof(kNetworkData)); DumpBuffer("netdata", kNetworkData, sizeof(kNetworkData)); + // Verify `FindRlocs()` + + instance->Get().FindRlocs(kAnyBrOrServer, kAnyRole, rlocs); + VerifyRlocsArray(rlocs, kExpectedRlocs); + + instance->Get().FindRlocs(kAnyBrOrServer, kRouterRoleOnly, rlocs); + VerifyRlocsArray(rlocs, kExpectedRlocs); + + instance->Get().FindRlocs(kAnyBrOrServer, kChildRoleOnly, rlocs); + VerifyOrQuit(rlocs.GetLength() == 0); + + instance->Get().FindRlocs(kBrProvidingExternalIpConn, kAnyRole, rlocs); + VerifyOrQuit(rlocs.GetLength() == 0); + // Verify all the "DNS/SRP Anycast Service" entries in Network Data printf("\n- - - - - - - - - - - - - - - - - - - -");