[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:
Abtin Keshavarzian
2022-01-18 17:40:46 -08:00
committed by GitHub
parent 88973676c5
commit 30ec50c5d2
4 changed files with 95 additions and 113 deletions
+74 -49
View File
@@ -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
View File
@@ -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;
-30
View File
@@ -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;
-26
View File
@@ -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.