diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 204b5086d..9127eaf06 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2026,6 +2026,7 @@ ThreadError Mle::HandleChildUpdateResponse(const Message &aMessage, const Ip6::M LeaderDataTlv leaderData; SourceAddressTlv sourceAddress; TimeoutTlv timeout; + NetworkDataTlv networkData; uint8_t tlvs[] = {Tlv::kNetworkData}; otLogInfoMle("Received Child Update Response\n"); @@ -2061,11 +2062,6 @@ ThreadError Mle::HandleChildUpdateResponse(const Message &aMessage, const Ip6::M SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData)); VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse); - if (static_cast(leaderData.GetDataVersion() - mNetworkData.GetVersion()) > 0) - { - SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs)); - } - // Source Address SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress)); VerifyOrExit(sourceAddress.IsValid(), error = kThreadError_Parse); @@ -2083,7 +2079,16 @@ ThreadError Mle::HandleChildUpdateResponse(const Message &aMessage, const Ip6::M mTimeout = timeout.GetTimeout(); } - if ((mode.GetMode() & ModeTlv::kModeRxOnWhenIdle) == 0) + // Network Data optional + if (Tlv::GetTlv(aMessage, Tlv::kNetworkData, sizeof(networkData), networkData) == kThreadError_None) + { + VerifyOrExit(networkData.IsValid(), error = kThreadError_Parse); + mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(), + (mDeviceMode & ModeTlv::kModeFullNetworkData) == 0, + networkData.GetNetworkData(), networkData.GetLength()); + } + + if ((mDeviceMode & ModeTlv::kModeRxOnWhenIdle) == 0) { mMesh.SetPollPeriod(Timer::SecToMsec(mTimeout / kMaxChildKeepAliveAttempts)); mMesh.SetRxOnWhenIdle(false); @@ -2093,6 +2098,23 @@ ThreadError Mle::HandleChildUpdateResponse(const Message &aMessage, const Ip6::M mMesh.SetRxOnWhenIdle(true); } + if (mDeviceMode & ModeTlv::kModeFullNetworkData) + { + // full network data + if (leaderData.GetDataVersion() != mNetworkData.GetVersion()) + { + SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs)); + } + } + else + { + // stable network data + if (leaderData.GetStableDataVersion() != mNetworkData.GetStableVersion()) + { + SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs)); + } + } + break; default: diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 108f21222..459dfcd71 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -1982,6 +1982,8 @@ exit: ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { + static const uint8_t kMaxResponseTlvs = 8; + ThreadError error = kThreadError_None; Mac::ExtAddress macAddr; ModeTlv mode; @@ -1990,7 +1992,7 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I LeaderDataTlv leaderData; TimeoutTlv timeout; Child *child; - uint8_t tlvs[7]; + uint8_t tlvs[kMaxResponseTlvs]; uint8_t tlvslength = 0; otLogInfoMle("Received Child Update Request\n"); @@ -2038,13 +2040,29 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I if (child->mMode & ModeTlv::kModeFullNetworkData) { + // full network data child->mNetworkDataVersion = leaderData.GetDataVersion(); + + if (leaderData.GetDataVersion() != mNetworkData.GetVersion()) + { + tlvs[tlvslength++] = Tlv::kNetworkData; + } } else { + // stable network data child->mNetworkDataVersion = leaderData.GetStableDataVersion(); + + if (leaderData.GetStableDataVersion() != mNetworkData.GetStableVersion()) + { + tlvs[tlvslength++] = Tlv::kNetworkData; + } } } + else + { + tlvs[tlvslength++] = Tlv::kNetworkData; + } // Timeout if (Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout) == kThreadError_None) @@ -2241,6 +2259,10 @@ ThreadError MleRouter::SendChildUpdateResponse(Child *aChild, const Ip6::Message SuccessOrExit(error = AppendMode(*message, aChild->mMode)); break; + case Tlv::kNetworkData: + SuccessOrExit(error = AppendNetworkData(*message, (aChild->mMode & ModeTlv::kModeFullNetworkData) == 0)); + break; + case Tlv::kResponse: SuccessOrExit(error = AppendResponse(*message, aChallenge->GetChallenge(), aChallenge->GetLength())); break;