diff --git a/src/core/api/border_routing_api.cpp b/src/core/api/border_routing_api.cpp index 183db0693..a9d4dc60e 100644 --- a/src/core/api/border_routing_api.cpp +++ b/src/core/api/border_routing_api.cpp @@ -131,14 +131,14 @@ otError otBorderRoutingGetPdOmrPrefix(otInstance *aInstance, otBorderRoutingPref { AssertPointerIsNotNull(aPrefixInfo); - return AsCoreType(aInstance).Get().GetPdOmrPrefix(*aPrefixInfo); + return AsCoreType(aInstance).Get().GetDhcp6PdOmrPrefix(*aPrefixInfo); } otError otBorderRoutingGetPdProcessedRaInfo(otInstance *aInstance, otPdProcessedRaInfo *aPdProcessedRaInfo) { AssertPointerIsNotNull(aPdProcessedRaInfo); - return AsCoreType(aInstance).Get().GetPdProcessedRaInfo(*aPdProcessedRaInfo); + return AsCoreType(aInstance).Get().GetDhcp6PdCounters(*aPdProcessedRaInfo); } #endif @@ -289,7 +289,7 @@ void otBorderRoutingDhcp6PdSetRequestCallback(otInstance otBorderRoutingRequestDhcp6PdCallback aCallback, void *aContext) { - AsCoreType(aInstance).Get().SetRequestDhcp6PdCallback(aCallback, aContext); + AsCoreType(aInstance).Get().SetDhcp6PdCallback(aCallback, aContext); } #endif diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index c3e343e0c..7d2dc6ef0 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -157,23 +157,23 @@ exit: } #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE -Error RoutingManager::GetPdOmrPrefix(PrefixTableEntry &aPrefixInfo) const +Error RoutingManager::GetDhcp6PdOmrPrefix(Dhcp6PdPrefix &aPrefix) const { Error error = kErrorNone; VerifyOrExit(IsInitialized(), error = kErrorInvalidState); - error = mPdPrefixManager.GetPrefixInfo(aPrefixInfo); + error = mPdPrefixManager.GetPrefix(aPrefix); exit: return error; } -Error RoutingManager::GetPdProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) +Error RoutingManager::GetDhcp6PdCounters(Dhcp6PdCounters &aCounters) { Error error = kErrorNone; VerifyOrExit(IsInitialized(), error = kErrorInvalidState); - error = mPdPrefixManager.GetProcessedRaInfo(aPdProcessedRaInfo); + error = mPdPrefixManager.GetCounters(aCounters); exit: return error; @@ -4414,30 +4414,30 @@ exit: return; } -Error RoutingManager::PdPrefixManager::GetPrefixInfo(PrefixTableEntry &aInfo) const +Error RoutingManager::PdPrefixManager::GetPrefix(Dhcp6PdPrefix &aPrefix) const { Error error = kErrorNone; VerifyOrExit(HasPrefix(), error = kErrorNotFound); - aInfo.mPrefix = mPrefix.GetPrefix(); - aInfo.mValidLifetime = mPrefix.GetValidLifetime(); - aInfo.mPreferredLifetime = mPrefix.GetPreferredLifetime(); - aInfo.mMsecSinceLastUpdate = TimerMilli::GetNow() - mPrefix.GetLastUpdateTime(); + aPrefix.mPrefix = mPrefix.GetPrefix(); + aPrefix.mValidLifetime = mPrefix.GetValidLifetime(); + aPrefix.mPreferredLifetime = mPrefix.GetPreferredLifetime(); + aPrefix.mMsecSinceLastUpdate = TimerMilli::GetNow() - mPrefix.GetLastUpdateTime(); exit: return error; } -Error RoutingManager::PdPrefixManager::GetProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) const +Error RoutingManager::PdPrefixManager::GetCounters(Dhcp6PdCounters &aCounters) const { Error error = kErrorNone; VerifyOrExit(HasPrefix(), error = kErrorNotFound); - aPdProcessedRaInfo.mNumPlatformRaReceived = mNumPlatformRaReceived; - aPdProcessedRaInfo.mNumPlatformPioProcessed = mNumPlatformPioProcessed; - aPdProcessedRaInfo.mLastPlatformRaMsec = TimerMilli::GetNow() - mLastPlatformRaTime; + aCounters.mNumPlatformRaReceived = mNumPlatformRaReceived; + aCounters.mNumPlatformPioProcessed = mNumPlatformPioProcessed; + aCounters.mLastPlatformRaMsec = TimerMilli::GetNow() - mLastPlatformRaTime; exit: return error; @@ -4458,7 +4458,7 @@ exit: return; } -void RoutingManager::PdPrefixManager::ProcessRa(const uint8_t *aRouterAdvert, const uint16_t aLength) +void RoutingManager::PdPrefixManager::ProcessPrefixesFromRa(const InfraIf::Icmp6Packet &aRaPacket) { // Processes a Router Advertisement (RA) message received on the // platform's Thread interface. This RA message, generated by @@ -4470,14 +4470,10 @@ void RoutingManager::PdPrefixManager::ProcessRa(const uint8_t *aRouterAdvert, co // 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); - VerifyOrExit(mState != kDhcp6PdStateDisabled); { - RouterAdvert::RxMessage raMsg = RouterAdvert::RxMessage(packet); + RouterAdvert::RxMessage raMsg = RouterAdvert::RxMessage(aRaPacket); PdPrefix favoredPrefix; VerifyOrExit(raMsg.IsValid()); @@ -4506,20 +4502,20 @@ exit: return; } -void RoutingManager::PdPrefixManager::ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry) +void RoutingManager::PdPrefixManager::ProcessPrefix(const Dhcp6PdPrefix &aPrefix) { // 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. + // (PD) server. Similar to `ProcessPrefixesFromRa()`, 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); + prefix.SetFrom(aPrefix); EvaluateCandidatePrefix(prefix, favoredPrefix); ApplyFavoredPrefix(favoredPrefix); @@ -4651,7 +4647,11 @@ const char *RoutingManager::PdPrefixManager::StateToString(State aState) extern "C" void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength) { - AsCoreType(aInstance).Get().mPdPrefixManager.ProcessRa(aMessage, aLength); + InfraIf::Icmp6Packet raMessage; + + raMessage.Init(aMessage, aLength); + + AsCoreType(aInstance).Get().ProcessDhcp6PdPrefixesFromRa(raMessage); } extern "C" void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance *aInstance, @@ -4659,7 +4659,7 @@ extern "C" void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance { AssertPointerIsNotNull(aPrefixInfo); - AsCoreType(aInstance).Get().mPdPrefixManager.ProcessPrefix(*aPrefixInfo); + AsCoreType(aInstance).Get().ProcessDhcp6PdPrefix(*aPrefixInfo); } #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index a54fc8209..7cd21f47f 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -58,6 +58,7 @@ #include #include #include +#include #include "border_router/infra_if.hpp" #include "common/array.hpp" @@ -84,10 +85,6 @@ namespace ot { namespace BorderRouter { -extern "C" void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength); -extern "C" void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance *aInstance, - const otBorderRoutingPrefixTableEntry *aPrefixInfo); - /** * Implements bi-directional routing between Thread and Infrastructure networks. * @@ -99,12 +96,6 @@ class RoutingManager : public InstanceLocator friend class ot::Notifier; friend class ot::Instance; -#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE - friend void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength); - friend void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance *aInstance, - const otBorderRoutingPrefixTableEntry *aPrefixInfo); -#endif - public: typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low). typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator. @@ -113,8 +104,9 @@ public: typedef otBorderRoutingRdnssAddrEntry RdnssAddrEntry; ///< RDNSS Address Entry. typedef otBorderRoutingRdnssAddrCallback RdnssAddrCallback; ///< RDNS Address changed callback. typedef otBorderRoutingPeerBorderRouterEntry PeerBrEntry; ///< Peer Border Router Entry. - typedef otPdProcessedRaInfo PdProcessedRaInfo; ///< Data of PdProcessedRaInfo. - typedef otBorderRoutingRequestDhcp6PdCallback PdCallback; ///< DHCPv6 PD callback. + typedef otBorderRoutingPrefixTableEntry Dhcp6PdPrefix; ///< DHCPv6 PD prefix. + typedef otPdProcessedRaInfo Dhcp6PdCounters; ///< DHCPv6 PD counters. + typedef otBorderRoutingRequestDhcp6PdCallback Dhcp6PdCallback; ///< DHCPv6 PD callback. typedef otBorderRoutingMultiAilCallback MultiAilCallback; ///< Multi AIL detection callback. /** @@ -639,32 +631,52 @@ public: * @param[in] aCallback A pointer to a callback function * @param[in] aContext A pointer to arbitrary context information. */ - void SetRequestDhcp6PdCallback(PdCallback aCallback, void *aContext) + void SetDhcp6PdCallback(Dhcp6PdCallback aCallback, void *aContext) { mPdPrefixManager.SetStateCallback(aCallback, aContext); } + /** + * Processes a delegated DHCPv6-PD prefix. + * + * Can be called again with a different prefix to report multiple delegated prefixes. Subsequent call for same + * prefix will renew or update the delegated prefix lifetimes. + * + * @param[in] aPrefix The delegated DHCPv6-PD prefix. + */ + void ProcessDhcp6PdPrefix(const Dhcp6PdPrefix &aPrefix) { mPdPrefixManager.ProcessPrefix(aPrefix); } + + /** + * Processes delegated DHCPv6-PD prefixes from a Router Advertisement. + * + * @param[in] aRaPacket The Router Advertisement packet. + */ + void ProcessDhcp6PdPrefixesFromRa(const InfraIf::Icmp6Packet &aRaPacket) + { + mPdPrefixManager.ProcessPrefixesFromRa(aRaPacket); + } + /** * Returns the DHCPv6-PD based off-mesh-routable (OMR) prefix. * - * @param[out] aPrefixInfo A reference to where the prefix info will be output to. + * @param[out] aPrefix A reference to return the DHCPv6 prefix. * * @retval kErrorNone Successfully retrieved the OMR prefix. * @retval kErrorNotFound There are no valid PD prefix on this BR. * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. */ - Error GetPdOmrPrefix(PrefixTableEntry &aPrefixInfo) const; + Error GetDhcp6PdOmrPrefix(Dhcp6PdPrefix &aPrefix) const; /** * Returns platform generated RA message processed counters and information. * - * @param[out] aPdProcessedRaInfo A reference to where the PD processed RA info will be output to. + * @param[out] aCounters A reference to return DHCPv6-PD counters. * * @retval kErrorNone Successfully retrieved the Info. - * @retval kErrorNotFound There are no valid RA process info on this BR. + * @retval kErrorNotFound There is no valid delegated PD prefix. * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. */ - Error GetPdProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo); + Error GetDhcp6PdCounters(Dhcp6PdCounters &aCounters); #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE @@ -1689,12 +1701,12 @@ private: const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); } State GetState(void) const { return mState; } - void ProcessRa(const uint8_t *aRouterAdvert, uint16_t aLength); - void ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry); - Error GetPrefixInfo(PrefixTableEntry &aInfo) const; - Error GetProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) const; + void ProcessPrefixesFromRa(const InfraIf::Icmp6Packet &aRaPacket); + void ProcessPrefix(const Dhcp6PdPrefix &aPrefix); + Error GetPrefix(Dhcp6PdPrefix &aPrefix) const; + Error GetCounters(Dhcp6PdCounters &aCounters) const; void HandleTimer(void) { WithdrawPrefix(); } - void SetStateCallback(PdCallback aCallback, void *aContext) { mStateCallback.Set(aCallback, aContext); } + void SetStateCallback(Dhcp6PdCallback aCallback, void *aContext) { mStateCallback.Set(aCallback, aContext); } void Evaluate(void); private: @@ -1716,7 +1728,7 @@ private: static const char *StateToString(State aState); using PrefixTimer = TimerMilliIn; - using StateCallback = Callback; + using StateCallback = Callback; State mState; uint32_t mNumPlatformPioProcessed; diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index 8f3f028c3..e9f70ab66 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -1011,20 +1011,6 @@ void SendRouterAdvert(const Ip6::Address &aRouterAddress, const RaFlags &aRaFlag DefaultRoute(0, NetworkData::kRoutePreferenceMedium), aRaFlags); } -template void SendRouterAdvertToBorderRoutingProcessIcmp6Ra(const Pio (&aPios)[kNumPios]) -{ - Ip6::Nd::RouterAdvert::TxMessage raMsg; - Icmp6Packet packet; - - BuildRouterAdvert(raMsg, aPios, kNumPios, nullptr, 0, nullptr, 0, - DefaultRoute(0, NetworkData::kRoutePreferenceMedium), RaFlags()); - raMsg.GetAsPacket(packet); - - otPlatBorderRoutingProcessIcmp6Ra(sInstance, packet.GetBytes(), packet.GetLength()); - Log("Passing RA to otPlatBorderRoutingProcessIcmp6Ra"); - LogRouterAdvert(packet); -} - struct OnLinkPrefix : public Pio { OnLinkPrefix(const Ip6::Prefix &aPrefix, @@ -4437,305 +4423,331 @@ void TestNat64PrefixSelection(void) #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE + void VerifyPdOmrPrefix(const Ip6::Prefix &aPrefix) { - otBorderRoutingPrefixTableEntry platformPrefixInfo; + BorderRouter::RoutingManager::Dhcp6PdPrefix pdPrefix; - VerifyOrQuit(otBorderRoutingGetPdOmrPrefix(sInstance, &platformPrefixInfo) == OT_ERROR_NONE); - VerifyOrQuit(AsCoreType(&platformPrefixInfo.mPrefix) == aPrefix); + SuccessOrQuit(sInstance->Get().GetDhcp6PdOmrPrefix(pdPrefix)); + VerifyOrQuit(AsCoreType(&pdPrefix.mPrefix) == aPrefix); } -void VerifyNoPdOmrPrefix() +void VerifyNoPdOmrPrefix(void) { - otBorderRoutingPrefixTableEntry platformPrefixInfo; + BorderRouter::RoutingManager::Dhcp6PdPrefix pdPrefix; - VerifyOrQuit(otBorderRoutingGetPdOmrPrefix(sInstance, &platformPrefixInfo) == OT_ERROR_NOT_FOUND); + VerifyOrQuit(sInstance->Get().GetDhcp6PdOmrPrefix(pdPrefix) == kErrorNotFound); } -void TestBorderRoutingProcessPlatfromGeneratedNd(void) +template void ReportPdPrefixesAsRa(const Pio (&aPios)[kNumPios]) { + Ip6::Nd::RouterAdvert::TxMessage raMsg; + Icmp6Packet packet; + + BuildRouterAdvert(raMsg, aPios, kNumPios, nullptr, 0, nullptr, 0, + DefaultRoute(0, NetworkData::kRoutePreferenceMedium), RaFlags()); + raMsg.GetAsPacket(packet); + + Log("Reporting DHCPv6-PD prefixes as RA"); + LogRouterAdvert(packet); + + sInstance->Get().ProcessDhcp6PdPrefixesFromRa(packet); +} + +void TestDhcp6Pd(void) +{ + static const uint8_t kInvalidDhcp6Ra1[] = { + 0x86, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static const uint8_t kInvalidDhcp6Ra2[] = { + 0x87, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static const uint8_t kInvalidDhcp6Ra3[] = { + 0x86, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x04, 0x41, 0xc0, 0x00, 0x00, 0x10, 0xe1, 0x00, 0x00, 0x04, 0xd2, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + struct InvalidDhcp6Ra + { + const uint8_t *mBytes; + uint16_t mLength; + }; + + static const InvalidDhcp6Ra kInvalidDhcp6Ras[] = { + {kInvalidDhcp6Ra1, sizeof(kInvalidDhcp6Ra1)}, + {kInvalidDhcp6Ra2, sizeof(kInvalidDhcp6Ra2)}, + {kInvalidDhcp6Ra3, sizeof(kInvalidDhcp6Ra3)}, + }; + Ip6::Prefix localOmr; + Ip6::Prefix prefix; + Ip6::Prefix ulaPrefix; + Ip6::Prefix newPrefix; + Ip6::Prefix shortPrefix; uint16_t heapAllocations; Log("--------------------------------------------------------------------------------------------"); - Log("TestBorderRoutingProcessPlatfromGeneratedNd"); + Log("TestDhcp6Pd"); InitTest(/* aEnableBorderRouting */ true); heapAllocations = sHeapAllocatedPtrs.GetLength(); - otBorderRoutingDhcp6PdSetEnabled(sInstance, true); + sInstance->Get().SetDhcp6PdEnabled(true); + VerifyOrQuit(sInstance->Get().GetDhcp6PdState() != + BorderRouter::RoutingManager::kDhcp6PdStateDisabled); + SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Log("Invalid DHCPv6-PD RA messages"); + + for (const InvalidDhcp6Ra &invalidRa : kInvalidDhcp6Ras) { - SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); - } + Icmp6Packet raPacket; - // 0. Reject invalid RA. - Log("0. Invalid RA message."); - { - { - const uint8_t testInvalidRaMessage[] = { - 0x86, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - otPlatBorderRoutingProcessIcmp6Ra(sInstance, testInvalidRaMessage, sizeof(testInvalidRaMessage)); - VerifyNoPdOmrPrefix(); - } - - { - const uint8_t testInvalidRaMessage[] = { - 0x87, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - otPlatBorderRoutingProcessIcmp6Ra(sInstance, testInvalidRaMessage, sizeof(testInvalidRaMessage)); - VerifyNoPdOmrPrefix(); - } - - { - const uint8_t testRaMessageWithInvalidPrefix[] = { - 0x86, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x04, 0x41, 0xc0, 0x00, 0x00, 0x10, 0xe1, 0x00, 0x00, 0x04, 0xd2, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - otPlatBorderRoutingProcessIcmp6Ra(sInstance, testRaMessageWithInvalidPrefix, - sizeof(testRaMessageWithInvalidPrefix)); - VerifyNoPdOmrPrefix(); - } - } - - // 1. Publish a prefix, and wait until it expired. - Log("1. Simple RA message."); - { - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:dead:beef::", 64); - - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)}); - - sExpectedRios.Add(raPrefix); - AdvanceTime(10000); - - VerifyPdOmrPrefix(raPrefix); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); - - AdvanceTime(1500000); - sExpectedRios.Clear(); - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); - - AdvanceTime(400000); - // Deprecated prefixes will be removed. + raPacket.Init(invalidRa.mBytes, invalidRa.mLength); + sInstance->Get().ProcessDhcp6PdPrefixesFromRa(raPacket); VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); } - // 1.1. Publish a prefix, and wait until it expired. - // Multiple prefixes are advertised, only the smallest one will be used. - Log("1.1. RA message with multiple prefixes."); - { - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:dead:beef::", 64); - Ip6::Prefix ulaRaPrefix = PrefixFromString("fd01:db8:deaf:beef::", 64); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(ulaRaPrefix, kValidLitime * 2, kPreferredLifetime * 2), - Pio(raPrefix, kValidLitime, kPreferredLifetime)}); + Log("Single DHCPv6-PD prefix"); - sExpectedRios.Add(raPrefix); - AdvanceTime(10000); + prefix = PrefixFromString("2001:db8:dead:beef::", 64); - VerifyPdOmrPrefix(raPrefix); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + ReportPdPrefixesAsRa({Pio(prefix, kValidLitime, kPreferredLifetime)}); - AdvanceTime(1500000); - sExpectedRios.Clear(); - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + sExpectedRios.Add(prefix); + AdvanceTime(10000); - AdvanceTime(400000); - // Deprecated prefixes will be removed. - VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - } + VerifyPdOmrPrefix(prefix); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - // 2. Publish a prefix, and renew it before it expired. - Log("2. Renew prefix lifetime."); - { - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:1:2::", 64); + AdvanceTime(1500000); + sExpectedRios.Clear(); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(400000); + // Deprecated prefixes will be removed. + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - sExpectedRios.Add(raPrefix); - AdvanceTime(10000); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Multiple prefixes are reported, ensure favored one is used. - VerifyPdOmrPrefix(raPrefix); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + Log("Multiple DHCPv6-PD prefixes"); - AdvanceTime(1500000); - sExpectedRios.Clear(); - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + prefix = PrefixFromString("2001:db8:dead:beef::", 64); + ulaPrefix = PrefixFromString("fd01:db8:deaf:beef::", 64); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)}); + ReportPdPrefixesAsRa( + {Pio(ulaPrefix, kValidLitime * 2, kPreferredLifetime * 2), Pio(prefix, kValidLitime, kPreferredLifetime)}); - AdvanceTime(400000); - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + sExpectedRios.Add(prefix); + AdvanceTime(10000); - AdvanceTime(1500000); - VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - } + VerifyPdOmrPrefix(prefix); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - // 3. Publish a prefix, and publish another prefix to replace it (with goodbye ra). - Log("3. Update prefix."); - { - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:1:2::", 64); - Ip6::Prefix newRaPrefix = PrefixFromString("2001:db8:3:4::", 64); + AdvanceTime(1500000); + sExpectedRios.Clear(); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(400000); + // Deprecated prefixes will be removed. + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - sExpectedRios.Add(raPrefix); - sExpectedRios.Clear(); - AdvanceTime(10000); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + Log("Renew DHCPv6-PD prefix lifetime"); - AdvanceTime(1000000); - VerifyPdOmrPrefix(raPrefix); + prefix = PrefixFromString("2001:db8:1:2::", 64); - sExpectedRios.Add(newRaPrefix); + ReportPdPrefixesAsRa({Pio(prefix, kValidLitime, kPreferredLifetime)}); - // When the prefix is replaced, there will be a short period when the old prefix is still in the netdata, and PD - // manager will refuse to request the prefix. - SendRouterAdvertToBorderRoutingProcessIcmp6Ra( - {Pio(raPrefix, 0, 0), Pio(newRaPrefix, kValidLitime, kPreferredLifetime)}); - // Advance a short period of time to wait for a stable PD state. - AdvanceTime(5000); - VerifyOrQuit(sInstance->Get().GetDhcp6PdState() == - BorderRouter::RoutingManager::kDhcp6PdStateRunning); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(newRaPrefix, kValidLitime, kPreferredLifetime)}); + sExpectedRios.Add(prefix); + AdvanceTime(10000); - AdvanceTime(1000000); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyPdOmrPrefix(newRaPrefix); + VerifyPdOmrPrefix(prefix); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - AdvanceTime(1000000); - VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - } + AdvanceTime(1500000); + sExpectedRios.Clear(); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - // 4. Short prefix will be extended to /64. - Log("4. Short prefix"); - { - // The prefix will be padded to a /64 prefix. - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:cafe:0::", 64); - Ip6::Prefix realRaPrefix; + ReportPdPrefixesAsRa({Pio(prefix, kValidLitime, kPreferredLifetime)}); - realRaPrefix.Set(raPrefix.GetBytes(), 48); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(realRaPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(400000); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - sExpectedRios.Add(raPrefix); - AdvanceTime(10000); + AdvanceTime(1500000); + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - VerifyPdOmrPrefix(raPrefix); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Report a prefix, and remove it and report a new DHCPv6-PD prefix - AdvanceTime(1500000); - sExpectedRios.Clear(); - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + Log("Update DHCPv6-PD prefix (add then remove and add new)"); - AdvanceTime(400000); - // Deprecated prefixes will be removed. - VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - } + prefix = PrefixFromString("2001:db8:1:2::", 64); + newPrefix = PrefixFromString("2001:db8:3:4::", 64); - // 5. Publish a prefix with long lifetime, and wait until it expired. - Log("5. RA message with long prefix lifetime"); - { - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:dead:beef::", 64); + ReportPdPrefixesAsRa({Pio(prefix, kValidLitime, kPreferredLifetime)}); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, 5000, 5000)}); + sExpectedRios.Add(prefix); + sExpectedRios.Clear(); + AdvanceTime(10000); - sExpectedRios.Add(raPrefix); - AdvanceTime(10 * 1000); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - VerifyPdOmrPrefix(raPrefix); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + AdvanceTime(1000000); + VerifyPdOmrPrefix(prefix); - AdvanceTime(4900 * 1000); - sExpectedRios.Clear(); - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + sExpectedRios.Add(newPrefix); - AdvanceTime(200 * 1000); - // Deprecated prefixes will be removed. - VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - } + // When the prefix is replaced, there will be a short period when the old prefix is still in the netdata, and PD + // manager will refuse to request the prefix. + ReportPdPrefixesAsRa({Pio(prefix, 0, 0), Pio(newPrefix, kValidLitime, kPreferredLifetime)}); + // Advance a short period of time to wait for a stable PD state. + AdvanceTime(5000); + VerifyOrQuit(sInstance->Get().GetDhcp6PdState() == + BorderRouter::RoutingManager::kDhcp6PdStateRunning); + ReportPdPrefixesAsRa({Pio(newPrefix, kValidLitime, kPreferredLifetime)}); - // 6. Replace a prefix, on some platforms, there might be no messages to deprecate the old prefix, instead, they - // send new prefixes directly. - // In this case, we still use the old prefix as long as the old prefix preferred lifetime is not exceeded, and - // replace it with the new prefix when expired. - Log("6. Replace prefix."); - { - Ip6::Prefix raPrefix = PrefixFromString("2001:db8:1:2::", 64); - Ip6::Prefix newRaPrefix = PrefixFromString("2001:db8:3:4::", 64); + AdvanceTime(1000000); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyPdOmrPrefix(newPrefix); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(1000000); + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - sExpectedRios.Add(raPrefix); - sExpectedRios.Clear(); - AdvanceTime(10 * 1000); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Report a shorter (/48) prefix, validate it is extended to /64. - VerifyPdOmrPrefix(raPrefix); - VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false); + Log("Short DHCPv6-PD prefix"); - AdvanceTime(1000 * 1000); - VerifyPdOmrPrefix(raPrefix); + prefix = PrefixFromString("2001:db8:cafe:0::", 64); - // Send new prefix without deprecating old prefix. - // The old prefix should be preferred for another (1800 - 10 - 1000) = 790s - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(newRaPrefix, kValidLitime, kPreferredLifetime)}); - AdvanceTime(500 * 1000); - VerifyPdOmrPrefix(raPrefix); + shortPrefix.Set(prefix.GetBytes(), 48); + ReportPdPrefixesAsRa({Pio(shortPrefix, kValidLitime, kPreferredLifetime)}); - AdvanceTime(300 * 1000); - // Old Prefix should be removed now. - VerifyNoPdOmrPrefix(); + sExpectedRios.Add(prefix); + AdvanceTime(10000); - sExpectedRios.Add(newRaPrefix); + VerifyPdOmrPrefix(prefix); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - // When the prefix is replaced, there will be a short period when the old prefix is still in the netdata, and PD - // manager will refuse to request the prefix. - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(newRaPrefix, kValidLitime, kPreferredLifetime)}); - // Advance a short period of time to wait for a stable PD state. - AdvanceTime(5000); - VerifyOrQuit(sInstance->Get().GetDhcp6PdState() == - BorderRouter::RoutingManager::kDhcp6PdStateRunning); - SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(newRaPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(1500000); + sExpectedRios.Clear(); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); - AdvanceTime(1000 * 1000); - VerifyOrQuit(sExpectedRios.SawAll()); - VerifyPdOmrPrefix(newRaPrefix); + AdvanceTime(400000); + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - AdvanceTime(1000 * 1000); - VerifyNoPdOmrPrefix(); - VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); - } + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Report a prefix with long lifetime, and wait until it expired. - SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, false)); + Log("Single DHCPv6-PD prefix with long lifetime"); + prefix = PrefixFromString("2001:db8:dead:beef::", 64); + + ReportPdPrefixesAsRa({Pio(prefix, 5000, 5000)}); + + sExpectedRios.Add(prefix); + AdvanceTime(10 * 1000); + + VerifyPdOmrPrefix(prefix); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); + + AdvanceTime(4900 * 1000); + sExpectedRios.Clear(); + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); + + AdvanceTime(200 * 1000); + // Deprecated prefixes will be removed. + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Replace a prefix: In some platforms there might be no messages to deprecate the old prefix, instead, they + // send new prefixes directly. In this case, we still use the old prefix as long as the old prefix preferred + // lifetime is not exceeded, and replace it with the new prefix when expired. + + Log("Replacing DHCPv6-PD prefix"); + + prefix = PrefixFromString("2001:db8:1:2::", 64); + newPrefix = PrefixFromString("2001:db8:3:4::", 64); + + ReportPdPrefixesAsRa({Pio(prefix, kValidLitime, kPreferredLifetime)}); + + sExpectedRios.Add(prefix); + sExpectedRios.Clear(); + AdvanceTime(10 * 1000); + + VerifyPdOmrPrefix(prefix); + VerifyOmrPrefixInNetData(prefix, /* aDefaultRoute */ false); + + AdvanceTime(1000 * 1000); + VerifyPdOmrPrefix(prefix); + + // Send new prefix without deprecating old prefix. + // The old prefix should be preferred for another (1800 - 10 - 1000) = 790s + ReportPdPrefixesAsRa({Pio(newPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(500 * 1000); + VerifyPdOmrPrefix(prefix); + + AdvanceTime(300 * 1000); + // Old Prefix should be removed now. + VerifyNoPdOmrPrefix(); + + sExpectedRios.Add(newPrefix); + + // When the prefix is replaced, there will be a short period when the old prefix is still in the netdata, and PD + // manager will refuse to request the prefix. + ReportPdPrefixesAsRa({Pio(newPrefix, kValidLitime, kPreferredLifetime)}); + // Advance a short period of time to wait for a stable PD state. + AdvanceTime(5000); + VerifyOrQuit(sInstance->Get().GetDhcp6PdState() == + BorderRouter::RoutingManager::kDhcp6PdStateRunning); + ReportPdPrefixesAsRa({Pio(newPrefix, kValidLitime, kPreferredLifetime)}); + + AdvanceTime(1000 * 1000); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyPdOmrPrefix(newPrefix); + + AdvanceTime(1000 * 1000); + VerifyNoPdOmrPrefix(); + VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + SuccessOrQuit(sInstance->Get().SetEnabled(false)); VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations); - Log("End of TestBorderRoutingProcessPlatfromGeneratedNd"); + Log("End of TestDhcp6Pd"); FinalizeTest(); } + #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE static void HandleRdnssChanged(void *aContext) @@ -5011,7 +5023,7 @@ int main(void) ot::TestNat64PrefixSelection(); #endif #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE - ot::TestBorderRoutingProcessPlatfromGeneratedNd(); + ot::TestDhcp6Pd(); #endif ot::TestRdnss();