mirror of
https://github.com/espressif/openthread.git
synced 2026-08-01 00:27:47 +00:00
[mle] simplify management of service ALOCs (#7326)
This commit updates the handling of service ALOCs in `Mle` by adding a new class `ServiceAloc` (subclass of `Ip6::Netif::UnicastAddress`) which provides some simple helper methods (e.g., `IsInUse()` to indicate whether the entry is currently added to `ThreadNetif`). It also simplifies `UpdateServiceAlocs()` which adds and removes ALOCs based on the service entries in the Thread Network Data. These changes allow us to remove some service related methods from `NetworkData` which are no longer needed or used (harmonizing how we iterate over service entries in Network Data).
This commit is contained in:
+74
-49
@@ -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<Mac::Mac>().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<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
|
||||
serviceAloc.GetAddress().SetPrefix(GetMeshLocalPrefix());
|
||||
}
|
||||
|
||||
serviceAloc.ApplyMeshLocalPrefix(GetMeshLocalPrefix());
|
||||
|
||||
if (serviceAloc.IsInUse())
|
||||
{
|
||||
Get<ThreadNetif>().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<NetworkData::Leader>().ContainsService(Mle::ServiceIdFromAloc(serviceAloc), rloc)))
|
||||
if (serviceAloc.GetAloc16() == aAloc16)
|
||||
{
|
||||
Get<ThreadNetif>().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<NetworkData::Leader>().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<NetworkData::Leader>().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<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
|
||||
serviceAloc.MarkAsNotInUse();
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceAloc == Mac::kShortAddrInvalid)
|
||||
{
|
||||
SuccessOrExit(GetServiceAloc(serviceId, mServiceAlocs[i].GetAddress()));
|
||||
Get<ThreadNetif>().AddUnicastAddress(mServiceAlocs[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Now add any new ALOCs if there is space in `mServiceAlocs`.
|
||||
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().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<ThreadNetif>().AddUnicastAddress(*newServiceAloc);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
void Mle::HandleAttachTimer(Timer &aTimer)
|
||||
{
|
||||
|
||||
+21
-8
@@ -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<uint8_t>(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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user