[mle] add Aloc16 helper class (#11818)

This commit introduces the `Mle::Aloc16` helper class to encapsulate
constants and helper methods related to Anycast Locators (ALOC16).

The new class provides static helpers for:
- Checking if a given ALOC16 has a specific purpose (e.g., Service,
  DHCPv6 Agent, Commissioner, Primary BBR).
- Converting between an ALOC16 and its related service, context, or
  session ID.

All existing code is updated to use the new helper methods. This
improves code readability and centralizes ALOC16 management.
This commit is contained in:
Abtin Keshavarzian
2025-08-18 11:00:11 -07:00
committed by GitHub
parent 12e0a7daa1
commit ca72e8d64a
8 changed files with 193 additions and 69 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ Local::Local(Instance &aInstance)
// Primary Backbone Router Aloc
mBbrPrimaryAloc.InitAsThreadOriginMeshLocal();
mBbrPrimaryAloc.GetAddress().GetIid().SetToLocator(Mle::kAloc16BackboneRouterPrimary);
mBbrPrimaryAloc.GetAddress().GetIid().SetToLocator(Mle::Aloc16::ForPrimaryBackboneRouter());
// All Network Backbone Routers Multicast Address.
mAllNetworkBackboneRouters.Clear();
+1 -1
View File
@@ -285,7 +285,7 @@ bool InterfaceIdentifier::IsAnycastServiceLocator(void) const
{
uint16_t locator = GetLocator();
return (IsLocator() && (locator >= Mle::kAloc16ServiceStart) && (locator <= Mle::kAloc16ServiceEnd));
return (IsLocator() && Mle::Aloc16::IsForService(locator));
}
void InterfaceIdentifier::ApplyPrefix(const Prefix &aPrefix)
+2 -3
View File
@@ -58,8 +58,7 @@ void Agent::UpdateService(void)
if (IsAlocInUse())
{
uint8_t contextId = static_cast<uint8_t>(mAloc.GetAddress().GetIid().GetLocator() -
Mle::kAloc16NeighborDiscoveryAgentStart + 1);
uint8_t contextId = Mle::Aloc16::ToNdAgentContextId(mAloc.GetAddress().GetIid().GetLocator());
bool found = false;
iterator = NetworkData::kIteratorInit;
@@ -104,7 +103,7 @@ void Agent::UpdateService(void)
if (error == kErrorNone)
{
uint16_t aloc16 = Mle::kAloc16NeighborDiscoveryAgentStart + lowpanContext.mContextId - 1;
uint16_t aloc16 = Mle::Aloc16::FromNdAgentContextId(lowpanContext.mContextId);
mAloc.InitAsThreadOrigin();
mAloc.GetAddress().SetToAnycastLocator(Get<Mle::Mle>().GetMeshLocalPrefix(), aloc16);
+6 -3
View File
@@ -1031,16 +1031,19 @@ void Mle::GetLeaderRloc(Ip6::Address &aAddress) const
aAddress.SetToRoutingLocator(mMeshLocalPrefix, GetLeaderRloc16());
}
void Mle::GetLeaderAloc(Ip6::Address &aAddress) const { aAddress.SetToAnycastLocator(mMeshLocalPrefix, kAloc16Leader); }
void Mle::GetLeaderAloc(Ip6::Address &aAddress) const
{
aAddress.SetToAnycastLocator(mMeshLocalPrefix, Aloc16::ForLeader());
}
void Mle::GetCommissionerAloc(uint16_t aSessionId, Ip6::Address &aAddress) const
{
aAddress.SetToAnycastLocator(mMeshLocalPrefix, CommissionerAloc16FromId(aSessionId));
aAddress.SetToAnycastLocator(mMeshLocalPrefix, Aloc16::FromCommissionerSessionId(aSessionId));
}
void Mle::GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const
{
aAddress.SetToAnycastLocator(mMeshLocalPrefix, ServiceAlocFromId(aServiceId));
aAddress.SetToAnycastLocator(mMeshLocalPrefix, Aloc16::FromServiceId(aServiceId));
}
const LeaderData &Mle::GetLeaderData(void)
+170 -48
View File
@@ -50,6 +50,7 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "common/num_utils.hpp"
#include "common/numeric_limits.hpp"
#include "common/offset_range.hpp"
#include "common/string.hpp"
@@ -168,20 +169,6 @@ enum RouterUpgradeReason : uint8_t
kReasonBorderRouterRequest = 5, ///< Device is Border Router.
};
constexpr uint16_t kAloc16Leader = 0xfc00;
constexpr uint16_t kAloc16DhcpAgentStart = 0xfc01;
constexpr uint16_t kAloc16DhcpAgentEnd = 0xfc0f;
constexpr uint16_t kAloc16ServiceStart = 0xfc10;
constexpr uint16_t kAloc16ServiceEnd = 0xfc1f;
constexpr uint16_t kAloc16ReservedStart = 0xfc20;
constexpr uint16_t kAloc16ReservedEnd = 0xfc2f;
constexpr uint16_t kAloc16CommissionerStart = 0xfc30;
constexpr uint16_t kAloc16CommissionerEnd = 0xfc37;
constexpr uint16_t kAloc16BackboneRouterPrimary = 0xfc38;
constexpr uint16_t kAloc16CommissionerMask = 0x0007;
constexpr uint16_t kAloc16NeighborDiscoveryAgentStart = 0xfc40;
constexpr uint16_t kAloc16NeighborDiscoveryAgentEnd = 0xfc4e;
/**
* Specifies the leader role start mode.
*
@@ -193,6 +180,174 @@ enum LeaderStartMode : uint8_t
kRestoringLeaderRoleAfterReset, ///< Restoring leader role after reset.
};
/**
* Provides ALOC16 helper methods.
*/
class Aloc16
{
public:
/**
* Indicates whether or not a given ALOC16 is the leader ALOC16.
*
* @param[in] aAloc16 The ALOC16 to check.
*
* @retval TRUE The @p aAloc16 is the leader ALOC16.
* @retval FALSE The @p aAloc16 is not the leader ALOC16.
*/
static bool IsForLeader(uint16_t aAloc16) { return aAloc16 == kLeader; }
/**
* Returns the leader ALOC16.
*
* @returns The leader ALOC16.
*/
static uint16_t ForLeader(void) { return kLeader; }
/**
* Indicates whether or not a given ALOC16 is for a DHCP agent.
*
* @param[in] aAloc16 The ALOC16 to check.
*
* @retval TRUE The @p aAloc16 is for a DHCP agent.
* @retval FALSE The @p aAloc16 is not for a DHCP agent.
*/
static bool IsForDhcp6Agent(uint16_t aAloc16) { return IsValueInRange(aAloc16, kDhcpAgentStart, kDhcpAgentEnd); }
/**
* Determines the Context ID associated with a DHCP agent ALOC16
*
* @param[in] aAloc16 The DHCP agent ALOC16.
*
* @returns The Context ID corresponding to @p aAloc16.
*/
static uint8_t ToDhcpAgentContextId(uint16_t aAloc16)
{
return static_cast<uint8_t>(aAloc16 - kDhcpAgentStart + 1);
}
/**
* Determines the DHCP agent ALOC16 for a given Context ID.
*
* @param[in] aContextId The Context ID.
*
* @returns The DHCP agent ALOC16 corresponding @p aContextId.
*/
static uint16_t FromDhcpAgentContextId(uint8_t aContextId) { return (kDhcpAgentStart + aContextId - 1); }
/**
* Indicates whether or not a given ALOC16 is for a Network Data service.
*
* @param[in] aAloc16 The ALOC16 to check.
*
* @retval TRUE The @p aAloc16 is for a Network Data service.
* @retval FALSE The @p aAloc16 is not for a Network Data service.
*/
static bool IsForService(uint16_t aAloc16) { return IsValueInRange(aAloc16, kServiceStart, kServiceEnd); }
/**
* Determines the Service ID associated with a Service ALOC16.
*
* @param[in] aAloc16 The Service ALOC16.
*
* @returns The Service ID corresponding to @p aAloc16.
*/
static uint8_t ToServiceId(uint16_t aAloc16) { return static_cast<uint8_t>(aAloc16 - kServiceStart); }
/**
* Determines the Service ALOC16 for a given Service ID.
*
* @param[in] aServiceId The Service ID.
*
* @returns The Service ALOC16 corresponding @p aServiceId.
*/
static uint16_t FromServiceId(uint8_t aServiceId) { return static_cast<uint16_t>(kServiceStart + aServiceId); }
/**
* Indicates whether or not a given ALOC16 is for a Commissioner.
*
* @param[in] aAloc16 The ALOC16 to check.
*
* @retval TRUE The @p aAloc16 is for a Commissioner.
* @retval FALSE The @p aAloc16 is not for a Commissioner.
*/
static bool IsForCommissioner(uint16_t aAloc16)
{
return IsValueInRange(aAloc16, kCommissionerStart, kCommissionerEnd);
}
/**
* Determines the Commissioner ALOC16 corresponding to a given Commissioner Session ID.
*
* @param[in] aSessionId The Commissioner Session ID.
*
* @returns The Commissioner ALOC16 corresponding to @p aSessionId.
*/
static uint16_t FromCommissionerSessionId(uint16_t aSessionId)
{
return static_cast<uint16_t>((aSessionId & kCommissionerMask) + kCommissionerStart);
}
/**
* Indicates whether or not a given ALOC16 is for the primary backbone router.
*
* @param[in] aAloc16 The ALOC16 to check.
*
* @retval TRUE The @p aAloc16 is for the primary backbone router.
* @retval FALSE The @p aAloc16 is not for the primary backbone router.
*/
static bool IsForPrimaryBackboneRouter(uint16_t aAloc16) { return aAloc16 == kPrimaryBackboneRouter; }
/**
* Returns the primary backbone router ALOC16.
*
* @returns The primary backbone router ALOC16.
*/
static uint16_t ForPrimaryBackboneRouter(void) { return kPrimaryBackboneRouter; }
/**
* Indicates whether or not a given ALOC16 is for a Neighbor Discovery agent.
*
* @param[in] aAloc16 The ALOC16 to check.
*
* @retval TRUE The @p aAloc16 is for a Neighbor Discovery agent.
* @retval FALSE The @p aAloc16 is not for a Neighbor Discovery agent.
*/
static bool IsForNdAgent(uint16_t aAloc16) { return IsValueInRange(aAloc16, kNdAgentStart, kNdAgentEnd); }
/**
* Determines the Context ID associated with a Neighbor Discovery agent ALOC16
*
* @param[in] aAloc16 The Neighbor Discovery agent ALOC16.
*
* @returns The Context ID corresponding to @p aAloc16.
*/
static uint8_t ToNdAgentContextId(uint16_t aAloc16) { return static_cast<uint8_t>(aAloc16 - kNdAgentStart + 1); }
/**
* Determines the Neighbor Discovery agent ALOC16 for a given Context ID.
*
* @param[in] aContextId The Context ID.
*
* @returns The Neighbor Discovery agent ALOC16 corresponding @p aContextId.
*/
static uint16_t FromNdAgentContextId(uint8_t aContextId) { return kNdAgentStart + aContextId - 1; }
private:
// The range [0xfc20, 0xfc2f] is reserved for future use.
static constexpr uint16_t kLeader = 0xfc00;
static constexpr uint16_t kDhcpAgentStart = 0xfc01;
static constexpr uint16_t kDhcpAgentEnd = 0xfc0f;
static constexpr uint16_t kServiceStart = 0xfc10;
static constexpr uint16_t kServiceEnd = 0xfc1f;
static constexpr uint16_t kCommissionerStart = 0xfc30;
static constexpr uint16_t kCommissionerEnd = 0xfc37;
static constexpr uint16_t kPrimaryBackboneRouter = 0xfc38;
static constexpr uint16_t kNdAgentStart = 0xfc40;
static constexpr uint16_t kNdAgentEnd = 0xfc4e;
static constexpr uint16_t kCommissionerMask = 0x0007;
};
/**
* Represents a MLE device mode.
*/
@@ -491,7 +646,7 @@ public:
private:
static uint8_t MaskFor(uint8_t aRouterId) { return (0x80 >> (aRouterId % 8)); }
uint8_t mRouterIdSet[BytesForBitSize(Mle::kMaxRouterId + 1)];
uint8_t mRouterIdSet[BytesForBitSize(kMaxRouterId + 1)];
} OT_TOOL_PACKED_END;
class TxChallenge;
@@ -634,39 +789,6 @@ inline bool RouterIdMatch(uint16_t aRloc16A, uint16_t aRloc16B)
return RouterIdFromRloc16(aRloc16A) == RouterIdFromRloc16(aRloc16B);
}
/**
* Returns the Service ID corresponding to a Service ALOC16.
*
* @param[in] aAloc16 The Service ALOC16 value.
*
* @returns The Service ID corresponding to given ALOC16.
*/
inline uint8_t ServiceIdFromAloc(uint16_t aAloc16) { return static_cast<uint8_t>(aAloc16 - kAloc16ServiceStart); }
/**
* Returns the Service ALOC16 corresponding to a Service ID.
*
* @param[in] aServiceId The Service ID value.
*
* @returns The Service ALOC16 corresponding to given ID.
*/
inline uint16_t ServiceAlocFromId(uint8_t aServiceId)
{
return static_cast<uint16_t>(aServiceId + kAloc16ServiceStart);
}
/**
* Returns the Commissioner Aloc corresponding to a Commissioner Session ID.
*
* @param[in] aSessionId The Commissioner Session ID value.
*
* @returns The Commissioner ALOC16 corresponding to given ID.
*/
inline uint16_t CommissionerAloc16FromId(uint16_t aSessionId)
{
return static_cast<uint16_t>((aSessionId & kAloc16CommissionerMask) + kAloc16CommissionerStart);
}
/**
* Derives RLOC16 from a given Router ID.
*
+2 -2
View File
@@ -586,7 +586,7 @@ bool MutableNetworkData::RemoveTemporaryDataIn(PrefixTlv &aPrefix)
{
if ((entry->IsDhcp() || entry->IsConfigure()) && (context != nullptr))
{
entry->SetRloc(Mle::kAloc16DhcpAgentStart + context->GetContextId() - 1);
entry->SetRloc(Mle::Aloc16::FromDhcpAgentContextId(context->GetContextId()));
}
else
{
@@ -639,7 +639,7 @@ bool MutableNetworkData::RemoveTemporaryDataIn(ServiceTlv &aService)
switch (cur->GetType())
{
case NetworkDataTlv::kTypeServer:
As<ServerTlv>(cur)->SetServer16(Mle::ServiceAlocFromId(aService.GetServiceId()));
As<ServerTlv>(cur)->SetServer16(Mle::Aloc16::FromServiceId(aService.GetServiceId()));
break;
default:
+9 -9
View File
@@ -105,34 +105,34 @@ Error Leader::AnycastLookup(uint16_t aAloc16, uint16_t &aRloc16) const
aRloc16 = Mle::kInvalidRloc16;
if (aAloc16 == Mle::kAloc16Leader)
if (Mle::Aloc16::IsForLeader(aAloc16))
{
aRloc16 = Get<Mle::Mle>().GetLeaderRloc16();
}
else if (IsValueInRange(aAloc16, Mle::kAloc16DhcpAgentStart, Mle::kAloc16DhcpAgentEnd))
else if (Mle::Aloc16::IsForDhcp6Agent(aAloc16))
{
uint8_t contextId = static_cast<uint8_t>(aAloc16 - Mle::kAloc16DhcpAgentStart + 1);
uint8_t contextId = Mle::Aloc16::ToDhcpAgentContextId(aAloc16);
error = LookupRouteForAgentAloc(contextId, IsEntryForDhcp6Agent, aRloc16);
}
else if (IsValueInRange(aAloc16, Mle::kAloc16ServiceStart, Mle::kAloc16ServiceEnd))
else if (Mle::Aloc16::IsForService(aAloc16))
{
error = LookupRouteForServiceAloc(aAloc16, aRloc16);
}
else if (IsValueInRange(aAloc16, Mle::kAloc16CommissionerStart, Mle::kAloc16CommissionerEnd))
else if (Mle::Aloc16::IsForCommissioner(aAloc16))
{
error = FindBorderAgentRloc(aRloc16);
}
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
else if (aAloc16 == Mle::kAloc16BackboneRouterPrimary)
else if (Mle::Aloc16::IsForPrimaryBackboneRouter(aAloc16))
{
VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = kErrorDrop);
aRloc16 = Get<BackboneRouter::Leader>().GetServer16();
}
#endif
else if (IsValueInRange(aAloc16, Mle::kAloc16NeighborDiscoveryAgentStart, Mle::kAloc16NeighborDiscoveryAgentEnd))
else if (Mle::Aloc16::IsForNdAgent(aAloc16))
{
uint8_t contextId = static_cast<uint8_t>(aAloc16 - Mle::kAloc16NeighborDiscoveryAgentStart + 1);
uint8_t contextId = Mle::Aloc16::ToNdAgentContextId(aAloc16);
error = LookupRouteForAgentAloc(contextId, IsEntryForNdAgent, aRloc16);
}
@@ -165,7 +165,7 @@ exit:
Error Leader::LookupRouteForServiceAloc(uint16_t aAloc16, uint16_t &aRloc16) const
{
Error error = kErrorNoRoute;
const ServiceTlv *serviceTlv = FindServiceById(Mle::ServiceIdFromAloc(aAloc16));
const ServiceTlv *serviceTlv = FindServiceById(Mle::Aloc16::ToServiceId(aAloc16));
if (serviceTlv != nullptr)
{
+2 -2
View File
@@ -268,7 +268,7 @@ void Manager::HandleNotifierEvents(Events aEvents)
while (Get<Leader>().GetNext(iterator, deviceRloc16, service) == kErrorNone)
{
if (service.mServiceId == Mle::ServiceIdFromAloc(serviceAloc.GetAloc16()))
if (service.mServiceId == Mle::Aloc16::ToServiceId(serviceAloc.GetAloc16()))
{
found = true;
break;
@@ -288,7 +288,7 @@ void Manager::HandleNotifierEvents(Events aEvents)
while (Get<Leader>().GetNext(iterator, deviceRloc16, service) == kErrorNone)
{
uint16_t aloc16 = Mle::ServiceAlocFromId(service.mServiceId);
uint16_t aloc16 = Mle::Aloc16::FromServiceId(service.mServiceId);
if (FindInServiceAlocs(aloc16) == nullptr)
{