mirror of
https://github.com/espressif/openthread.git
synced 2026-08-26 04:09:52 +00:00
[slaac] simplify adding/removing addresses and other enhancements (#9579)
This commit makes the following smaller enhancements in `Slaac` class: - Adds a new `ShouldUseForSlaac()` method to check if a network data prefix should be used for SLAAC, checking flags and applying the filter if set. - Introduces separate `RemoveAddresses()` and `AddAddresses()` methods to manage SLAAC addresses, replacing the previous `Update()` method. - Adds helper methods to `RemoveAllAddresses()`, `RemoveAddress()` to remove a specific address, and `AddAddressFor(prefix)` to generate and add an address for a given prefix. - Simplifies `GenerateIid()` by removing unused input parameters.
This commit is contained in:
@@ -146,7 +146,7 @@ Error DuaManager::GenerateDomainUnicastAddressIid(void)
|
||||
Error error;
|
||||
uint8_t dadCounter = mDadCounter;
|
||||
|
||||
if ((error = Get<Utils::Slaac>().GenerateIid(mDomainUnicastAddress, nullptr, 0, &dadCounter)) == kErrorNone)
|
||||
if ((error = Get<Utils::Slaac>().GenerateIid(mDomainUnicastAddress, dadCounter)) == kErrorNone)
|
||||
{
|
||||
if (dadCounter != mDadCounter)
|
||||
{
|
||||
|
||||
+132
-129
@@ -62,9 +62,10 @@ void Slaac::Enable(void)
|
||||
{
|
||||
VerifyOrExit(!mEnabled);
|
||||
|
||||
LogInfo("Enabling");
|
||||
mEnabled = true;
|
||||
Update(kModeAdd);
|
||||
LogInfo("Enabled");
|
||||
|
||||
AddAddresses();
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -74,15 +75,15 @@ void Slaac::Disable(void)
|
||||
{
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
LogInfo("Disabling");
|
||||
RemoveAllAddresses();
|
||||
LogInfo("Disabled");
|
||||
mEnabled = false;
|
||||
Update(kModeRemove);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Slaac::SetFilter(otIp6SlaacPrefixFilter aFilter)
|
||||
void Slaac::SetFilter(PrefixFilter aFilter)
|
||||
{
|
||||
VerifyOrExit(aFilter != mFilter);
|
||||
|
||||
@@ -90,26 +91,40 @@ void Slaac::SetFilter(otIp6SlaacPrefixFilter aFilter)
|
||||
LogInfo("Filter %s", (mFilter != nullptr) ? "updated" : "disabled");
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
Update(kModeAdd | kModeRemove);
|
||||
RemoveAddresses();
|
||||
AddAddresses();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
bool Slaac::ShouldFilter(const Ip6::Prefix &aPrefix) const
|
||||
bool Slaac::ShouldUseForSlaac(const NetworkData::OnMeshPrefixConfig &aConfig) const
|
||||
{
|
||||
return (mFilter != nullptr) && mFilter(&GetInstance(), &aPrefix);
|
||||
bool shouldUse = false;
|
||||
|
||||
VerifyOrExit(aConfig.mSlaac && !aConfig.mDp);
|
||||
VerifyOrExit(aConfig.GetPrefix().GetLength() == Ip6::NetworkPrefix::kLength);
|
||||
|
||||
if (mFilter != nullptr)
|
||||
{
|
||||
VerifyOrExit(!mFilter(&GetInstance(), &aConfig.GetPrefix()));
|
||||
}
|
||||
|
||||
shouldUse = true;
|
||||
|
||||
exit:
|
||||
return shouldUse;
|
||||
}
|
||||
|
||||
void Slaac::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
UpdateMode mode = kModeNone;
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
if (aEvents.Contains(kEventThreadNetdataChanged))
|
||||
{
|
||||
mode |= kModeAdd | kModeRemove;
|
||||
RemoveAddresses();
|
||||
AddAddresses();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (aEvents.Contains(kEventIp6AddressRemoved))
|
||||
@@ -123,12 +138,7 @@ void Slaac::HandleNotifierEvents(Events aEvents)
|
||||
// prefix. So on IPv6 address removal event, we check if SLAAC module need
|
||||
// to add any addresses.
|
||||
|
||||
mode |= kModeAdd;
|
||||
}
|
||||
|
||||
if (mode != kModeNone)
|
||||
{
|
||||
Update(mode);
|
||||
AddAddresses();
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -143,122 +153,126 @@ bool Slaac::DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aCon
|
||||
(aAddr.GetAddress().MatchesPrefix(aConfig.GetPrefix())));
|
||||
}
|
||||
|
||||
void Slaac::Update(UpdateMode aMode)
|
||||
void Slaac::RemoveAddresses(void)
|
||||
{
|
||||
NetworkData::Iterator iterator;
|
||||
NetworkData::OnMeshPrefixConfig config;
|
||||
bool found;
|
||||
// Remove any SLAAC addresses with no matching on-mesh prefix.
|
||||
|
||||
if (aMode & kModeRemove)
|
||||
for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
|
||||
{
|
||||
// If enabled, remove any SLAAC addresses with no matching on-mesh prefix,
|
||||
// otherwise (when disabled) remove all previously added SLAAC addresses.
|
||||
NetworkData::Iterator iterator;
|
||||
NetworkData::OnMeshPrefixConfig config;
|
||||
bool found = false;
|
||||
|
||||
for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
|
||||
if (!slaacAddr.mValid)
|
||||
{
|
||||
if (!slaacAddr.mValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
found = false;
|
||||
|
||||
if (mEnabled)
|
||||
{
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
|
||||
{
|
||||
if (config.mDp)
|
||||
{
|
||||
// Skip domain prefix which is processed in MLE.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.mSlaac && !ShouldFilter(config.GetPrefix()) &&
|
||||
DoesConfigMatchNetifAddr(config, slaacAddr))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
LogInfo("Removing address %s", slaacAddr.GetAddress().ToString().AsCString());
|
||||
|
||||
Get<ThreadNetif>().RemoveUnicastAddress(slaacAddr);
|
||||
slaacAddr.mValid = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((aMode & kModeAdd) && mEnabled)
|
||||
{
|
||||
// Generate and add SLAAC addresses for any newly added on-mesh prefixes.
|
||||
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
|
||||
{
|
||||
Ip6::Prefix &prefix = config.GetPrefix();
|
||||
|
||||
if (config.mDp || !config.mSlaac || (prefix.GetLength() != Ip6::NetworkPrefix::kLength) ||
|
||||
ShouldFilter(prefix))
|
||||
if (ShouldUseForSlaac(config) && DoesConfigMatchNetifAddr(config, slaacAddr))
|
||||
{
|
||||
continue;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
found = false;
|
||||
|
||||
for (const Ip6::Netif::UnicastAddress &netifAddr : Get<ThreadNetif>().GetUnicastAddresses())
|
||||
{
|
||||
if (DoesConfigMatchNetifAddr(config, netifAddr))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
bool added = false;
|
||||
|
||||
for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
|
||||
{
|
||||
if (slaacAddr.mValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
slaacAddr.InitAsSlaacOrigin(config.mOnMesh ? prefix.mLength : 128, config.mPreferred);
|
||||
slaacAddr.GetAddress().SetPrefix(prefix);
|
||||
|
||||
IgnoreError(GenerateIid(slaacAddr));
|
||||
|
||||
LogInfo("Adding address %s", slaacAddr.GetAddress().ToString().AsCString());
|
||||
|
||||
Get<ThreadNetif>().AddUnicastAddress(slaacAddr);
|
||||
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!added)
|
||||
{
|
||||
LogWarn("Failed to add - max %d addresses supported and already in use",
|
||||
GetArrayLength(mAddresses));
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
RemoveAddress(slaacAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
|
||||
uint8_t *aNetworkId,
|
||||
uint8_t aNetworkIdLength,
|
||||
uint8_t *aDadCounter) const
|
||||
void Slaac::RemoveAllAddresses(void)
|
||||
{
|
||||
for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
|
||||
{
|
||||
if (slaacAddr.mValid)
|
||||
{
|
||||
RemoveAddress(slaacAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Slaac::RemoveAddress(Ip6::Netif::UnicastAddress &aAddress)
|
||||
{
|
||||
LogInfo("Removing %s", aAddress.GetAddress().ToString().AsCString());
|
||||
|
||||
Get<ThreadNetif>().RemoveUnicastAddress(aAddress);
|
||||
aAddress.mValid = false;
|
||||
}
|
||||
|
||||
void Slaac::AddAddresses(void)
|
||||
{
|
||||
NetworkData::Iterator iterator;
|
||||
NetworkData::OnMeshPrefixConfig config;
|
||||
|
||||
// Generate and add SLAAC addresses for any newly added on-mesh prefixes.
|
||||
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (!ShouldUseForSlaac(config))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const Ip6::Netif::UnicastAddress &netifAddr : Get<ThreadNetif>().GetUnicastAddresses())
|
||||
{
|
||||
if (DoesConfigMatchNetifAddr(config, netifAddr))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
AddAddressFor(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Slaac::AddAddressFor(const NetworkData::OnMeshPrefixConfig &aConfig)
|
||||
{
|
||||
Ip6::Netif::UnicastAddress *newAddress = nullptr;
|
||||
uint8_t dadCounter = 0;
|
||||
|
||||
for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
|
||||
{
|
||||
if (!slaacAddr.mValid)
|
||||
{
|
||||
newAddress = &slaacAddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newAddress == nullptr)
|
||||
{
|
||||
LogWarn("Failed to add - already have max %u addresses", kNumAddresses);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
newAddress->InitAsSlaacOrigin(aConfig.mOnMesh ? aConfig.GetPrefix().mLength : 128, aConfig.mPreferred);
|
||||
newAddress->GetAddress().SetPrefix(aConfig.GetPrefix());
|
||||
|
||||
IgnoreError(GenerateIid(*newAddress, dadCounter));
|
||||
|
||||
LogInfo("Adding address %s", newAddress->GetAddress().ToString().AsCString());
|
||||
|
||||
Get<ThreadNetif>().AddUnicastAddress(*newAddress);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress, uint8_t &aDadCounter) const
|
||||
{
|
||||
/*
|
||||
* This method generates a semantically opaque IID per RFC 7217.
|
||||
@@ -268,7 +282,7 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
|
||||
* - RID is random (but stable) Identifier.
|
||||
* - For pseudo-random function `F()` SHA-256 is used in this method.
|
||||
* - `Net_Iface` is set to constant string "wpan".
|
||||
* - `Network_ID` is not used if `aNetworkId` is `nullptr` (optional per RF-7217).
|
||||
* - `Network_ID` is not used (optional per RFC 7217).
|
||||
* - The `secret_key` is randomly generated on first use (using true
|
||||
* random number generator) and saved in non-volatile settings for
|
||||
* future use.
|
||||
@@ -277,7 +291,6 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
|
||||
|
||||
Error error = kErrorFailed;
|
||||
const uint8_t netIface[] = {'w', 'p', 'a', 'n'};
|
||||
uint8_t dadCounter = aDadCounter ? *aDadCounter : 0;
|
||||
IidSecretKey secretKey;
|
||||
Crypto::Sha256 sha256;
|
||||
Crypto::Sha256::Hash hash;
|
||||
@@ -287,18 +300,13 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
|
||||
|
||||
GetIidSecretKey(secretKey);
|
||||
|
||||
for (uint16_t count = 0; count < kMaxIidCreationAttempts; count++, dadCounter++)
|
||||
for (uint16_t count = 0; count < kMaxIidCreationAttempts; count++, aDadCounter++)
|
||||
{
|
||||
sha256.Start();
|
||||
sha256.Update(aAddress.mAddress.mFields.m8, BitVectorBytes(aAddress.mPrefixLength));
|
||||
|
||||
if (aNetworkId)
|
||||
{
|
||||
sha256.Update(aNetworkId, aNetworkIdLength);
|
||||
}
|
||||
|
||||
sha256.Update(netIface);
|
||||
sha256.Update(dadCounter);
|
||||
sha256.Update(aDadCounter);
|
||||
sha256.Update(secretKey);
|
||||
sha256.Finish(hash);
|
||||
|
||||
@@ -310,11 +318,6 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aDadCounter)
|
||||
{
|
||||
*aDadCounter = dadCounter;
|
||||
}
|
||||
|
||||
// Exit and return the address if the IID is not reserved,
|
||||
ExitNow(error = kErrorNone);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ class Slaac : public InstanceLocator, private NonCopyable
|
||||
friend class ot::Notifier;
|
||||
|
||||
public:
|
||||
typedef otIp6SlaacPrefixFilter PrefixFilter; ///< Prefix filter function pointer.
|
||||
|
||||
/**
|
||||
* Represents the secret key used for generating semantically opaque IID (per RFC 7217).
|
||||
*
|
||||
@@ -120,8 +122,10 @@ public:
|
||||
*
|
||||
* The filter can be set to `nullptr` to disable filtering (i.e., allow SLAAC addresses for all prefixes).
|
||||
*
|
||||
* @param[in] aFilter The filter to use.
|
||||
*
|
||||
*/
|
||||
void SetFilter(otIp6SlaacPrefixFilter aFilter);
|
||||
void SetFilter(PrefixFilter aFilter);
|
||||
|
||||
/**
|
||||
* Generates the IID of an IPv6 address.
|
||||
@@ -129,45 +133,34 @@ public:
|
||||
* @param[in,out] aAddress A reference to the address that will be filled with the IID generated.
|
||||
* Note the prefix of the address must already be filled and will be used
|
||||
* to generate the IID.
|
||||
* @param[in] aNetworkId A pointer to a byte array of Network_ID to generate IID.
|
||||
* @param[in] aNetworkIdLength The size of array @p aNetworkId.
|
||||
* @param[in,out] aDadCounter A pointer to the DAD_Counter that is employed to resolve Duplicate
|
||||
* Address Detection conflicts.
|
||||
* @param[in,out] aDadCounter The DAD_Counter that is employed to resolve Duplicate Address Detection
|
||||
* conflicts.
|
||||
*
|
||||
* @retval kErrorNone If successfully generated the IID.
|
||||
* @retval kErrorFailed If no valid IID was generated.
|
||||
*
|
||||
*/
|
||||
Error GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
|
||||
uint8_t *aNetworkId = nullptr,
|
||||
uint8_t aNetworkIdLength = 0,
|
||||
uint8_t *aDadCounter = nullptr) const;
|
||||
Error GenerateIid(Ip6::Netif::UnicastAddress &aAddress, uint8_t &aDadCounter) const;
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kNumAddresses = OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES;
|
||||
|
||||
static constexpr uint16_t kMaxIidCreationAttempts = 256; // Maximum number of attempts when generating IID.
|
||||
|
||||
typedef uint8_t UpdateMode;
|
||||
|
||||
// Values for `UpdateMode` input parameter in `Update()`.
|
||||
|
||||
static constexpr UpdateMode kModeNone = 0x0; // No action.
|
||||
static constexpr UpdateMode kModeAdd = 1 << 0; // Add new SLAAC addresses for new prefixes in network data.
|
||||
|
||||
// Remove SLAAC addresses.
|
||||
// - When SLAAC is enabled, remove addresses with no matching prefix in network data,
|
||||
// - When SLAAC is disabled, remove all previously added addresses.
|
||||
static constexpr UpdateMode kModeRemove = 1 << 1;
|
||||
|
||||
bool ShouldFilter(const Ip6::Prefix &aPrefix) const;
|
||||
void Update(UpdateMode aMode);
|
||||
bool ShouldUseForSlaac(const NetworkData::OnMeshPrefixConfig &aConfig) const;
|
||||
void RemoveAddresses(void);
|
||||
void RemoveAllAddresses(void);
|
||||
void AddAddresses(void);
|
||||
void RemoveAddress(Ip6::Netif::UnicastAddress &aAddress);
|
||||
void AddAddressFor(const NetworkData::OnMeshPrefixConfig &aConfig);
|
||||
void GetIidSecretKey(IidSecretKey &aKey) const;
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
static bool DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aConfig,
|
||||
const Ip6::Netif::UnicastAddress &aAddr);
|
||||
|
||||
bool mEnabled;
|
||||
otIp6SlaacPrefixFilter mFilter;
|
||||
Ip6::Netif::UnicastAddress mAddresses[OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES];
|
||||
PrefixFilter mFilter;
|
||||
Ip6::Netif::UnicastAddress mAddresses[kNumAddresses];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user