mirror of
https://github.com/espressif/openthread.git
synced 2026-07-28 06:37:46 +00:00
Implement "last-in wins" duplicate IPv6 address resolution (#1720)
This commit implements "last-in wins" duplicate IPv6 address resolution policy for children's registered addresses. When a child registers a new address, it is checked if the same IPv6 address is registered by another child and if so the address is removed from the other child's registered IPv6 address list. Duplicate addresses can occur if a previously attached child attaches to same parent again (after a reset, memory wipe) using a new random extended address before the old entry in the child table is timed out and then trying to register its globally unique IPv6 address as the new child.
This commit is contained in:
committed by
Jonathan Hui
parent
bb4ffe373c
commit
849dcba11b
@@ -1965,7 +1965,10 @@ exit:
|
||||
ThreadError MleRouter::UpdateChildAddresses(const AddressRegistrationTlv &aTlv, Child &aChild)
|
||||
{
|
||||
const AddressRegistrationEntry *entry;
|
||||
Ip6::Address address;
|
||||
Lowpan::Context context;
|
||||
Child *child;
|
||||
uint8_t index;
|
||||
|
||||
aChild.ClearIp6Addresses();
|
||||
|
||||
@@ -1980,12 +1983,39 @@ ThreadError MleRouter::UpdateChildAddresses(const AddressRegistrationTlv &aTlv,
|
||||
{
|
||||
// xxx check if context id exists
|
||||
mNetif.GetNetworkDataLeader().GetContext(entry->GetContextId(), context);
|
||||
memcpy(&aChild.GetIp6Address(count), context.mPrefix, BitVectorBytes(context.mPrefixLength));
|
||||
aChild.GetIp6Address(count).SetIid(entry->GetIid());
|
||||
memcpy(&address, context.mPrefix, BitVectorBytes(context.mPrefixLength));
|
||||
address.SetIid(entry->GetIid());
|
||||
}
|
||||
else
|
||||
{
|
||||
aChild.GetIp6Address(count) = *entry->GetIp6Address();
|
||||
address = *entry->GetIp6Address();
|
||||
}
|
||||
|
||||
aChild.GetIp6Address(count) = address;
|
||||
|
||||
// We check if the same address is in-use by another child, if so
|
||||
// remove it. This implements "last-in wins" duplicate address
|
||||
// resolution policy.
|
||||
//
|
||||
// Duplicate addresses can occur if a previously attached child
|
||||
// attaches to same parent again (after a reset, memory wipe) using
|
||||
// a new random extended address before the old entry in the child
|
||||
// table is timed out and then trying to register its globally unique
|
||||
// IPv6 address as the new child.
|
||||
|
||||
for (int i = 0; i < mMaxChildrenAllowed; i++)
|
||||
{
|
||||
child = &mChildren[i];
|
||||
|
||||
if (!child->IsStateValidOrRestoring() || (child == &aChild))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child->FindIp6Address(address, &index) == kThreadError_None)
|
||||
{
|
||||
child->RemoveIp6Address(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3253,12 +3283,9 @@ Neighbor *MleRouter::GetNeighbor(const Ip6::Address &aAddress)
|
||||
ExitNow(rval = child);
|
||||
}
|
||||
|
||||
for (uint8_t j = 0; j < Child::kMaxIp6AddressPerChild; j++)
|
||||
if (child->FindIp6Address(aAddress, NULL) == kThreadError_None)
|
||||
{
|
||||
if (child->GetIp6Address(j) == aAddress)
|
||||
{
|
||||
ExitNow(rval = child);
|
||||
}
|
||||
ExitNow(rval = child);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,42 @@ void Neighbor::GenerateChallenge(void)
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError Child::FindIp6Address(const Ip6::Address &aAddress, uint8_t *aIndex) const
|
||||
{
|
||||
ThreadError error = kThreadError_NotFound;
|
||||
|
||||
for (uint8_t index = 0; index < kMaxIp6AddressPerChild; index++)
|
||||
{
|
||||
if (mIp6Address[index] == aAddress)
|
||||
{
|
||||
if (aIndex != NULL)
|
||||
{
|
||||
*aIndex = index;
|
||||
}
|
||||
|
||||
error = kThreadError_None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void Child::RemoveIp6Address(uint8_t aIndex)
|
||||
{
|
||||
VerifyOrExit(aIndex < kMaxIp6AddressPerChild);
|
||||
|
||||
for (uint8_t i = aIndex; i < kMaxIp6AddressPerChild - 1; i++)
|
||||
{
|
||||
mIp6Address[i] = mIp6Address[i + 1];
|
||||
}
|
||||
|
||||
memset(&mIp6Address[kMaxIp6AddressPerChild - 1], 0, sizeof(Ip6::Address));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Child::GenerateChallenge(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < sizeof(mAttachChallenge); i++)
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
* Check if the neighbor/child is in valid state or if it is being restored.
|
||||
* When in these states messages can be sent to and/or received from the neighbor/child.
|
||||
*
|
||||
* @returns `true` if the neighbor is in valid, restored, or being restored states, `false` otherwise.
|
||||
* @returns TRUE if the neighbor is in valid, restored, or being restored states, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsStateValidOrRestoring(void) const { return (mState == kStateValid) || (mState == kStateRestored); }
|
||||
@@ -370,6 +370,28 @@ public:
|
||||
*/
|
||||
Ip6::Address &GetIp6Address(uint8_t aIndex) { return mIp6Address[aIndex]; }
|
||||
|
||||
/**
|
||||
* This method searches for a given IPv6 address in the child's IPv6 address list and provides the index of the
|
||||
* address in the list if it is found.
|
||||
*
|
||||
* @param[in] aAddress The IPv6 address to search for in the IPv6 address list.
|
||||
* @param[out] aIndex Pointer to variable where the index of address is provided if address is found in
|
||||
* the list. @p aIndex can be set NULL if index is not required.
|
||||
*
|
||||
* @retval kThreadError_None Successfully found the address in IPv6 address list and updated @p aIndex.
|
||||
* @retval kThreadError_NotFound Could not find the address in the list.
|
||||
*
|
||||
*/
|
||||
ThreadError FindIp6Address(const Ip6::Address &aAddress, uint8_t *aIndex) const;
|
||||
|
||||
/**
|
||||
* This method removes the address at index @p aIndex.
|
||||
*
|
||||
* @param[in] aIndex The index into the IPv6 address list.
|
||||
*
|
||||
*/
|
||||
void RemoveIp6Address(uint8_t aIndex);
|
||||
|
||||
/**
|
||||
* This method gets the child timeout.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user