mirror of
https://github.com/espressif/openthread.git
synced 2026-08-19 00:49:53 +00:00
[child] enhance Child::AddressIterator (#5269)
This commit enhances the iterator `Child::AddressIterator` which is used to iterate over IPv6 address list of a `Child`. The new model enables range-based `for` loops to be used. It also enables filtering addresses based on type (e.g., iterate over multicast addresses only). The unit test `test_child.cpp` is also updated to verify the newly added functionalities of `AddressIterator`.
This commit is contained in:
@@ -273,22 +273,28 @@ otError otThreadGetChildInfoByIndex(otInstance *aInstance, uint16_t aChildIndex,
|
||||
|
||||
otError otThreadGetChildNextIp6Address(otInstance * aInstance,
|
||||
uint16_t aChildIndex,
|
||||
otChildIp6AddressIterator *aIterator,
|
||||
otChildIp6AddressIterator *aIterIndex,
|
||||
otIp6Address * aAddress)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Instance & instance = *static_cast<Instance *>(aInstance);
|
||||
Child::Ip6AddressIterator iterator;
|
||||
Ip6::Address * address;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Instance & instance = *static_cast<Instance *>(aInstance);
|
||||
const Child *child;
|
||||
|
||||
OT_ASSERT(aIterator != nullptr && aAddress != nullptr);
|
||||
OT_ASSERT(aIterIndex != nullptr && aAddress != nullptr);
|
||||
|
||||
address = static_cast<Ip6::Address *>(aAddress);
|
||||
iterator.Set(*aIterator);
|
||||
child = instance.Get<ChildTable>().GetChildAtIndex(aChildIndex);
|
||||
VerifyOrExit(child != nullptr, error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(child->IsStateValidOrRestoring(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
SuccessOrExit(error = instance.Get<Mle::MleRouter>().GetChildNextIp6Address(aChildIndex, iterator, *address));
|
||||
{
|
||||
Child::AddressIterator iter(*child, *aIterIndex);
|
||||
|
||||
*aIterator = iterator.Get();
|
||||
VerifyOrExit(!iter.IsDone(), error = OT_ERROR_NOT_FOUND);
|
||||
*aAddress = *iter.GetAddress();
|
||||
|
||||
iter++;
|
||||
*aIterIndex = iter.GetAsIndex();
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
@@ -369,6 +369,31 @@ uint8_t Address::PrefixMatch(const otIp6Address &aOther) const
|
||||
return PrefixMatch(mFields.m8, aOther.mFields.m8, sizeof(Address));
|
||||
}
|
||||
|
||||
bool Address::MatchesFilter(TypeFilter aFilter) const
|
||||
{
|
||||
bool matches = true;
|
||||
|
||||
switch (aFilter)
|
||||
{
|
||||
case kTypeAny:
|
||||
break;
|
||||
|
||||
case kTypeUnicast:
|
||||
matches = !IsUnspecified() && !IsMulticast();
|
||||
break;
|
||||
|
||||
case kTypeMulticast:
|
||||
matches = IsMulticast();
|
||||
break;
|
||||
|
||||
case kTypeMulticastLargerThanRealmLocal:
|
||||
matches = IsMulticastLargerThanRealmLocal();
|
||||
break;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
otError Address::FromString(const char *aBuf)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -324,6 +324,18 @@ public:
|
||||
kGlobalScope = 14, ///< Global scope
|
||||
};
|
||||
|
||||
/**
|
||||
* This enumeration defines IPv6 address type filter.
|
||||
*
|
||||
*/
|
||||
enum TypeFilter : uint8_t
|
||||
{
|
||||
kTypeAny, ///< Accept any IPv6 address (unicast or multicast).
|
||||
kTypeUnicast, ///< Accept unicast IPv6 addresses only.
|
||||
kTypeMulticast, ///< Accept multicast IPv6 addresses only.
|
||||
kTypeMulticastLargerThanRealmLocal, ///< Accept multicast IPv6 addresses with scope larger than Realm Local.
|
||||
};
|
||||
|
||||
/**
|
||||
* This type defines the fixed-length `String` object returned from `ToString()`.
|
||||
*
|
||||
@@ -618,6 +630,17 @@ public:
|
||||
*/
|
||||
uint8_t PrefixMatch(const otIp6Address &aOther) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether address matches a given type filter.
|
||||
*
|
||||
* @param[in] aFilter An address type filter.
|
||||
*
|
||||
* @retval TRUE The address matches @p aFilter.
|
||||
* @retval FALSE The address does not match @p aFilter.
|
||||
*
|
||||
*/
|
||||
bool MatchesFilter(TypeFilter aFilter) const;
|
||||
|
||||
/**
|
||||
* This method converts an IPv6 address string to binary.
|
||||
*
|
||||
|
||||
@@ -3640,23 +3640,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError MleRouter::GetChildNextIp6Address(uint16_t aChildIndex,
|
||||
Child::Ip6AddressIterator &aIterator,
|
||||
Ip6::Address & aAddress)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Child * child = nullptr;
|
||||
|
||||
child = mChildTable.GetChildAtIndex(aChildIndex);
|
||||
VerifyOrExit(child != nullptr, error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(child->IsStateValidOrRestoring(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
error = child->GetNextIp6Address(aIterator, aAddress);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::RestoreChildren(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -4425,19 +4408,17 @@ otError MleRouter::AppendConnectivity(Message &aMessage)
|
||||
|
||||
otError MleRouter::AppendChildAddresses(Message &aMessage, Child &aChild)
|
||||
{
|
||||
otError error;
|
||||
Ip6::Address address;
|
||||
Child::Ip6AddressIterator iterator;
|
||||
Tlv tlv;
|
||||
AddressRegistrationEntry entry;
|
||||
Lowpan::Context context;
|
||||
uint8_t length = 0;
|
||||
uint16_t startOffset = aMessage.GetLength();
|
||||
otError error;
|
||||
Tlv tlv;
|
||||
AddressRegistrationEntry entry;
|
||||
Lowpan::Context context;
|
||||
uint8_t length = 0;
|
||||
uint16_t startOffset = aMessage.GetLength();
|
||||
|
||||
tlv.SetType(Tlv::kAddressRegistration);
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
|
||||
|
||||
while (aChild.GetNextIp6Address(iterator, address) == OT_ERROR_NONE)
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
{
|
||||
if (address.IsMulticast() || Get<NetworkData::Leader>().GetContext(address, context) != OT_ERROR_NONE)
|
||||
{
|
||||
|
||||
@@ -441,21 +441,6 @@ public:
|
||||
*/
|
||||
otError GetChildInfoByIndex(uint16_t aChildIndex, otChildInfo &aChildInfo);
|
||||
|
||||
/**
|
||||
* This methods gets the next IPv6 address (using an iterator) for a given child.
|
||||
*
|
||||
* @param[in] aChildIndex The child index.
|
||||
* @param[inout] aIterator A reference to iterator. On success the iterator will be updated to point to next
|
||||
* entry in the list.
|
||||
* @param[out] aAddress A reference to an IPv6 address where the child's next address is placed (on success).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully found the next address (@p aAddress and @ aIterator are updated).
|
||||
* @retval OT_ERROR_NOT_FOUND The child has no subsequent IPv6 address entry.
|
||||
* @retval OT_ERROR_INVALID_ARGS Child at @p aChildIndex is not valid.
|
||||
*
|
||||
*/
|
||||
otError GetChildNextIp6Address(uint16_t aChildIndex, Child::Ip6AddressIterator &aIterator, Ip6::Address &aAddress);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the RLOC16 is an MTD child of this device.
|
||||
*
|
||||
|
||||
@@ -111,6 +111,39 @@ void Neighbor::GenerateChallenge(void)
|
||||
Random::Crypto::FillBuffer(mValidPending.mPending.mChallenge, sizeof(mValidPending.mPending.mChallenge)));
|
||||
}
|
||||
|
||||
const Ip6::Address *Child::AddressIterator::GetAddress(void) 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).
|
||||
|
||||
return (mIndex == 0) ? &mMeshLocalAddress : ((mIndex < kMaxIndex) ? &mChild.mIp6Address[mIndex - 1] : nullptr);
|
||||
}
|
||||
|
||||
void Child::AddressIterator::Update(void)
|
||||
{
|
||||
const Ip6::Address *address;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ((mIndex == 0) && (mChild.GetMeshLocalIp6Address(mMeshLocalAddress) != OT_ERROR_NONE))
|
||||
{
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
address = GetAddress();
|
||||
|
||||
VerifyOrExit((address != nullptr) && !address->IsUnspecified(), mIndex = kMaxIndex);
|
||||
|
||||
VerifyOrExit(!address->MatchesFilter(mFilter), OT_NOOP);
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Child::Clear(void)
|
||||
{
|
||||
Instance &instance = GetInstance();
|
||||
@@ -138,31 +171,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Child::GetNextIp6Address(Ip6AddressIterator &aIterator, Ip6::Address &aAddress) const
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otChildIp6AddressIterator index;
|
||||
|
||||
// Index zero corresponds to the Mesh Local IPv6 address (if any).
|
||||
|
||||
if (aIterator.Get() == 0)
|
||||
{
|
||||
aIterator.Increment();
|
||||
VerifyOrExit(GetMeshLocalIp6Address(aAddress) == OT_ERROR_NOT_FOUND, OT_NOOP);
|
||||
}
|
||||
|
||||
index = aIterator.Get() - 1;
|
||||
|
||||
VerifyOrExit(index < kNumIp6Addresses, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
VerifyOrExit(!mIp6Address[index].IsUnspecified(), error = OT_ERROR_NOT_FOUND);
|
||||
aAddress = mIp6Address[index];
|
||||
aIterator.Increment();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Child::AddIp6Address(const Ip6::Address &aAddress)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
+161
-25
@@ -497,6 +497,8 @@ private:
|
||||
*/
|
||||
class Child : public Neighbor, public IndirectSender::ChildInfo, public DataPollHandler::ChildInfo
|
||||
{
|
||||
class AddressIteratorBuilder;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
@@ -504,53 +506,160 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class defines an iterator used by `GetNextIp6Address()` to go through IPv6 address entries of a child.
|
||||
* This class defines an iterator used to go through IPv6 address entries of a child.
|
||||
*
|
||||
*/
|
||||
class Ip6AddressIterator
|
||||
class AddressIterator
|
||||
{
|
||||
friend class Child;
|
||||
friend class AddressIteratorBuilder;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the iterator object.
|
||||
*
|
||||
* After initialization a call to `GetNextIp6Address()` would start at the first IPv6 address entry in the list.
|
||||
* This type represents an index indicating the current IPv6 address entry to which the iterator is pointing.
|
||||
*
|
||||
*/
|
||||
Ip6AddressIterator(void)
|
||||
: mIndex(0)
|
||||
typedef otChildIp6AddressIterator Index;
|
||||
|
||||
/**
|
||||
* This constructor initializes the iterator associated with a given `Child` starting from beginning of the
|
||||
* IPv6 address list.
|
||||
*
|
||||
* @param[in] aChild A reference to a child entry.
|
||||
* @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses.
|
||||
*
|
||||
*/
|
||||
AddressIterator(const Child &aChild, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny)
|
||||
: AddressIterator(aChild, 0, aFilter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method resets the iterator.
|
||||
* This constructor initializes the iterator associated with a given `Child` starting from a given index
|
||||
*
|
||||
* After reset the next call to `GetNextIp6Address()` would start at the first IPv6 address entry in the list.
|
||||
* @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.
|
||||
*
|
||||
*/
|
||||
void Reset(void) { mIndex = 0; }
|
||||
AddressIterator(const Child &aChild, Index aIndex, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny)
|
||||
: mChild(aChild)
|
||||
, mFilter(aFilter)
|
||||
, mIndex(aIndex)
|
||||
{
|
||||
Update();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the iterator from an `otChildIp6AddressIterator`
|
||||
* This method converts the iterator into an index.
|
||||
*
|
||||
* @param[in] aChildAddressIterator A child address iterator
|
||||
* @returns An index corresponding to the iterator.
|
||||
*
|
||||
*/
|
||||
void Set(otChildIp6AddressIterator aChildAddressIterator) { mIndex = aChildAddressIterator; }
|
||||
Index GetAsIndex(void) const { return mIndex; }
|
||||
|
||||
/**
|
||||
* This method returns the iterator as an `otChildIp6AddressIterator`
|
||||
* This method gets the iterator's associated `Child` entry.
|
||||
*
|
||||
* @returns The iterator as an `otChildIp6AddressIterator`
|
||||
* @returns The associated child entry.
|
||||
*
|
||||
*/
|
||||
otChildIp6AddressIterator Get(void) const { return mIndex; }
|
||||
const Child &GetChild(void) const { return mChild; }
|
||||
|
||||
/**
|
||||
* This method 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;
|
||||
|
||||
/**
|
||||
* This method 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); }
|
||||
|
||||
/**
|
||||
* This method 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(); }
|
||||
|
||||
/**
|
||||
* This method 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(); }
|
||||
|
||||
/**
|
||||
* This method overloads the `*` dereference operator and gets a reference to `Ip6::Address` to which the
|
||||
* iterator is currently pointing.
|
||||
*
|
||||
* This method 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(); }
|
||||
|
||||
/**
|
||||
* This method overloads operator `==` to evaluate whether or not two `Iterator` instances are equal.
|
||||
*
|
||||
* This method 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); }
|
||||
|
||||
/**
|
||||
* This method overloads operator `!=` to evaluate whether or not two `Iterator` instances are unequal.
|
||||
*
|
||||
* This method 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 unequal.
|
||||
* @retval FALSE If the two `Iterator` objects are not unequal.
|
||||
*
|
||||
*/
|
||||
bool operator!=(const AddressIterator &aOther) const { return !(*this == aOther); }
|
||||
|
||||
private:
|
||||
void Increment(void) { mIndex++; }
|
||||
enum IteratorType : uint8_t
|
||||
{
|
||||
kEndIterator,
|
||||
};
|
||||
|
||||
otChildIp6AddressIterator mIndex;
|
||||
enum : 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -593,16 +702,26 @@ public:
|
||||
const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; }
|
||||
|
||||
/**
|
||||
* This method gets the next IPv6 address in the list.
|
||||
* This method enables range-based `for` loop iteration over all (or a subset of) IPv6 addresses.
|
||||
*
|
||||
* @param[inout] aIterator A reference to an IPv6 address iterator.
|
||||
* @param[out] aAddress A reference to an IPv6 address to provide the next address (if any).
|
||||
* This method should be used as follows: to iterate over all addresses
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully found the next address and updated @p aAddress and @p aIterator.
|
||||
* @retval OT_ERROR_NOT_FOUND No subsequent IPv6 address exists in the IPv6 address list.
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
otError GetNextIp6Address(Ip6AddressIterator &aIterator, Ip6::Address &aAddress) const;
|
||||
AddressIteratorBuilder IterateIp6Addresses(Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) const
|
||||
{
|
||||
return AddressIteratorBuilder(*this, aFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds an IPv6 address to the list.
|
||||
@@ -753,6 +872,23 @@ private:
|
||||
kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1,
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
uint8_t mNetworkDataVersion; ///< Current Network Data version
|
||||
Ip6::InterfaceIdentifier mMeshLocalIid; ///< IPv6 address IID for mesh-local address
|
||||
Ip6::Address mIp6Address[kNumIp6Addresses]; ///< Registered IPv6 addresses
|
||||
|
||||
+100
-17
@@ -46,11 +46,9 @@ enum
|
||||
|
||||
void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, const Ip6::Address aAddressList[])
|
||||
{
|
||||
Child::Ip6AddressIterator iterator;
|
||||
Ip6::Address address;
|
||||
bool addressObserved[kMaxChildIp6Addresses];
|
||||
bool addressIsMeshLocal[kMaxChildIp6Addresses];
|
||||
bool hasMeshLocal = false;
|
||||
Ip6::Address::TypeFilter filters[] = {Ip6::Address::kTypeUnicast, Ip6::Address::kTypeMulticast};
|
||||
bool addressObserved[kMaxChildIp6Addresses];
|
||||
bool hasMeshLocal = false;
|
||||
|
||||
for (uint8_t index = 0; index < aAddressListLength; index++)
|
||||
{
|
||||
@@ -58,16 +56,8 @@ void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, co
|
||||
}
|
||||
|
||||
memset(addressObserved, 0, sizeof(addressObserved));
|
||||
memset(addressIsMeshLocal, 0, sizeof(addressObserved));
|
||||
|
||||
for (uint8_t index = 0; index < aAddressListLength; index++)
|
||||
{
|
||||
{
|
||||
addressIsMeshLocal[index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
while (aChild.GetNextIp6Address(iterator, address) == OT_ERROR_NONE)
|
||||
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
|
||||
{
|
||||
bool addressIsInList = false;
|
||||
|
||||
@@ -81,12 +71,14 @@ void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, co
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(addressIsInList, "Child::GetNextIp6Address() returned an address not in the expected list");
|
||||
VerifyOrQuit(addressIsInList, "Child::IterateIp6Addresses() returned an address not in the expected list");
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < aAddressListLength; index++)
|
||||
{
|
||||
VerifyOrQuit(addressObserved[index], "Child::GetNextIp6Address() missed an entry from the expected list");
|
||||
Ip6::Address address;
|
||||
|
||||
VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");
|
||||
|
||||
if (sInstance->Get<Mle::MleRouter>().IsMeshLocalAddress(aAddressList[index]))
|
||||
{
|
||||
@@ -98,9 +90,100 @@ void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, co
|
||||
|
||||
if (!hasMeshLocal)
|
||||
{
|
||||
Ip6::Address address;
|
||||
|
||||
VerifyOrQuit(aChild.GetMeshLocalIp6Address(address) == OT_ERROR_NOT_FOUND,
|
||||
"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), "Address::MatchesFilter() failed");
|
||||
|
||||
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, "AddressIterator:operator== failed");
|
||||
VerifyOrQuit(!iter1.IsDone(), "AddressIterator::IsDone() failed");
|
||||
VerifyOrQuit(*iter1.GetAddress() == address, "AddressIterator::GetAddress() failed");
|
||||
VerifyOrQuit(*iter1.GetAddress() == *iter2.GetAddress(), "AddressIterator::GetAddress() failed");
|
||||
|
||||
iterIndex = iter1.GetAsIndex();
|
||||
VerifyOrQuit(iter2.GetAsIndex() == iterIndex, "AddressIterator: GetAsIndex() failed");
|
||||
|
||||
{
|
||||
Child::AddressIterator iter3(aChild, iterIndex);
|
||||
VerifyOrQuit(iter3 == iter1, "AddressIterator(iterIndex) failed");
|
||||
|
||||
iter3++;
|
||||
VerifyOrQuit(iter3 != iter1, "AddressIterator(iterIndex) failed");
|
||||
}
|
||||
|
||||
iter1++;
|
||||
VerifyOrQuit(iter1 != iter2, "AddressIterator:operator!= failed");
|
||||
iter2++;
|
||||
}
|
||||
|
||||
VerifyOrQuit(iter1.IsDone(), "AddressIterator::IsDone() failed");
|
||||
VerifyOrQuit(iter2.IsDone(), "AddressIterator::IsDone() failed");
|
||||
VerifyOrQuit(iter1 == iter2, "AddressIterator:operator== failed");
|
||||
|
||||
iterIndex = iter1.GetAsIndex();
|
||||
VerifyOrQuit(iter2.GetAsIndex() == iterIndex, "AddressIterator: GetAsIndex() failed");
|
||||
|
||||
{
|
||||
Child::AddressIterator iter3(aChild, iterIndex);
|
||||
VerifyOrQuit(iter3 == iter1, "AddressIterator(iterIndex) failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestChildIp6Address(void)
|
||||
@@ -110,7 +193,7 @@ void TestChildIp6Address(void)
|
||||
uint8_t numAddresses;
|
||||
const char * ip6Addresses[] = {
|
||||
"fd00:1234::1234",
|
||||
"fd6b:e251:52fb:0:12e6:b94c:1c28:c56a",
|
||||
"ff6b:e251:52fb:0:12e6:b94c:1c28:c56a",
|
||||
"fd00:1234::204c:3d7c:98f6:9a1b",
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user