[nat64] allocate NAT64 prefix and OMR prefix from the same /48 BR ULA prefix (#7436)

This commit updates the local NAT64 prefix and OMR prefix to be
allocated from the same /48 BR ULA prefix. The /48 prefix is generated
randomly and is saved in Settings for recovery. The subnet id of
prefixes are statically assigned to avoid conflict with each other in
a simple way.
This commit is contained in:
Yi
2022-03-09 14:33:44 -08:00
committed by GitHub
parent 9021935bcc
commit 304caab7ba
7 changed files with 119 additions and 93 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (196)
#define OPENTHREAD_API_VERSION (197)
/**
* @addtogroup api-instance
+3 -2
View File
@@ -68,12 +68,13 @@ enum
OT_SETTINGS_KEY_RESERVED = 0x0006, ///< Reserved (previously auto-start).
OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID.
OT_SETTINGS_KEY_DAD_INFO = 0x0008, ///< Duplicate Address Detection (DAD) information.
OT_SETTINGS_KEY_OMR_PREFIX = 0x0009, ///< Off-mesh routable (OMR) prefix.
OT_SETTINGS_KEY_LEGACY_OMR_PREFIX = 0x0009, ///< Reserved. Legacy Off-mesh routable (OMR) prefix.
OT_SETTINGS_KEY_ON_LINK_PREFIX = 0x000a, ///< On-link prefix for infrastructure link.
OT_SETTINGS_KEY_SRP_ECDSA_KEY = 0x000b, ///< SRP client ECDSA public/private key pair.
OT_SETTINGS_KEY_SRP_CLIENT_INFO = 0x000c, ///< The SRP client info (selected SRP server address).
OT_SETTINGS_KEY_SRP_SERVER_INFO = 0x000d, ///< The SRP server info (UDP port).
OT_SETTINGS_KEY_NAT64_PREFIX = 0x000e, ///< NAT64 prefix.
OT_SETTINGS_KEY_LEGACY_NAT64_PREFIX = 0x000e, ///< Reserved. Legacy NAT64 prefix.
OT_SETTINGS_KEY_BR_ULA_PREFIX = 0x000f, ///< BR ULA prefix.
};
/**
+50 -52
View File
@@ -79,6 +79,8 @@ RoutingManager::RoutingManager(Instance &aInstance)
, mRouterSolicitCount(0)
, mRoutingPolicyTimer(aInstance, HandleRoutingPolicyTimer)
{
mBrUlaPrefix.Clear();
mLocalOmrPrefix.Clear();
mLocalOnLinkPrefix.Clear();
@@ -93,11 +95,12 @@ Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning)
VerifyOrExit(!IsInitialized(), error = kErrorInvalidState);
VerifyOrExit(aInfraIfIndex > 0, error = kErrorInvalidArgs);
SuccessOrExit(error = LoadOrGenerateRandomOmrPrefix());
SuccessOrExit(error = LoadOrGenerateRandomOnLinkPrefix());
SuccessOrExit(error = LoadOrGenerateRandomBrUlaPrefix());
GenerateOmrPrefix();
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
SuccessOrExit(error = LoadOrGenerateRandomNat64Prefix());
GenerateNat64Prefix();
#endif
SuccessOrExit(error = LoadOrGenerateRandomOnLinkPrefix());
mInfraIfIndex = aInfraIfIndex;
@@ -162,38 +165,62 @@ exit:
}
#endif
Error RoutingManager::LoadOrGenerateRandomOmrPrefix(void)
Error RoutingManager::LoadOrGenerateRandomBrUlaPrefix(void)
{
Error error = kErrorNone;
bool generated = false;
if (Get<Settings>().Read<Settings::OmrPrefix>(mLocalOmrPrefix) != kErrorNone || !IsValidOmrPrefix(mLocalOmrPrefix))
if (Get<Settings>().Read<Settings::BrUlaPrefix>(mBrUlaPrefix) != kErrorNone || !IsValidBrUlaPrefix(mBrUlaPrefix))
{
Ip6::NetworkPrefix randomOmrPrefix;
Ip6::NetworkPrefix randomUlaPrefix;
LogNote("No valid OMR prefix found in settings, generating new one");
LogNote("No valid /48 BR ULA prefix found in settings, generating new one");
// TODO: generate OMR prefix from the /48 BR ULA prefix
error = randomOmrPrefix.GenerateRandomUla();
if (error != kErrorNone)
{
LogCrit("Failed to generate random OMR prefix");
ExitNow();
}
SuccessOrExit(error = randomUlaPrefix.GenerateRandomUla());
mLocalOmrPrefix.Set(randomOmrPrefix);
IgnoreError(Get<Settings>().Save<Settings::OmrPrefix>(mLocalOmrPrefix));
mBrUlaPrefix.Set(randomUlaPrefix);
mBrUlaPrefix.SetSubnetId(0);
mBrUlaPrefix.SetLength(kBrUlaPrefixLength);
IgnoreError(Get<Settings>().Save<Settings::BrUlaPrefix>(mBrUlaPrefix));
generated = true;
}
OT_UNUSED_VARIABLE(generated);
LogNote("Local OMR prefix: %s (%s)", mLocalOmrPrefix.ToString().AsCString(), generated ? "generated" : "loaded");
LogNote("BR ULA prefix: %s (%s)", mBrUlaPrefix.ToString().AsCString(), generated ? "generated" : "loaded");
exit:
if (error != kErrorNone)
{
LogCrit("Failed to generate random /48 BR ULA prefix");
}
return error;
}
void RoutingManager::GenerateOmrPrefix(void)
{
IgnoreError(Get<Settings>().Delete<Settings::LegacyOmrPrefix>());
mLocalOmrPrefix = mBrUlaPrefix;
mLocalOmrPrefix.SetSubnetId(kOmrPrefixSubnetId);
mLocalOmrPrefix.SetLength(kOmrPrefixLength);
LogInfo("Generated OMR prefix: %s", mLocalOmrPrefix.ToString().AsCString());
}
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
void RoutingManager::GenerateNat64Prefix(void)
{
mLocalNat64Prefix = mBrUlaPrefix;
mLocalNat64Prefix.SetSubnetId(kNat64PrefixSubnetId);
mLocalNat64Prefix.mPrefix.mFields.m32[2] = 0;
mLocalNat64Prefix.SetLength(kNat64PrefixLength);
LogInfo("Generated NAT64 prefix: %s", mLocalNat64Prefix.ToString().AsCString());
}
#endif
Error RoutingManager::LoadOrGenerateRandomOnLinkPrefix(void)
{
Error error = kErrorNone;
@@ -211,9 +238,8 @@ Error RoutingManager::LoadOrGenerateRandomOnLinkPrefix(void)
ExitNow();
}
randomOnLinkPrefix.m8[6] = 0;
randomOnLinkPrefix.m8[7] = 0;
mLocalOnLinkPrefix.Set(randomOnLinkPrefix);
mLocalOnLinkPrefix.SetSubnetId(0);
IgnoreError(Get<Settings>().Save<Settings::OnLinkPrefix>(mLocalOnLinkPrefix));
generated = true;
@@ -228,39 +254,6 @@ exit:
return error;
}
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
Error RoutingManager::LoadOrGenerateRandomNat64Prefix(void)
{
Error error = kErrorNone;
if (Get<Settings>().Read<Settings::Nat64Prefix>(mLocalNat64Prefix) != kErrorNone ||
!mLocalNat64Prefix.IsValidNat64())
{
Ip6::NetworkPrefix randomNat64Prefix;
constexpr uint8_t nat64PrefixLength = 96;
LogNote("No valid NAT64 prefix found in settings, generating new one");
// TODO: generate NAT64 prefix from the /48 BR ULA prefix
error = randomNat64Prefix.GenerateRandomUla();
if (error != kErrorNone)
{
LogCrit("Failed to generate random NAT64 prefix");
ExitNow();
}
mLocalNat64Prefix.Clear();
mLocalNat64Prefix.Set(randomNat64Prefix);
mLocalNat64Prefix.SetLength(nat64PrefixLength);
IgnoreError(Get<Settings>().Save<Settings::Nat64Prefix>(mLocalNat64Prefix));
}
exit:
return error;
}
#endif
void RoutingManager::EvaluateState(void)
{
if (mIsEnabled && Get<Mle::MleRouter>().IsAttached() && mInfraIfIsRunning)
@@ -945,6 +938,11 @@ void RoutingManager::SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefix
}
}
bool RoutingManager::IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix)
{
return aBrUlaPrefix.mLength == kBrUlaPrefixLength && aBrUlaPrefix.mPrefix.mFields.m8[0] == 0xfd;
}
bool RoutingManager::IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig)
{
return IsValidOmrPrefix(aOnMeshPrefixConfig.GetPrefix()) && aOnMeshPrefixConfig.mSlaac && !aOnMeshPrefixConfig.mDp;
+16 -7
View File
@@ -198,6 +198,11 @@ private:
static constexpr uint8_t kOmrPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits.
static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits.
static constexpr uint8_t kBrUlaPrefixLength = 48; // The length of a BR ULA prefix. In bits.
static constexpr uint8_t kNat64PrefixLength = 96; // The length of a NAT64 prefix. In bits.
static constexpr uint16_t kOmrPrefixSubnetId = 1; // The subnet ID of an OMR prefix within a BR ULA prefix.
static constexpr uint16_t kNat64PrefixSubnetId = 2; // The subnet ID of a NAT64 prefix within a BR ULA prefix.
// The maximum number of initial Router Advertisements.
static constexpr uint32_t kMaxInitRtrAdvertisements = 3;
@@ -289,14 +294,15 @@ private:
void HandleNotifierEvents(Events aEvents);
bool IsInitialized(void) const { return mInfraIfIndex != 0; }
bool IsEnabled(void) const { return mIsEnabled; }
Error LoadOrGenerateRandomOmrPrefix(void);
Error LoadOrGenerateRandomBrUlaPrefix(void);
void GenerateOmrPrefix(void);
Error LoadOrGenerateRandomOnLinkPrefix(void);
const Ip6::Prefix *EvaluateOnLinkPrefix(void);
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
Error LoadOrGenerateRandomNat64Prefix(void);
void EvaluateNat64Prefix(void);
void GenerateNat64Prefix(void);
void EvaluateNat64Prefix(void);
#endif
void EvaluateRoutingPolicy(void);
@@ -338,6 +344,7 @@ private:
bool UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *aRouterAdvMessage);
void ResetDiscoveredPrefixStaleTimer(void);
static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix);
static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix);
static bool IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio);
@@ -358,8 +365,11 @@ private:
// messages will be sent.
uint32_t mInfraIfIndex;
// The OMR prefix loaded from local persistent storage or randomly
// generated if non is found in persistent storage.
// The /48 BR ULA prefix loaded from local persistent storage or
// randomly generated if none is found in persistent storage.
Ip6::Prefix mBrUlaPrefix;
// The OMR prefix allocated from the /48 BR ULA prefix.
Ip6::Prefix mLocalOmrPrefix;
// The advertised OMR prefixes. For a stable Thread network without
@@ -381,8 +391,7 @@ private:
TimeMilli mTimeAdvertisedOnLinkPrefix;
TimerMilli mOnLinkPrefixDeprecateTimer;
// The NAT64 prefix loaded from local persistent storage or
// randomly generated if none is found in persistent storage.
// The NAT64 prefix allocated from the /48 BR ULA prefix.
Ip6::Prefix mLocalNat64Prefix;
// True if the local NAT64 prefix is advertised in Thread network.
+10 -7
View File
@@ -149,12 +149,13 @@ const char *SettingsBase::KeyToString(Key aKey)
"", // (6) kKeyReserved
"SlaacIidSecretKey", // (7) kKeySlaacIidSecretKey
"DadInfo", // (8) kKeyDadInfo
"OmrPrefix", // (9) kKeyOmrPrefix
"LegacyOmrPrefix", // (9) kKeyLegacyOmrPrefix
"OnLinkPrefix", // (10) kKeyOnLinkPrefix
"SrpEcdsaKey", // (11) kKeySrpEcdsaKey
"SrpClientInfo", // (12) kKeySrpClientInfo
"SrpServerInfo", // (13) kKeySrpServerInfo
"Nat64Prefix", // (14) kKeyNat64Prefix
"LegacyNat64Prefix", // (14) kKeyLegacyNat64Prefix
"BrUlaPrefix", // (15) kKeyBrUlaPrefix
};
static_assert(1 == kKeyActiveDataset, "kKeyActiveDataset value is incorrect");
@@ -165,14 +166,15 @@ const char *SettingsBase::KeyToString(Key aKey)
static_assert(6 == kKeyReserved, "kKeyReserved value is incorrect");
static_assert(7 == kKeySlaacIidSecretKey, "kKeySlaacIidSecretKey value is incorrect");
static_assert(8 == kKeyDadInfo, "kKeyDadInfo value is incorrect");
static_assert(9 == kKeyOmrPrefix, "kKeyOmrPrefix value is incorrect");
static_assert(9 == kKeyLegacyOmrPrefix, "kKeyLegacyOmrPrefix value is incorrect");
static_assert(10 == kKeyOnLinkPrefix, "kKeyOnLinkPrefix value is incorrect");
static_assert(11 == kKeySrpEcdsaKey, "kKeySrpEcdsaKey value is incorrect");
static_assert(12 == kKeySrpClientInfo, "kKeySrpClientInfo value is incorrect");
static_assert(13 == kKeySrpServerInfo, "kKeySrpServerInfo value is incorrect");
static_assert(14 == kKeyNat64Prefix, "kKeyNat64Prefix value is incorrect");
static_assert(14 == kKeyLegacyNat64Prefix, "kKeyLegacyNat64Prefix value is incorrect");
static_assert(15 == kKeyBrUlaPrefix, "kKeyBrUlaPrefix value is incorrect");
static_assert(kLastKey == kKeyNat64Prefix, "kLastKey is not valid");
static_assert(kLastKey == kKeyBrUlaPrefix, "kLastKey is not valid");
OT_ASSERT(aKey <= kLastKey);
@@ -429,9 +431,10 @@ void Settings::Log(Action aAction, Error aError, Key aKey, const void *aValue)
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
case kKeyOmrPrefix:
case kKeyBrUlaPrefix:
case kKeyLegacyOmrPrefix:
case kKeyOnLinkPrefix:
case kKeyNat64Prefix:
case kKeyLegacyNat64Prefix:
LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue));
break;
#endif
+23 -24
View File
@@ -118,15 +118,16 @@ public:
kKeyReserved = OT_SETTINGS_KEY_RESERVED,
kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO,
kKeyOmrPrefix = OT_SETTINGS_KEY_OMR_PREFIX,
kKeyLegacyOmrPrefix = OT_SETTINGS_KEY_LEGACY_OMR_PREFIX,
kKeyOnLinkPrefix = OT_SETTINGS_KEY_ON_LINK_PREFIX,
kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO,
kKeyNat64Prefix = OT_SETTINGS_KEY_NAT64_PREFIX,
kKeyLegacyNat64Prefix = OT_SETTINGS_KEY_LEGACY_NAT64_PREFIX,
kKeyBrUlaPrefix = OT_SETTINGS_KEY_BR_ULA_PREFIX,
};
static constexpr Key kLastKey = kKeyNat64Prefix; ///< The last (numerically) enumerator value in `Key`.
static constexpr Key kLastKey = kKeyBrUlaPrefix; ///< The last (numerically) enumerator value in `Key`.
/**
* This structure represents the device's own network information for settings storage.
@@ -570,18 +571,33 @@ public:
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
/**
* This class defines constants and types for OMR prefix settings.
* This class defines constants and types for BR ULA prefix settings.
*
*/
class OmrPrefix
class BrUlaPrefix
{
public:
static constexpr Key kKey = kKeyOmrPrefix; ///< The associated key.
static constexpr Key kKey = kKeyBrUlaPrefix; ///< The associated key.
typedef Ip6::Prefix ValueType; ///< The associated value type.
private:
OmrPrefix(void) = default;
BrUlaPrefix(void) = default;
};
/**
* This class defines constants and types for legacy OMR prefix settings.
*
*/
class LegacyOmrPrefix
{
public:
static constexpr Key kKey = kKeyLegacyOmrPrefix; ///< The associated key.
typedef Ip6::Prefix ValueType; ///< The associated value type.
private:
LegacyOmrPrefix(void) = default;
};
/**
@@ -598,23 +614,6 @@ public:
private:
OnLinkPrefix(void) = default;
};
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
/**
* This class defines constants and types for NAT64 prefix settings.
*
*/
class Nat64Prefix
{
public:
static constexpr Key kKey = kKeyNat64Prefix; ///< The associated key.
typedef Ip6::Prefix ValueType; ///< The associated value type.
private:
Nat64Prefix(void) = default;
};
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+16
View File
@@ -110,6 +110,14 @@ public:
*/
const uint8_t *GetBytes(void) const { return mPrefix.mFields.m8; }
/**
* This method gets the subnet ID of the prefix.
*
* @returns The 16-bit subnet ID.
*
*/
uint16_t GetSubnetId(void) const { return HostSwap16(mPrefix.mFields.m16[3]); }
/**
* This method gets the prefix length (in bits).
*
@@ -143,6 +151,14 @@ public:
*/
void Set(const NetworkPrefix &aNetworkPrefix) { Set(aNetworkPrefix.m8, NetworkPrefix::kLength); }
/**
* This method sets the subnet ID of the prefix.
*
* @param[in] aSubnetId A 16-bit subnet ID.
*
*/
void SetSubnetId(uint16_t aSubnetId) { mPrefix.mFields.m16[3] = HostSwap16(aSubnetId); }
/**
* This method set the prefix length.
*