[test] update RoutingManager unit test adding new helper methods (#7951)

This commit updates `test_routing_manager` unit test and adds a new
set of helper methods to simplify the implementation of test-case:

- `VerifyOmrPrefixInNetData()` to check OMR prefix in Network Data.
- `VerifyExternalRoutesInNetData()` to check external route prefixes
   in Network Data.
- `VerifyPrefixTable()` to check the on-link and route prefixes in
  discovered prefix table.
- Different flavors of `SendRouterAdvert()` to send RA with different
  PIOs, RIOs, and default route info (in header).

This commit also breaks the test-cases into multiple functions each
covering specific aspect.
This commit is contained in:
Abtin Keshavarzian
2022-07-28 17:26:49 -07:00
committed by GitHub
parent 747a0a8069
commit 4e8eeccfe8
+369 -320
View File
@@ -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 <uint16_t kLength> 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<int8_t>(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 <uint16_t kNumPios, uint16_t kNumRios>
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 <uint16_t kNumPios>
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 <uint16_t kNumRios>
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 <uint16_t kNumOnLinkPrefixes, uint16_t kNumRoutePrefixes>
void VerifyPrefixTable(const OnLinkPrefix (&aOnLinkPrefixes)[kNumOnLinkPrefixes],
const RoutePrefix (&aRoutePrefixes)[kNumRoutePrefixes])
{
Instance & instance = *static_cast<Instance *>(testInitInstance());
BorderRouter::RoutingManager & rm = instance.Get<BorderRouter::RoutingManager>();
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<BorderRouter::RoutingManager>().InitPrefixTableIterator(iter);
while (sInstance->Get<BorderRouter::RoutingManager>().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<int8_t>(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<Instance *>(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<BorderRouter::RoutingManager>().SetEnabled(true));
SuccessOrQuit(rm.SetEnabled(true));
SuccessOrQuit(rm.GetOnLinkPrefix(localOnLink));
SuccessOrQuit(rm.GetOmrPrefix(localOmr));
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().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<NetworkData::Leader>().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<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
iterator = NetworkData::kIteratorInit;
// We expect to see local on-link prefix in net data as external route.
SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig));
VerifyOrQuit(routeConfig.GetPrefix() == localOnLink);
VerifyOrQuit(routeConfig.mStable == true);
VerifyOrQuit(routeConfig.mPreference == NetworkData::kRoutePreferenceMedium);
VerifyOrQuit(instance.Get<NetworkData::Leader>().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<int8_t>(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<NetworkData::Leader>().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<NetworkData::Leader>().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<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
{
VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
(routeConfig.GetPrefix() == routePrefix));
VerifyOrQuit(static_cast<int8_t>(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<int8_t>(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<int8_t>(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium);
}
}
else if (routerAddr == routerAddressB)
{
VerifyOrQuit(!entry.mIsOnLink);
VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix);
VerifyOrQuit(entry.mValidLifetime = kValidLitime);
VerifyOrQuit(static_cast<int8_t>(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<NetworkData::Leader>().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<NetworkData::Leader>().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<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
{
counter++;
if (routeConfig.GetPrefix() == routePrefix)
{
VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceHigh);
}
else
{
VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix));
VerifyOrQuit(static_cast<int8_t>(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<int8_t>(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<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
{
counter++;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
(routeConfig.GetPrefix() == routePrefix));
VerifyOrQuit(static_cast<int8_t>(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<BorderRouter::RoutingManager>().SetEnabled(true));
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().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<NetworkData::Leader>().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<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
counter = 0;
iterator = NetworkData::kIteratorInit;
while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
{
counter++;
VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
(routeConfig.GetPrefix() == routePrefix));
VerifyOrQuit(static_cast<int8_t>(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<NetworkData::Leader>().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<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
counter = 0;
iterator = NetworkData::kIteratorInit;
while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
{
counter++;
VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
(routeConfig.GetPrefix() == routePrefix));
VerifyOrQuit(static_cast<int8_t>(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");