mirror of
https://github.com/espressif/openthread.git
synced 2026-08-21 09:59:52 +00:00
[child] add GetIp6Addresses() and simplify MLR state tracking (#10424)
This commit introduces several changes to the `Child` class for managing registered IPv6 addresses by MTD children: - A new method, `Child::GetIp6Addresses()`, is added, returning the `Array` of registered IPv6 address entries. This array includes all tracked child IPv6 addresses except for the mesh-local EID, which can be retrieved using `Child::GetMeshLocalIp6Address()`. - The simplified model enables easy iteration over the address array using `Array` range-based `for` loops. With this change, the complex `AddressIterator` and `AddressIteratorBuilder` nested classes are removed, streamlining the code. - MLR state tracking for child IPv6 address entries is simplified with the introduction of a new class, `Child::Ip6AddrEntry`, representing a registered IPv6 address entry. This class provides `GetMlrState()` and `SetMlrState()`, enforcing that the MLR state can only be set on a child IPv6 address entry.
This commit is contained in:
@@ -250,15 +250,7 @@ otError otThreadGetChildNextIp6Address(otInstance *aInstance,
|
||||
VerifyOrExit(child != nullptr, error = kErrorInvalidArgs);
|
||||
VerifyOrExit(child->IsStateValidOrRestoring(), error = kErrorInvalidArgs);
|
||||
|
||||
{
|
||||
Child::AddressIterator iter(*child, *aIterator);
|
||||
|
||||
VerifyOrExit(!iter.IsDone(), error = kErrorNotFound);
|
||||
*aAddress = *iter.GetAddress();
|
||||
|
||||
iter++;
|
||||
*aIterator = iter.GetAsIndex();
|
||||
}
|
||||
error = child->GetNextIp6Address(*aIterator, AsCoreType(aAddress));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
+69
-72
@@ -44,6 +44,9 @@ namespace ot {
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Child::Info
|
||||
|
||||
void Child::Info::SetFrom(const Child &aChild)
|
||||
{
|
||||
Clear();
|
||||
@@ -75,51 +78,50 @@ void Child::Info::SetFrom(const Child &aChild)
|
||||
#endif
|
||||
}
|
||||
|
||||
const Ip6::Address *Child::AddressIterator::GetAddress(void) const
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Child::Ip6AddrEntry
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
|
||||
MlrState Child::Ip6AddrEntry::GetMlrState(const Child &aChild) const
|
||||
{
|
||||
// `mIndex` value of zero indicates mesh-local IPv6 address.
|
||||
// Non-zero value specifies the index into address array starting
|
||||
// from one for first element (i.e, `mIndex - 1` gives the array
|
||||
// index).
|
||||
MlrState state = kMlrStateRegistering;
|
||||
Ip6AddressArray::IndexType index;
|
||||
|
||||
const Ip6::Address *address = nullptr;
|
||||
OT_ASSERT(aChild.mIp6Addresses.IsInArrayBuffer(this));
|
||||
|
||||
if (mIndex == 0)
|
||||
index = aChild.mIp6Addresses.IndexOf(*this);
|
||||
|
||||
if (aChild.mMlrToRegisterMask.Get(index))
|
||||
{
|
||||
address = &mMeshLocalAddress;
|
||||
ExitNow();
|
||||
state = kMlrStateToRegister;
|
||||
}
|
||||
else if (aChild.mMlrRegisteredMask.Get(index))
|
||||
{
|
||||
state = kMlrStateRegistered;
|
||||
}
|
||||
|
||||
VerifyOrExit(mIndex - 1 < mChild.mIp6Addresses.GetLength());
|
||||
address = &mChild.mIp6Addresses[static_cast<Ip6AddressArray::IndexType>(mIndex - 1)];
|
||||
|
||||
exit:
|
||||
return address;
|
||||
return state;
|
||||
}
|
||||
|
||||
void Child::AddressIterator::Update(void)
|
||||
// NOLINTNEXTLINE(readability-make-member-function-const)
|
||||
void Child::Ip6AddrEntry::SetMlrState(MlrState aState, Child &aChild)
|
||||
{
|
||||
const Ip6::Address *address;
|
||||
Ip6AddressArray::IndexType index;
|
||||
|
||||
if ((mIndex == 0) && (mChild.GetMeshLocalIp6Address(mMeshLocalAddress) != kErrorNone))
|
||||
{
|
||||
mIndex++;
|
||||
}
|
||||
OT_ASSERT(aChild.mIp6Addresses.IsInArrayBuffer(this));
|
||||
|
||||
while (true)
|
||||
{
|
||||
address = GetAddress();
|
||||
index = aChild.mIp6Addresses.IndexOf(*this);
|
||||
|
||||
VerifyOrExit((address != nullptr) && !address->IsUnspecified(), mIndex = kMaxIndex);
|
||||
|
||||
VerifyOrExit(!address->MatchesFilter(mFilter));
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
aChild.mMlrToRegisterMask.Set(index, aState == kMlrStateToRegister);
|
||||
aChild.mMlrRegisteredMask.Set(index, aState == kMlrStateRegistered);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Child
|
||||
|
||||
void Child::Clear(void)
|
||||
{
|
||||
Instance &instance = GetInstance();
|
||||
@@ -164,6 +166,29 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Child::GetNextIp6Address(AddressIterator &aIterator, Ip6::Address &aAddress) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
if (aIterator == 0)
|
||||
{
|
||||
aIterator++;
|
||||
|
||||
if (GetMeshLocalIp6Address(aAddress) == kErrorNone)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit(aIterator - 1 < mIp6Addresses.GetLength(), error = kErrorNotFound);
|
||||
|
||||
aAddress = mIp6Addresses[static_cast<Ip6AddressArray::IndexType>(aIterator - 1)];
|
||||
aIterator++;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Child::AddIp6Address(const Ip6::Address &aAddress)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -177,8 +202,8 @@ Error Child::AddIp6Address(const Ip6::Address &aAddress)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(!mIp6Addresses.Contains(aAddress), error = kErrorAlready);
|
||||
error = mIp6Addresses.PushBack(aAddress);
|
||||
VerifyOrExit(!mIp6Addresses.ContainsMatching(aAddress), error = kErrorAlready);
|
||||
error = mIp6Addresses.PushBack(static_cast<const Ip6AddrEntry &>(aAddress));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -187,7 +212,7 @@ exit:
|
||||
Error Child::RemoveIp6Address(const Ip6::Address &aAddress)
|
||||
{
|
||||
Error error = kErrorNotFound;
|
||||
Ip6::Address *entry;
|
||||
Ip6AddrEntry *entry;
|
||||
|
||||
if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
|
||||
{
|
||||
@@ -200,7 +225,7 @@ Error Child::RemoveIp6Address(const Ip6::Address &aAddress)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
entry = mIp6Addresses.Find(aAddress);
|
||||
entry = mIp6Addresses.FindMatching(aAddress);
|
||||
VerifyOrExit(entry != nullptr);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
@@ -239,7 +264,7 @@ bool Child::HasIp6Address(const Ip6::Address &aAddress) const
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
hasAddress = mIp6Addresses.Contains(aAddress);
|
||||
hasAddress = mIp6Addresses.ContainsMatching(aAddress);
|
||||
|
||||
exit:
|
||||
return hasAddress;
|
||||
@@ -266,49 +291,21 @@ exit:
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
|
||||
bool Child::HasMlrRegisteredAddress(const Ip6::Address &aAddress) const
|
||||
{
|
||||
bool has = false;
|
||||
bool hasAddress = false;
|
||||
const Ip6AddrEntry *entry;
|
||||
|
||||
VerifyOrExit(mMlrRegisteredMask.HasAny());
|
||||
|
||||
for (const Ip6::Address &address : IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
{
|
||||
if (GetAddressMlrState(address) == kMlrStateRegistered && address == aAddress)
|
||||
{
|
||||
ExitNow(has = true);
|
||||
}
|
||||
}
|
||||
entry = mIp6Addresses.FindMatching(aAddress);
|
||||
VerifyOrExit(entry != nullptr);
|
||||
hasAddress = entry->GetMlrState(*this) == kMlrStateRegistered;
|
||||
|
||||
exit:
|
||||
return has;
|
||||
return hasAddress;
|
||||
}
|
||||
|
||||
MlrState Child::GetAddressMlrState(const Ip6::Address &aAddress) const
|
||||
{
|
||||
uint16_t addressIndex;
|
||||
|
||||
OT_ASSERT(mIp6Addresses.IsInArrayBuffer(&aAddress));
|
||||
|
||||
addressIndex = mIp6Addresses.IndexOf(aAddress);
|
||||
|
||||
return mMlrToRegisterMask.Get(addressIndex)
|
||||
? kMlrStateToRegister
|
||||
: (mMlrRegisteredMask.Get(addressIndex) ? kMlrStateRegistered : kMlrStateRegistering);
|
||||
}
|
||||
|
||||
void Child::SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState)
|
||||
{
|
||||
uint16_t addressIndex;
|
||||
|
||||
OT_ASSERT(mIp6Addresses.IsInArrayBuffer(&aAddress));
|
||||
|
||||
addressIndex = mIp6Addresses.IndexOf(aAddress);
|
||||
|
||||
mMlrToRegisterMask.Set(addressIndex, aState == kMlrStateToRegister);
|
||||
mMlrRegisteredMask.Set(addressIndex, aState == kMlrStateRegistered);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
|
||||
+86
-195
@@ -42,6 +42,10 @@ namespace ot {
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD < 2
|
||||
#error OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD should be at least set to 2.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents a Thread Child.
|
||||
*
|
||||
@@ -54,11 +58,27 @@ class Child : public Neighbor,
|
||||
public CslTxScheduler::ChildInfo
|
||||
#endif
|
||||
{
|
||||
class AddressIteratorBuilder;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kMaxRequestTlvs = 6;
|
||||
|
||||
/**
|
||||
* Maximum number of registered IPv6 addresses per child (excluding the mesh-local EID).
|
||||
*
|
||||
*/
|
||||
static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1;
|
||||
|
||||
/**
|
||||
* Represents the iterator for registered IPv6 address list of an MTD child.
|
||||
*
|
||||
*/
|
||||
typedef otChildIp6AddressIterator AddressIterator;
|
||||
|
||||
/**
|
||||
* The initial value for an `AddressIterator`.
|
||||
*
|
||||
*/
|
||||
static constexpr AddressIterator kAddressIteratorInit = OT_CHILD_IP6_ADDRESS_ITERATOR_INIT;
|
||||
|
||||
/**
|
||||
* Represents diagnostic information for a Thread Child.
|
||||
*
|
||||
@@ -76,146 +96,53 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines an iterator used to go through IPv6 address entries of a child.
|
||||
* Represents an IPv6 address entry registered by an MTD child.
|
||||
*
|
||||
*/
|
||||
class AddressIterator : public Unequatable<AddressIterator>
|
||||
class Ip6AddrEntry : public Ip6::Address
|
||||
{
|
||||
friend class AddressIteratorBuilder;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Represents an index indicating the current IPv6 address entry to which the iterator is pointing.
|
||||
* Indicates whether the entry matches a given IPv6 address.
|
||||
*
|
||||
* @param[in] aAddress The IPv6 address.
|
||||
*
|
||||
* @retval TRUE The entry matches @p aAddress.
|
||||
* @retval FALSE The entry does not match @p aAddress.
|
||||
*
|
||||
*/
|
||||
typedef otChildIp6AddressIterator Index;
|
||||
bool Matches(const Ip6::Address &aAddress) const { return (*this == aAddress); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
/**
|
||||
* Gets the MLR state of the IPv6 address entry.
|
||||
*
|
||||
* @param[in] aChild The child owning this address entry.
|
||||
*
|
||||
* @returns The MLR state of IPv6 address entry.
|
||||
*
|
||||
*/
|
||||
MlrState GetMlrState(const Child &aChild) const;
|
||||
|
||||
/**
|
||||
* Initializes the iterator associated with a given `Child` starting from beginning of the
|
||||
* IPv6 address list.
|
||||
* Sets the MLR state of the IPv6 address entry.
|
||||
*
|
||||
* @param[in] aChild A reference to a child entry.
|
||||
* @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses.
|
||||
* @param[in] aState The MLR state.
|
||||
* @param[in] aChild The child owning this address entry.
|
||||
*
|
||||
*/
|
||||
explicit AddressIterator(const Child &aChild, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny)
|
||||
: AddressIterator(aChild, 0, aFilter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the iterator associated with a given `Child` starting from a given index
|
||||
*
|
||||
* @param[in] aChild A reference to the child entry.
|
||||
* @param[in] aIndex An index (`Index`) with which to initialize the iterator.
|
||||
* @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses.
|
||||
*
|
||||
*/
|
||||
AddressIterator(const Child &aChild, Index aIndex, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny)
|
||||
: mChild(aChild)
|
||||
, mFilter(aFilter)
|
||||
, mIndex(aIndex)
|
||||
{
|
||||
Update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the iterator into an index.
|
||||
*
|
||||
* @returns An index corresponding to the iterator.
|
||||
*
|
||||
*/
|
||||
Index GetAsIndex(void) const { return mIndex; }
|
||||
|
||||
/**
|
||||
* Gets the iterator's associated `Child` entry.
|
||||
*
|
||||
* @returns The associated child entry.
|
||||
*
|
||||
*/
|
||||
const Child &GetChild(void) const { return mChild; }
|
||||
|
||||
/**
|
||||
* Gets the current `Child` IPv6 Address to which the iterator is pointing.
|
||||
*
|
||||
* @returns A pointer to the associated IPv6 Address, or `nullptr` if iterator is done.
|
||||
*
|
||||
*/
|
||||
const Ip6::Address *GetAddress(void) const;
|
||||
|
||||
/**
|
||||
* Indicates whether the iterator has reached end of the list.
|
||||
*
|
||||
* @retval TRUE There are no more entries in the list (reached end of the list).
|
||||
* @retval FALSE The current entry is valid.
|
||||
*
|
||||
*/
|
||||
bool IsDone(void) const { return (mIndex >= kMaxIndex); }
|
||||
|
||||
/**
|
||||
* Overloads `++` operator (pre-increment) to advance the iterator.
|
||||
*
|
||||
* The iterator is moved to point to the next `Address` entry. If there are no more `Ip6::Address` entries
|
||||
* `IsDone()` returns `true`.
|
||||
*
|
||||
*/
|
||||
void operator++(void) { mIndex++, Update(); }
|
||||
|
||||
/**
|
||||
* Overloads `++` operator (post-increment) to advance the iterator.
|
||||
*
|
||||
* The iterator is moved to point to the next `Address` entry. If there are no more `Ip6::Address` entries
|
||||
* `IsDone()` returns `true`.
|
||||
*
|
||||
*/
|
||||
void operator++(int) { mIndex++, Update(); }
|
||||
|
||||
/**
|
||||
* Overloads the `*` dereference operator and gets a reference to `Ip6::Address` to which the
|
||||
* iterator is currently pointing.
|
||||
*
|
||||
* MUST be used when the iterator is not done (i.e., `IsDone()` returns `false`).
|
||||
*
|
||||
* @returns A reference to the `Ip6::Address` entry currently pointed by the iterator.
|
||||
*
|
||||
*/
|
||||
const Ip6::Address &operator*(void) const { return *GetAddress(); }
|
||||
|
||||
/**
|
||||
* Overloads operator `==` to evaluate whether or not two `Iterator` instances are equal.
|
||||
*
|
||||
* MUST be used when the two iterators are associated with the same `Child` entry.
|
||||
*
|
||||
* @param[in] aOther The other `Iterator` to compare with.
|
||||
*
|
||||
* @retval TRUE If the two `Iterator` objects are equal.
|
||||
* @retval FALSE If the two `Iterator` objects are not equal.
|
||||
*
|
||||
*/
|
||||
bool operator==(const AddressIterator &aOther) const { return (mIndex == aOther.mIndex); }
|
||||
|
||||
private:
|
||||
enum IteratorType : uint8_t
|
||||
{
|
||||
kEndIterator,
|
||||
};
|
||||
|
||||
static constexpr uint16_t kMaxIndex = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
|
||||
|
||||
AddressIterator(const Child &aChild, IteratorType)
|
||||
: mChild(aChild)
|
||||
, mIndex(kMaxIndex)
|
||||
{
|
||||
}
|
||||
|
||||
void Update(void);
|
||||
|
||||
const Child &mChild;
|
||||
Ip6::Address::TypeFilter mFilter;
|
||||
Index mIndex;
|
||||
Ip6::Address mMeshLocalAddress;
|
||||
void SetMlrState(MlrState aState, Child &aChild);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents an array of IPv6 address entries registered by an MTD child.
|
||||
*
|
||||
* This array does not include the mesh-local EID.
|
||||
*
|
||||
*/
|
||||
typedef Array<Ip6AddrEntry, kNumIp6Addresses> Ip6AddressArray;
|
||||
|
||||
/**
|
||||
* Initializes the `Child` object.
|
||||
*
|
||||
@@ -264,26 +191,37 @@ public:
|
||||
const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; }
|
||||
|
||||
/**
|
||||
* Enables range-based `for` loop iteration over all (or a subset of) IPv6 addresses.
|
||||
* Gets an array of registered IPv6 address entries by the child.
|
||||
*
|
||||
* Should be used as follows: to iterate over all addresses
|
||||
* The array does not include the mesh-local EID. The ML-EID can retrieved using `GetMeshLocalIp6Address()`.
|
||||
*
|
||||
* for (const Ip6::Address &address : child.IterateIp6Addresses()) { ... }
|
||||
*
|
||||
* or to iterate over a subset of IPv6 addresses determined by a given address type filter
|
||||
*
|
||||
* for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticast)) { ... }
|
||||
*
|
||||
* @param[in] aFilter An IPv6 address type filter restricting iteration to certain type of addresses (default is
|
||||
* to accept any address type).
|
||||
*
|
||||
* @returns An IteratorBuilder instance.
|
||||
* @returns The array of registered IPv6 addresses by the child.
|
||||
*
|
||||
*/
|
||||
AddressIteratorBuilder IterateIp6Addresses(Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) const
|
||||
{
|
||||
return AddressIteratorBuilder(*this, aFilter);
|
||||
}
|
||||
const Ip6AddressArray &GetIp6Addresses(void) const { return mIp6Addresses; }
|
||||
|
||||
/**
|
||||
* Gets an array of registered IPv6 address entries by the child.
|
||||
*
|
||||
* The array does not include the mesh-local EID. The ML-EID can retrieved using `GetMeshLocalIp6Address()`.
|
||||
*
|
||||
* @returns The array of registered IPv6 addresses by the child.
|
||||
*
|
||||
*/
|
||||
Ip6AddressArray &GetIp6Addresses(void) { return mIp6Addresses; }
|
||||
|
||||
/**
|
||||
* Iterates over all registered IPv6 addresses (using an iterator).
|
||||
*
|
||||
* @param[in,out] aIterator The iterator to use. On success the iterator will be updated.
|
||||
* To get the first IPv6 address the iterator should be set to `kAddressIteratorInit`
|
||||
* @param[out] aAddress A reference to an IPv6 address to return the address.
|
||||
*
|
||||
* @retval kErrorNone Successfully got the next IPv6 address. @p aIterator and @p aAddress are updated.
|
||||
* @retval kErrorNotFound No more address.
|
||||
*
|
||||
*/
|
||||
Error GetNextIp6Address(AddressIterator &aIterator, Ip6::Address &aAddress) const;
|
||||
|
||||
/**
|
||||
* Adds an IPv6 address to the list.
|
||||
@@ -441,30 +379,7 @@ public:
|
||||
*/
|
||||
void ResetSecondsSinceLastSupervision(void) { mSecondsSinceSupervision = 0; }
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
/**
|
||||
* Returns MLR state of an IPv6 multicast address.
|
||||
*
|
||||
* @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`.
|
||||
*
|
||||
* @param[in] aAddress The IPv6 multicast address.
|
||||
*
|
||||
* @returns MLR state of the IPv6 multicast address.
|
||||
*
|
||||
*/
|
||||
MlrState GetAddressMlrState(const Ip6::Address &aAddress) const;
|
||||
|
||||
/**
|
||||
* Sets MLR state of an IPv6 multicast address.
|
||||
*
|
||||
* @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`.
|
||||
*
|
||||
* @param[in] aAddress The IPv6 multicast address.
|
||||
* @param[in] aState The target MLR state.
|
||||
*
|
||||
*/
|
||||
void SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
/**
|
||||
* Returns if the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
|
||||
*
|
||||
@@ -493,40 +408,16 @@ public:
|
||||
*
|
||||
*/
|
||||
bool HasAnyMlrToRegisterAddress(void) const { return mMlrToRegisterMask.HasAny(); }
|
||||
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
|
||||
private:
|
||||
#if OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD < 2
|
||||
#error OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD should be at least set to 2.
|
||||
#endif
|
||||
|
||||
static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1;
|
||||
|
||||
typedef BitVector<kNumIp6Addresses> ChildIp6AddressMask;
|
||||
typedef Array<Ip6::Address, kNumIp6Addresses> Ip6AddressArray;
|
||||
|
||||
class AddressIteratorBuilder
|
||||
{
|
||||
public:
|
||||
AddressIteratorBuilder(const Child &aChild, Ip6::Address::TypeFilter aFilter)
|
||||
: mChild(aChild)
|
||||
, mFilter(aFilter)
|
||||
{
|
||||
}
|
||||
|
||||
AddressIterator begin(void) { return AddressIterator(mChild, mFilter); }
|
||||
AddressIterator end(void) { return AddressIterator(mChild, AddressIterator::kEndIterator); }
|
||||
|
||||
private:
|
||||
const Child &mChild;
|
||||
Ip6::Address::TypeFilter mFilter;
|
||||
};
|
||||
typedef BitVector<kNumIp6Addresses> ChildIp6AddressMask;
|
||||
|
||||
uint32_t mTimeout;
|
||||
|
||||
Ip6::InterfaceIdentifier mMeshLocalIid;
|
||||
Ip6AddressArray mIp6Addresses;
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
ChildIp6AddressMask mMlrToRegisterMask;
|
||||
ChildIp6AddressMask mMlrRegisteredMask;
|
||||
#endif
|
||||
|
||||
@@ -4844,19 +4844,18 @@ Error Mle::TxMessage::AppendAddressRegistrationTlv(Child &aChild)
|
||||
tlv.SetType(Tlv::kAddressRegistration);
|
||||
SuccessOrExit(error = Append(tlv));
|
||||
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
// The parent must echo back all registered IPv6 addresses except
|
||||
// for the ML-EID, which is excluded by `Child::GetIp6Addresses()`.
|
||||
|
||||
for (const Ip6::Address &address : aChild.GetIp6Addresses())
|
||||
{
|
||||
if (address.IsMulticast() || Get<NetworkData::Leader>().GetContext(address, context) != kErrorNone)
|
||||
{
|
||||
SuccessOrExit(error = AppendAddressEntry(address));
|
||||
}
|
||||
else if (context.mContextId != kMeshLocalPrefixContextId)
|
||||
{
|
||||
SuccessOrExit(error = AppendCompressedAddressEntry(context.mContextId, address));
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
SuccessOrExit(error = AppendCompressedAddressEntry(context.mContextId, address));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1790,12 +1790,16 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||
{
|
||||
OT_ASSERT(aChild.IsStateValid());
|
||||
|
||||
for (const Ip6::Address &childAddress :
|
||||
aChild.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (const Child::Ip6AddrEntry &addrEntry : aChild.GetIp6Addresses())
|
||||
{
|
||||
if (aChild.GetAddressMlrState(childAddress) == kMlrStateRegistered)
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
IgnoreError(oldMlrRegisteredAddresses.PushBack(childAddress));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addrEntry.GetMlrState(aChild) == kMlrStateRegistered)
|
||||
{
|
||||
IgnoreError(oldMlrRegisteredAddresses.PushBack(addrEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,18 +151,25 @@ void MlrManager::UpdateProxiedSubscriptions(Child &aChild, const MlrAddressArray
|
||||
VerifyOrExit(aChild.IsStateValid());
|
||||
|
||||
// Search the new multicast addresses and set its flag accordingly
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (Child::Ip6AddrEntry &addrEntry : aChild.GetIp6Addresses())
|
||||
{
|
||||
bool isMlrRegistered = aOldMlrRegisteredAddresses.Contains(address);
|
||||
bool isMlrRegistered;
|
||||
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
isMlrRegistered = aOldMlrRegisteredAddresses.Contains(addrEntry);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLR_ENABLE
|
||||
// Check if it's a new multicast address against parent Netif
|
||||
isMlrRegistered = isMlrRegistered || IsAddressMlrRegisteredByNetif(address);
|
||||
isMlrRegistered = isMlrRegistered || IsAddressMlrRegisteredByNetif(addrEntry);
|
||||
#endif
|
||||
// Check if it's a new multicast address against other Children
|
||||
isMlrRegistered = isMlrRegistered || IsAddressMlrRegisteredByAnyChildExcept(address, &aChild);
|
||||
isMlrRegistered = isMlrRegistered || IsAddressMlrRegisteredByAnyChildExcept(addrEntry, &aChild);
|
||||
|
||||
aChild.SetAddressMlrState(address, isMlrRegistered ? kMlrStateRegistered : kMlrStateToRegister);
|
||||
addrEntry.SetMlrState(isMlrRegistered ? kMlrStateRegistered : kMlrStateToRegister, aChild);
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -253,17 +260,22 @@ void MlrManager::SendMlr(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
|
||||
{
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addresses.IsFull())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (child.GetAddressMlrState(address) == kMlrStateToRegister)
|
||||
if (addrEntry.GetMlrState(child) == kMlrStateToRegister)
|
||||
{
|
||||
addresses.AddUnique(address);
|
||||
child.SetAddressMlrState(address, kMlrStateRegistering);
|
||||
addresses.AddUnique(addrEntry);
|
||||
addrEntry.SetMlrState(kMlrStateRegistering, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,11 +526,16 @@ void MlrManager::SetMulticastAddressMlrState(MlrState aFromState, MlrState aToSt
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||
{
|
||||
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
|
||||
{
|
||||
if (child.GetAddressMlrState(address) == aFromState)
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
child.SetAddressMlrState(address, aToState);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addrEntry.GetMlrState(child) == aFromState)
|
||||
{
|
||||
addrEntry.SetMlrState(aToState, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,13 +563,18 @@ void MlrManager::FinishMlr(bool aSuccess, const AddressArray &aFailedAddresses)
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||
{
|
||||
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
|
||||
{
|
||||
if (child.GetAddressMlrState(address) == kMlrStateRegistering)
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
bool success = aSuccess || !aFailedAddresses.IsEmptyOrContains(address);
|
||||
continue;
|
||||
}
|
||||
|
||||
child.SetAddressMlrState(address, success ? kMlrStateRegistered : kMlrStateToRegister);
|
||||
if (addrEntry.GetMlrState(child) == kMlrStateRegistering)
|
||||
{
|
||||
bool success = aSuccess || !aFailedAddresses.IsEmptyOrContains(addrEntry);
|
||||
|
||||
addrEntry.SetMlrState(success ? kMlrStateRegistered : kMlrStateToRegister, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -648,11 +670,16 @@ void MlrManager::LogMulticastAddresses(void)
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||
for (const Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||
{
|
||||
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (const Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
|
||||
{
|
||||
LogDebg("%-32s%c %04x", address.ToString().AsCString(), "-rR"[child.GetAddressMlrState(address)],
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LogDebg("%-32s%c %04x", addrEntry.ToString().AsCString(), "-rR"[addrEntry.GetMlrState(child)],
|
||||
child.GetRloc16());
|
||||
}
|
||||
}
|
||||
@@ -709,11 +736,16 @@ void MlrManager::CheckInvariants(void) const
|
||||
}
|
||||
#endif
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||
for (const Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||
{
|
||||
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
|
||||
for (const Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
|
||||
{
|
||||
registeringNum += (child.GetAddressMlrState(address) == kMlrStateRegistering);
|
||||
if (!addrEntry.IsMulticastLargerThanRealmLocal())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
registeringNum += (addrEntry.GetMlrState(child) == kMlrStateRegistering);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -750,14 +750,18 @@ exit:
|
||||
Error Server::AppendChildIp6AddressListTlv(Coap::Message &aAnswer, const Child &aChild)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t numIp6Addr = 0;
|
||||
uint16_t numIp6Addr = aChild.GetIp6Addresses().GetLength();
|
||||
ChildIp6AddressListTlvValue tlvValue;
|
||||
Ip6::Address mlEid;
|
||||
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
if (aChild.GetMeshLocalIp6Address(mlEid) == kErrorNone)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(address);
|
||||
numIp6Addr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mlEid.Clear();
|
||||
}
|
||||
|
||||
VerifyOrExit(numIp6Addr > 0);
|
||||
|
||||
@@ -782,7 +786,12 @@ Error Server::AppendChildIp6AddressListTlv(Coap::Message &aAnswer, const Child &
|
||||
|
||||
SuccessOrExit(error = aAnswer.Append(tlvValue));
|
||||
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
if (!mlEid.IsUnspecified())
|
||||
{
|
||||
SuccessOrExit(error = aAnswer.Append(mlEid));
|
||||
}
|
||||
|
||||
for (const Ip6::Address &address : aChild.GetIp6Addresses())
|
||||
{
|
||||
SuccessOrExit(error = aAnswer.Append(address));
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, co
|
||||
|
||||
memset(addressObserved, 0, sizeof(addressObserved));
|
||||
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
for (const Ip6::Address &address : aChild.GetIp6Addresses())
|
||||
{
|
||||
bool addressIsInList = false;
|
||||
|
||||
@@ -78,14 +78,16 @@ void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, co
|
||||
{
|
||||
Ip6::Address address;
|
||||
|
||||
VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");
|
||||
|
||||
if (sInstance->Get<Mle::MleRouter>().IsMeshLocalAddress(aAddressList[index]))
|
||||
{
|
||||
SuccessOrQuit(aChild.GetMeshLocalIp6Address(address));
|
||||
VerifyOrQuit(address == aAddressList[index], "GetMeshLocalIp6Address() did not return expected address");
|
||||
hasMeshLocal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasMeshLocal)
|
||||
@@ -95,95 +97,6 @@ void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, co
|
||||
VerifyOrQuit(aChild.GetMeshLocalIp6Address(address) == kErrorNotFound,
|
||||
"Child::GetMeshLocalIp6Address() returned an address not in the expected list");
|
||||
}
|
||||
|
||||
// Iterate over unicast and multicast addresses separately.
|
||||
|
||||
memset(addressObserved, 0, sizeof(addressObserved));
|
||||
|
||||
for (Ip6::Address::TypeFilter filter : filters)
|
||||
{
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses(filter))
|
||||
{
|
||||
bool addressIsInList = false;
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case Ip6::Address::kTypeMulticast:
|
||||
VerifyOrQuit(address.IsMulticast(), "Address::TypeFilter failed");
|
||||
break;
|
||||
|
||||
case Ip6::Address::kTypeUnicast:
|
||||
VerifyOrQuit(!address.IsMulticast(), "Address::TypeFilter failed");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyOrQuit(address.MatchesFilter(filter));
|
||||
|
||||
for (uint8_t index = 0; index < aAddressListLength; index++)
|
||||
{
|
||||
if (address == aAddressList[index])
|
||||
{
|
||||
VerifyOrQuit(addressObserved[index] == false,
|
||||
"Child::IterateIp6Addresses() returned duplicate addr");
|
||||
addressObserved[index] = true;
|
||||
addressIsInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(addressIsInList, "Child::IterateIp6Addresses() returned an address not in the expected list");
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < aAddressListLength; index++)
|
||||
{
|
||||
VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");
|
||||
}
|
||||
|
||||
// Verify behavior of `Child::AddressIterator
|
||||
{
|
||||
Child::AddressIterator iter1(aChild);
|
||||
Child::AddressIterator iter2(aChild);
|
||||
Child::AddressIterator::Index iterIndex;
|
||||
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
{
|
||||
VerifyOrQuit(iter1 == iter2);
|
||||
VerifyOrQuit(!iter1.IsDone());
|
||||
VerifyOrQuit(*iter1.GetAddress() == address);
|
||||
VerifyOrQuit(*iter1.GetAddress() == *iter2.GetAddress());
|
||||
|
||||
iterIndex = iter1.GetAsIndex();
|
||||
VerifyOrQuit(iter2.GetAsIndex() == iterIndex);
|
||||
|
||||
{
|
||||
Child::AddressIterator iter3(aChild, iterIndex);
|
||||
VerifyOrQuit(iter3 == iter1, "AddressIterator(iterIndex) failed");
|
||||
|
||||
iter3++;
|
||||
VerifyOrQuit(iter3 != iter1, "AddressIterator(iterIndex) failed");
|
||||
}
|
||||
|
||||
iter1++;
|
||||
VerifyOrQuit(iter1 != iter2);
|
||||
iter2++;
|
||||
}
|
||||
|
||||
VerifyOrQuit(iter1.IsDone());
|
||||
VerifyOrQuit(iter2.IsDone());
|
||||
VerifyOrQuit(iter1 == iter2);
|
||||
|
||||
iterIndex = iter1.GetAsIndex();
|
||||
VerifyOrQuit(iter2.GetAsIndex() == iterIndex);
|
||||
|
||||
{
|
||||
Child::AddressIterator iter3(aChild, iterIndex);
|
||||
VerifyOrQuit(iter3 == iter1, "AddressIterator(iterIndex) failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestChildIp6Address(void)
|
||||
|
||||
Reference in New Issue
Block a user