diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 384a618ba..6f8f72c5f 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -128,14 +128,6 @@ Mle::Mle(Instance &aInstance) mLeaderAloc.InitAsThreadOriginRealmLocalScope(); -#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - for (Ip6::Netif::UnicastAddress &serviceAloc : mServiceAlocs) - { - serviceAloc.InitAsThreadOriginRealmLocalScope(); - serviceAloc.GetAddress().GetIid().SetLocator(Mac::kShortAddrInvalid); - } -#endif - meshLocalPrefix.SetFromExtendedPanId(Get().GetExtendedPanId()); mMeshLocal64.InitAsThreadOriginRealmLocalScope(); @@ -890,17 +882,20 @@ void Mle::ApplyMeshLocalPrefix(void) #endif #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - - for (Ip6::Netif::UnicastAddress &serviceAloc : mServiceAlocs) + for (ServiceAloc &serviceAloc : mServiceAlocs) { - if (serviceAloc.GetAddress().GetIid().GetLocator() != Mac::kShortAddrInvalid) + if (serviceAloc.IsInUse()) { Get().RemoveUnicastAddress(serviceAloc); - serviceAloc.GetAddress().SetPrefix(GetMeshLocalPrefix()); + } + + serviceAloc.ApplyMeshLocalPrefix(GetMeshLocalPrefix()); + + if (serviceAloc.IsInUse()) + { Get().AddUnicastAddress(serviceAloc); } } - #endif #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE @@ -1621,64 +1616,94 @@ exit: } #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE -void Mle::UpdateServiceAlocs(void) + +Mle::ServiceAloc::ServiceAloc(void) { - uint16_t rloc = GetRloc16(); - uint16_t serviceAloc = 0; - uint8_t serviceId = 0; - NetworkData::Iterator serviceIterator = NetworkData::kIteratorInit; - size_t serviceAlocsLength = OT_ARRAY_LENGTH(mServiceAlocs); - size_t i = 0; + InitAsThreadOriginRealmLocalScope(); + GetAddress().GetIid().SetToLocator(kNotInUse); +} - VerifyOrExit(!IsDisabled()); +Mle::ServiceAloc *Mle::FindInServiceAlocs(uint16_t aAloc16) +{ + // Search in `mServiceAlocs` for an entry matching `aAloc16`. + // Can be used with `aAloc16 = ServerAloc::kNotInUse` to find + // an unused entry in the array. - // First remove all alocs which are no longer necessary, to free up space in mServiceAlocs - for (i = 0; i < serviceAlocsLength; i++) + ServiceAloc *match = nullptr; + + for (ServiceAloc &serviceAloc : mServiceAlocs) { - serviceAloc = mServiceAlocs[i].GetAddress().GetIid().GetLocator(); - - if ((serviceAloc != Mac::kShortAddrInvalid) && - (!Get().ContainsService(Mle::ServiceIdFromAloc(serviceAloc), rloc))) + if (serviceAloc.GetAloc16() == aAloc16) { - Get().RemoveUnicastAddress(mServiceAlocs[i]); - mServiceAlocs[i].GetAddress().GetIid().SetLocator(Mac::kShortAddrInvalid); + match = &serviceAloc; + break; } } - // Now add any missing service alocs which should be there, if there is enough space in mServiceAlocs - while (Get().GetNextServiceId(serviceIterator, rloc, serviceId) == kErrorNone) - { - for (i = 0; i < serviceAlocsLength; i++) - { - serviceAloc = mServiceAlocs[i].GetAddress().GetIid().GetLocator(); + return match; +} - if ((serviceAloc != Mac::kShortAddrInvalid) && (Mle::ServiceIdFromAloc(serviceAloc) == serviceId)) +void Mle::UpdateServiceAlocs(void) +{ + NetworkData::Iterator iterator; + NetworkData::ServiceConfig service; + + VerifyOrExit(!IsDisabled()); + + // First remove all ALOCs which are no longer in the Network + // Data to free up space in `mServiceAlocs` array. + + for (ServiceAloc &serviceAloc : mServiceAlocs) + { + bool found = false; + + if (!serviceAloc.IsInUse()) + { + continue; + } + + iterator = NetworkData::kIteratorInit; + + while (Get().GetNextService(iterator, GetRloc16(), service) == kErrorNone) + { + if (service.mServiceId == ServiceIdFromAloc(serviceAloc.GetAloc16())) { + found = true; break; } } - if (i >= serviceAlocsLength) + if (!found) { - // Service Aloc is not there, but it should be. Lets add it into first empty space - for (i = 0; i < serviceAlocsLength; i++) - { - serviceAloc = mServiceAlocs[i].GetAddress().GetIid().GetLocator(); + Get().RemoveUnicastAddress(serviceAloc); + serviceAloc.MarkAsNotInUse(); + } + } - if (serviceAloc == Mac::kShortAddrInvalid) - { - SuccessOrExit(GetServiceAloc(serviceId, mServiceAlocs[i].GetAddress())); - Get().AddUnicastAddress(mServiceAlocs[i]); - break; - } - } + // Now add any new ALOCs if there is space in `mServiceAlocs`. + + iterator = NetworkData::kIteratorInit; + + while (Get().GetNextService(iterator, GetRloc16(), service) == kErrorNone) + { + uint16_t aloc16 = ServiceAlocFromId(service.mServiceId); + + if (FindInServiceAlocs(aloc16) == nullptr) + { + // No matching ALOC in `mServiceAlocs`, so we try to add it. + ServiceAloc *newServiceAloc = FindInServiceAlocs(ServiceAloc::kNotInUse); + + VerifyOrExit(newServiceAloc != nullptr); + newServiceAloc->SetAloc16(aloc16); + Get().AddUnicastAddress(*newServiceAloc); } } exit: return; } -#endif + +#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE void Mle::HandleAttachTimer(Timer &aTimer) { diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 96004eddb..796fb554c 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -585,7 +585,7 @@ public: /** * This method returns the Service ID corresponding to a Service ALOC16. * - * @param[in] aAloc16 The Servicer ALOC16 value. + * @param[in] aAloc16 The Service ALOC16 value. * * @returns The Service ID corresponding to given ALOC16. * @@ -593,7 +593,7 @@ public: static uint8_t ServiceIdFromAloc(uint16_t aAloc16) { return static_cast(aAloc16 - kAloc16ServiceStart); } /** - * This method returns the Service Aloc corresponding to a Service ID. + * This method returns the Service ALOC16 corresponding to a Service ID. * * @param[in] aServiceId The Service ID value. * @@ -1763,6 +1763,22 @@ private: uint8_t mCommand; } OT_TOOL_PACKED_END; +#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + class ServiceAloc : public Ip6::Netif::UnicastAddress + { + public: + static constexpr uint16_t kNotInUse = Mac::kShortAddrInvalid; + + ServiceAloc(void); + + bool IsInUse(void) const { return GetAloc16() != kNotInUse; } + void MarkAsNotInUse(void) { SetAloc16(kNotInUse); } + uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); } + void SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); } + void ApplyMeshLocalPrefix(const MeshLocalPrefix &aPrefix) { GetAddress().SetPrefix(aPrefix); } + }; +#endif + Error Start(StartMode aMode); void Stop(StopMode aMode); void HandleNotifierEvents(Events aEvents); @@ -1829,11 +1845,8 @@ private: bool IsNetworkDataNewer(const LeaderData &aLeaderData); #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - /** - * This method scans for network data from the leader and updates IP addresses assigned to this - * interface to make sure that all Service ALOCs (0xfc10-0xfc1f) are properly set. - */ - void UpdateServiceAlocs(void); + ServiceAloc *FindInServiceAlocs(uint16_t aAloc16); + void UpdateServiceAlocs(void); #endif #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH @@ -1903,7 +1916,7 @@ private: uint64_t mAlternateTimestamp; #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - Ip6::Netif::UnicastAddress mServiceAlocs[kMaxServiceAlocs]; + ServiceAloc mServiceAlocs[kMaxServiceAlocs]; #endif otMleCounters mCounters; diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index 1da6ce54a..700c45575 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -272,18 +272,6 @@ exit: return error; } -Error NetworkData::GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const -{ - Error error; - ServiceConfig config; - - SuccessOrExit(error = GetNextService(aIterator, aRloc16, config)); - aServiceId = config.mServiceId; - -exit: - return error; -} - bool NetworkData::ContainsOnMeshPrefix(const OnMeshPrefixConfig &aPrefix) const { bool contains = false; @@ -338,24 +326,6 @@ bool NetworkData::ContainsService(const ServiceConfig &aService) const return contains; } -bool NetworkData::ContainsService(uint8_t aServiceId, uint16_t aRloc16) const -{ - bool contains = false; - Iterator iterator = kIteratorInit; - uint8_t serviceId; - - while (GetNextServiceId(iterator, aRloc16, serviceId) == kErrorNone) - { - if (serviceId == aServiceId) - { - contains = true; - break; - } - } - - return contains; -} - bool NetworkData::ContainsEntriesFrom(const NetworkData &aComapre, uint16_t aRloc16) const { bool contains = true; diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index 9db8a6eab..dc6649251 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -266,19 +266,6 @@ public: */ Error GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const; - /** - * This method provides the next Service ID in the Thread Network Data for a given RLOC16. - * - * @param[inout] aIterator A reference to the Network Data iterator. - * @param[in] aRloc16 The RLOC16 value. - * @param[out] aServiceId A reference to variable where the Service ID will be placed. - * - * @retval kErrorNone Successfully found the next service. - * @retval kErrorNotFound No subsequent service exists in the Thread Network Data. - * - */ - Error GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const; - /** * This method indicates whether or not the Thread Network Data contains a given on mesh prefix entry. * @@ -312,19 +299,6 @@ public: */ bool ContainsService(const ServiceConfig &aService) const; - /** - * This method indicates whether or not the Thread Network Data contains the service with a given Service ID - * associated with @p aRloc16. - * - * @param[in] aServiceId The Service ID to search for. - * @param[in] aRloc16 The RLOC16 to consider. - * - * @retval TRUE if Network Data contains a service matching @p aServiceId for @p aRloc16. - * @retval FALSE if Network Data does not contain a service matching @p aServiceId for @p aRloc16. - * - */ - bool ContainsService(uint8_t aServiceId, uint16_t aRloc16) const; - /** * This method indicates whether or not the Thread Network Data contains all the on mesh prefixes, external * routes, and service entries as in another given Network Data associated with a given RLOC16.