diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 63a216985..99b622fbd 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -404,13 +404,6 @@ private: #endif }; - enum AnycastType : uint8_t - { - kAnycastDhcp6Agent, - kAnycastNeighborDiscoveryAgent, - kAnycastService, - }; - struct RxInfo : public InstanceLocator { static constexpr uint16_t kInfoStringSize = 70; @@ -557,8 +550,6 @@ private: void SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::Headers &aIp6Headers); Error UpdateIp6Route(Message &aMessage); Error UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &aMessage); - void EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const; - Error AnycastRouteLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aMeshDest) const; Error UpdateMeshRoute(Message &aMessage); bool UpdateReassemblyList(void); void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 740132b9a..6f7039640 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -408,102 +408,6 @@ exit: return error; } -void MeshForwarder::EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const -{ - uint8_t cost = Get().GetPathCost(aDest); - - if ((aBestDest == Mle::kInvalidRloc16) || (cost < aBestCost)) - { - aBestDest = aDest; - aBestCost = cost; - } -} - -Error MeshForwarder::AnycastRouteLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aMeshDest) const -{ - NetworkData::Iterator iterator = NetworkData::kIteratorInit; - uint8_t bestCost = Mle::kMaxRouteCost; - uint16_t bestDest = Mle::kInvalidRloc16; - - switch (aType) - { - case kAnycastDhcp6Agent: - case kAnycastNeighborDiscoveryAgent: - { - NetworkData::OnMeshPrefixConfig config; - Lowpan::Context context; - - SuccessOrExit(Get().GetContext(aServiceId, context)); - - while (Get().GetNextOnMeshPrefix(iterator, config) == kErrorNone) - { - if (config.GetPrefix() != context.mPrefix) - { - continue; - } - - switch (aType) - { - case kAnycastDhcp6Agent: - if (!(config.mDhcp || config.mConfigure)) - { - continue; - } - break; - case kAnycastNeighborDiscoveryAgent: - if (!config.mNdDns) - { - continue; - } - break; - default: - OT_ASSERT(false); - break; - } - - EvaluateRoutingCost(config.mRloc16, bestCost, bestDest); - } - - break; - } - case kAnycastService: - { - NetworkData::ServiceConfig config; - - while (Get().GetNextService(iterator, config) == kErrorNone) - { - if (config.mServiceId != aServiceId) - { - continue; - } - - EvaluateRoutingCost(config.mServerConfig.mRloc16, bestCost, bestDest); - } - - break; - } - } - - if (Mle::IsChildRloc16(bestDest)) - { - // If the selected destination is a child, we use its parent - // as the destination unless the device itself is the - // parent of the `bestDest`. - - uint16_t bestDestParent = Mle::ParentRloc16ForRloc16(bestDest); - - if (!Get().HasRloc16(bestDestParent)) - { - bestDest = bestDestParent; - } - } - - aMeshDest = bestDest; - -exit: - return (bestDest != Mle::kInvalidRloc16) ? kErrorNone : kErrorNoRoute; -} - Error MeshForwarder::UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &aMessage) { Mle::MleRouter &mle = Get(); @@ -524,42 +428,7 @@ Error MeshForwarder::UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &a { uint16_t aloc16 = aIp6Header.GetDestination().GetIid().GetLocator(); - if (aloc16 == Mle::kAloc16Leader) - { - mMeshDest = mle.GetLeaderRloc16(); - } - else if (aloc16 <= Mle::kAloc16DhcpAgentEnd) - { - uint8_t contextId = static_cast(aloc16 - Mle::kAloc16DhcpAgentStart + 1); - SuccessOrExit(error = AnycastRouteLookup(contextId, kAnycastDhcp6Agent, mMeshDest)); - } - else if (aloc16 <= Mle::kAloc16ServiceEnd) - { - uint8_t serviceId = static_cast(aloc16 - Mle::kAloc16ServiceStart); - SuccessOrExit(error = AnycastRouteLookup(serviceId, kAnycastService, mMeshDest)); - } - else if (aloc16 <= Mle::kAloc16CommissionerEnd) - { - SuccessOrExit(error = Get().FindBorderAgentRloc(mMeshDest)); - } - -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) - else if (aloc16 == Mle::kAloc16BackboneRouterPrimary) - { - VerifyOrExit(Get().HasPrimary(), error = kErrorDrop); - mMeshDest = Get().GetServer16(); - } -#endif - else if ((aloc16 >= Mle::kAloc16NeighborDiscoveryAgentStart) && - (aloc16 <= Mle::kAloc16NeighborDiscoveryAgentEnd)) - { - uint8_t contextId = static_cast(aloc16 - Mle::kAloc16NeighborDiscoveryAgentStart + 1); - SuccessOrExit(error = AnycastRouteLookup(contextId, kAnycastNeighborDiscoveryAgent, mMeshDest)); - } - else - { - ExitNow(error = kErrorDrop); - } + SuccessOrExit(error = Get().AnycastLookup(aloc16, mMeshDest)); // If the selected ALOC destination, `mMeshDest`, is a sleepy // child of this device, prepare the message for indirect tx diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index 0c13a2f67..f7ba0c138 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -363,6 +363,19 @@ public: */ void IncrementVersionAndStableVersion(void); + /** + * Performs anycast ALOC route lookup using the Network Data. + * + * @param[in] aAloc16 The ALOC16 destination to lookup. + * @param[out] aRloc16 A reference to return the RLOC16 for the selected route. + * + * @retval kErrorNone Successfully lookup best option for @p aAloc16. @p aRloc16 is updated. + * @retval kErrorNoRoute No valid route was found. + * @retval kErrorDrop The @p aAloc16 is not valid. + * + */ + Error AnycastLookup(uint16_t aAloc16, uint16_t &aRloc16) const; + /** * Returns CONTEXT_ID_RESUSE_DELAY value. * @@ -467,6 +480,13 @@ private: static constexpr uint8_t kMinServiceId = 0x00; static constexpr uint8_t kMaxServiceId = 0x0f; + enum AnycastType : uint8_t + { + kAnycastDhcp6Agent, + kAnycastNdAgent, + kAnycastService, + }; + class ChangedFlags { public: @@ -551,6 +571,9 @@ private: void HandleTimer(void); + Error AnycastLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aRloc16) const; + void EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const; + void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData); Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags); diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index a174ba7c7..684d907cb 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -115,6 +115,148 @@ exit: return; } +Error Leader::AnycastLookup(uint16_t aAloc16, uint16_t &aRloc16) const +{ + Error error = kErrorNone; + + if (aAloc16 == Mle::kAloc16Leader) + { + aRloc16 = Get().GetLeaderRloc16(); + } + else if (aAloc16 <= Mle::kAloc16DhcpAgentEnd) + { + uint8_t contextId = static_cast(aAloc16 - Mle::kAloc16DhcpAgentStart + 1); + + error = AnycastLookup(contextId, kAnycastDhcp6Agent, aRloc16); + } + else if (aAloc16 <= Mle::kAloc16ServiceEnd) + { + uint8_t serviceId = static_cast(aAloc16 - Mle::kAloc16ServiceStart); + + error = AnycastLookup(serviceId, kAnycastService, aRloc16); + } + else if (aAloc16 <= Mle::kAloc16CommissionerEnd) + { + error = FindBorderAgentRloc(aRloc16); + } +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + else if (aAloc16 == Mle::kAloc16BackboneRouterPrimary) + { + VerifyOrExit(Get().HasPrimary(), error = kErrorDrop); + aRloc16 = Get().GetServer16(); + } +#endif + else if ((aAloc16 >= Mle::kAloc16NeighborDiscoveryAgentStart) && (aAloc16 <= Mle::kAloc16NeighborDiscoveryAgentEnd)) + { + uint8_t contextId = static_cast(aAloc16 - Mle::kAloc16NeighborDiscoveryAgentStart + 1); + + error = AnycastLookup(contextId, kAnycastNdAgent, aRloc16); + } + else + { + ExitNow(error = kErrorDrop); + } + +exit: + return error; +} + +Error Leader::AnycastLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aRloc16) const +{ + Iterator iterator = kIteratorInit; + uint8_t bestCost = Mle::kMaxRouteCost; + uint16_t bestDest = Mle::kInvalidRloc16; + + switch (aType) + { + case kAnycastDhcp6Agent: + case kAnycastNdAgent: + { + OnMeshPrefixConfig config; + Lowpan::Context context; + + SuccessOrExit(GetContext(aServiceId, context)); + + while (GetNextOnMeshPrefix(iterator, config) == kErrorNone) + { + if (config.GetPrefix() != context.mPrefix) + { + continue; + } + + switch (aType) + { + case kAnycastDhcp6Agent: + if (!(config.mDhcp || config.mConfigure)) + { + continue; + } + break; + case kAnycastNdAgent: + if (!config.mNdDns) + { + continue; + } + break; + default: + OT_ASSERT(false); + break; + } + + EvaluateRoutingCost(config.mRloc16, bestCost, bestDest); + } + + break; + } + case kAnycastService: + { + ServiceConfig config; + + while (GetNextService(iterator, config) == kErrorNone) + { + if (config.mServiceId != aServiceId) + { + continue; + } + + EvaluateRoutingCost(config.mServerConfig.mRloc16, bestCost, bestDest); + } + + break; + } + } + + if (Mle::IsChildRloc16(bestDest)) + { + // If the selected destination is a child, we use its parent + // as the destination unless the device itself is the + // parent of the `bestDest`. + + uint16_t bestDestParent = Mle::ParentRloc16ForRloc16(bestDest); + + if (!Get().HasRloc16(bestDestParent)) + { + bestDest = bestDestParent; + } + } + + aRloc16 = bestDest; + +exit: + return (bestDest != Mle::kInvalidRloc16) ? kErrorNone : kErrorNoRoute; +} + +void Leader::EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const +{ + uint8_t cost = Get().GetPathCost(aDest); + + if ((aBestDest == Mle::kInvalidRloc16) || (cost < aBestCost)) + { + aBestDest = aDest; + aBestCost = cost; + } +} + void Leader::RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode) { ChangedFlags flags;