diff --git a/include/openthread-types.h b/include/openthread-types.h index bdcda7aa7..80f138f8a 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -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 }; /** diff --git a/include/openthread.h b/include/openthread.h index 7c9ecbd6c..3edd2a190 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -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); + /** * @} * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 4af048cd5..5e7b947a8 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -42,6 +42,7 @@ #include "cli_dataset.hpp" #include #include +#include #include 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 diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 9b8fa30ae..12cf4daf3 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -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; diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index fa2bfbdcd..3d707313e 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -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(aFirst)->PrefixMatch(*static_cast(aSecond)); + +exit: + return rval; +} + ThreadError otGetActiveDataset(otOperationalDataset *aDataset) { ThreadError error = kThreadError_None; diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 8da052127..abcf25974 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -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(otPlatRandomGet()); mStableVersion = static_cast(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(mTlvs); - cur < reinterpret_cast(mTlvs + mLength); - cur = cur->GetNext()) - { - if (cur->GetType() != NetworkDataTlv::kTypePrefix) - { - continue; - } - - prefix = reinterpret_cast(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(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; diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index b2787f05f..f92e6ec65 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -263,8 +263,6 @@ private: uint32_t mContextIdReuseDelay; Timer mTimer; - Ip6::NetifUnicastAddress mAddresses[4]; - Coap::Resource mServerData; uint8_t mStableVersion; uint8_t mVersion;