From eb8a9260376368a018be0208c3570b12c1ead786 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 2 Jun 2025 12:55:02 -0700 Subject: [PATCH] [routing-manager] simplify PD prefix processing (#11554) This commit simplifies the processing of PD prefixes provided by the platform to `PdPrefixManager`. The platform can report DHCPv6 PD prefixes in two ways: through a Router Advertisement (RA) message containing Prefix Information Options (PIOs) or by providing a PD prefix directly. Previously, these two paths were processed in a single method, which made the code harder to read and follow. This commit refactors the logic to separate these two paths while using common helper methods. This change introduces `EvaluateCandidatePrefix()`, which evaluates a single candidate prefix and tracks the most favored one. After all candidates are evaluated, `ApplyFavoredPrefix()` is called to apply the most favored prefix and update the current PD prefix if necessary. --- src/core/border_router/routing_manager.cpp | 96 ++++++++++++---------- src/core/border_router/routing_manager.hpp | 4 +- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 7797082f7..34bbf421c 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -4465,44 +4465,27 @@ void RoutingManager::PdPrefixManager::ProcessRa(const uint8_t *aRouterAdvert, co // software entities like dnsmasq, radvd, or systemd-networkd, is // part of the DHCPv6 prefix delegation process for distributing // prefixes to interfaces. + // + // Each PIO in the RA is evaluated as a candidate PD prefix. After + // all candidates are evaluated, the most favored one is applied to + // update the current PD prefix if necessary. InfraIf::Icmp6Packet packet; packet.Init(aRouterAdvert, aLength); - Process(&packet, nullptr); -} -void RoutingManager::PdPrefixManager::ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry) -{ - // Processes a prefix delegated by a DHCPv6 Prefix Delegation - // (PD) server. Similar to `ProcessRa()`, but sets the prefix - // directly instead of parsing an RA message. Calling this method - // again with new values can update the prefix's lifetime. + VerifyOrExit(mState != kDhcp6PdStateDisabled); - Process(nullptr, &aPrefixTableEntry); -} - -void RoutingManager::PdPrefixManager::Process(const InfraIf::Icmp6Packet *aRaPacket, - const PrefixTableEntry *aPrefixTableEntry) -{ - // Processes DHCPv6 Prefix Delegation (PD) prefixes, either from - // an RA message or directly set. Requires either `aRaPacket` or - // `aPrefixTableEntry` to be non-null. - - Error error = kErrorNone; - PdPrefix favoredPrefix; - PdPrefix prefix; - - VerifyOrExit(mState != kDhcp6PdStateDisabled, error = kErrorInvalidState); - - if (aRaPacket != nullptr) { - RouterAdvert::RxMessage raMsg = RouterAdvert::RxMessage(*aRaPacket); + RouterAdvert::RxMessage raMsg = RouterAdvert::RxMessage(packet); + PdPrefix favoredPrefix; - VerifyOrExit(raMsg.IsValid(), error = kErrorParse); + VerifyOrExit(raMsg.IsValid()); for (const Option &option : raMsg) { + PdPrefix prefix; + if (option.GetType() != Option::kTypePrefixInfo || !static_cast(option).IsValid()) { continue; @@ -4510,28 +4493,54 @@ void RoutingManager::PdPrefixManager::Process(const InfraIf::Icmp6Packet *aRaPac mNumPlatformPioProcessed++; prefix.SetFrom(static_cast(option)); - ProcessPdPrefix(prefix, favoredPrefix); + EvaluateCandidatePrefix(prefix, favoredPrefix); } mNumPlatformRaReceived++; mLastPlatformRaTime = TimerMilli::GetNow(); + + ApplyFavoredPrefix(favoredPrefix); } - else // aPrefixTableEntry != nullptr - { - prefix.SetFrom(*aPrefixTableEntry); - ProcessPdPrefix(prefix, favoredPrefix); - } + +exit: + return; +} + +void RoutingManager::PdPrefixManager::ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry) +{ + // Processes a prefix delegated by a DHCPv6 Prefix Delegation + // (PD) server. Similar to `ProcessRa()`, but sets the prefix + // directly instead of parsing an RA message. Calling this method + // again with new values can refresh the prefix (renew its lifetime) + // or update the prefix's lifetime. + + PdPrefix favoredPrefix; + PdPrefix prefix; + + VerifyOrExit(mState != kDhcp6PdStateDisabled); + + prefix.SetFrom(aPrefixTableEntry); + EvaluateCandidatePrefix(prefix, favoredPrefix); + ApplyFavoredPrefix(favoredPrefix); + +exit: + return; +} + +void RoutingManager::PdPrefixManager::ApplyFavoredPrefix(const PdPrefix &aFavoredPrefix) +{ + // Applies the most favored prefix from a batch of candidates to + // update the PD prefix. if (HasPrefix() && mPrefix.IsDeprecated()) { LogInfo("DHCPv6 PD prefix %s is deprecated", mPrefix.GetPrefix().ToString().AsCString()); - mPrefix.Clear(); - Get().ScheduleRoutingPolicyEvaluation(kImmediately); + WithdrawPrefix(); } - if (favoredPrefix.IsFavoredOver(mPrefix)) + if (aFavoredPrefix.IsFavoredOver(mPrefix)) { - mPrefix = favoredPrefix; + mPrefix = aFavoredPrefix; LogInfo("DHCPv6 PD prefix set to %s", mPrefix.GetPrefix().ToString().AsCString()); Get().ScheduleRoutingPolicyEvaluation(kImmediately); } @@ -4544,14 +4553,13 @@ void RoutingManager::PdPrefixManager::Process(const InfraIf::Icmp6Packet *aRaPac { mTimer.Stop(); } - -exit: - LogWarnOnError(error, "process DHCPv6 delegated prefix"); - OT_UNUSED_VARIABLE(error); } -void RoutingManager::PdPrefixManager::ProcessPdPrefix(PdPrefix &aPrefix, PdPrefix &aFavoredPrefix) +void RoutingManager::PdPrefixManager::EvaluateCandidatePrefix(PdPrefix &aPrefix, PdPrefix &aFavoredPrefix) { + // Evaluates a single candidate prefix and tracks the most favored + // one seen so far. + if (!aPrefix.IsValidPdPrefix()) { LogWarn("Ignore invalid DHCPv6 PD prefix %s", aPrefix.GetPrefix().ToString().AsCString()); @@ -4561,8 +4569,8 @@ void RoutingManager::PdPrefixManager::ProcessPdPrefix(PdPrefix &aPrefix, PdPrefi aPrefix.GetPrefix().Tidy(); aPrefix.GetPrefix().SetLength(kOmrPrefixLength); - // Check if there is an update to the current prefix. The valid or - // preferred lifetime may have changed. + // Check if `aPrefix` matches the current `mPrefix`. Update it to + // refresh and/or update its lifetime. if (HasPrefix() && (mPrefix.GetPrefix() == aPrefix.GetPrefix())) { diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index e5c458a69..c813b48de 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -1709,8 +1709,8 @@ private: void UpdateState(void); void SetState(State aState); - void Process(const InfraIf::Icmp6Packet *aRaPacket, const PrefixTableEntry *aPrefixTableEntry); - void ProcessPdPrefix(PdPrefix &aPrefix, PdPrefix &aFavoredPrefix); + void EvaluateCandidatePrefix(PdPrefix &aPrefix, PdPrefix &aFavoredPrefix); + void ApplyFavoredPrefix(const PdPrefix &aFavoredPrefix); void WithdrawPrefix(void); static const char *StateToString(State aState);