diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index 56085d0d3..a5ecc9280 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -54,7 +54,9 @@ static const char kInfraIfAddress[] = "fe80::1"; static constexpr uint32_t kValidLitime = 2000; static constexpr uint32_t kPreferredLifetime = 1800; -static otInstance *sInstance; +static constexpr uint16_t kMaxRaSize = 800; + +static ot::Instance *sInstance; static uint32_t sNow = 0; static uint32_t sAlarmTime; @@ -361,30 +363,276 @@ Ip6::Address AddressFromString(const char *aString) return address; } -void TestRoutingManager(void) +void VerifyOmrPrefixInNetData(const Ip6::Prefix &aOmrPrefix, bool aDefaultRoute = false) +{ + otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; + NetworkData::OnMeshPrefixConfig prefixConfig; + + Log("VerifyOmrPrefixInNetData(%s, def-route:%s)", aOmrPrefix.ToString().AsCString(), aDefaultRoute ? "yes" : "no"); + + SuccessOrQuit(otNetDataGetNextOnMeshPrefix(sInstance, &iterator, &prefixConfig)); + VerifyOrQuit(prefixConfig.GetPrefix() == aOmrPrefix); + VerifyOrQuit(prefixConfig.mStable == true); + VerifyOrQuit(prefixConfig.mSlaac == true); + VerifyOrQuit(prefixConfig.mPreferred == true); + VerifyOrQuit(prefixConfig.mOnMesh == true); + VerifyOrQuit(prefixConfig.mDefaultRoute == aDefaultRoute); + + VerifyOrQuit(otNetDataGetNextOnMeshPrefix(sInstance, &iterator, &prefixConfig) == kErrorNotFound); +} + +using NetworkData::RoutePreference; + +struct ExternalRoute +{ + ExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aPreference) + : mPrefix(aPrefix) + , mPreference(aPreference) + { + } + + const Ip6::Prefix &mPrefix; + RoutePreference mPreference; +}; + +template void VerifyExternalRoutesInNetData(const ExternalRoute (&aExternRoutes)[kLength]) +{ + otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; + NetworkData::ExternalRouteConfig routeConfig; + uint16_t counter; + + Log("VerifyExternalRoutesInNetData()"); + + counter = 0; + + while (otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) == kErrorNone) + { + bool didFind = false; + + counter++; + + Log(" prefix:%s, prf:%s", routeConfig.GetPrefix().ToString().AsCString(), + PreferenceToString(routeConfig.mPreference)); + + for (const ExternalRoute &externalRoute : aExternRoutes) + { + if (externalRoute.mPrefix == routeConfig.GetPrefix()) + { + VerifyOrQuit(static_cast(routeConfig.mPreference) == externalRoute.mPreference); + didFind = true; + break; + } + } + + VerifyOrQuit(didFind); + } + + VerifyOrQuit(counter == kLength); +} + +struct Pio +{ + Pio(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime) + : mPrefix(aPrefix) + , mValidLifetime(aValidLifetime) + , mPreferredLifetime(aPreferredLifetime) + { + } + + const Ip6::Prefix &mPrefix; + uint32_t mValidLifetime; + uint32_t mPreferredLifetime; +}; + +struct Rio +{ + Rio(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, RoutePreference aPreference) + : mPrefix(aPrefix) + , mValidLifetime(aValidLifetime) + , mPreference(aPreference) + { + } + + const Ip6::Prefix &mPrefix; + uint32_t mValidLifetime; + RoutePreference mPreference; +}; + +struct DefaultRoute +{ + DefaultRoute(uint32_t aLifetime, RoutePreference aPreference) + : mLifetime(aLifetime) + , mPreference(aPreference) + { + } + + uint32_t mLifetime; + RoutePreference mPreference; +}; + +void SendRouterAdvert(const Ip6::Address &aRouterAddress, + const Pio * aPios, + uint16_t aNumPios, + const Rio * aRios, + uint16_t aNumRios, + const DefaultRoute &aDefaultRoute) +{ + Ip6::Nd::RouterAdvertMessage::Header header; + uint8_t buffer[kMaxRaSize]; + + header.SetRouterLifetime(aDefaultRoute.mLifetime); + header.SetDefaultRouterPreference(aDefaultRoute.mPreference); + + { + Ip6::Nd::RouterAdvertMessage raMsg(header, buffer); + + for (; aNumPios > 0; aPios++, aNumPios--) + { + SuccessOrQuit( + raMsg.AppendPrefixInfoOption(aPios->mPrefix, aPios->mValidLifetime, aPios->mPreferredLifetime)); + } + + for (; aNumRios > 0; aRios++, aNumRios--) + { + SuccessOrQuit(raMsg.AppendRouteInfoOption(aRios->mPrefix, aRios->mValidLifetime, aRios->mPreference)); + } + + SendRouterAdvert(aRouterAddress, raMsg.GetAsPacket()); + Log("Sending RA from router %s", aRouterAddress.ToString().AsCString()); + LogRouterAdvert(raMsg.GetAsPacket()); + } +} + +template +void SendRouterAdvert(const Ip6::Address &aRouterAddress, + const Pio (&aPios)[kNumPios], + const Rio (&aRios)[kNumRios], + const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium)) +{ + SendRouterAdvert(aRouterAddress, aPios, kNumPios, aRios, kNumRios, aDefaultRoute); +} + +template +void SendRouterAdvert(const Ip6::Address &aRouterAddress, + const Pio (&aPios)[kNumPios], + const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium)) +{ + SendRouterAdvert(aRouterAddress, aPios, kNumPios, nullptr, 0, aDefaultRoute); +} + +template +void SendRouterAdvert(const Ip6::Address &aRouterAddress, + const Rio (&aRios)[kNumRios], + const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium)) +{ + SendRouterAdvert(aRouterAddress, nullptr, 0, aRios, kNumRios, aDefaultRoute); +} + +void SendRouterAdvert(const Ip6::Address &aRouterAddress, const DefaultRoute &aDefaultRoute) +{ + SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, aDefaultRoute); +} + +struct OnLinkPrefix : public Pio +{ + OnLinkPrefix(const Ip6::Prefix & aPrefix, + uint32_t aValidLifetime, + uint32_t aPreferredLifetime, + const Ip6::Address &aRouterAddress) + : Pio(aPrefix, aValidLifetime, aPreferredLifetime) + , mRouterAddress(aRouterAddress) + { + } + + const Ip6::Address &mRouterAddress; +}; + +struct RoutePrefix : public Rio +{ + RoutePrefix(const Ip6::Prefix & aPrefix, + uint32_t aValidLifetime, + RoutePreference aPreference, + const Ip6::Address &aRouterAddress) + : Rio(aPrefix, aValidLifetime, aPreference) + , mRouterAddress(aRouterAddress) + { + } + + const Ip6::Address &mRouterAddress; +}; + +template +void VerifyPrefixTable(const OnLinkPrefix (&aOnLinkPrefixes)[kNumOnLinkPrefixes], + const RoutePrefix (&aRoutePrefixes)[kNumRoutePrefixes]) { - Instance & instance = *static_cast(testInitInstance()); - BorderRouter::RoutingManager & rm = instance.Get(); - Ip6::Prefix localOnLink; - Ip6::Prefix localOmr; - Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64); - Ip6::Prefix routePrefix = PrefixFromString("2000:1234:5678::", 64); - Ip6::Prefix omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64); - Ip6::Address routerAddressA = AddressFromString("fd00::aaaa"); - Ip6::Address routerAddressB = AddressFromString("fd00::bbbb"); BorderRouter::RoutingManager::PrefixTableIterator iter; BorderRouter::RoutingManager::PrefixTableEntry entry; - NetworkData::Iterator iterator; - NetworkData::OnMeshPrefixConfig prefixConfig; - NetworkData::ExternalRouteConfig routeConfig; - uint8_t counter; - uint8_t buffer[800]; + uint16_t onLinkPrefixCount = 0; + uint16_t routePrefixCount = 0; + Log("VerifyPrefixTable()"); + + sInstance->Get().InitPrefixTableIterator(iter); + + while (sInstance->Get().GetNextPrefixTableEntry(iter, entry) == kErrorNone) + { + bool didFind = false; + + if (entry.mIsOnLink) + { + Log(" on-link prefix:%s, valid:%u, preferred:%u, router:%s", + AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime, entry.mPreferredLifetime, + AsCoreType(&entry.mRouterAddress).ToString().AsCString()); + + onLinkPrefixCount++; + + for (const OnLinkPrefix &onLinkPrefix : aOnLinkPrefixes) + { + if ((onLinkPrefix.mPrefix == AsCoreType(&entry.mPrefix)) && + (AsCoreType(&entry.mRouterAddress) == onLinkPrefix.mRouterAddress)) + { + VerifyOrQuit(entry.mValidLifetime == onLinkPrefix.mValidLifetime); + VerifyOrQuit(entry.mPreferredLifetime == onLinkPrefix.mPreferredLifetime); + didFind = true; + break; + } + } + } + else + { + Log(" route prefix:%s, valid:%u, prf:%s, router:%s", AsCoreType(&entry.mPrefix).ToString().AsCString(), + entry.mValidLifetime, PreferenceToString(entry.mRoutePreference), + AsCoreType(&entry.mRouterAddress).ToString().AsCString()); + + routePrefixCount++; + + for (const RoutePrefix &routePrefix : aRoutePrefixes) + { + if ((routePrefix.mPrefix == AsCoreType(&entry.mPrefix)) && + (AsCoreType(&entry.mRouterAddress) == routePrefix.mRouterAddress)) + { + VerifyOrQuit(entry.mValidLifetime == routePrefix.mValidLifetime); + VerifyOrQuit(static_cast(entry.mRoutePreference) == routePrefix.mPreference); + didFind = true; + break; + } + } + } + + VerifyOrQuit(didFind); + } + + VerifyOrQuit(onLinkPrefixCount == kNumOnLinkPrefixes); + VerifyOrQuit(routePrefixCount == kNumRoutePrefixes); +} + +void InitTest(void) +{ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Initialize OT instance. sNow = 0; - sInstance = &instance; + sInstance = static_cast(testInitInstance()); memset(&sRadioTxFrame, 0, sizeof(sRadioTxFrame)); sRadioTxFrame.mPsdu = sRadioTxFramePsdu; @@ -406,6 +654,23 @@ void TestRoutingManager(void) AdvanceTime(10000); VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER); +} + +//--------------------------------------------------------------------------------------------------------------------- + +void TestSamePrefixesFromMultipleRouters(void) +{ + Ip6::Prefix localOnLink; + Ip6::Prefix localOmr; + Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64); + Ip6::Prefix routePrefix = PrefixFromString("2000:1234:5678::", 64); + Ip6::Address routerAddressA = AddressFromString("fd00::aaaa"); + Ip6::Address routerAddressB = AddressFromString("fd00::bbbb"); + + Log("--------------------------------------------------------------------------------------------"); + Log("TestSamePrefixesFromMultipleRouters"); + + InitTest(); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Start Routing Manager. Check emitted RS and RA messages. @@ -415,12 +680,10 @@ void TestRoutingManager(void) sSawExpectedRio = false; sExpectedPio = kPioAdvertisingLocalOnLink; - Log("Starting RoutingManager"); + SuccessOrQuit(sInstance->Get().SetEnabled(true)); - SuccessOrQuit(rm.SetEnabled(true)); - - SuccessOrQuit(rm.GetOnLinkPrefix(localOnLink)); - SuccessOrQuit(rm.GetOmrPrefix(localOmr)); + SuccessOrQuit(sInstance->Get().GetOnLinkPrefix(localOnLink)); + SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); Log("Local on-link prefix is %s", localOnLink.ToString().AsCString()); Log("Local OMR prefix is %s", localOmr.ToString().AsCString()); @@ -437,43 +700,14 @@ void TestRoutingManager(void) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to include the local OMR and on-link prefix. - iterator = NetworkData::kIteratorInit; - - // We expect to see OMR prefix in net data as on-mesh prefix. - SuccessOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig)); - VerifyOrQuit(prefixConfig.GetPrefix() == localOmr); - VerifyOrQuit(prefixConfig.mStable == true); - VerifyOrQuit(prefixConfig.mSlaac == true); - VerifyOrQuit(prefixConfig.mPreferred == true); - VerifyOrQuit(prefixConfig.mOnMesh == true); - VerifyOrQuit(prefixConfig.mDefaultRoute == false); - - VerifyOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound); - - iterator = NetworkData::kIteratorInit; - - // We expect to see local on-link prefix in net data as external route. - SuccessOrQuit(instance.Get().GetNextExternalRoute(iterator, routeConfig)); - VerifyOrQuit(routeConfig.GetPrefix() == localOnLink); - VerifyOrQuit(routeConfig.mStable == true); - VerifyOrQuit(routeConfig.mPreference == NetworkData::kRoutePreferenceMedium); - - VerifyOrQuit(instance.Get().GetNextExternalRoute(iterator, routeConfig) == kErrorNotFound); + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A with a new on-link (PIO) and route prefix (RIO). - { - Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer); - - SuccessOrQuit(raMsg.AppendPrefixInfoOption(onLinkPrefix, kValidLitime, kPreferredLifetime)); - SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)); - - SendRouterAdvert(routerAddressA, raMsg.GetAsPacket()); - - Log("Send RA from router A"); - LogRouterAdvert(raMsg.GetAsPacket()); - } + SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}, + {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check that the local on-link prefix is now deprecating in the new RA. @@ -490,120 +724,35 @@ void TestRoutingManager(void) // Check the discovered prefix table and ensure info from router A // is present in the table. - counter = 0; - - rm.InitPrefixTableIterator(iter); - - while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone) - { - counter++; - VerifyOrQuit(AsCoreType(&entry.mRouterAddress) == routerAddressA); - - if (entry.mIsOnLink) - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime); - } - else - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(static_cast(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium); - } - } - - VerifyOrQuit(counter == 2); + VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, + {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to include new prefixes from router A. - iterator = NetworkData::kIteratorInit; - - // We expect to see OMR prefix in net data as on-mesh prefix. - SuccessOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig)); - VerifyOrQuit(prefixConfig.GetPrefix() == localOmr); - VerifyOrQuit(prefixConfig.mStable == true); - VerifyOrQuit(prefixConfig.mSlaac == true); - VerifyOrQuit(prefixConfig.mPreferred == true); - VerifyOrQuit(prefixConfig.mOnMesh == true); - VerifyOrQuit(prefixConfig.mDefaultRoute == false); - - VerifyOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound); - - iterator = NetworkData::kIteratorInit; - - counter = 0; - - // We expect to see 3 entries, our local on link and new prefixes from router A. - while (instance.Get().GetNextExternalRoute(iterator, routeConfig) == kErrorNone) - { - VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) || - (routeConfig.GetPrefix() == routePrefix)); - VerifyOrQuit(static_cast(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium); - counter++; - } - - VerifyOrQuit(counter == 3); + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), + ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), + ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send the same RA again from router A with the on-link (PIO) and route prefix (RIO). - { - Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer); - - SuccessOrQuit(raMsg.AppendPrefixInfoOption(onLinkPrefix, kValidLitime, kPreferredLifetime)); - SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)); - - SendRouterAdvert(routerAddressA, raMsg.GetAsPacket()); - - Log("Send RA from router A"); - LogRouterAdvert(raMsg.GetAsPacket()); - } + SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}, + {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check the discovered prefix table and ensure info from router A // remains unchanged. - counter = 0; - - rm.InitPrefixTableIterator(iter); - - while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone) - { - counter++; - VerifyOrQuit(AsCoreType(&entry.mRouterAddress) == routerAddressA); - - if (entry.mIsOnLink) - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime); - } - else - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(static_cast(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium); - } - } - - VerifyOrQuit(counter == 2); + VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, + {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router B with same route prefix (RIO) but with // high route preference. - { - Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer); - - SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh)); - - SendRouterAdvert(routerAddressB, raMsg.GetAsPacket()); - - Log("Send RA from router B"); - LogRouterAdvert(raMsg.GetAsPacket()); - } + SendRouterAdvert(routerAddressB, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh)}); AdvanceTime(10000); @@ -611,99 +760,27 @@ void TestRoutingManager(void) // Check the discovered prefix table and ensure info from router B // is also included in the table. - counter = 0; - - rm.InitPrefixTableIterator(iter); - - while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone) - { - const Ip6::Address &routerAddr = AsCoreType(&entry.mRouterAddress); - counter++; - - if (routerAddr == routerAddressA) - { - if (entry.mIsOnLink) - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime); - } - else - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(static_cast(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium); - } - } - else if (routerAddr == routerAddressB) - { - VerifyOrQuit(!entry.mIsOnLink); - VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(static_cast(entry.mRoutePreference) == NetworkData::kRoutePreferenceHigh); - } - else - { - VerifyOrQuit(false, "Unexpected entry in prefix table with unknown router address"); - } - } - - VerifyOrQuit(counter == 3); + VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, + {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA), + RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh, routerAddressB)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. - iterator = NetworkData::kIteratorInit; - - // We expect to see OMR prefix in net data as on-mesh prefix - SuccessOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig)); - VerifyOrQuit(prefixConfig.GetPrefix() == localOmr); - VerifyOrQuit(prefixConfig.mStable == true); - VerifyOrQuit(prefixConfig.mSlaac == true); - VerifyOrQuit(prefixConfig.mPreferred == true); - VerifyOrQuit(prefixConfig.mOnMesh == true); - VerifyOrQuit(prefixConfig.mDefaultRoute == false); - - VerifyOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound); - - iterator = NetworkData::kIteratorInit; - - counter = 0; + VerifyOmrPrefixInNetData(localOmr); // We expect to see 3 entries, our local on link and new prefixes // from router A and B. The `routePrefix` now should have high // preference. - while (instance.Get().GetNextExternalRoute(iterator, routeConfig) == kErrorNone) - { - counter++; - - if (routeConfig.GetPrefix() == routePrefix) - { - VerifyOrQuit(static_cast(routeConfig.mPreference) == NetworkData::kRoutePreferenceHigh); - } - else - { - VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix)); - VerifyOrQuit(static_cast(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium); - } - } - - VerifyOrQuit(counter == 3); + VerifyExternalRoutesInNetData({ExternalRoute(routePrefix, NetworkData::kRoutePreferenceHigh), + ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), + ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router B removing the route prefix. - { - Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer); - - SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, 0, NetworkData::kRoutePreferenceHigh)); - - SendRouterAdvert(routerAddressB, raMsg.GetAsPacket()); - - Log("Send RA from router B"); - LogRouterAdvert(raMsg.GetAsPacket()); - } + SendRouterAdvert(routerAddressB, {Rio(routePrefix, 0, NetworkData::kRoutePreferenceHigh)}); AdvanceTime(10000); @@ -711,48 +788,65 @@ void TestRoutingManager(void) // Check the discovered prefix table and ensure info from router B // is now removed from the table. - counter = 0; - - rm.InitPrefixTableIterator(iter); - - while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone) - { - counter++; - - VerifyOrQuit(AsCoreType(&entry.mRouterAddress) == routerAddressA); - - if (entry.mIsOnLink) - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime); - } - else - { - VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix); - VerifyOrQuit(entry.mValidLifetime = kValidLitime); - VerifyOrQuit(static_cast(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium); - } - } - - VerifyOrQuit(counter == 2); + VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, + {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data, all prefixes should be again at medium preference. - counter = 0; - iterator = NetworkData::kIteratorInit; + VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), + ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), + ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); - while (instance.Get().GetNextExternalRoute(iterator, routeConfig) == kErrorNone) - { - counter++; + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) || - (routeConfig.GetPrefix() == routePrefix)); - VerifyOrQuit(static_cast(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium); - } + Log("End of TestSamePrefixesFromMultipleRouters"); - VerifyOrQuit(counter == 3); + testFreeInstance(sInstance); +} + +void TestOmrSelection(void) +{ + Ip6::Prefix localOnLink; + Ip6::Prefix localOmr; + Ip6::Prefix omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64); + NetworkData::OnMeshPrefixConfig prefixConfig; + + Log("--------------------------------------------------------------------------------------------"); + Log("TestOmrSelection"); + + InitTest(); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Start Routing Manager. Check emitted RS and RA messages. + + sRsEmitted = false; + sRaValidated = false; + sSawExpectedRio = false; + sExpectedPio = kPioAdvertisingLocalOnLink; + + SuccessOrQuit(sInstance->Get().SetEnabled(true)); + + SuccessOrQuit(sInstance->Get().GetOnLinkPrefix(localOnLink)); + SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); + + Log("Local on-link prefix is %s", localOnLink.ToString().AsCString()); + Log("Local OMR prefix is %s", localOmr.ToString().AsCString()); + + sExpectedRioPrefix = localOmr; + + AdvanceTime(30000); + + VerifyOrQuit(sRsEmitted); + VerifyOrQuit(sRaValidated); + VerifyOrQuit(sSawExpectedRio); + Log("Received RA was validated"); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data to include the local OMR and on-link prefix. + + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Add a new OMR prefix directly into net data. The new prefix should @@ -777,6 +871,7 @@ void TestRoutingManager(void) sRaValidated = false; sSawExpectedRio = false; + sExpectedPio = kPioAdvertisingLocalOnLink; sExpectedRioPrefix = omrPrefix; AdvanceTime(20000); @@ -788,32 +883,9 @@ void TestRoutingManager(void) // Check Network Data. We should now see that the local OMR prefix // is removed. - iterator = NetworkData::kIteratorInit; + VerifyOmrPrefixInNetData(omrPrefix); - // We expect to see new OMR prefix in net data. - SuccessOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig)); - VerifyOrQuit(prefixConfig.GetPrefix() == omrPrefix); - VerifyOrQuit(prefixConfig.mStable == true); - VerifyOrQuit(prefixConfig.mSlaac == true); - VerifyOrQuit(prefixConfig.mPreferred == true); - VerifyOrQuit(prefixConfig.mOnMesh == true); - VerifyOrQuit(prefixConfig.mDefaultRoute == false); - - VerifyOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound); - - counter = 0; - iterator = NetworkData::kIteratorInit; - - while (instance.Get().GetNextExternalRoute(iterator, routeConfig) == kErrorNone) - { - counter++; - - VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) || - (routeConfig.GetPrefix() == routePrefix)); - VerifyOrQuit(static_cast(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium); - } - - VerifyOrQuit(counter == 3); + VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Remove the OMR prefix previously added in net data. @@ -839,38 +911,14 @@ void TestRoutingManager(void) // Check Network Data. We should see that the local OMR prefix is // added again. - iterator = NetworkData::kIteratorInit; + VerifyOmrPrefixInNetData(localOmr); - // We expect to see new OMR prefix in net data as on-mesh prefix. - SuccessOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig)); - VerifyOrQuit(prefixConfig.GetPrefix() == localOmr); - VerifyOrQuit(prefixConfig.mStable == true); - VerifyOrQuit(prefixConfig.mSlaac == true); - VerifyOrQuit(prefixConfig.mPreferred == true); - VerifyOrQuit(prefixConfig.mOnMesh == true); - VerifyOrQuit(prefixConfig.mDefaultRoute == false); - - VerifyOrQuit(instance.Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound); - - counter = 0; - iterator = NetworkData::kIteratorInit; - - while (instance.Get().GetNextExternalRoute(iterator, routeConfig) == kErrorNone) - { - counter++; - - VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) || - (routeConfig.GetPrefix() == routePrefix)); - VerifyOrQuit(static_cast(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium); - } - - VerifyOrQuit(counter == 3); + VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Log("End of test"); - - testFreeInstance(&instance); + Log("End of TestOmrSelection"); + testFreeInstance(sInstance); } #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE @@ -878,7 +926,8 @@ void TestRoutingManager(void) int main(void) { #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE - TestRoutingManager(); + TestSamePrefixesFromMultipleRouters(); + TestOmrSelection(); printf("All tests passed\n"); #else printf("BORDER_ROUTING feature is not enabled\n");