Make client responsible for configuring IPv6 addresses. (#410)

* OpenThread no longer automatically configures IPv6 addresses based on network data.
* Added IPv6 address configuration to CLI to support certification tests.
* Added notification to indicate when the Thread Network Data is updated.
* Added otIp6PrefixMatch API to compute prefix match.
This commit is contained in:
Jonathan Hui
2016-08-17 16:11:46 -07:00
committed by GitHub
parent 94f1da1ada
commit 139e85f781
7 changed files with 145 additions and 107 deletions
+10 -9
View File
@@ -343,18 +343,19 @@ typedef struct otLinkModeConfig
*/
enum
{
OT_IP6_ADDRESS_ADDED = 1 << 0, ///< IPv6 address was added
OT_IP6_ADDRESS_REMOVED = 1 << 1, ///< IPv6 address was removed
OT_IP6_ADDRESS_ADDED = 1 << 0, ///< IPv6 address was added
OT_IP6_ADDRESS_REMOVED = 1 << 1, ///< IPv6 address was removed
OT_NET_ROLE = 1 << 3, ///< Device role (disabled, detached, child, router, leader) changed
OT_NET_PARTITION_ID = 1 << 4, ///< Partition ID changed
OT_NET_KEY_SEQUENCE = 1 << 5, ///< Thread Key Sequence changed
OT_NET_ROLE = 1 << 3, ///< Device role (disabled, detached, child, router, leader) changed
OT_NET_PARTITION_ID = 1 << 4, ///< Partition ID changed
OT_NET_KEY_SEQUENCE = 1 << 5, ///< Thread Key Sequence changed
OT_THREAD_CHILD_ADDED = 1 << 6, ///< Child was added
OT_THREAD_CHILD_REMOVED = 1 << 7, ///< Child was removed
OT_THREAD_CHILD_ADDED = 1 << 6, ///< Child was added
OT_THREAD_CHILD_REMOVED = 1 << 7, ///< Child was removed
OT_THREAD_NETDATA_UPDATED = 1 << 8, ///< Thread Network Data updated
OT_IP6_LL_ADDR_CHANGED = 1 << 8, ///< The link-local address has changed
OT_IP6_ML_ADDR_CHANGED = 1 << 9, ///< The mesh-local address has changed
OT_IP6_LL_ADDR_CHANGED = 1 << 9, ///< The link-local address has changed
OT_IP6_ML_ADDR_CHANGED = 1 << 10, ///< The mesh-local address has changed
};
/**
+11
View File
@@ -1657,6 +1657,17 @@ bool otIsIcmpEchoEnabled(void);
*/
void otSetIcmpEchoEnabled(bool aEnabled);
/**
* This function returns the prefix match length (bits) for two IPv6 addresses.
*
* @param[in] aFirst A pointer to the first IPv6 address.
* @param[in] aSecond A pointer to the second IPv6 address.
*
* @returns The prefix match length in bits.
*
*/
uint8_t otIp6PrefixMatch(const otIp6Address *aFirst, const otIp6Address *aSecond);
/**
* @}
*
+108
View File
@@ -42,6 +42,7 @@
#include "cli_dataset.hpp"
#include <common/encoding.hpp>
#include <common/new.hpp>
#include <platform/random.h>
#include <platform/uart.h>
using Thread::Encoding::BigEndian::HostSwap16;
@@ -113,6 +114,8 @@ uint16_t Interpreter::sLength;
uint16_t Interpreter::sCount;
uint32_t Interpreter::sInterval;
static otNetifAddress sAutoAddresses[8];
void Interpreter::Init(void)
{
sIcmpEcho = new(&sIcmpEchoBuf) Ip6::IcmpEcho(&HandleEchoResponse, NULL);
@@ -120,6 +123,7 @@ void Interpreter::Init(void)
sLength = 8;
sCount = 1;
sInterval = 1000;
otSetStateChangedCallback(&HandleNetifStateChanged, NULL);
}
int Interpreter::Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength)
@@ -1780,5 +1784,109 @@ exit:
return;
}
void Interpreter::HandleNetifStateChanged(uint32_t aFlags, void *aContext)
{
otNetworkDataIterator iterator;
otBorderRouterConfig config;
VerifyOrExit((aFlags & OT_THREAD_NETDATA_UPDATED) != 0, ;);
// remove addresses
for (size_t i = 0; i < sizeof(sAutoAddresses) / sizeof(sAutoAddresses[0]); i++)
{
otNetifAddress *address = &sAutoAddresses[i];
bool found = false;
if (address->mValidLifetime == 0)
{
continue;
}
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
while (otGetNextOnMeshPrefix(false, &iterator, &config) == kThreadError_None)
{
if (config.mSlaac == false)
{
continue;
}
if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength &&
config.mPrefix.mLength == address->mPrefixLength)
{
found = true;
break;
}
}
if (!found)
{
otRemoveUnicastAddress(address);
address->mValidLifetime = 0;
}
}
// add addresses
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
while (otGetNextOnMeshPrefix(false, &iterator, &config) == kThreadError_None)
{
bool found = false;
if (config.mSlaac == false)
{
continue;
}
for (size_t i = 0; i < sizeof(sAutoAddresses) / sizeof(sAutoAddresses[0]); i++)
{
otNetifAddress *address = &sAutoAddresses[i];
if (address->mValidLifetime == 0)
{
continue;
}
if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength &&
config.mPrefix.mLength == address->mPrefixLength)
{
found = true;
break;
}
}
if (!found)
{
for (size_t i = 0; i < sizeof(sAutoAddresses) / sizeof(sAutoAddresses[0]); i++)
{
otNetifAddress *address = &sAutoAddresses[i];
if (address->mValidLifetime != 0)
{
continue;
}
memset(address, 0, sizeof(*address));
memcpy(&address->mAddress, &config.mPrefix.mPrefix, 8);
for (size_t j = 8; j < sizeof(address->mAddress); j++)
{
address->mAddress.mFields.m8[j] = (uint8_t)otPlatRandomGet();
}
address->mPrefixLength = config.mPrefix.mLength;
address->mPreferredLifetime = config.mPreferred ? 0xffffffff : 0;
address->mValidLifetime = 0xffffffff;
otAddUnicastAddress(address);
break;
}
}
}
exit:
(void)aContext;
return;
}
} // namespace Cli
} // namespace Thread
+1
View File
@@ -185,6 +185,7 @@ private:
static void HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandlePingTimer(void *aContext);
static void HandleActiveScanResult(otActiveScanResult *aResult);
static void HandleNetifStateChanged(uint32_t aFlags, void *aContext);
static const struct Command sCommands[];
static otNetifAddress sAddress;
+12
View File
@@ -1094,6 +1094,18 @@ void otSetIcmpEchoEnabled(bool aEnabled)
Ip6::Icmp::SetEchoEnabled(aEnabled);
}
uint8_t otIp6PrefixMatch(const otIp6Address *aFirst, const otIp6Address *aSecond)
{
uint8_t rval;
VerifyOrExit(aFirst != NULL && aSecond != NULL, rval = 0);
rval = static_cast<const Ip6::Address *>(aFirst)->PrefixMatch(*static_cast<const Ip6::Address *>(aSecond));
exit:
return rval;
}
ThreadError otGetActiveDataset(otOperationalDataset *aDataset)
{
ThreadError error = kThreadError_None;
+3 -96
View File
@@ -63,7 +63,6 @@ Leader::Leader(ThreadNetif &aThreadNetif):
void Leader::Reset(void)
{
memset(mAddresses, 0, sizeof(mAddresses));
memset(mContextLastUsed, 0, sizeof(mContextLastUsed));
mVersion = static_cast<uint8_t>(otPlatRandomGet());
mStableVersion = static_cast<uint8_t>(otPlatRandomGet());
@@ -212,97 +211,6 @@ exit:
return error;
}
ThreadError Leader::ConfigureAddresses(void)
{
PrefixTlv *prefix;
// clear out addresses that are not on-mesh
for (size_t i = 0; i < sizeof(mAddresses) / sizeof(mAddresses[0]); i++)
{
if (mAddresses[i].mValidLifetime == 0 ||
IsOnMesh(mAddresses[i].GetAddress()))
{
continue;
}
mNetif.RemoveUnicastAddress(mAddresses[i]);
mAddresses[i].mValidLifetime = 0;
}
// configure on-mesh addresses
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
cur = cur->GetNext())
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
{
continue;
}
prefix = reinterpret_cast<PrefixTlv *>(cur);
ConfigureAddress(*prefix);
}
return kThreadError_None;
}
ThreadError Leader::ConfigureAddress(PrefixTlv &aPrefix)
{
BorderRouterTlv *borderRouter;
BorderRouterEntry *entry;
// look for Border Router TLV
if ((borderRouter = FindBorderRouter(aPrefix)) == NULL)
{
ExitNow();
}
// check if SLAAC flag is set
if ((entry = borderRouter->GetEntry(0)) == NULL ||
entry->IsSlaac() == false)
{
ExitNow();
}
// check if address is already added for this prefix
for (size_t i = 0; i < sizeof(mAddresses) / sizeof(mAddresses[0]); i++)
{
if (mAddresses[i].mValidLifetime != 0 &&
mAddresses[i].mPrefixLength == aPrefix.GetPrefixLength() &&
PrefixMatch(mAddresses[i].mAddress.mFields.m8, aPrefix.GetPrefix(), aPrefix.GetPrefixLength()) >= 0)
{
mAddresses[i].mPreferredLifetime = entry->IsPreferred() ? 0xffffffff : 0;
ExitNow();
}
}
// configure address for this prefix
for (size_t i = 0; i < sizeof(mAddresses) / sizeof(mAddresses[0]); i++)
{
if (mAddresses[i].mValidLifetime != 0)
{
continue;
}
memset(&mAddresses[i], 0, sizeof(mAddresses[i]));
memcpy(mAddresses[i].mAddress.mFields.m8, aPrefix.GetPrefix(), BitVectorBytes(aPrefix.GetPrefixLength()));
for (size_t j = 8; j < sizeof(mAddresses[i].mAddress); j++)
{
mAddresses[i].mAddress.mFields.m8[j] = static_cast<uint8_t>(otPlatRandomGet());
}
mAddresses[i].mPrefixLength = aPrefix.GetPrefixLength();
mAddresses[i].mPreferredLifetime = entry->IsPreferred() ? 0xffffffff : 0;
mAddresses[i].mValidLifetime = 0xffffffff;
mNetif.AddUnicastAddress(mAddresses[i]);
break;
}
exit:
return kThreadError_None;
}
bool Leader::IsOnMesh(const Ip6::Address &aAddress)
{
PrefixTlv *prefix;
@@ -527,8 +435,8 @@ void Leader::SetNetworkData(uint8_t aVersion, uint8_t aStableVersion, bool aStab
otDumpDebgNetData("set network data", mTlvs, mLength);
ConfigureAddresses();
mMle.HandleNetworkDataUpdate();
mNetif.SetStateChangedFlags(OT_THREAD_NETDATA_UPDATED);
}
void Leader::RemoveBorderRouter(uint16_t aRloc16)
@@ -546,11 +454,10 @@ void Leader::RemoveBorderRouter(uint16_t aRloc16)
{
mStableVersion++;
}
ConfigureAddresses();
}
mMle.HandleNetworkDataUpdate();
mNetif.SetStateChangedFlags(OT_THREAD_NETDATA_UPDATED);
}
void Leader::HandleServerData(void *aContext, Coap::Header &aHeader, Message &aMessage,
@@ -785,8 +692,8 @@ ThreadError Leader::RegisterNetworkData(uint16_t aRloc16, uint8_t *aTlvs, uint8_
}
}
ConfigureAddresses();
mMle.HandleNetworkDataUpdate();
mNetif.SetStateChangedFlags(OT_THREAD_NETDATA_UPDATED);
exit:
return error;
-2
View File
@@ -263,8 +263,6 @@ private:
uint32_t mContextIdReuseDelay;
Timer mTimer;
Ip6::NetifUnicastAddress mAddresses[4];
Coap::Resource mServerData;
uint8_t mStableVersion;
uint8_t mVersion;