mirror of
https://github.com/espressif/openthread.git
synced 2026-08-10 04:37:47 +00:00
[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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user