[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:
Abtin Keshavarzian
2020-07-23 12:16:45 -07:00
committed by GitHub
parent 7a612437ed
commit 2efe99c507
8 changed files with 365 additions and 118 deletions
+100 -17
View File
@@ -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",
};