From b78b71b537ea13419543d14eacbf164b15af6c99 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 1 Dec 2023 10:14:44 -0800 Subject: [PATCH] [srp-client] track registered addresses (#9652) This commit enhances the SRP client to track registered addresses when auto host address mode is enabled. A new field `mSrpRegistered` is added to `Ip6::Netif::UnicastAddress` to track whether the address is registered by the SRP client. This optimization ensures that the SRP client only performs registration when there is a change to the list of addresses that need to be registered, preventing unnecessary re-registration and reduces communication overhead, e.g., when a deprecating non-preferred address which is not registered by SRP client is timed out and removed. --- include/openthread/instance.h | 2 +- include/openthread/ip6.h | 1 + src/core/net/netif.cpp | 24 +++++- src/core/net/netif.hpp | 22 ++++- src/core/net/srp_client.cpp | 116 +++++++++++++++++++++------ src/core/net/srp_client.hpp | 4 +- src/core/thread/address_resolver.cpp | 2 +- src/core/thread/mle.hpp | 8 ++ 8 files changed, 145 insertions(+), 34 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index b67b303f1..3acb6e437 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (379) +#define OPENTHREAD_API_VERSION (380) /** * @addtogroup api-instance diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index 850c64c6b..8b32d7ca4 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -189,6 +189,7 @@ typedef struct otNetifAddress unsigned int mScopeOverride : 4; ///< The IPv6 scope of this address. bool mRloc : 1; ///< TRUE if the address is an RLOC, FALSE otherwise. bool mMeshLocal : 1; ///< TRUE if the address is mesh-local, FALSE otherwise. + bool mSrpRegistered : 1; ///< Used by OT core only (indicates whether registered by SRP Client). const struct otNetifAddress *mNext; ///< A pointer to the next network interface address. } otNetifAddress; diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp index ff39891e7..1b739afca 100644 --- a/src/core/net/netif.cpp +++ b/src/core/net/netif.cpp @@ -377,15 +377,29 @@ exit: return; } -void Netif::RemoveUnicastAddress(const UnicastAddress &aAddress) +void Netif::RemoveUnicastAddress(UnicastAddress &aAddress) { SuccessOrExit(mUnicastAddresses.Remove(aAddress)); + aAddress.mSrpRegistered = false; SignalUnicastAddressChange(kAddressRemoved, aAddress); exit: return; } +void Netif::UpdatePreferredFlagOn(UnicastAddress &aAddress, bool aPreferred) +{ + VerifyOrExit(HasUnicastAddress(aAddress)); + VerifyOrExit(aAddress.mPreferred != aPreferred); + + SignalUnicastAddressChange(kAddressRemoved, aAddress); + aAddress.mPreferred = aPreferred; + SignalUnicastAddressChange(kAddressAdded, aAddress); + +exit: + return; +} + void Netif::SignalUnicastAddressChange(AddressEvent aEvent, const UnicastAddress &aAddress) { Event event; @@ -443,9 +457,10 @@ Error Netif::AddExternalUnicastAddress(const UnicastAddress &aAddress) entry = mExtUnicastAddressPool.Allocate(); VerifyOrExit(entry != nullptr, error = kErrorNoBufs); - *entry = aAddress; - entry->mRloc = false; - entry->mMeshLocal = false; + *entry = aAddress; + entry->mRloc = false; + entry->mMeshLocal = false; + entry->mSrpRegistered = false; mUnicastAddresses.Push(*entry); SignalUnicastAddressChange(kAddressAdded, *entry); @@ -504,6 +519,7 @@ void Netif::ApplyNewMeshLocalPrefix(void) if (address.mMeshLocal) { SignalUnicastAddressChange(kAddressRemoved, address); + address.mSrpRegistered = false; address.GetAddress().SetPrefix(Get().GetMeshLocalPrefix()); SignalUnicastAddressChange(kAddressAdded, address); } diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index 0e5057134..663eb218e 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -397,6 +397,14 @@ public: */ const LinkedList &GetUnicastAddresses(void) const { return mUnicastAddresses; } + /** + * Returns the linked list of unicast addresses. + * + * @returns The linked list of unicast addresses. + * + */ + LinkedList &GetUnicastAddresses(void) { return mUnicastAddresses; } + /** * Adds a unicast address to the network interface. * @@ -421,7 +429,19 @@ public: * @param[in] aAddress A reference to the unicast address. * */ - void RemoveUnicastAddress(const UnicastAddress &aAddress); + void RemoveUnicastAddress(UnicastAddress &aAddress); + + /** + * Updates the preferred flag on a previously added (internal to OpenThread core) unicast address. + * + * If the address is not added to the network interface or the current preferred flag of @p aAddress is the same as + * the given @p aPreferred, no action is performed. + * + * @param[in] aAddress The unicast address + * @param[in] aPreferred The new value for preferred flag. + * + */ + void UpdatePreferredFlagOn(UnicastAddress &aAddress, bool aPreferred); /** * Indicates whether or not an address is assigned to the interface. diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp index 617091ca1..cbc24c4ff 100644 --- a/src/core/net/srp_client.cpp +++ b/src/core/net/srp_client.cpp @@ -244,13 +244,13 @@ Client::Client(Instance &aInstance) , mState(kStateStopped) , mTxFailureRetryCount(0) , mShouldRemoveKeyLease(false) - , mAutoHostAddressAddedMeshLocal(false) , mSingleServiceMode(false) #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE , mServiceKeyRecordEnabled(false) , mUseShortLeaseOption(false) #endif , mUpdateMessageId(0) + , mAutoHostAddressCount(0) , mRetryWaitInterval(kMinRetryWaitInterval) , mTtl(0) , mLease(0) @@ -421,20 +421,11 @@ void Client::HandleNotifierEvents(Events aEvents) } #endif - if (mHostInfo.IsAutoAddressEnabled()) + if (aEvents.ContainsAny(kEventIp6AddressAdded | kEventIp6AddressRemoved | kEventThreadMeshLocalAddrChanged) && + ShouldUpdateHostAutoAddresses()) { - Events::Flags eventFlags = (kEventIp6AddressAdded | kEventIp6AddressRemoved); - - if (mAutoHostAddressAddedMeshLocal) - { - eventFlags |= kEventThreadMeshLocalAddrChanged; - } - - if (aEvents.ContainsAny(eventFlags)) - { - IgnoreError(UpdateHostInfoStateOnAddressChange()); - UpdateState(); - } + IgnoreError(UpdateHostInfoStateOnAddressChange()); + UpdateState(); } } @@ -494,6 +485,13 @@ Error Client::EnableAutoHostAddress(void) VerifyOrExit(!mHostInfo.IsAutoAddressEnabled()); SuccessOrExit(error = UpdateHostInfoStateOnAddressChange()); + for (Ip6::Netif::UnicastAddress &unicastAddress : Get().GetUnicastAddresses()) + { + unicastAddress.mSrpRegistered = false; + } + + mAutoHostAddressCount = 0; + mHostInfo.EnableAutoAddress(); UpdateState(); @@ -515,6 +513,68 @@ exit: return error; } +bool Client::ShouldUpdateHostAutoAddresses(void) const +{ + bool shouldUpdate = false; + uint16_t registeredCount = 0; + Ip6::Netif::UnicastAddress &ml64 = Get().GetMeshLocal64UnicastAddress(); + + VerifyOrExit(mHostInfo.IsAutoAddressEnabled()); + + // Check all addresses on `ThreadNetif` excluding the mesh local + // EID (`ml64`). If any address should be registered but is not, + // or if any address was registered earlier but no longer should + // be, the host information needs to be re-registered to update + // the addresses. If there is no eligible address, then `ml64` + // should be registered, so its status is checked. Finally, the + // number of addresses that should be registered is verified + // against the previous value `mAutoHostAddressCount` to handle + // the case where an earlier registered address is now removed. + + for (const Ip6::Netif::UnicastAddress &unicastAddress : Get().GetUnicastAddresses()) + { + if (&unicastAddress == &ml64) + { + continue; + } + + if (ShouldHostAutoAddressRegister(unicastAddress) != unicastAddress.mSrpRegistered) + { + ExitNow(shouldUpdate = true); + } + + if (unicastAddress.mSrpRegistered) + { + registeredCount++; + } + } + + if (registeredCount == 0) + { + ExitNow(shouldUpdate = !ml64.mSrpRegistered); + } + + shouldUpdate = (registeredCount != mAutoHostAddressCount); + +exit: + return shouldUpdate; +} + +bool Client::ShouldHostAutoAddressRegister(const Ip6::Netif::UnicastAddress &aUnicastAddress) const +{ + bool shouldRegister = false; + + VerifyOrExit(aUnicastAddress.mValid); + VerifyOrExit(aUnicastAddress.mPreferred); + VerifyOrExit(!aUnicastAddress.GetAddress().IsLinkLocal()); + VerifyOrExit(!Get().IsMeshLocalAddress(aUnicastAddress.GetAddress())); + + shouldRegister = true; + +exit: + return shouldRegister; +} + Error Client::UpdateHostInfoStateOnAddressChange(void) { Error error = kErrorNone; @@ -1244,25 +1304,29 @@ Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) // and mesh-local addresses. If no address is appended, we include // the mesh local EID. - mAutoHostAddressAddedMeshLocal = true; + mAutoHostAddressCount = 0; - for (const Ip6::Netif::UnicastAddress &unicastAddress : Get().GetUnicastAddresses()) + for (Ip6::Netif::UnicastAddress &unicastAddress : Get().GetUnicastAddresses()) { - const Ip6::Address &address = unicastAddress.GetAddress(); - - if (address.IsLinkLocal() || Get().IsMeshLocalAddress(address) || !unicastAddress.mPreferred || - !unicastAddress.mValid) + if (ShouldHostAutoAddressRegister(unicastAddress)) { - continue; + SuccessOrExit(error = AppendAaaaRecord(unicastAddress.GetAddress(), aMessage, aInfo)); + unicastAddress.mSrpRegistered = true; + mAutoHostAddressCount++; + } + else + { + unicastAddress.mSrpRegistered = false; } - - SuccessOrExit(error = AppendAaaaRecord(address, aMessage, aInfo)); - mAutoHostAddressAddedMeshLocal = false; } - if (mAutoHostAddressAddedMeshLocal) + if (mAutoHostAddressCount == 0) { - SuccessOrExit(error = AppendAaaaRecord(Get().GetMeshLocal64(), aMessage, aInfo)); + Ip6::Netif::UnicastAddress &ml64 = Get().GetMeshLocal64UnicastAddress(); + + SuccessOrExit(error = AppendAaaaRecord(ml64.GetAddress(), aMessage, aInfo)); + ml64.mSrpRegistered = true; + mAutoHostAddressCount++; } } else diff --git a/src/core/net/srp_client.hpp b/src/core/net/srp_client.hpp index 5260ea6ac..32b1ea0de 100644 --- a/src/core/net/srp_client.hpp +++ b/src/core/net/srp_client.hpp @@ -1001,6 +1001,8 @@ private: void Pause(void); void HandleNotifierEvents(Events aEvents); void HandleRoleChanged(void); + bool ShouldUpdateHostAutoAddresses(void) const; + bool ShouldHostAutoAddressRegister(const Ip6::Netif::UnicastAddress &aUnicastAddress) const; Error UpdateHostInfoStateOnAddressChange(void); void UpdateServiceStateToRemove(Service &aService); State GetState(void) const { return mState; } @@ -1065,7 +1067,6 @@ private: State mState; uint8_t mTxFailureRetryCount : 4; bool mShouldRemoveKeyLease : 1; - bool mAutoHostAddressAddedMeshLocal : 1; bool mSingleServiceMode : 1; #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE bool mServiceKeyRecordEnabled : 1; @@ -1073,6 +1074,7 @@ private: #endif uint16_t mUpdateMessageId; + uint16_t mAutoHostAddressCount; uint32_t mRetryWaitInterval; TimeMilli mLeaseRenewTime; diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index a779a1158..28f6483cd 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -785,7 +785,7 @@ void AddressResolver::HandleTmf(Coap::Message &aMessage, const SuccessOrExit(error = Tlv::Find(aMessage, target)); SuccessOrExit(error = Tlv::Find(aMessage, meshLocalIid)); - for (const Ip6::Netif::UnicastAddress &address : Get().GetUnicastAddresses()) + for (Ip6::Netif::UnicastAddress &address : Get().GetUnicastAddresses()) { if (address.GetAddress() == target && Get().GetMeshLocal64().GetIid() != meshLocalIid) { diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 8f3e9eaa0..33d0920cf 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -530,6 +530,14 @@ public: */ const Ip6::Address &GetMeshLocal64(void) const { return mMeshLocal64.GetAddress(); } + /** + * Returns a reference to the ML-EID as a `Netif::UnicastAddress`. + * + * @returns A reference to the ML-EID. + * + */ + Ip6::Netif::UnicastAddress &GetMeshLocal64UnicastAddress(void) { return mMeshLocal64; } + /** * Returns the Router ID of the Leader. *