mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 06:17:47 +00:00
[routing-manager] learn and copy M & O flags from discovered routers (#9607)
This commit implements a mechanism in `RoutingManager` to learn the Managed Address Config `M` and Other Config `O` flags in received RA message from discovered routers on the infrastructure link and copy the same flags in the emitted RA message from BR. If any discovered router on the infrastructure that is not itself a stub router (i.e., does not include the Stub Router flag) includes the `M` or `O` flags, the same flag are included in the emitted RA message. If a discovered router has failed to respond to the maximum number of NS probe attempts, we consider it as offline and ignore its flags. This commit also adds a detailed test case in `test_routing_manager` to validate the newly added mechanism.
This commit is contained in:
@@ -620,6 +620,12 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
|
||||
|
||||
LogInfo("Preparing RA");
|
||||
|
||||
mDiscoveredPrefixTable.DetermineAndSetFlags(raMsg);
|
||||
|
||||
LogInfo("- RA Header - flags - M:%u O:%u", raMsg.GetHeader().IsManagedAddressConfigFlagSet(),
|
||||
raMsg.GetHeader().IsOtherConfigFlagSet());
|
||||
LogInfo("- RA Header - default route - lifetime:%u", raMsg.GetHeader().GetRouterLifetime());
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
|
||||
SuccessOrAssert(raMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true));
|
||||
LogInfo("- FlagsExt - StubRouter:1");
|
||||
@@ -1242,7 +1248,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6
|
||||
|
||||
UpdateRouterOnRx(*router);
|
||||
|
||||
RemoveRoutersWithNoEntries();
|
||||
RemoveRoutersWithNoEntriesOrFlags();
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -1472,7 +1478,7 @@ void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &a
|
||||
VerifyOrExit(!removedEntries.IsEmpty());
|
||||
|
||||
FreeEntries(removedEntries);
|
||||
RemoveRoutersWithNoEntries();
|
||||
RemoveRoutersWithNoEntriesOrFlags();
|
||||
|
||||
SignalTableChanged();
|
||||
|
||||
@@ -1482,21 +1488,17 @@ exit:
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)
|
||||
{
|
||||
// Remove all entries from the table and unpublish them
|
||||
// from Network Data.
|
||||
// Remove all entries from the table.
|
||||
|
||||
for (Router &router : mRouters)
|
||||
{
|
||||
if (!router.mEntries.IsEmpty())
|
||||
{
|
||||
SignalTableChanged();
|
||||
}
|
||||
|
||||
FreeEntries(router.mEntries);
|
||||
}
|
||||
|
||||
RemoveRoutersWithNoEntries();
|
||||
FreeRouters(mRouters);
|
||||
mEntryTimer.Stop();
|
||||
|
||||
SignalTableChanged();
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold)
|
||||
@@ -1592,11 +1594,11 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMill
|
||||
return foundOnLink ? Min(onLinkStaleTime, routeStaleTime) : routeStaleTime;
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntries(void)
|
||||
void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntriesOrFlags(void)
|
||||
{
|
||||
LinkedList<Router> routersToFree;
|
||||
|
||||
mRouters.RemoveAllMatching(Router::kContainsNoEntries, routersToFree);
|
||||
mRouters.RemoveAllMatching(Router::kContainsNoEntriesOrFlags, routersToFree);
|
||||
FreeRouters(routersToFree);
|
||||
}
|
||||
|
||||
@@ -1668,7 +1670,7 @@ void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
|
||||
router.mEntries.RemoveAllMatching(Entry::ExpirationChecker(now), expiredEntries);
|
||||
}
|
||||
|
||||
RemoveRoutersWithNoEntries();
|
||||
RemoveRoutersWithNoEntriesOrFlags();
|
||||
|
||||
if (!expiredEntries.IsEmpty())
|
||||
{
|
||||
@@ -1792,6 +1794,42 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::DetermineAndSetFlags(Ip6::Nd::RouterAdvertMessage &aRaMessage) const
|
||||
{
|
||||
// Determine the `M` and `O` flags to include in the RA message
|
||||
// header `aRaMessage` to be emitted.
|
||||
//
|
||||
// If any discovered router on infrastructure which is not itself a
|
||||
// stub router (e.g., another Thread BR) includes the `M` or `O`
|
||||
// flag, we also include the same flag.
|
||||
//
|
||||
// If a router has failed to respond to max number of NS probe
|
||||
// attempts, we consider it as offline and ignore its flags.
|
||||
|
||||
for (const Router &router : mRouters)
|
||||
{
|
||||
if (router.mStubRouterFlag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (router.mNsProbeCount > Router::kMaxNsProbes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (router.mManagedAddressConfigFlag)
|
||||
{
|
||||
aRaMessage.GetHeader().SetManagedAddressConfigFlag();
|
||||
}
|
||||
|
||||
if (router.mOtherConfigFlag)
|
||||
{
|
||||
aRaMessage.GetHeader().SetOtherConfigFlag();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
|
||||
{
|
||||
static_cast<Iterator &>(aIterator).Init(mRouters);
|
||||
@@ -1995,6 +2033,27 @@ uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// DiscoveredPrefixTable::Router
|
||||
|
||||
bool RoutingManager::DiscoveredPrefixTable::Router::Matches(EmptyChecker aChecker) const
|
||||
{
|
||||
// Checks whether or not a `Router` instance has any useful info. An
|
||||
// entry can be removed if it does not advertise M or O flags and
|
||||
// also does not have any advertised prefix entries (RIO/PIO). If
|
||||
// the router already failed to respond to max NS probe attempts,
|
||||
// we consider it as offline and therefore do not consider its
|
||||
// flags anymore.
|
||||
|
||||
OT_UNUSED_VARIABLE(aChecker);
|
||||
|
||||
bool hasFlags = false;
|
||||
|
||||
if (mNsProbeCount <= kMaxNsProbes)
|
||||
{
|
||||
hasFlags = (mManagedAddressConfigFlag || mOtherConfigFlag);
|
||||
}
|
||||
|
||||
return !hasFlags && mEntries.IsEmpty();
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::Router::CopyInfoTo(RouterEntry &aEntry) const
|
||||
{
|
||||
aEntry.mAddress = mAddress;
|
||||
|
||||
@@ -635,6 +635,8 @@ private:
|
||||
|
||||
TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
|
||||
|
||||
void DetermineAndSetFlags(Ip6::Nd::RouterAdvertMessage &aRaMessage) const;
|
||||
|
||||
void InitIterator(PrefixTableIterator &aIterator) const;
|
||||
Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
|
||||
Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const;
|
||||
@@ -770,11 +772,11 @@ private:
|
||||
|
||||
enum EmptyChecker : uint8_t
|
||||
{
|
||||
kContainsNoEntries
|
||||
kContainsNoEntriesOrFlags
|
||||
};
|
||||
|
||||
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
|
||||
bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }
|
||||
bool Matches(EmptyChecker aChecker) const;
|
||||
void CopyInfoTo(RouterEntry &aEntry) const;
|
||||
|
||||
Router *mNext;
|
||||
@@ -816,7 +818,7 @@ private:
|
||||
bool Contains(const Entry::Checker &aChecker) const;
|
||||
void RemovePrefix(const Entry::Matcher &aMatcher);
|
||||
void RemoveOrDeprecateEntriesFromInactiveRouters(void);
|
||||
void RemoveRoutersWithNoEntries(void);
|
||||
void RemoveRoutersWithNoEntriesOrFlags(void);
|
||||
void FreeRouters(LinkedList<Router> &aRouters);
|
||||
void FreeEntries(LinkedList<Entry> &aEntries);
|
||||
void UpdateNetworkDataOnChangeTo(Entry &aEntry);
|
||||
|
||||
@@ -733,6 +733,14 @@ public:
|
||||
*/
|
||||
const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
|
||||
|
||||
/**
|
||||
* Gets the RA message's header.
|
||||
*
|
||||
* @returns The RA message's header.
|
||||
*
|
||||
*/
|
||||
Header &GetHeader(void) { return *reinterpret_cast<Header *>(AsNonConst(mData.GetBytes())); }
|
||||
|
||||
/**
|
||||
* Appends a Prefix Info Option to the RA message.
|
||||
*
|
||||
|
||||
@@ -155,6 +155,18 @@ bool sRespondToNs; // Indicates whether or not to respond to NS.
|
||||
ExpectedPio sExpectedPio; // Expected PIO in the emitted RA by BR (MUST be seen in RA to set `sRaValidated`).
|
||||
uint32_t sOnLinkLifetime; // Valid lifetime for local on-link prefix from the last processed RA.
|
||||
|
||||
enum ExpectedRaHeaderFlags
|
||||
{
|
||||
kRaHeaderFlagsSkipChecking, // Skip checking the RA header flags.
|
||||
kRaHeaderFlagsNone, // Expect no flag (neither M or O).
|
||||
kRaHeaderFlagsOnlyM, // Expect M flag only.
|
||||
kRaHeaderFlagsOnlyO, // Expect O flag only.
|
||||
kRaHeaderFlagsBothMAndO, // Expect both M and O flags.
|
||||
};
|
||||
|
||||
// The expected RA header flags when validating emitted RA message.
|
||||
ExpectedRaHeaderFlags sExpectedRaHeaderFlags;
|
||||
|
||||
// Array containing deprecating prefixes from PIOs in the last processed RA.
|
||||
Array<DeprecatingPrefix, kMaxDeprecatingPrefixes> sDeprecatingPrefixes;
|
||||
|
||||
@@ -371,9 +383,36 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
|
||||
bool sawExpectedPio = false;
|
||||
Array<Ip6::Prefix, kMaxPrefixes> pioPrefixes;
|
||||
Array<Ip6::Prefix, kMaxPrefixes> rioPrefixes;
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
|
||||
bool sawStubRouterFlag = false;
|
||||
#endif
|
||||
|
||||
VerifyOrQuit(raMsg.IsValid());
|
||||
|
||||
VerifyOrQuit(raMsg.GetHeader().GetRouterLifetime() == 0);
|
||||
|
||||
switch (sExpectedRaHeaderFlags)
|
||||
{
|
||||
case kRaHeaderFlagsSkipChecking:
|
||||
break;
|
||||
case kRaHeaderFlagsNone:
|
||||
VerifyOrQuit(!raMsg.GetHeader().IsManagedAddressConfigFlagSet());
|
||||
VerifyOrQuit(!raMsg.GetHeader().IsOtherConfigFlagSet());
|
||||
break;
|
||||
case kRaHeaderFlagsOnlyM:
|
||||
VerifyOrQuit(raMsg.GetHeader().IsManagedAddressConfigFlagSet());
|
||||
VerifyOrQuit(!raMsg.GetHeader().IsOtherConfigFlagSet());
|
||||
break;
|
||||
case kRaHeaderFlagsOnlyO:
|
||||
VerifyOrQuit(!raMsg.GetHeader().IsManagedAddressConfigFlagSet());
|
||||
VerifyOrQuit(raMsg.GetHeader().IsOtherConfigFlagSet());
|
||||
break;
|
||||
case kRaHeaderFlagsBothMAndO:
|
||||
VerifyOrQuit(raMsg.GetHeader().IsManagedAddressConfigFlagSet());
|
||||
VerifyOrQuit(raMsg.GetHeader().IsOtherConfigFlagSet());
|
||||
break;
|
||||
}
|
||||
|
||||
sDeprecatingPrefixes.Clear();
|
||||
|
||||
for (const Ip6::Nd::Option &option : raMsg)
|
||||
@@ -456,6 +495,7 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
|
||||
|
||||
VerifyOrQuit(flagsOption.IsValid());
|
||||
VerifyOrQuit(flagsOption.IsStubRouterFlagSet());
|
||||
sawStubRouterFlag = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -465,6 +505,10 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
|
||||
VerifyOrQuit(sawStubRouterFlag);
|
||||
#endif
|
||||
|
||||
if (!sRaValidated)
|
||||
{
|
||||
switch (sExpectedPio)
|
||||
@@ -524,6 +568,8 @@ void LogRouterAdvert(const Icmp6Packet &aPacket)
|
||||
|
||||
VerifyOrQuit(raMsg.IsValid());
|
||||
|
||||
Log(" RA header - M:%u, O:%u", raMsg.GetHeader().IsManagedAddressConfigFlagSet(),
|
||||
raMsg.GetHeader().IsOtherConfigFlagSet());
|
||||
Log(" RA header - lifetime %u, prf:%s", raMsg.GetHeader().GetRouterLifetime(),
|
||||
PreferenceToString(raMsg.GetHeader().GetDefaultRouterPreference()));
|
||||
|
||||
@@ -788,13 +834,28 @@ struct DefaultRoute
|
||||
RoutePreference mPreference;
|
||||
};
|
||||
|
||||
struct RaFlags : public Clearable<RaFlags>
|
||||
{
|
||||
RaFlags(void)
|
||||
: mManagedAddressConfigFlag(false)
|
||||
, mOtherConfigFlag(false)
|
||||
, mStubRouterFlag(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool mManagedAddressConfigFlag;
|
||||
bool mOtherConfigFlag;
|
||||
bool mStubRouterFlag;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
uint16_t BuildRouterAdvert(uint8_t (&aBuffer)[N],
|
||||
const Pio *aPios,
|
||||
uint16_t aNumPios,
|
||||
const Rio *aRios,
|
||||
uint16_t aNumRios,
|
||||
const DefaultRoute &aDefaultRoute)
|
||||
const DefaultRoute &aDefaultRoute,
|
||||
const RaFlags &aRaFlags)
|
||||
{
|
||||
Ip6::Nd::RouterAdvertMessage::Header header;
|
||||
uint16_t length;
|
||||
@@ -802,9 +863,24 @@ uint16_t BuildRouterAdvert(uint8_t (&aBuffer)[N],
|
||||
header.SetRouterLifetime(aDefaultRoute.mLifetime);
|
||||
header.SetDefaultRouterPreference(aDefaultRoute.mPreference);
|
||||
|
||||
if (aRaFlags.mManagedAddressConfigFlag)
|
||||
{
|
||||
header.SetManagedAddressConfigFlag();
|
||||
}
|
||||
|
||||
if (aRaFlags.mOtherConfigFlag)
|
||||
{
|
||||
header.SetOtherConfigFlag();
|
||||
}
|
||||
|
||||
{
|
||||
Ip6::Nd::RouterAdvertMessage raMsg(header, aBuffer);
|
||||
|
||||
if (aRaFlags.mStubRouterFlag)
|
||||
{
|
||||
SuccessOrQuit(raMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true));
|
||||
}
|
||||
|
||||
for (; aNumPios > 0; aPios++, aNumPios--)
|
||||
{
|
||||
SuccessOrQuit(
|
||||
@@ -827,10 +903,11 @@ void SendRouterAdvert(const Ip6::Address &aRouterAddress,
|
||||
uint16_t aNumPios,
|
||||
const Rio *aRios,
|
||||
uint16_t aNumRios,
|
||||
const DefaultRoute &aDefaultRoute)
|
||||
const DefaultRoute &aDefaultRoute,
|
||||
const RaFlags &aRaFlags)
|
||||
{
|
||||
uint8_t buffer[kMaxRaSize];
|
||||
uint16_t length = BuildRouterAdvert(buffer, aPios, aNumPios, aRios, aNumRios, aDefaultRoute);
|
||||
uint16_t length = BuildRouterAdvert(buffer, aPios, aNumPios, aRios, aNumRios, aDefaultRoute, aRaFlags);
|
||||
|
||||
SendRouterAdvert(aRouterAddress, buffer, length);
|
||||
Log("Sending RA from router %s", aRouterAddress.ToString().AsCString());
|
||||
@@ -841,37 +918,48 @@ 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))
|
||||
const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
|
||||
const RaFlags &aRaFlags = RaFlags())
|
||||
{
|
||||
SendRouterAdvert(aRouterAddress, aPios, kNumPios, aRios, kNumRios, aDefaultRoute);
|
||||
SendRouterAdvert(aRouterAddress, aPios, kNumPios, aRios, kNumRios, aDefaultRoute, aRaFlags);
|
||||
}
|
||||
|
||||
template <uint16_t kNumPios>
|
||||
void SendRouterAdvert(const Ip6::Address &aRouterAddress,
|
||||
const Pio (&aPios)[kNumPios],
|
||||
const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium))
|
||||
const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
|
||||
const RaFlags &aRaFlags = RaFlags())
|
||||
{
|
||||
SendRouterAdvert(aRouterAddress, aPios, kNumPios, nullptr, 0, aDefaultRoute);
|
||||
SendRouterAdvert(aRouterAddress, aPios, kNumPios, nullptr, 0, aDefaultRoute, aRaFlags);
|
||||
}
|
||||
|
||||
template <uint16_t kNumRios>
|
||||
void SendRouterAdvert(const Ip6::Address &aRouterAddress,
|
||||
const Rio (&aRios)[kNumRios],
|
||||
const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium))
|
||||
const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
|
||||
const RaFlags &aRaFlags = RaFlags())
|
||||
{
|
||||
SendRouterAdvert(aRouterAddress, nullptr, 0, aRios, kNumRios, aDefaultRoute);
|
||||
SendRouterAdvert(aRouterAddress, nullptr, 0, aRios, kNumRios, aDefaultRoute, aRaFlags);
|
||||
}
|
||||
|
||||
void SendRouterAdvert(const Ip6::Address &aRouterAddress, const DefaultRoute &aDefaultRoute)
|
||||
void SendRouterAdvert(const Ip6::Address &aRouterAddress,
|
||||
const DefaultRoute &aDefaultRoute,
|
||||
const RaFlags &aRaFlags = RaFlags())
|
||||
{
|
||||
SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, aDefaultRoute);
|
||||
SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, aDefaultRoute, aRaFlags);
|
||||
}
|
||||
|
||||
void SendRouterAdvert(const Ip6::Address &aRouterAddress, const RaFlags &aRaFlags)
|
||||
{
|
||||
SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
|
||||
aRaFlags);
|
||||
}
|
||||
|
||||
template <uint16_t kNumPios> void SendRouterAdvertToBorderRoutingProcessIcmp6Ra(const Pio (&aPios)[kNumPios])
|
||||
{
|
||||
uint8_t buffer[kMaxRaSize];
|
||||
uint16_t length =
|
||||
BuildRouterAdvert(buffer, aPios, kNumPios, nullptr, 0, DefaultRoute(0, NetworkData::kRoutePreferenceMedium));
|
||||
uint16_t length = BuildRouterAdvert(buffer, aPios, kNumPios, nullptr, 0,
|
||||
DefaultRoute(0, NetworkData::kRoutePreferenceMedium), RaFlags());
|
||||
|
||||
otPlatBorderRoutingProcessIcmp6Ra(sInstance, buffer, length);
|
||||
Log("Passing RA to otPlatBorderRoutingProcessIcmp6Ra");
|
||||
@@ -996,6 +1084,66 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
|
||||
|
||||
void VerifyPrefixTableIsEmpty(void) { VerifyPrefixTable(nullptr, 0, nullptr, 0); }
|
||||
|
||||
struct InfraRouter
|
||||
{
|
||||
InfraRouter(const Ip6::Address &aAddress,
|
||||
bool aManagedAddressConfigFlag,
|
||||
bool aOtherConfigFlag,
|
||||
bool aStubRouterFlag)
|
||||
: mAddress(aAddress)
|
||||
{
|
||||
mFlags.Clear();
|
||||
mFlags.mManagedAddressConfigFlag = aManagedAddressConfigFlag;
|
||||
mFlags.mOtherConfigFlag = aOtherConfigFlag;
|
||||
mFlags.mStubRouterFlag = aStubRouterFlag;
|
||||
}
|
||||
|
||||
Ip6::Address mAddress;
|
||||
RaFlags mFlags;
|
||||
};
|
||||
|
||||
template <uint16_t kNumRouters> void VerifyDiscoveredRouters(const InfraRouter (&aRouters)[kNumRouters])
|
||||
{
|
||||
VerifyDiscoveredRouters(aRouters, kNumRouters);
|
||||
}
|
||||
|
||||
void VerifyDiscoveredRouters(const InfraRouter *aRouters, uint16_t aNumRouters)
|
||||
{
|
||||
BorderRouter::RoutingManager::PrefixTableIterator iter;
|
||||
BorderRouter::RoutingManager::RouterEntry entry;
|
||||
uint16_t count = 0;
|
||||
|
||||
Log("VerifyDiscoveredRouters()");
|
||||
|
||||
sInstance->Get<BorderRouter::RoutingManager>().InitPrefixTableIterator(iter);
|
||||
|
||||
while (sInstance->Get<BorderRouter::RoutingManager>().GetNextRouterEntry(iter, entry) == kErrorNone)
|
||||
{
|
||||
bool didFind = false;
|
||||
|
||||
Log(" address:%s, M:%u, O:%u, StubRouter:%u", AsCoreType(&entry.mAddress).ToString().AsCString(),
|
||||
entry.mManagedAddressConfigFlag, entry.mOtherConfigFlag, entry.mStubRouterFlag);
|
||||
|
||||
for (uint16_t index = 0; index < aNumRouters; index++)
|
||||
{
|
||||
if (AsCoreType(&entry.mAddress) == aRouters[index].mAddress)
|
||||
{
|
||||
VerifyOrQuit(entry.mManagedAddressConfigFlag == aRouters[index].mFlags.mManagedAddressConfigFlag);
|
||||
VerifyOrQuit(entry.mOtherConfigFlag == aRouters[index].mFlags.mOtherConfigFlag);
|
||||
VerifyOrQuit(entry.mStubRouterFlag == aRouters[index].mFlags.mStubRouterFlag);
|
||||
didFind = true;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(didFind);
|
||||
count++;
|
||||
}
|
||||
|
||||
VerifyOrQuit(count == aNumRouters);
|
||||
}
|
||||
|
||||
void VerifyDiscoveredRoutersIsEmpty(void) { VerifyDiscoveredRouters(nullptr, 0); }
|
||||
|
||||
void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false)
|
||||
{
|
||||
uint32_t delay = 10000;
|
||||
@@ -1032,19 +1180,20 @@ void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false)
|
||||
SuccessOrQuit(otThreadSetEnabled(sInstance, true));
|
||||
SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, aEnablBorderRouting));
|
||||
|
||||
// Reset all test flags
|
||||
sRsEmitted = false;
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kNoPio;
|
||||
sExpectedRios.Clear();
|
||||
sRespondToNs = true;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Ensure device starts as leader.
|
||||
|
||||
AdvanceTime(delay);
|
||||
|
||||
VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
|
||||
|
||||
// Reset all test flags
|
||||
sRsEmitted = false;
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kNoPio;
|
||||
sExpectedRios.Clear();
|
||||
sRespondToNs = true;
|
||||
}
|
||||
|
||||
void FinalizeTest(void)
|
||||
@@ -2599,6 +2748,178 @@ void TestRouterNsProbe(void)
|
||||
FinalizeTest();
|
||||
}
|
||||
|
||||
void TestLearningAndCopyingOfFlags(void)
|
||||
{
|
||||
Ip6::Prefix localOnLink;
|
||||
Ip6::Prefix localOmr;
|
||||
Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64);
|
||||
Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
|
||||
Ip6::Address routerAddressB = AddressFromString("fd00::bbbb");
|
||||
Ip6::Address routerAddressC = AddressFromString("fd00::cccc");
|
||||
uint16_t heapAllocations;
|
||||
RaFlags raFlags;
|
||||
|
||||
Log("--------------------------------------------------------------------------------------------");
|
||||
Log("TestLearningAndCopyingOfFlags");
|
||||
|
||||
InitTest();
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Start Routing Manager. Check emitted RS and RA messages.
|
||||
|
||||
sRsEmitted = false;
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kPioAdvertisingLocalOnLink;
|
||||
sExpectedRios.Clear();
|
||||
|
||||
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
||||
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());
|
||||
|
||||
sExpectedRios.Add(localOmr);
|
||||
|
||||
AdvanceTime(30000);
|
||||
|
||||
VerifyOrQuit(sRsEmitted);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
Log("Received RA was validated");
|
||||
|
||||
VerifyDiscoveredRoutersIsEmpty();
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Send an RA from router A with M flag set, and make sure the
|
||||
// emitted RA from BR also includes M flag.
|
||||
|
||||
raFlags.Clear();
|
||||
raFlags.mManagedAddressConfigFlag = true;
|
||||
|
||||
SendRouterAdvert(routerAddressA, raFlags);
|
||||
|
||||
AdvanceTime(1);
|
||||
VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ false)});
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsOnlyM;
|
||||
|
||||
AdvanceTime(610 * 1000);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Send an RA from router A without the M flag. Now the emitted
|
||||
// RA should no longer contain the M flag.
|
||||
|
||||
raFlags.Clear();
|
||||
|
||||
SendRouterAdvert(routerAddressA, raFlags);
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
|
||||
|
||||
AdvanceTime(1);
|
||||
VerifyDiscoveredRoutersIsEmpty();
|
||||
|
||||
AdvanceTime(610 * 1000);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Send an RA from router A with both M and StubRouter flags.
|
||||
// Since it is from a stub router, the M flag should be ignored.
|
||||
// Ensure emitted RA does not set the M flag.
|
||||
|
||||
raFlags.Clear();
|
||||
raFlags.mManagedAddressConfigFlag = true;
|
||||
raFlags.mStubRouterFlag = true;
|
||||
|
||||
SendRouterAdvert(routerAddressA, raFlags);
|
||||
|
||||
AdvanceTime(1);
|
||||
VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true)});
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
|
||||
|
||||
AdvanceTime(610 * 1000);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Send an RA from router B with O flag and check that emitted
|
||||
// RA include the same flag.
|
||||
|
||||
raFlags.Clear();
|
||||
raFlags.mOtherConfigFlag = true;
|
||||
|
||||
SendRouterAdvert(routerAddressB, raFlags);
|
||||
|
||||
AdvanceTime(1);
|
||||
VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true),
|
||||
InfraRouter(routerAddressB, /* M */ false, /* O */ true, /* StubRouter */ false)});
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsOnlyO;
|
||||
|
||||
AdvanceTime(610 * 1000);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Send an RA from router C with M flag and check that emitted
|
||||
// RA now includes both M and O flags.
|
||||
|
||||
raFlags.Clear();
|
||||
raFlags.mManagedAddressConfigFlag = true;
|
||||
|
||||
SendRouterAdvert(routerAddressC, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)},
|
||||
DefaultRoute(0, NetworkData::kRoutePreferenceMedium), raFlags);
|
||||
|
||||
AdvanceTime(1);
|
||||
VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true),
|
||||
InfraRouter(routerAddressB, /* M */ false, /* O */ true, /* StubRouter */ false),
|
||||
InfraRouter(routerAddressC, /* M */ true, /* O */ false, /* StubRouter */ false)});
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kPioDeprecatingLocalOnLink;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsBothMAndO;
|
||||
|
||||
AdvanceTime(610 * 1000);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Stop responding to NS, this should cause all routers
|
||||
// to age and considered offline
|
||||
|
||||
sRespondToNs = false;
|
||||
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsSkipChecking;
|
||||
|
||||
AdvanceTime(300 * 1000);
|
||||
|
||||
// Router C should be in the table since it will have a deprecating
|
||||
// on-link prefix.
|
||||
VerifyDiscoveredRouters({InfraRouter(routerAddressC, /* M */ true, /* O */ false, /* StubRouter */ false)});
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kPioAdvertisingLocalOnLink;
|
||||
sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
|
||||
|
||||
AdvanceTime(610 * 1000);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
|
||||
VerifyDiscoveredRoutersIsEmpty();
|
||||
|
||||
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
||||
|
||||
Log("End of TestLearningAndCopyingOfFlags");
|
||||
FinalizeTest();
|
||||
}
|
||||
|
||||
void TestConflictingPrefix(void)
|
||||
{
|
||||
static const otExtendedPanId kExtPanId1 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x08}};
|
||||
@@ -3569,6 +3890,7 @@ int main(void)
|
||||
ot::TestExtPanIdChange();
|
||||
ot::TestConflictingPrefix();
|
||||
ot::TestRouterNsProbe();
|
||||
ot::TestLearningAndCopyingOfFlags();
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
|
||||
ot::TestSavedOnLinkPrefixes();
|
||||
#endif
|
||||
@@ -3580,7 +3902,7 @@ int main(void)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
||||
ot::TestBorderRoutingProcessPlatfromGeneratedNd();
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
||||
#endif
|
||||
|
||||
printf("All tests passed\n");
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user