mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 09:07:47 +00:00
[routing-manager] deprecate previous local on-link prefix on xpanid change (#8112)
This commit updates `RoutingManager` to deprecate a previously advertised local on-link prefix when extended PAN ID gets changed. The local on-link prefix is derived from Thread network extended PAN ID. On extended PAN ID change, we continue to include the the old prefix (if it was being advertised) in the emitted RAs as PIO (with zero preferred lifetime) and continue to publish it in Network Data up to its lifetime. This ensures that any device on infrastructure link side that may be using an IPv6 address based on this old prefix can continue to communicate with the Thread mesh devices. This commit also adds a test-case in `test_routing_manager` to validate the behavior of the newly added mechanism when ext PAN ID changes while the local on-link is being advertised and also while it was being deprecated.
This commit is contained in:
@@ -678,13 +678,13 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
|
||||
// RA message max length is derived to accommodate:
|
||||
//
|
||||
// - The RA header,
|
||||
// - At most one PIO (for local on-link prefix),
|
||||
// - At most two PIOs (for current and old local on-link prefixes),
|
||||
// - At most twice `kMaxOnMeshPrefixes` RIO for on-mesh prefixes.
|
||||
// Factor two is used for RIO to account for entries invalidating
|
||||
// previous prefixes while adding new ones.
|
||||
|
||||
static constexpr uint16_t kMaxRaLength =
|
||||
sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::PrefixInfoOption) +
|
||||
sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::PrefixInfoOption) * 2 +
|
||||
2 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix));
|
||||
|
||||
uint8_t buffer[kMaxRaLength];
|
||||
@@ -693,9 +693,10 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
|
||||
NetworkData::OnMeshPrefixConfig prefixConfig;
|
||||
|
||||
// Append PIO for local on-link prefix if is either being
|
||||
// advertised or deprecated.
|
||||
// advertised or deprecated and for old prefix if is being
|
||||
// deprecated.
|
||||
|
||||
mLocalOnLinkPrefix.AppendAsPioTo(raMsg);
|
||||
mLocalOnLinkPrefix.AppendAsPiosTo(raMsg);
|
||||
|
||||
// Determine which previously advertised prefixes need to be
|
||||
// invalidated. Under `kInvalidateAllPrevPrefixes` mode we need
|
||||
@@ -2038,6 +2039,7 @@ RoutingManager::LocalOnLinkPrefix::LocalOnLinkPrefix(Instance &aInstance)
|
||||
, mTimer(aInstance, HandleTimer)
|
||||
{
|
||||
mPrefix.Clear();
|
||||
mOldPrefix.Clear();
|
||||
}
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::Generate(void)
|
||||
@@ -2061,9 +2063,18 @@ void RoutingManager::LocalOnLinkPrefix::Start(void)
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::Stop(void)
|
||||
{
|
||||
mTimer.Stop();
|
||||
|
||||
if (mOldPrefix.GetLength() != 0)
|
||||
{
|
||||
Get<RoutingManager>().UnpublishExternalRoute(mOldPrefix);
|
||||
mOldPrefix.Clear();
|
||||
}
|
||||
|
||||
VerifyOrExit(mState != kIdle);
|
||||
|
||||
Get<RoutingManager>().UnpublishExternalRoute(mPrefix);
|
||||
|
||||
mState = kDeprecating;
|
||||
|
||||
// Start deprecating the local on-link prefix to send a PIO
|
||||
@@ -2084,11 +2095,10 @@ Error RoutingManager::LocalOnLinkPrefix::Advertise(void)
|
||||
|
||||
VerifyOrExit(mState != kAdvertising);
|
||||
|
||||
mTimer.Stop();
|
||||
|
||||
SuccessOrExit(error = Get<RoutingManager>().PublishExternalRoute(mPrefix, NetworkData::kRoutePreferenceMedium));
|
||||
|
||||
mState = kAdvertising;
|
||||
mState = kAdvertising;
|
||||
mExpireTime = TimerMilli::GetNow() + TimeMilli::SecToMsec(kDefaultOnLinkPrefixLifetime);
|
||||
LogInfo("Start advertising on-link prefix %s", mPrefix.ToString().AsCString());
|
||||
|
||||
exit:
|
||||
@@ -2107,36 +2117,41 @@ void RoutingManager::LocalOnLinkPrefix::Deprecate(void)
|
||||
VerifyOrExit(mState == kAdvertising);
|
||||
|
||||
mState = kDeprecating;
|
||||
mTimer.FireAtIfEarlier(mExpireTime);
|
||||
LogInfo("Deprecate local on-link prefix %s", mPrefix.ToString().AsCString());
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::AppendAsPioTo(Ip6::Nd::RouterAdvertMessage &aRaMessage)
|
||||
void RoutingManager::LocalOnLinkPrefix::AppendAsPiosTo(Ip6::Nd::RouterAdvertMessage &aRaMessage)
|
||||
{
|
||||
AppendCurPrefix(aRaMessage);
|
||||
AppendOldPrefix(aRaMessage);
|
||||
}
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::AppendCurPrefix(Ip6::Nd::RouterAdvertMessage &aRaMessage)
|
||||
{
|
||||
// Append the local on-link prefix to the `aRaMessage` as a PIO
|
||||
// only if it is being advertised or deprecated.
|
||||
//
|
||||
// If in `kAdvertising` state, we restart the lifetime timer.
|
||||
// If in `kAdvertising` state, we reset the expire time.
|
||||
// If in `kDeprecating` state, we include it as PIO with zero
|
||||
// preferred lifetime and the remaining valid lifetime which
|
||||
// is tracked by the timer.
|
||||
// preferred lifetime and the remaining valid lifetime.
|
||||
|
||||
uint32_t validLifetime = kDefaultOnLinkPrefixLifetime;
|
||||
uint32_t preferredLifetime = kDefaultOnLinkPrefixLifetime;
|
||||
TimeMilli now;
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kAdvertising:
|
||||
mTimer.Start(TimeMilli::SecToMsec(kDefaultOnLinkPrefixLifetime));
|
||||
mExpireTime = now + TimeMilli::SecToMsec(kDefaultOnLinkPrefixLifetime);
|
||||
break;
|
||||
|
||||
case kDeprecating:
|
||||
now = TimerMilli::GetNow();
|
||||
VerifyOrExit(mTimer.IsRunning() && (mTimer.GetFireTime() > now));
|
||||
validLifetime = TimeMilli::MsecToSec(mTimer.GetFireTime() - now);
|
||||
VerifyOrExit(mExpireTime > now);
|
||||
validLifetime = TimeMilli::MsecToSec(mExpireTime - now);
|
||||
preferredLifetime = 0;
|
||||
break;
|
||||
|
||||
@@ -2153,22 +2168,41 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::AppendOldPrefix(Ip6::Nd::RouterAdvertMessage &aRaMessage)
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
uint32_t validLifetime;
|
||||
|
||||
VerifyOrExit((mOldPrefix.GetLength() != 0) && (mOldExpireTime > now));
|
||||
|
||||
validLifetime = TimeMilli::MsecToSec(mOldExpireTime - now);
|
||||
SuccessOrAssert(aRaMessage.AppendPrefixInfoOption(mOldPrefix, validLifetime, 0));
|
||||
|
||||
LogInfo("RouterAdvert: Added PIO for %s (valid=%u, preferred=0)", mOldPrefix.ToString().AsCString(), validLifetime);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::HandleExtPanIdChange(void)
|
||||
{
|
||||
// If the prefix is advertised or being deprecated we remember it
|
||||
// as `mOldPrefix` and deprecate it. It will be included in
|
||||
// emitted RAs as PIO with zero preferred lifetime. It will still
|
||||
// be present in Network Data until its expire time so to allow
|
||||
// Thread nodes to continue to communicate with `InfraIf` devices
|
||||
// using addresses based on this prefix.
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kIdle:
|
||||
break;
|
||||
|
||||
case kAdvertising:
|
||||
Get<RoutingManager>().UnpublishExternalRoute(mPrefix);
|
||||
|
||||
// TODO: consider deprecating/invalidating the existing
|
||||
// on-link prefix.
|
||||
break;
|
||||
|
||||
case kDeprecating:
|
||||
mTimer.Stop();
|
||||
mOldPrefix = mPrefix;
|
||||
mOldExpireTime = mExpireTime;
|
||||
mTimer.FireAtIfEarlier(mOldExpireTime);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2183,19 +2217,41 @@ void RoutingManager::LocalOnLinkPrefix::HandleTimer(Timer &aTimer)
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::HandleTimer(void)
|
||||
{
|
||||
VerifyOrExit(mState == kDeprecating);
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
|
||||
LogInfo("Local on-link prefix %s expired", mPrefix.ToString().AsCString());
|
||||
|
||||
if (!Get<RoutingManager>().mDiscoveredPrefixTable.ContainsOnLinkPrefix(mPrefix))
|
||||
if ((mState == kDeprecating) && (now >= mExpireTime))
|
||||
{
|
||||
Get<RoutingManager>().UnpublishExternalRoute(mPrefix);
|
||||
LogInfo("Local on-link prefix %s expired", mPrefix.ToString().AsCString());
|
||||
Unpublish(mPrefix);
|
||||
mState = kIdle;
|
||||
}
|
||||
|
||||
mState = kIdle;
|
||||
if ((mOldPrefix.GetLength() != 0) && (now >= mOldExpireTime))
|
||||
{
|
||||
LogInfo("Old local on-link prefix %s expired", mOldPrefix.ToString().AsCString());
|
||||
Unpublish(mOldPrefix);
|
||||
mOldPrefix.Clear();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
// Re-schedule the timer
|
||||
|
||||
if (mState == kDeprecating)
|
||||
{
|
||||
mTimer.FireAt(mExpireTime);
|
||||
}
|
||||
|
||||
if (mOldPrefix.GetLength() != 0)
|
||||
{
|
||||
mTimer.FireAtIfEarlier(mOldExpireTime);
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingManager::LocalOnLinkPrefix::Unpublish(const Ip6::Prefix &aPrefix)
|
||||
{
|
||||
if (!Get<RoutingManager>().mDiscoveredPrefixTable.ContainsOnLinkPrefix(aPrefix))
|
||||
{
|
||||
Get<RoutingManager>().UnpublishExternalRoute(aPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -590,7 +590,7 @@ private:
|
||||
void Stop(void);
|
||||
Error Advertise(void);
|
||||
void Deprecate(void);
|
||||
void AppendAsPioTo(Ip6::Nd::RouterAdvertMessage &aRaMessage);
|
||||
void AppendAsPiosTo(Ip6::Nd::RouterAdvertMessage &aRaMessage);
|
||||
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
|
||||
bool IsAdvertising(void) const { return (mState == kAdvertising); }
|
||||
void HandleExtPanIdChange(void);
|
||||
@@ -603,11 +603,18 @@ private:
|
||||
kDeprecating,
|
||||
};
|
||||
|
||||
void AppendCurPrefix(Ip6::Nd::RouterAdvertMessage &aRaMessage);
|
||||
void AppendOldPrefix(Ip6::Nd::RouterAdvertMessage &aRaMessage);
|
||||
void Unpublish(const Ip6::Prefix &aPrefix);
|
||||
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
|
||||
Ip6::Prefix mPrefix;
|
||||
State mState;
|
||||
TimeMilli mExpireTime;
|
||||
Ip6::Prefix mOldPrefix;
|
||||
TimeMilli mOldExpireTime;
|
||||
TimerMilli mTimer;
|
||||
};
|
||||
|
||||
|
||||
@@ -78,10 +78,13 @@ enum ExpectedPio
|
||||
|
||||
static Ip6::Address sInfraIfAddress;
|
||||
|
||||
bool sRsEmitted; // Indicates if an RS message was emitted by BR.
|
||||
bool sRaValidated; // Indicates if an RA was emitted by BR and successfully validated.
|
||||
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.
|
||||
bool sRsEmitted; // Indicates if an RS message was emitted by BR.
|
||||
bool sRaValidated; // Indicates if an RA was emitted by BR and successfully validated.
|
||||
ExpectedPio sExpectedPio; // Expected PIO in the emitted RA by BR (MUST be seen in RA to set `sRaValidated`).
|
||||
bool sExpectOldOnLinkPio; // Expect to see old local prefix PIO
|
||||
uint32_t sOnLinkLifetime; // Valid lifetime for local on-link prefix from the last processed RA.
|
||||
uint32_t sOldOnLinkLifetime; // Valid lifetime of the old local prefix PIO (when `sExpectOldOnLinkPio`).
|
||||
Ip6::Prefix sOldOnLinkPrefix; // The old on-link PIO prefix in last processed RA (when `sExpectOldOnLinkPio`)
|
||||
|
||||
static constexpr uint16_t kMaxRioPrefixes = 10;
|
||||
|
||||
@@ -208,7 +211,6 @@ otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
|
||||
Log(" Router Advertisement message");
|
||||
LogRouterAdvert(packet);
|
||||
ValidateRouterAdvert(packet);
|
||||
sRaValidated = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -257,6 +259,8 @@ void AdvanceTime(uint32_t aDuration)
|
||||
void ValidateRouterAdvert(const Icmp6Packet &aPacket)
|
||||
{
|
||||
Ip6::Nd::RouterAdvertMessage raMsg(aPacket);
|
||||
bool sawExpectedPio = false;
|
||||
bool sawExpecteOldPio = false;
|
||||
|
||||
VerifyOrQuit(raMsg.IsValid());
|
||||
|
||||
@@ -273,22 +277,39 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
|
||||
VerifyOrQuit(pio.IsValid());
|
||||
pio.GetPrefix(prefix);
|
||||
|
||||
VerifyOrQuit(sExpectedPio != kNoPio, "Received RA contain an unexpected PIO");
|
||||
|
||||
SuccessOrQuit(otBorderRoutingGetOnLinkPrefix(sInstance, &localOnLink));
|
||||
VerifyOrQuit(prefix == localOnLink);
|
||||
|
||||
if (sExpectedPio == kPioAdvertisingLocalOnLink)
|
||||
if (prefix == localOnLink)
|
||||
{
|
||||
VerifyOrQuit(pio.GetPreferredLifetime() > 0, "On link prefix is deprecated unexpectedly");
|
||||
switch (sExpectedPio)
|
||||
{
|
||||
case kNoPio:
|
||||
break;
|
||||
|
||||
case kPioAdvertisingLocalOnLink:
|
||||
VerifyOrQuit(pio.GetPreferredLifetime() > 0, "On link prefix is deprecated unexpectedly");
|
||||
sOnLinkLifetime = pio.GetValidLifetime();
|
||||
sawExpectedPio = true;
|
||||
break;
|
||||
|
||||
case kPioDeprecatingLocalOnLink:
|
||||
VerifyOrQuit(pio.GetPreferredLifetime() == 0, "On link prefix is not deprecated");
|
||||
sOnLinkLifetime = pio.GetValidLifetime();
|
||||
sawExpectedPio = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(pio.GetPreferredLifetime() == 0, "On link prefix is not deprecated");
|
||||
VerifyOrQuit(pio.GetPreferredLifetime() == 0, "Old on link prefix is not deprecated");
|
||||
sOldOnLinkPrefix = prefix;
|
||||
sOldOnLinkLifetime = pio.GetValidLifetime();
|
||||
|
||||
if (sExpectOldOnLinkPio)
|
||||
{
|
||||
sawExpecteOldPio = true;
|
||||
}
|
||||
}
|
||||
|
||||
sOnLinkLifetime = pio.GetValidLifetime();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -316,6 +337,25 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
|
||||
VerifyOrQuit(false, "Unexpected option type in RA msg");
|
||||
}
|
||||
}
|
||||
|
||||
if (!sRaValidated)
|
||||
{
|
||||
switch (sExpectedPio)
|
||||
{
|
||||
case kNoPio:
|
||||
break;
|
||||
case kPioAdvertisingLocalOnLink:
|
||||
case kPioDeprecatingLocalOnLink:
|
||||
VerifyOrQuit(sawExpectedPio, "Did not see on-link prefix PIO in the RA");
|
||||
}
|
||||
|
||||
if (sExpectOldOnLinkPio)
|
||||
{
|
||||
VerifyOrQuit(sawExpecteOldPio, "Did not see old on-link prefix PIO in the RA");
|
||||
}
|
||||
|
||||
sRaValidated = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LogRouterAdvert(const Icmp6Packet &aPacket)
|
||||
@@ -702,6 +742,12 @@ void InitTest(void)
|
||||
AdvanceTime(10000);
|
||||
|
||||
VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
|
||||
|
||||
// Reset all test flags
|
||||
sRsEmitted = false;
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kNoPio;
|
||||
sExpectedRios.Clear();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1435,6 +1481,246 @@ void TestDomainPrefixAsOmr(void)
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
|
||||
void TestExtPanIdChange(void)
|
||||
{
|
||||
static constexpr uint32_t kMaxRaTxInterval = 601; // In seconds
|
||||
|
||||
static const otExtendedPanId kExtPanId1 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x08}};
|
||||
static const otExtendedPanId kExtPanId2 = {{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x99, 0x88}};
|
||||
|
||||
Ip6::Prefix localOnLink;
|
||||
Ip6::Prefix oldLocalOnLink;
|
||||
Ip6::Prefix localOmr;
|
||||
Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64);
|
||||
Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
|
||||
uint32_t oldPrefixLifetime;
|
||||
otOperationalDataset dataset;
|
||||
|
||||
Log("--------------------------------------------------------------------------------------------");
|
||||
Log("TestExtPanIdChange");
|
||||
|
||||
InitTest();
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Start Routing Manager. Check emitted RS and RA messages.
|
||||
|
||||
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());
|
||||
|
||||
sRsEmitted = false;
|
||||
sRaValidated = false;
|
||||
sExpectedPio = kPioAdvertisingLocalOnLink;
|
||||
sExpectedRios.Clear();
|
||||
sExpectedRios.Add(localOmr);
|
||||
|
||||
AdvanceTime(30000);
|
||||
|
||||
VerifyOrQuit(sRsEmitted);
|
||||
VerifyOrQuit(sRaValidated);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
Log("Local on-link prefix is being advertised, lifetime: %d", sOnLinkLifetime);
|
||||
|
||||
//= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
// Check behavior when ext PAN ID changes while the local on-link is
|
||||
// being advertised.
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Change the extended PAN ID.
|
||||
|
||||
Log("Changing ext PAN ID");
|
||||
|
||||
oldLocalOnLink = localOnLink;
|
||||
oldPrefixLifetime = sOnLinkLifetime;
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectOldOnLinkPio = true;
|
||||
sExpectedPio = kPioAdvertisingLocalOnLink;
|
||||
|
||||
SuccessOrQuit(otDatasetGetActive(sInstance, &dataset));
|
||||
|
||||
VerifyOrQuit(dataset.mComponents.mIsExtendedPanIdPresent);
|
||||
|
||||
dataset.mExtendedPanId = kExtPanId1;
|
||||
SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
|
||||
|
||||
AdvanceTime(500);
|
||||
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
|
||||
Log("Local on-link prefix changed to %s from %s", localOnLink.ToString().AsCString(),
|
||||
oldLocalOnLink.ToString().AsCString());
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate the received RA message and that it contains the
|
||||
// old on-link prefix being deprecated.
|
||||
|
||||
AdvanceTime(30000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
VerifyOrQuit(sOldOnLinkPrefix == oldLocalOnLink);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate the Network Data to contain both the current and old
|
||||
// local on-link prefixes.
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr);
|
||||
VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium),
|
||||
ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Wait for old local on-link prefix to expire.
|
||||
|
||||
while (oldPrefixLifetime > kMaxRaTxInterval)
|
||||
{
|
||||
// Ensure Network Data entries remain as before. Mainly we still
|
||||
// see the deprecating local on-link prefix.
|
||||
|
||||
VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium),
|
||||
ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
// Keep checking the emitted RAs and make sure the prefix
|
||||
// is included with smaller lifetime every time.
|
||||
|
||||
sRaValidated = false;
|
||||
|
||||
AdvanceTime(kMaxRaTxInterval * 1000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
Log("Old on-link prefix is deprecating, remaining lifetime:%d", sOldOnLinkLifetime);
|
||||
VerifyOrQuit(sOldOnLinkLifetime < oldPrefixLifetime);
|
||||
oldPrefixLifetime = sOldOnLinkLifetime;
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// The local on-link prefix must be expired now and should no
|
||||
// longer be seen in the emitted RA message.
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectOldOnLinkPio = false;
|
||||
|
||||
AdvanceTime(kMaxRaTxInterval * 1000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
Log("Old on-link prefix is now expired");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate the Network Data now only contains the current local
|
||||
// on-link prefix.
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr);
|
||||
VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
//= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
// Check behavior when ext PAN ID changes while the local on-link is being
|
||||
// deprecated.
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Send an RA from router A with a new on-link (PIO) which is preferred over
|
||||
// the local on-link prefix.
|
||||
|
||||
SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate that the local on-link prefix is deprecated.
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectOldOnLinkPio = false;
|
||||
sExpectedPio = kPioDeprecatingLocalOnLink;
|
||||
|
||||
AdvanceTime(30000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Change the extended PAN ID.
|
||||
|
||||
oldLocalOnLink = localOnLink;
|
||||
oldPrefixLifetime = sOnLinkLifetime;
|
||||
|
||||
dataset.mExtendedPanId = kExtPanId2;
|
||||
SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
|
||||
|
||||
AdvanceTime(500);
|
||||
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
|
||||
Log("Local on-link prefix changed to %s from %s", localOnLink.ToString().AsCString(),
|
||||
oldLocalOnLink.ToString().AsCString());
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate that the old local on-link prefix is still being included
|
||||
// as PIO in the emitted RA.
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectOldOnLinkPio = true;
|
||||
sExpectedPio = kNoPio;
|
||||
|
||||
AdvanceTime(30000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate that Network Data contains the old local on-link
|
||||
// prefix along with entry from router A.
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr);
|
||||
VerifyExternalRoutesInNetData({ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium),
|
||||
ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Wait for old local on-link prefix to expire.
|
||||
|
||||
while (oldPrefixLifetime > kMaxRaTxInterval)
|
||||
{
|
||||
// Send same RA from router A to keep its on-link prefix alive.
|
||||
|
||||
SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
|
||||
|
||||
// Ensure Network Data entries remain as before. Mainly we still
|
||||
// see the deprecating old local on-link prefix.
|
||||
|
||||
VerifyExternalRoutesInNetData({ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium),
|
||||
ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
// Keep checking the emitted RAs and make sure the prefix
|
||||
// is included with smaller lifetime every time.
|
||||
|
||||
sRaValidated = false;
|
||||
|
||||
AdvanceTime(kMaxRaTxInterval * 1000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
Log("Old on-link prefix is deprecating, remaining lifetime:%d", sOldOnLinkLifetime);
|
||||
VerifyOrQuit(sOldOnLinkLifetime < oldPrefixLifetime);
|
||||
oldPrefixLifetime = sOldOnLinkLifetime;
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// The old on-link prefix must be expired now and should no
|
||||
// longer be seen in the emitted RA message.
|
||||
|
||||
sRaValidated = false;
|
||||
sExpectOldOnLinkPio = false;
|
||||
|
||||
AdvanceTime(kMaxRaTxInterval * 1000);
|
||||
|
||||
VerifyOrQuit(sRaValidated);
|
||||
Log("Old on-link prefix is now expired");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate the Network Data to now only contains entry from router A
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr);
|
||||
VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
Log("End of TestExtPanIdChange");
|
||||
|
||||
testFreeInstance(sInstance);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
int main(void)
|
||||
@@ -1447,6 +1733,7 @@ int main(void)
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
TestDomainPrefixAsOmr();
|
||||
#endif
|
||||
TestExtPanIdChange();
|
||||
printf("All tests passed\n");
|
||||
#else
|
||||
printf("BORDER_ROUTING feature is not enabled\n");
|
||||
|
||||
Reference in New Issue
Block a user