From a05954b01e28cfe18180a0ecf18b08a95295b9ae Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 7 Nov 2023 12:43:02 -0800 Subject: [PATCH] [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. --- src/core/thread/dua_manager.cpp | 2 +- src/core/utils/slaac_address.cpp | 261 ++++++++++++++++--------------- src/core/utils/slaac_address.hpp | 43 +++-- 3 files changed, 151 insertions(+), 155 deletions(-) diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp index 20fb792e8..7d78879a3 100644 --- a/src/core/thread/dua_manager.cpp +++ b/src/core/thread/dua_manager.cpp @@ -146,7 +146,7 @@ Error DuaManager::GenerateDomainUnicastAddressIid(void) Error error; uint8_t dadCounter = mDadCounter; - if ((error = Get().GenerateIid(mDomainUnicastAddress, nullptr, 0, &dadCounter)) == kErrorNone) + if ((error = Get().GenerateIid(mDomainUnicastAddress, dadCounter)) == kErrorNone) { if (dadCounter != mDadCounter) { diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp index dacbbcd55..76a53ba26 100644 --- a/src/core/utils/slaac_address.cpp +++ b/src/core/utils/slaac_address.cpp @@ -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().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().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().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().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().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().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().GetNextOnMeshPrefix(iterator, config) == kErrorNone) + { + bool found = false; + + if (!ShouldUseForSlaac(config)) + { + continue; + } + + for (const Ip6::Netif::UnicastAddress &netifAddr : Get().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().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); } diff --git a/src/core/utils/slaac_address.hpp b/src/core/utils/slaac_address.hpp index 3e73f1920..99feca2fc 100644 --- a/src/core/utils/slaac_address.hpp +++ b/src/core/utils/slaac_address.hpp @@ -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]; }; /**