diff --git a/src/core/thread/meshcop_dataset_manager.cpp b/src/core/thread/meshcop_dataset_manager.cpp index d369dc71e..cd8b5fec9 100644 --- a/src/core/thread/meshcop_dataset_manager.cpp +++ b/src/core/thread/meshcop_dataset_manager.cpp @@ -188,8 +188,13 @@ ThreadError DatasetManager::Clear(uint8_t &aFlags, bool aOnlyClearNetwork) ThreadError DatasetManager::Set(const Dataset &aDataset) { mNetwork.Set(aDataset); - mLocal.Set(aDataset); - mLocal.Store(); + + if (mLocal.Compare(aDataset) != 0) + { + mLocal.Set(aDataset); + mLocal.Store(); + } + return kThreadError_None; } diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 12652a006..32b21c041 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1012,38 +1012,37 @@ exit: return error; } -ThreadError Mle::AppendActiveTimestamp(Message &aMessage) +ThreadError Mle::AppendActiveTimestamp(Message &aMessage, bool aCouldUseLocal) { ThreadError error; ActiveTimestampTlv timestampTlv; - const MeshCoP::Timestamp *timestamp(mNetif.GetActiveDataset().GetNetwork().GetTimestamp()); + const MeshCoP::Timestamp *timestamp; - VerifyOrExit(timestamp || mDeviceState == kDeviceStateLeader, error = kThreadError_None); + if ((timestamp = mNetif.GetActiveDataset().GetNetwork().GetTimestamp()) == NULL && aCouldUseLocal) + { + timestamp = mNetif.GetActiveDataset().GetLocal().GetTimestamp(); + } + + VerifyOrExit(timestamp, error = kThreadError_None); timestampTlv.Init(); - - // only for Leader: set active timestamp to 0 if it is not initialized - if (timestamp == NULL) - { - timestampTlv.SetSeconds(0); - timestampTlv.SetTicks(0); - } - else - { - *static_cast(×tampTlv) = *timestamp; - } - + *static_cast(×tampTlv) = *timestamp; error = aMessage.Append(×tampTlv, sizeof(timestampTlv)); exit: return error; } -ThreadError Mle::AppendPendingTimestamp(Message &aMessage) +ThreadError Mle::AppendPendingTimestamp(Message &aMessage, bool aCouldUseLocal) { ThreadError error; PendingTimestampTlv timestampTlv; - const MeshCoP::Timestamp *timestamp(mNetif.GetPendingDataset().GetNetwork().GetTimestamp()); + const MeshCoP::Timestamp *timestamp; + + if ((timestamp = mNetif.GetPendingDataset().GetNetwork().GetTimestamp()) == NULL && aCouldUseLocal) + { + timestamp = mNetif.GetPendingDataset().GetLocal().GetTimestamp(); + } VerifyOrExit(timestamp && timestamp->GetSeconds() != 0, error = kThreadError_None); @@ -1328,8 +1327,11 @@ ThreadError Mle::SendChildIdRequest(void) } SuccessOrExit(error = AppendTlvRequest(*message, tlvs, sizeof(tlvs))); - SuccessOrExit(error = AppendActiveTimestamp(*message)); - SuccessOrExit(error = AppendPendingTimestamp(*message)); + SuccessOrExit(error = AppendActiveTimestamp(*message, true)); + // SuccessOrExit(error = AppendPendingTimestamp(*message, false)); + // we should not include the Local Pending Timestamp TLV in Child ID Request, this is a workaround for + // Certification test 9.2.15 and 9.2.16 (https://github.com/openthread/openthread/issues/918) + SuccessOrExit(error = AppendPendingTimestamp(*message, true)); memset(&destination, 0, sizeof(destination)); destination.mFields.m16[0] = HostSwap16(0xfe80); @@ -1362,8 +1364,8 @@ ThreadError Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t message->SetLinkSecurityEnabled(false); SuccessOrExit(error = AppendHeader(*message, Header::kCommandDataRequest)); SuccessOrExit(error = AppendTlvRequest(*message, aTlvs, aTlvsLength)); - SuccessOrExit(error = AppendActiveTimestamp(*message)); - SuccessOrExit(error = AppendPendingTimestamp(*message)); + SuccessOrExit(error = AppendActiveTimestamp(*message, false)); + SuccessOrExit(error = AppendPendingTimestamp(*message, false)); SuccessOrExit(error = SendMessage(*message, aDestination)); @@ -1492,7 +1494,7 @@ ThreadError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce) } else { - SuccessOrExit(error = AppendActiveTimestamp(*message)); + SuccessOrExit(error = AppendActiveTimestamp(*message, false)); } panid.Init(); @@ -2300,6 +2302,11 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa aMessage.Read(offset, sizeof(tlv), &tlv); mNetif.GetActiveDataset().Set(activeTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()); } + else if (mNetif.GetActiveDataset().GetNetwork().GetTimestamp() == NULL && + mNetif.GetActiveDataset().GetLocal().GetTimestamp() != NULL) + { + mNetif.GetActiveDataset().Set(mNetif.GetActiveDataset().GetLocal()); + } } // Pending Timestamp @@ -2313,6 +2320,12 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa aMessage.Read(offset, sizeof(tlv), &tlv); mNetif.GetPendingDataset().Set(pendingTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()); } + // this is a workaround for Certification test 9.2.15 and 9.2.16 (https://github.com/openthread/openthread/issues/918) + else if (mNetif.GetPendingDataset().GetNetwork().GetTimestamp() == NULL && + mNetif.GetPendingDataset().GetLocal().GetTimestamp() != NULL) + { + mNetif.GetPendingDataset().Set(mNetif.GetPendingDataset().GetLocal()); + } } else { diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 5917d139e..8b1a7077c 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -959,23 +959,25 @@ protected: * This method appends a Active Timestamp TLV to a message. * * @param[in] aMessage A reference to the message. + * @param[in] aCouldUseLocal Ture to use local Active Timestamp when network Active Timestamp is not available, False not. * * @retval kThreadError_None Successfully appended the Active Timestamp TLV. * @retval kThreadError_NoBufs Insufficient buffers available to append the Active Timestamp TLV. * */ - ThreadError AppendActiveTimestamp(Message &aMessage); + ThreadError AppendActiveTimestamp(Message &aMessage, bool aCouldUseLocal); /** * This method appends a Pending Timestamp TLV to a message. * * @param[in] aMessage A reference to the message. + * @param[in] aCouldUseLocal Ture to use local Pending Timestamp when network Pending Timestamp is not available, False not. * * @retval kThreadError_None Successfully appended the Pending Timestamp TLV. * @retval kThreadError_NoBufs Insufficient buffers available to append the Pending Timestamp TLV. * */ - ThreadError AppendPendingTimestamp(Message &aMessage); + ThreadError AppendPendingTimestamp(Message &aMessage, bool aCouldUseLocal); /** * This method appends a Thread Discovery TLV to a message. diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 40f5a13b1..5f897a61e 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2275,8 +2275,8 @@ ThreadError MleRouter::SendChildIdResponse(Child *aChild) SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildIdResponse)); SuccessOrExit(error = AppendSourceAddress(*message)); SuccessOrExit(error = AppendLeaderData(*message)); - SuccessOrExit(error = AppendActiveTimestamp(*message)); - SuccessOrExit(error = AppendPendingTimestamp(*message)); + SuccessOrExit(error = AppendActiveTimestamp(*message, false)); + SuccessOrExit(error = AppendPendingTimestamp(*message, false)); if (aChild->mState != Neighbor::kStateValid) { @@ -2423,8 +2423,8 @@ ThreadError MleRouter::SendDataResponse(const Ip6::Address &aDestination, const SuccessOrExit(error = AppendHeader(*message, Header::kCommandDataResponse)); SuccessOrExit(error = AppendSourceAddress(*message)); SuccessOrExit(error = AppendLeaderData(*message)); - SuccessOrExit(error = AppendActiveTimestamp(*message)); - SuccessOrExit(error = AppendPendingTimestamp(*message)); + SuccessOrExit(error = AppendActiveTimestamp(*message, false)); + SuccessOrExit(error = AppendPendingTimestamp(*message, false)); for (int i = 0; i < aTlvsLength; i++) {