[child] update how IPv6 addresses of a child are managed (#2485)

This commit updates/enhances the `Child` class methods related to
managing of the list of IPv6 addresses associated with a child. The
new model provides APIs to add or remove an IPv6 address, check if the
list contains an address, and a method to iterate through all IPv6
addresses of a child. The `mle_router` and `address_resolver` and NCP
implementations are updated to use the new APIs.

This commit also adds a unit test `test_child` to verify  the newly
added methods.
This commit is contained in:
Abtin Keshavarzian
2018-01-22 16:52:14 +00:00
committed by Jonathan Hui
parent 2636df1952
commit 5e6e262dfb
13 changed files with 530 additions and 92 deletions
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (c) 2018, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_platform.h"
#include <openthread/config.h>
#include <openthread/openthread.h>
#include "common/instance.hpp"
#include "test_util.h"
#include "thread/topology.hpp"
namespace ot {
static ot::Instance *sInstance;
enum
{
kMaxChildIp6Addresses = OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD
};
void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, const Ip6::Address aAddressList[])
{
Child::Ip6AddressIterator iterator;
Ip6::Address address;
bool addressObserved[kMaxChildIp6Addresses];
for (uint8_t index = 0; index < aAddressListLength; index++)
{
VerifyOrQuit(aChild.HasIp6Address(aAddressList[index]), "HasIp6Address() failed\n");
}
memset(addressObserved, 0, sizeof(addressObserved));
while (aChild.GetNextIp6Address(iterator, address) == OT_ERROR_NONE)
{
bool addressIsInList = false;
for (uint8_t index = 0; index < aAddressListLength; index++)
{
if (address == aAddressList[index])
{
addressIsInList = true;
addressObserved[index] = true;
break;
}
}
VerifyOrQuit(addressIsInList, "Child::GetNextIp6Address() returned an address not in the expected list\n");
}
for (uint8_t index = 0; index < aAddressListLength; index++)
{
VerifyOrQuit(addressObserved[index], "Child::GetNextIp6Address() missed an entry from the expected list\n");
}
}
void TestChildIp6Address(void)
{
Child child;
Ip6::Address addresses[kMaxChildIp6Addresses];
const char *ip6Addresses[] =
{
"fe80::1234",
"fd6b:e251:52fb:0:12e6:b94c:1c28:c56a",
"fd00:1234::204c:3d7c:98f6:9a1b",
"fd00:cafe::204c:3d7c:98f6:9a1b",
};
uint8_t numAddresses = static_cast<uint8_t>(sizeof(ip6Addresses) / sizeof(ip6Addresses[0]));
sInstance = testInitInstance();
VerifyOrQuit(sInstance != NULL, "Null instance");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("\nConverting IPv6 addresses from string");
for (uint8_t index = 0; index < numAddresses; index++)
{
VerifyOrQuit(index < kMaxChildIp6Addresses, "Too many IPv6 addresses in the unit test");
SuccessOrQuit(addresses[index].FromString(ip6Addresses[index]),
"could not convert IPv6 address from string");
}
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Child state after init");
memset(&child, 0, sizeof(child));
VerifyChildIp6Addresses(child, 0, NULL);
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Adding a single IPv6 address");
for (uint8_t index = 0; index < numAddresses; index++)
{
SuccessOrQuit(child.AddIp6Address(addresses[index]), "AddIp6Address() failed");
VerifyChildIp6Addresses(child, 1, &addresses[index]);
child.ClearIp6Addresses();
VerifyChildIp6Addresses(child, 0, NULL);
}
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Adding multiple IPv6 addresses");
for (uint8_t index = 0; index < numAddresses; index++)
{
SuccessOrQuit(child.AddIp6Address(addresses[index]), "AddIp6Address() failed");
VerifyChildIp6Addresses(child, index + 1, addresses);
}
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Checking for failure when adding an address already in list");
for (uint8_t index = 0; index < numAddresses; index++)
{
VerifyOrQuit(child.AddIp6Address(addresses[index]) == OT_ERROR_ALREADY,
"AddIp6Address() did not fail when adding same address");
VerifyChildIp6Addresses(child, numAddresses, addresses);
}
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Removing addresses from list starting from front of the list");
for (uint8_t index = 0; index < numAddresses; index++)
{
SuccessOrQuit(child.RemoveIp6Address(addresses[index]), "RemoveIp6Address() failed");
VerifyChildIp6Addresses(child, numAddresses - 1 - index, &addresses[index + 1]);
VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == OT_ERROR_NOT_FOUND,
"RemoveIp6Address() did not fail when removing an address not on the list");
}
VerifyChildIp6Addresses(child, 0, NULL);
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Removing addresses from list starting from back of the list");
for (uint8_t index = 0; index < numAddresses; index++)
{
SuccessOrQuit(child.AddIp6Address(addresses[index]), "AddIp6Address() failed");
}
for (uint8_t index = numAddresses - 1; index > 0; index--)
{
SuccessOrQuit(child.RemoveIp6Address(addresses[index]), "RemoveIp6Address() failed");
VerifyChildIp6Addresses(child, index, &addresses[0]);
VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == OT_ERROR_NOT_FOUND,
"RemoveIp6Address() did not fail when removing an address not on the list");
}
printf(" -- PASS\n");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
printf("Removing address entries from middle of the list");
for (uint8_t indexToRemove = 1; indexToRemove < numAddresses - 1; indexToRemove++)
{
child.ClearIp6Addresses();
for (uint8_t index = 0; index < numAddresses; index++)
{
SuccessOrQuit(child.AddIp6Address(addresses[index]), "AddIp6Address() failed");
}
SuccessOrQuit(child.RemoveIp6Address(addresses[indexToRemove]), "RemoveIp6Address() failed");
VerifyOrQuit(child.RemoveIp6Address(addresses[indexToRemove]) == OT_ERROR_NOT_FOUND,
"RemoveIp6Address() did not fail when removing an address not on the list");
{
Ip6::Address updatedAddressList[kMaxChildIp6Addresses];
uint8_t updatedListIndex = 0;
for (uint8_t index = 0; index < numAddresses; index++)
{
if (index != indexToRemove)
{
updatedAddressList[updatedListIndex++] = addresses[index];
}
}
VerifyChildIp6Addresses(child, updatedListIndex, updatedAddressList);
}
}
printf(" -- PASS\n");
testFreeInstance(sInstance);
}
} // namespace ot
#ifdef ENABLE_TEST_MAIN
int main(void)
{
ot::TestChildIp6Address();
printf("\nAll tests passed.\n");
return 0;
}
#endif