From 55d53b627ce1735b88f745e0bddaf14058bc9f9e Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Wed, 31 Aug 2016 19:58:19 -0700 Subject: [PATCH] Automatically update leader with network data. (#480) --- src/core/thread/mle.cpp | 2 + src/core/thread/mle_router.cpp | 2 + src/core/thread/network_data.cpp | 144 ++++++++++++++++++++++++- src/core/thread/network_data.hpp | 69 +++++++++++- src/core/thread/network_data_local.cpp | 23 +++- src/core/thread/network_data_local.hpp | 5 + 6 files changed, 239 insertions(+), 6 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 0129b59ab..356daf32a 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -961,6 +961,8 @@ void Mle::HandleNetifStateChanged(uint32_t aFlags) { mSendChildUpdateRequest.Post(); } + + mNetif.GetNetworkDataLocal().SendServerDataNotification(); } } diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 46edafe53..d8caac0ff 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -1369,6 +1369,8 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M UpdateRoutes(route, routerId); + mNetif.GetNetworkDataLocal().SendServerDataNotification(); + exit: return error; } diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index 680f39672..67d3c34d5 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -66,6 +66,12 @@ void NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLen } ThreadError NetworkData::GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig) +{ + return GetNextOnMeshPrefix(aIterator, Mac::kShortAddrBroadcast, aConfig); +} + +ThreadError NetworkData::GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, uint16_t aRloc16, + otBorderRouterConfig *aConfig) { ThreadError error = kThreadError_NotFound; NetworkDataTlv *cur = reinterpret_cast(mTlvs + *aIterator); @@ -75,7 +81,7 @@ ThreadError NetworkData::GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, o { PrefixTlv *prefix; BorderRouterTlv *borderRouter; - BorderRouterEntry *borderRouterEntry; + BorderRouterEntry *borderRouterEntry = NULL; if (cur->GetType() != NetworkDataTlv::kTypePrefix) { @@ -89,9 +95,22 @@ ThreadError NetworkData::GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, o continue; } - borderRouterEntry = borderRouter->GetEntry(0); + for (uint8_t i = 0; i < borderRouter->GetNumEntries(); i++) + { + if (aRloc16 == Mac::kShortAddrBroadcast || borderRouter->GetEntry(i)->GetRloc() == aRloc16) + { + borderRouterEntry = borderRouter->GetEntry(i); + break; + } + } - memcpy(&aConfig->mPrefix.mPrefix, prefix->GetPrefix(), sizeof(aConfig->mPrefix.mPrefix)); + if (borderRouterEntry == NULL) + { + continue; + } + + memset(aConfig, 0, sizeof(*aConfig)); + memcpy(&aConfig->mPrefix.mPrefix, prefix->GetPrefix(), BitVectorBytes(prefix->GetPrefixLength())); aConfig->mPrefix.mLength = prefix->GetPrefixLength(); aConfig->mPreference = borderRouterEntry->GetPreference(); aConfig->mPreferred = borderRouterEntry->IsPreferred(); @@ -111,6 +130,125 @@ exit: return error; } +ThreadError NetworkData::GetNextExternalRoute(otNetworkDataIterator *aIterator, otExternalRouteConfig *aConfig) +{ + return GetNextExternalRoute(aIterator, Mac::kShortAddrBroadcast, aConfig); +} + +ThreadError NetworkData::GetNextExternalRoute(otNetworkDataIterator *aIterator, uint16_t aRloc16, + otExternalRouteConfig *aConfig) +{ + ThreadError error = kThreadError_NotFound; + NetworkDataTlv *cur = reinterpret_cast(mTlvs + *aIterator); + NetworkDataTlv *end = reinterpret_cast(mTlvs + mLength); + + for (; cur < end; cur = cur->GetNext()) + { + PrefixTlv *prefix; + HasRouteTlv *hasRoute; + HasRouteEntry *hasRouteEntry = NULL; + + if (cur->GetType() != NetworkDataTlv::kTypePrefix) + { + continue; + } + + prefix = static_cast(cur); + + if ((hasRoute = FindHasRoute(*prefix)) == NULL) + { + continue; + } + + for (uint8_t i = 0; i < hasRoute->GetNumEntries(); i++) + { + if (aRloc16 == Mac::kShortAddrBroadcast || hasRoute->GetEntry(i)->GetRloc() == aRloc16) + { + hasRouteEntry = hasRoute->GetEntry(i); + break; + } + } + + if (hasRouteEntry == NULL) + { + continue; + } + + memset(aConfig, 0, sizeof(*aConfig)); + memcpy(&aConfig->mPrefix.mPrefix, prefix->GetPrefix(), BitVectorBytes(prefix->GetPrefixLength())); + aConfig->mPrefix.mLength = prefix->GetPrefixLength(); + aConfig->mPreference = hasRouteEntry->GetPreference(); + aConfig->mStable = cur->IsStable(); + + *aIterator = static_cast(reinterpret_cast(cur->GetNext()) - mTlvs); + + ExitNow(error = kThreadError_None); + } + +exit: + return error; +} + +bool NetworkData::ContainsOnMeshPrefixes(NetworkData &aCompare, uint16_t aRloc16) +{ + otNetworkDataIterator outerIterator = OT_NETWORK_DATA_ITERATOR_INIT; + otBorderRouterConfig outerConfig; + bool rval = true; + + while (aCompare.GetNextOnMeshPrefix(&outerIterator, aRloc16, &outerConfig) == kThreadError_None) + { + otNetworkDataIterator innerIterator = OT_NETWORK_DATA_ITERATOR_INIT; + otBorderRouterConfig innerConfig; + ThreadError error; + + while ((error = GetNextOnMeshPrefix(&innerIterator, aRloc16, &innerConfig)) == kThreadError_None) + { + if (memcmp(&outerConfig, &innerConfig, sizeof(outerConfig)) == 0) + { + break; + } + } + + if (error != kThreadError_None) + { + ExitNow(rval = false); + } + } + +exit: + return rval; +} + +bool NetworkData::ContainsExternalRoutes(NetworkData &aCompare, uint16_t aRloc16) +{ + otNetworkDataIterator outerIterator = OT_NETWORK_DATA_ITERATOR_INIT; + otExternalRouteConfig outerConfig; + bool rval = true; + + while (aCompare.GetNextExternalRoute(&outerIterator, aRloc16, &outerConfig) == kThreadError_None) + { + otNetworkDataIterator innerIterator = OT_NETWORK_DATA_ITERATOR_INIT; + otExternalRouteConfig innerConfig; + ThreadError error; + + while ((error = GetNextExternalRoute(&innerIterator, aRloc16, &innerConfig)) == kThreadError_None) + { + if (memcmp(&outerConfig, &innerConfig, sizeof(outerConfig)) == 0) + { + break; + } + } + + if (error != kThreadError_None) + { + ExitNow(rval = false); + } + } + +exit: + return rval; +} + void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength) { NetworkDataTlv *cur = reinterpret_cast(aData); diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index b60965fb2..dab49fc12 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -108,8 +108,8 @@ public: /** * This method provides the next On Mesh prefix in the Thread Network Data. * - * @param[out] aIterator A pointer to the Network Data iterator context. - * @param[out] aConfig A pointer to where the On Mesh Prefix information will be placed. + * @param[inout] aIterator A pointer to the Network Data iterator context. + * @param[out] aConfig A pointer to where the On Mesh Prefix information will be placed. * * @retval kThreadError_None Successfully found the next On Mesh prefix. * @retval kThreadError_NotFound No subsequent On Mesh prefix exists in the Thread Network Data. @@ -117,6 +117,71 @@ public: */ ThreadError GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig); + /** + * This method provides the next On Mesh prefix in the Thread Network Data for a given RLOC16. + * + * @param[inout] aIterator A pointer to the Network Data iterator context. + * @param[in] aRloc16 The RLOC16 value. + * @param[out] aConfig A pointer to where the On Mesh Prefix information will be placed. + * + * @retval kThreadError_None Successfully found the next On Mesh prefix. + * @retval kThreadError_NotFound No subsequent On Mesh prefix exists in the Thread Network Data. + * + */ + ThreadError GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, uint16_t aRloc16, otBorderRouterConfig *aConfig); + + /** + * This method provides the next external route in the Thread Network Data. + * + * @param[inout] aIterator A pointer to the Network Data iterator context. + * @param[out] aConfig A pointer to where the external route information will be placed. + * + * @retval kThreadError_None Successfully found the next external route. + * @retval kThreadError_NotFound No subsequent external route exists in the Thread Network Data. + * + */ + ThreadError GetNextExternalRoute(otNetworkDataIterator *aIterator, otExternalRouteConfig *aConfig); + + /** + * This method provides the next external route in the Thread Network Data for a given RLOC16. + * + * @param[inout] aIterator A pointer to the Network Data iterator context. + * @param[in] aRloc16 The RLOC16 value. + * @param[out] aConfig A pointer to where the external route information will be placed. + * + * @retval kThreadError_None Successfully found the next external route. + * @retval kThreadError_NotFound No subsequent external route exists in the Thread Network Data. + * + */ + ThreadError GetNextExternalRoute(otNetworkDataIterator *aIterator, uint16_t aRloc16, + otExternalRouteConfig *aConfig); + + /** + * This method indicates whether or not the Thread Network Data contains all of the on mesh prefix information + * in @p aCompare associated with @p aRloc16. + * + * @param[in] aCompare The Network Data to use for the query. + * @param[in] aRloc16 The RLOC16 to consider. + * + * @returns TRUE if this object contains all on mesh prefix information in @p aCompare associated with @p aRloc16, + * FALSE otherwise. + * + */ + bool ContainsOnMeshPrefixes(NetworkData &aCompare, uint16_t aRloc16); + + /** + * This method indicates whether or not the Thread Network Data contains all of the external route information + * in @p aCompare associated with @p aRloc16. + * + * @param[in] aCompare The Network Data to use for the query. + * @param[in] aRloc16 The RLOC16 to consider. + * + * @returns TRUE if this object contains all external route information in @p aCompare associated with @p aRloc16, + * FALSE otherwise. + * + */ + bool ContainsExternalRoutes(NetworkData &aCompare, uint16_t aRloc16); + protected: /** * This method returns a pointer to the Border Router TLV within a given Prefix TLV. diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp index b9e0b52bd..3306d15d3 100644 --- a/src/core/thread/network_data_local.cpp +++ b/src/core/thread/network_data_local.cpp @@ -43,7 +43,8 @@ namespace NetworkData { Local::Local(ThreadNetif &aThreadNetif): NetworkData(aThreadNetif), - mOldRloc(Mac::kShortAddrInvalid) + mOldRloc(Mac::kShortAddrInvalid), + mLeader(aThreadNetif.GetNetworkDataLeader()) { } @@ -195,13 +196,33 @@ ThreadError Local::UpdateRloc(BorderRouterTlv &aBorderRouter) return kThreadError_None; } +bool Local::IsOnMeshPrefixConsistent(void) +{ + return (mLeader.ContainsOnMeshPrefixes(*this, mMle.GetRloc16()) && + ContainsOnMeshPrefixes(mLeader, mMle.GetRloc16())); +} + +bool Local::IsExternalRouteConsistent(void) +{ + return (mLeader.ContainsExternalRoutes(*this, mMle.GetRloc16()) && + ContainsExternalRoutes(mLeader, mMle.GetRloc16())); +} + ThreadError Local::SendServerDataNotification(void) { ThreadError error = kThreadError_None; uint16_t rloc = mMle.GetRloc16(); + VerifyOrExit((mMle.GetDeviceMode() & Mle::ModeTlv::kModeFFD) == 0 || + (mMle.IsRouterRoleEnabled() == false) || + (mMle.GetDeviceState() >= Mle::kDeviceStateRouter) || + (mMle.GetActiveRouterCount() >= mMle.GetRouterUpgradeThreshold()), + error = kThreadError_InvalidState); + UpdateRloc(); + VerifyOrExit(!IsOnMeshPrefixConsistent() || !IsExternalRouteConsistent(), error = kThreadError_None); + if (mOldRloc == rloc) { mOldRloc = Mac::kShortAddrInvalid; diff --git a/src/core/thread/network_data_local.hpp b/src/core/thread/network_data_local.hpp index 0eccce10b..85b627d9b 100644 --- a/src/core/thread/network_data_local.hpp +++ b/src/core/thread/network_data_local.hpp @@ -135,7 +135,12 @@ private: ThreadError UpdateRloc(HasRouteTlv &aHasRoute); ThreadError UpdateRloc(BorderRouterTlv &aBorderRouter); + bool IsOnMeshPrefixConsistent(void); + bool IsExternalRouteConsistent(void); + uint16_t mOldRloc; + + Leader &mLeader; }; } // namespace NetworkData