diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 72e41dca2..1e0e8cfcd 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2132,6 +2132,7 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I LeaderDataTlv leaderData; TimeoutTlv timeout; Child *child; + TlvRequestTlv tlvRequest; uint8_t tlvs[kMaxResponseTlvs]; uint8_t tlvslength = 0; @@ -2164,6 +2165,7 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I child->SetDeviceMode(mode.GetMode()); tlvs[tlvslength++] = Tlv::kMode; + // Parent MUST include Leader Data TLV in Child Update Response tlvs[tlvslength++] = Tlv::kLeaderData; // Challenge @@ -2187,31 +2189,6 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I if (Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData) == kThreadError_None) { VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse); - - if (child->IsFullNetworkData()) - { - // full network data - child->SetNetworkDataVersion(leaderData.GetDataVersion()); - - if (leaderData.GetDataVersion() != mNetif.GetNetworkDataLeader().GetVersion()) - { - tlvs[tlvslength++] = Tlv::kNetworkData; - } - } - else - { - // stable network data - child->SetNetworkDataVersion(leaderData.GetStableDataVersion()); - - if (leaderData.GetStableDataVersion() != mNetif.GetNetworkDataLeader().GetStableVersion()) - { - tlvs[tlvslength++] = Tlv::kNetworkData; - } - } - } - else - { - tlvs[tlvslength++] = Tlv::kNetworkData; } // Timeout @@ -2222,6 +2199,25 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I tlvs[tlvslength++] = Tlv::kTimeout; } + // TLV Request + if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == kThreadError_None) + { + uint8_t tlv; + TlvRequestIterator iterator = TLVREQUESTTLV_ITERATOR_INIT; + + VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= (Child::kMaxRequestTlvs - tlvslength), + error = kThreadError_Parse); + + while (tlvRequest.GetNextTlv(iterator, tlv) == kThreadError_None) + { + // Here skips Tlv::kLeaderData because it has already been included by default + if (tlv != Tlv::kLeaderData) + { + tlvs[tlvslength++] = tlv; + } + } + } + child->SetLastHeard(Timer::GetNow()); SendChildUpdateResponse(child, aMessageInfo, tlvs, tlvslength, &challenge); diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp index 02b587941..3c7fe56f5 100644 --- a/src/core/thread/mle_tlvs.hpp +++ b/src/core/thread/mle_tlvs.hpp @@ -52,6 +52,10 @@ namespace Thread { namespace Mle { +#define TLVREQUESTTLV_ITERATOR_INIT 0 ///< Initializer for TlvRequestTlvIterator. + +typedef uint8_t TlvRequestIterator; ///< Used to iterate through TlvRequestTlv. + /** * @addtogroup core-mle-tlvs * @@ -871,6 +875,27 @@ public: */ const uint8_t *GetTlvs(void) const { return mTlvs; } + /** + * This method provides the next Tlv in the TlvRequestTlv. + * + * @retval kThreadError_None Successfully found the next Tlv. + * @retval kThreadError_NotFound No subsequent Tlv exists in TlvRequestTlv. + * + */ + ThreadError GetNextTlv(TlvRequestIterator &aIterator, uint8_t &aTlv) + { + ThreadError error = kThreadError_NotFound; + + if (aIterator < GetLength()) + { + aTlv = mTlvs[aIterator]; + aIterator = static_cast(aIterator + sizeof(uint8_t)); + error = kThreadError_None; + } + + return error; + } + /** * This method sets the list of TLVs. *