From ed31bfefb6e79c523ecd3481e97eb2be0083b471 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 26 Oct 2022 01:37:40 -0700 Subject: [PATCH] [address-resolver] allow addr resolution using net data service (#8318) This commit implements a new optimization in `AddressResolver` allowing it to resolve on-mesh IPv6 addresses using info from Thread Network Data DNS/SRP Service (Unicast Address) entries. When determining EID-to-RLOC mapping in `Resolve()`, we first try to match the EID against unicast addresses discovered from DNS/SRP service entries. This is limited to entries where the address/port info is encoded as part of server data. If a match is found the associated RLOC16 of the BR which added the entry in Network Data will be used (i.e., the `server16` field from Network data server sub-TLV). This optimization is used on devices where MLE Mode indicates they receive full Network Data and not the stable subset (since stable subset will not provide RLOC16 info). This commit adds a similar check in `UpdateSnoopedCacheEntry()` so that the limited snoop cache entries are not unnecessarily used for addresses which can be resolved using Network Data services. --- src/core/config/tmf.h | 10 ++++++ src/core/thread/address_resolver.cpp | 43 ++++++++++++++++++++++++ src/core/thread/address_resolver.hpp | 6 ++-- src/core/thread/mle_types.hpp | 2 ++ src/core/thread/network_data_service.cpp | 3 ++ src/core/thread/network_data_service.hpp | 1 + tests/unit/test_network_data.cpp | 17 +++++----- 7 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/core/config/tmf.h b/src/core/config/tmf.h index 5d43f73e1..0bd1f3651 100644 --- a/src/core/config/tmf.h +++ b/src/core/config/tmf.h @@ -106,6 +106,16 @@ #define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY 120 #endif +/** + * @def OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES + * + * Define as 1 to allow address resolution of on-mesh addresses using Thread Network Data DNS/SRP Service entries. + * + */ +#ifndef OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES +#define OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES 1 +#endif + /** * @def OPENTHREAD_CONFIG_TMF_PENDING_DATASET_MINIMUM_DELAY * diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index d88f165cc..812986502 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -376,6 +376,10 @@ void AddressResolver::UpdateSnoopedCacheEntry(const Ip6::Address &aEid, VerifyOrExit(Get().IsFullThreadDevice()); +#if OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES + VerifyOrExit(ResolveUsingNetDataServices(aEid, macAddress) != kErrorNone); +#endif + VerifyOrExit(UpdateCacheEntry(aEid, aRloc16) != kErrorNone); // Skip if the `aRloc16` (i.e., the source of the snooped message) @@ -470,6 +474,10 @@ Error AddressResolver::Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRlo CacheEntry * prev = nullptr; CacheEntryList *list; +#if OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES + VerifyOrExit(ResolveUsingNetDataServices(aEid, aRloc16) != kErrorNone); +#endif + entry = FindCacheEntry(aEid, list, prev); if (entry == nullptr) @@ -548,6 +556,41 @@ exit: return error; } +#if OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES + +Error AddressResolver::ResolveUsingNetDataServices(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16) +{ + // Tries to resolve `aEid` Network Data DNS/SRP Unicast address + // service entries. Returns `kErrorNone` and updates `aRloc16` + // if successful, otherwise returns `kErrorNotFound`. + + Error error = kErrorNotFound; + NetworkData::Service::Manager::Iterator iterator; + NetworkData::Service::DnsSrpUnicast::Info unicastInfo; + + VerifyOrExit(Get().GetDeviceMode().GetNetworkDataType() == NetworkData::kFullSet); + + while (Get().GetNextDnsSrpUnicastInfo(iterator, unicastInfo) == kErrorNone) + { + if (unicastInfo.mOrigin != NetworkData::Service::DnsSrpUnicast::kFromServerData) + { + continue; + } + + if (aEid == unicastInfo.mSockAddr.GetAddress()) + { + aRloc16 = unicastInfo.mRloc16; + error = kErrorNone; + ExitNow(); + } + } + +exit: + return error; +} + +#endif // OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES + Error AddressResolver::SendAddressQuery(const Ip6::Address &aEid) { Error error; diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp index 0b76af9be..6695fc32d 100644 --- a/src/core/thread/address_resolver.hpp +++ b/src/core/thread/address_resolver.hpp @@ -338,8 +338,10 @@ private: CacheEntry *NewCacheEntry(bool aSnoopedEntry); void RemoveCacheEntry(CacheEntry &aEntry, CacheEntryList &aList, CacheEntry *aPrevEntry, Reason aReason); Error UpdateCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16); - - Error SendAddressQuery(const Ip6::Address &aEid); + Error SendAddressQuery(const Ip6::Address &aEid); +#if OPENTHREAD_CONFIG_TMF_ALLOW_ADDRESS_RESOLUTION_USING_NET_DATA_SERVICES + Error ResolveUsingNetDataServices(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16); +#endif static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp index 19f577867..44be29ea4 100644 --- a/src/core/thread/mle_types.hpp +++ b/src/core/thread/mle_types.hpp @@ -161,6 +161,8 @@ constexpr uint8_t kRouterSelectionJitter = 120; ///< (in sec) constexpr uint8_t kRouterDowngradeThreshold = 23; constexpr uint8_t kRouterUpgradeThreshold = 16; +constexpr uint16_t kInvalidRloc16 = Mac::kShortAddrInvalid; ///< Invalid RLOC16. + /** * Threshold to accept a router upgrade request with reason `kBorderRouterRequest` (number of BRs acting as router in * Network Data). diff --git a/src/core/thread/network_data_service.cpp b/src/core/thread/network_data_service.cpp index 4bc60da48..7ed771452 100644 --- a/src/core/thread/network_data_service.cpp +++ b/src/core/thread/network_data_service.cpp @@ -288,6 +288,7 @@ Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicast::Info aInfo.mSockAddr.SetAddress(serverData->GetAddress()); aInfo.mSockAddr.SetPort(serverData->GetPort()); aInfo.mOrigin = DnsSrpUnicast::kFromServerData; + aInfo.mRloc16 = aIterator.mServerSubTlv->GetServer16(); ExitNow(); } @@ -300,6 +301,7 @@ Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicast::Info aIterator.mServerSubTlv->GetServer16()); aInfo.mSockAddr.SetPort(Encoding::BigEndian::ReadUint16(data.GetBytes())); aInfo.mOrigin = DnsSrpUnicast::kFromServerData; + aInfo.mRloc16 = aIterator.mServerSubTlv->GetServer16(); ExitNow(); } } @@ -322,6 +324,7 @@ Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicast::Info aInfo.mSockAddr.SetAddress(dnsServiceData->GetAddress()); aInfo.mSockAddr.SetPort(dnsServiceData->GetPort()); aInfo.mOrigin = DnsSrpUnicast::kFromServiceData; + aInfo.mRloc16 = Mle::kInvalidRloc16; ExitNow(); } diff --git a/src/core/thread/network_data_service.hpp b/src/core/thread/network_data_service.hpp index bd41dc775..ed8903994 100644 --- a/src/core/thread/network_data_service.hpp +++ b/src/core/thread/network_data_service.hpp @@ -258,6 +258,7 @@ public: { Ip6::SockAddr mSockAddr; ///< The socket address (IPv6 address and port) of the DNS/SRP server. Origin mOrigin; ///< The origin of the socket address (whether from service or server data). + uint16_t mRloc16; ///< The BR RLOC16 adding the entry (only used when `mOrigin == kFromServerData`). }; /** diff --git a/tests/unit/test_network_data.cpp b/tests/unit/test_network_data.cpp index 44df23646..9d1523b74 100644 --- a/tests/unit/test_network_data.cpp +++ b/tests/unit/test_network_data.cpp @@ -642,6 +642,7 @@ void TestNetworkDataDsnSrpServices(void) const char * mAddress; uint16_t mPort; Service::DnsSrpUnicast::Origin mOrigin; + uint16_t mRloc16; bool Matches(Service::DnsSrpUnicast::Info aInfo) const { @@ -650,7 +651,7 @@ void TestNetworkDataDsnSrpServices(void) SuccessOrQuit(sockAddr.GetAddress().FromString(mAddress)); sockAddr.SetPort(mPort); - return (aInfo.mSockAddr == sockAddr) && (aInfo.mOrigin == mOrigin); + return (aInfo.mSockAddr == sockAddr) && (aInfo.mOrigin == mOrigin) && (aInfo.mRloc16 == mRloc16); } }; @@ -671,11 +672,11 @@ void TestNetworkDataDsnSrpServices(void) }; const UnicastEntry kUnicastEntries[] = { - {"fdde:ad00:beef:0:2d0e:c627:5556:18d9", 0x1234, Service::DnsSrpUnicast::kFromServiceData}, - {"fd00:aabb:ccdd:eeff:11:2233:4455:6677", 0xabcd, Service::DnsSrpUnicast::kFromServerData}, - {"fdde:ad00:beef:0:0:ff:fe00:2800", 0x5678, Service::DnsSrpUnicast::kFromServerData}, - {"fd00:1234:5678:9abc:def0:123:4567:89ab", 0x0e, Service::DnsSrpUnicast::kFromServerData}, - {"fdde:ad00:beef:0:0:ff:fe00:6c00", 0xcd12, Service::DnsSrpUnicast::kFromServerData}, + {"fdde:ad00:beef:0:2d0e:c627:5556:18d9", 0x1234, Service::DnsSrpUnicast::kFromServiceData, 0xfffe}, + {"fd00:aabb:ccdd:eeff:11:2233:4455:6677", 0xabcd, Service::DnsSrpUnicast::kFromServerData, 0x6c00}, + {"fdde:ad00:beef:0:0:ff:fe00:2800", 0x5678, Service::DnsSrpUnicast::kFromServerData, 0x2800}, + {"fd00:1234:5678:9abc:def0:123:4567:89ab", 0x0e, Service::DnsSrpUnicast::kFromServerData, 0x4c00}, + {"fdde:ad00:beef:0:0:ff:fe00:6c00", 0xcd12, Service::DnsSrpUnicast::kFromServerData, 0x6c00}, }; const uint8_t kPreferredAnycastEntryIndex = 2; @@ -725,8 +726,8 @@ void TestNetworkDataDsnSrpServices(void) for (const UnicastEntry &entry : kUnicastEntries) { SuccessOrQuit(manager.GetNextDnsSrpUnicastInfo(iterator, unicastInfo)); - printf("\nunicastInfo { %s, origin:%s }", unicastInfo.mSockAddr.ToString().AsCString(), - kOriginStrings[unicastInfo.mOrigin]); + printf("\nunicastInfo { %s, origin:%s, rloc16:%04x }", unicastInfo.mSockAddr.ToString().AsCString(), + kOriginStrings[unicastInfo.mOrigin], unicastInfo.mRloc16); VerifyOrQuit(entry.Matches(unicastInfo), "GetNextDnsSrpUnicastInfo() returned incorrect info"); }