[routing-manager] add Nat64PrefixManager nested class. (#8178)

This commit adds `Nat64PrefixManager` class in `RoutingManager` which
contains the NAT64 related logic including generation of local NAT64
prefix, discovery of infra interface prefix, maintaining the
discovered prefix lifetime, and selection of the NAT64 prefix to
publish in Network Data. This class encapsulates all variables and
methods related to NAT64.
This commit is contained in:
Abtin Keshavarzian
2022-09-19 11:01:44 -07:00
committed by GitHub
parent 6df8627135
commit bacf8d625f
3 changed files with 196 additions and 145 deletions
+1 -1
View File
@@ -128,7 +128,7 @@ void InfraIf::DiscoverNat64PrefixDone(uint32_t aIfIndex, const Ip6::Prefix &aPre
VerifyOrExit(aIfIndex == mIfIndex, error = kErrorInvalidArgs);
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
Get<RoutingManager>().UpdateInfraIfNat64Prefix(aPrefix);
Get<RoutingManager>().HandleDiscoverNat64PrefixDone(aPrefix);
#endif
exit:
+156 -118
View File
@@ -72,7 +72,7 @@ RoutingManager::RoutingManager(Instance &aInstance)
, mLocalOnLinkPrefix(aInstance)
, mDiscoveredPrefixTable(aInstance)
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
, mInfraIfNat64PrefixStaleTimer(aInstance, HandleInfraIfNat64PrefixStaleTimer)
, mNat64PrefixManager(aInstance)
#endif
, mRsSender(aInstance)
, mDiscoveredPrefixStaleTimer(aInstance, HandleDiscoveredPrefixStaleTimer)
@@ -81,11 +81,6 @@ RoutingManager::RoutingManager(Instance &aInstance)
mFavoredDiscoveredOnLinkPrefix.Clear();
mBrUlaPrefix.Clear();
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
mInfraIfNat64Prefix.Clear();
mLocalNat64Prefix.Clear();
mPublishedNat64Prefix.Clear();
#endif
}
Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning)
@@ -97,7 +92,7 @@ Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning)
SuccessOrExit(error = LoadOrGenerateRandomBrUlaPrefix());
mLocalOmrPrefix.GenerateFrom(mBrUlaPrefix);
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
GenerateNat64Prefix();
mNat64PrefixManager.GenerateLocalPrefix(mBrUlaPrefix);
#endif
mLocalOnLinkPrefix.Generate();
@@ -180,7 +175,7 @@ Error RoutingManager::GetNat64Prefix(Ip6::Prefix &aPrefix)
Error error = kErrorNone;
VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
aPrefix = mLocalNat64Prefix;
aPrefix = mNat64PrefixManager.GetLocalPrefix();
exit:
return error;
@@ -191,9 +186,7 @@ Error RoutingManager::GetFavoredNat64Prefix(Ip6::Prefix &aPrefix, RoutePreferenc
Error error = kErrorNone;
VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
aPrefix = mInfraIfNat64Prefix.IsValidNat64() ? mInfraIfNat64Prefix : mLocalNat64Prefix;
aRoutePreference =
mInfraIfNat64Prefix.IsValidNat64() ? NetworkData::kRoutePreferenceMedium : NetworkData::kRoutePreferenceLow;
aPrefix = mNat64PrefixManager.GetFavoredPrefix(aRoutePreference);
exit:
return error;
@@ -233,47 +226,6 @@ exit:
return error;
}
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
void RoutingManager::DiscoverInfraIfNat64Prefix(void)
{
Error error = kErrorNone;
VerifyOrExit(IsInitialized() && mInfraIf.IsRunning(), error = kErrorInvalidState);
LogInfo("Discovering infrastructure NAT64 prefix on %s", mInfraIf.ToString().AsCString());
error = mInfraIf.DiscoverNat64Prefix();
exit:
if (error != kErrorNone)
{
LogWarn("Failed to request infrastructure NAT64 prefix on %s: %s", mInfraIf.ToString().AsCString(),
ErrorToString(error));
}
}
void RoutingManager::UpdateInfraIfNat64Prefix(const Ip6::Prefix &aPrefix)
{
mInfraIfNat64Prefix = aPrefix;
LogInfo("Get infrastructure NAT64 prefix: %s",
mInfraIfNat64Prefix.IsValidNat64() ? mInfraIfNat64Prefix.ToString().AsCString() : "none");
if (mIsRunning)
{
ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
}
}
void RoutingManager::GenerateNat64Prefix(void)
{
mLocalNat64Prefix = mBrUlaPrefix;
mLocalNat64Prefix.SetSubnetId(kNat64PrefixSubnetId);
mLocalNat64Prefix.mPrefix.mFields.m32[2] = 0;
mLocalNat64Prefix.SetLength(kNat64PrefixLength);
LogInfo("Generated local NAT64 prefix: %s", mLocalNat64Prefix.ToString().AsCString());
}
#endif
void RoutingManager::EvaluateState(void)
{
if (mIsEnabled && Get<Mle::MleRouter>().IsAttached() && mInfraIf.IsRunning())
@@ -297,7 +249,7 @@ void RoutingManager::Start(void)
mLocalOnLinkPrefix.Start();
mRsSender.Start();
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
mInfraIfNat64PrefixStaleTimer.Start(0);
mNat64PrefixManager.Start();
#endif
}
}
@@ -314,14 +266,9 @@ void RoutingManager::Stop(void)
mLocalOnLinkPrefix.Stop();
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
if (mPublishedNat64Prefix.IsValidNat64())
{
UnpublishExternalRoute(mPublishedNat64Prefix);
}
mPublishedNat64Prefix.Clear();
mInfraIfNat64Prefix.Clear();
mInfraIfNat64PrefixStaleTimer.Stop();
mNat64PrefixManager.Stop();
#endif
SendRouterAdvertisement(kInvalidateAllPrevPrefixes);
mAdvertisedPrefixes.Clear();
@@ -572,48 +519,6 @@ exit:
return;
}
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
void RoutingManager::EvaluateNat64Prefix(void)
{
Ip6::Prefix nat64Prefix;
RoutePreference routePreference;
Error error;
NetworkData::ExternalRouteConfig preferredNat64PrefixConfig;
bool shouldPublish;
OT_ASSERT(mIsRunning);
LogInfo("Evaluating NAT64 prefix");
SuccessOrAssert(GetFavoredNat64Prefix(nat64Prefix, routePreference));
error = Get<NetworkData::Leader>().GetPreferredNat64Prefix(preferredNat64PrefixConfig);
// NAT64 prefix is expected to be published from this BR when one of the following is true:
// - no NAT64 prefix exits in Network Data yet
// - the preferred NAT64 prefix in Network Data has lower preference than this BR's prefix
// - the preferred NAT64 prefix in Network Data was published by this BR
// - the preferred NAT64 prefix in Network Data is same as the infrastructure prefix
// TODO: change to check RLOC16 to determine if the NAT64 prefix was published by this BR
shouldPublish = (error == kErrorNotFound || preferredNat64PrefixConfig.mPreference < routePreference ||
preferredNat64PrefixConfig.GetPrefix() == mPublishedNat64Prefix ||
preferredNat64PrefixConfig.GetPrefix() == mInfraIfNat64Prefix);
if (mPublishedNat64Prefix.IsValidNat64() && (!shouldPublish || nat64Prefix != mPublishedNat64Prefix))
{
UnpublishExternalRoute(mPublishedNat64Prefix);
mPublishedNat64Prefix.Clear();
}
if (shouldPublish && nat64Prefix != mPublishedNat64Prefix &&
PublishExternalRoute(nat64Prefix, routePreference, /* aNat64= */ true) == kErrorNone)
{
mPublishedNat64Prefix = nat64Prefix;
}
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
Get<Nat64::Translator>().SetNat64Prefix(mPublishedNat64Prefix);
#endif
}
#endif
// This method evaluate the routing policy depends on prefix and route
// information on Thread Network and infra link. As a result, this
// method May send RA messages on infra link and publish/unpublish
@@ -627,7 +532,7 @@ void RoutingManager::EvaluateRoutingPolicy(void)
EvaluateOnLinkPrefix();
EvaluateOmrPrefix();
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
EvaluateNat64Prefix();
mNat64PrefixManager.Evaluate();
#endif
SendRouterAdvertisement(kAdvPrefixesFromNetData);
@@ -969,21 +874,6 @@ void RoutingManager::HandleRoutingPolicyTimer(Timer &aTimer)
aTimer.Get<RoutingManager>().EvaluateRoutingPolicy();
}
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
void RoutingManager::HandleInfraIfNat64PrefixStaleTimer(Timer &aTimer)
{
aTimer.Get<RoutingManager>().HandleInfraIfNat64PrefixStaleTimer();
}
void RoutingManager::HandleInfraIfNat64PrefixStaleTimer(void)
{
DiscoverInfraIfNat64Prefix();
mInfraIfNat64PrefixStaleTimer.Start(TimeMilli::SecToMsec(kDefaultNat64PrefixLifetime));
LogInfo("NAT64 prefix timer scheduled in %u seconds", kDefaultNat64PrefixLifetime);
}
#endif
void RoutingManager::HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress)
{
OT_UNUSED_VARIABLE(aPacket);
@@ -2290,6 +2180,154 @@ void RoutingManager::OnMeshPrefixArray::MarkAsDeleted(const OnMeshPrefix &aPrefi
}
}
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// Nat64PrefixManager
RoutingManager::Nat64PrefixManager::Nat64PrefixManager(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimer(aInstance, HandleTimer)
{
mInfraIfPrefix.Clear();
mLocalPrefix.Clear();
mPublishedPrefix.Clear();
}
void RoutingManager::Nat64PrefixManager::Start(void)
{
mTimer.Start(0);
}
void RoutingManager::Nat64PrefixManager::Stop(void)
{
if (mPublishedPrefix.IsValidNat64())
{
Get<RoutingManager>().UnpublishExternalRoute(mPublishedPrefix);
}
mPublishedPrefix.Clear();
mInfraIfPrefix.Clear();
mTimer.Stop();
}
void RoutingManager::Nat64PrefixManager::GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix)
{
mLocalPrefix = aBrUlaPrefix;
mLocalPrefix.SetSubnetId(kNat64PrefixSubnetId);
mLocalPrefix.mPrefix.mFields.m32[2] = 0;
mLocalPrefix.SetLength(kNat64PrefixLength);
LogInfo("Generated local NAT64 prefix: %s", mLocalPrefix.ToString().AsCString());
}
const Ip6::Prefix &RoutingManager::Nat64PrefixManager::GetFavoredPrefix(RoutePreference &aPreference) const
{
const Ip6::Prefix *favoredPrefix = &mInfraIfPrefix;
if (mInfraIfPrefix.IsValidNat64())
{
aPreference = NetworkData::kRoutePreferenceMedium;
}
else
{
favoredPrefix = &mLocalPrefix;
aPreference = NetworkData::kRoutePreferenceLow;
}
return *favoredPrefix;
}
void RoutingManager::Nat64PrefixManager::Evaluate(void)
{
Error error;
Ip6::Prefix prefix;
RoutePreference preference;
NetworkData::ExternalRouteConfig netdataPrefixConfig;
bool shouldPublish;
LogInfo("Evaluating NAT64 prefix");
prefix = GetFavoredPrefix(preference);
error = Get<NetworkData::Leader>().GetPreferredNat64Prefix(netdataPrefixConfig);
// NAT64 prefix is expected to be published from this BR
// when one of the following is true:
//
// - No NAT64 prefix in Network Data.
// - The preferred NAT64 prefix in Network Data has lower
// preference than this BR's prefix.
// - The preferred NAT64 prefix in Network Data was published
// by this BR.
// - The preferred NAT64 prefix in Network Data is same as the
// discovered infrastructure prefix.
//
// TODO: change to check RLOC16 to determine if the NAT64 prefix
// was published by this BR.
shouldPublish =
((error == kErrorNotFound) || (netdataPrefixConfig.mPreference < preference) ||
(netdataPrefixConfig.GetPrefix() == mPublishedPrefix) || (netdataPrefixConfig.GetPrefix() == mInfraIfPrefix));
if (mPublishedPrefix.IsValidNat64() && (!shouldPublish || (prefix != mPublishedPrefix)))
{
Get<RoutingManager>().UnpublishExternalRoute(mPublishedPrefix);
mPublishedPrefix.Clear();
}
if (shouldPublish && (prefix != mPublishedPrefix) &&
(Get<RoutingManager>().PublishExternalRoute(prefix, preference, /* aNat64 */ true) == kErrorNone))
{
mPublishedPrefix = prefix;
}
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
Get<Nat64::Translator>().SetNat64Prefix(mPublishedPrefix);
#endif
}
void RoutingManager::Nat64PrefixManager::HandleTimer(Timer &aTimer)
{
aTimer.Get<RoutingManager>().mNat64PrefixManager.HandleTimer();
}
void RoutingManager::Nat64PrefixManager::HandleTimer(void)
{
Discover();
mTimer.Start(TimeMilli::SecToMsec(kDefaultNat64PrefixLifetime));
LogInfo("NAT64 prefix timer scheduled in %u seconds", kDefaultNat64PrefixLifetime);
}
void RoutingManager::Nat64PrefixManager::Discover(void)
{
Error error = Get<RoutingManager>().mInfraIf.DiscoverNat64Prefix();
if (error == kErrorNone)
{
LogInfo("Discovering infraif NAT64 prefix");
}
else
{
LogWarn("Failed to discover infraif NAT64 prefix: %s", ErrorToString(error));
}
}
void RoutingManager::Nat64PrefixManager::HandleDiscoverDone(const Ip6::Prefix &aPrefix)
{
mInfraIfPrefix = aPrefix;
LogInfo("Infraif NAT64 prefix: %s", mInfraIfPrefix.IsValidNat64() ? mInfraIfPrefix.ToString().AsCString() : "none");
if (Get<RoutingManager>().mIsRunning)
{
Get<RoutingManager>().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
}
}
#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// RsSender
+39 -26
View File
@@ -230,12 +230,14 @@ public:
Error GetFavoredNat64Prefix(Ip6::Prefix &aPrefix, RoutePreference &aRoutePreference);
/**
* This method updates mInfraIfNat64Prefix to @p aPrefix.
* This method informs `RoutingManager` of the result of the discovery request of NAT64 prefix on infrastructure
* interface (`InfraIf::DiscoverNat64Prefix()`).
*
* @param[in] aPrefix A NAT64 prefix on infrastructure link.
* @param[in] aPrefix The discovered NAT64 prefix on `InfraIf`.
*
*/
void UpdateInfraIfNat64Prefix(const Ip6::Prefix &aPrefix);
void HandleDiscoverNat64PrefixDone(const Ip6::Prefix &aPrefix) { mNat64PrefixManager.HandleDiscoverDone(aPrefix); }
#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
/**
@@ -627,6 +629,38 @@ private:
void MarkAsDeleted(const OnMeshPrefix &aPrefix);
};
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
class Nat64PrefixManager : public InstanceLocator
{
public:
// This class manages the NAT64 related functions including
// generation of local NAT64 prefix, discovery of infra
// interface prefix, maintaining the discovered prefix
// lifetime, and selection of the NAT64 prefix to publish in
// Network Data.
explicit Nat64PrefixManager(Instance &aInstance);
void Start(void);
void Stop(void);
void GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix);
const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; }
const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const;
void Evaluate(void);
void HandleDiscoverDone(const Ip6::Prefix &aPrefix);
private:
void Discover(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
Ip6::Prefix mInfraIfPrefix; // The latest NAT64 prefix discovered on the infrastructure interface.
Ip6::Prefix mLocalPrefix; // The local prefix (from BR ULA prefix).
Ip6::Prefix mPublishedPrefix; // The prefix published in Network Data (may be empty or local or from infra-if).
TimerMilli mTimer;
};
#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
struct RaInfo
{
// Tracks info about emitted RA messages: Number of RAs sent,
@@ -692,14 +726,7 @@ private:
bool IsEnabled(void) const { return mIsEnabled; }
Error LoadOrGenerateRandomBrUlaPrefix(void);
void EvaluateOnLinkPrefix(void);
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
void DiscoverInfraIfNat64Prefix(void);
void GenerateNat64Prefix(void);
void EvaluateNat64Prefix(void);
#endif
void EvaluateOnLinkPrefix(void);
void EvaluateRoutingPolicy(void);
void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode);
void EvaluateOmrPrefix(void);
@@ -713,10 +740,6 @@ private:
static void HandleDiscoveredPrefixStaleTimer(Timer &aTimer);
void HandleDiscoveredPrefixStaleTimer(void);
static void HandleRoutingPolicyTimer(Timer &aTimer);
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
static void HandleInfraIfNat64PrefixStaleTimer(Timer &aTimer);
void HandleInfraIfNat64PrefixStaleTimer(void);
#endif
void DeprecateOnLinkPrefix(void);
void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
@@ -764,17 +787,7 @@ private:
DiscoveredPrefixTable mDiscoveredPrefixTable;
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
// The latest NAT64 prefix discovered on the infrastructure interface.
Ip6::Prefix mInfraIfNat64Prefix;
// The NAT64 prefix allocated from the /48 BR ULA prefix.
Ip6::Prefix mLocalNat64Prefix;
// The NAT64 prefix published in Network Data. It can have the following value:
// - empty: no NAT64 prefix is published from this BR
// - the local NAT64 prefix
// - the latest published infrastructure NAT64 prefix, which might differs from mInfraIfNat64Prefix
Ip6::Prefix mPublishedNat64Prefix;
TimerMilli mInfraIfNat64PrefixStaleTimer;
Nat64PrefixManager mNat64PrefixManager;
#endif
RaInfo mRaInfo;