From 9d66542ed841beabc3a2d72ab20d146ed3ce43b5 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Wed, 16 Aug 2017 09:59:58 -0700 Subject: [PATCH] [mle] enable retransmission of network data to SEDs (#2107) The Thread Specification requires the router to repeatedly transmit new Thread Network Data to the SED until it receive an explicit acknolwedgment from the SED. Prior to this commit, when network data changes, a router attempts to update the SED by sending a single MLE Data Response message. If the message is lost for any reason (e.g. no available message buffers, link-layer delivery failure, etc.), the router will not attempt to send the MLE Data Response again to update the SED's network data. This commit makes the following changes: - The router communicates updated network data in an MLE Child Update Request message, requiring the SED to send an MLE Child Update Response message with the Leader Data TLV. - The router repeatedly attempts to transmit new network data to the SED until it receives a Leader Data TLV with the updated version. --- src/core/thread/mle_router.cpp | 39 +++++++++++++++++++----------- src/core/thread/mle_router_ftd.hpp | 1 + 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index bdd3da41f..3cbc06f76 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -1888,6 +1888,8 @@ void MleRouter::HandleStateUpdateTimer(void) } } + SynchronizeChildNetworkData(); + mStateUpdateTimer.Start(kStateUpdatePeriod); exit: @@ -2461,7 +2463,6 @@ exit: otError MleRouter::HandleNetworkDataUpdateRouter(void) { static const uint8_t tlvs[] = {Tlv::kNetworkData}; - ThreadNetif &netif = GetNetif(); Ip6::Address destination; uint16_t delay; @@ -2474,37 +2475,47 @@ otError MleRouter::HandleNetworkDataUpdateRouter(void) delay = (mRole == OT_DEVICE_ROLE_LEADER) ? 0 : (otPlatRandomGet() % kUnsolicitedDataResponseJitter); SendDataResponse(destination, tlvs, sizeof(tlvs), delay); + SynchronizeChildNetworkData(); + +exit: + return OT_ERROR_NONE; +} + +void MleRouter::SynchronizeChildNetworkData(void) +{ + ThreadNetif &netif = GetNetif(); + + VerifyOrExit(mRole == OT_DEVICE_ROLE_ROUTER || mRole == OT_DEVICE_ROLE_LEADER); + for (uint8_t i = 0; i < mMaxChildrenAllowed; i++) { Child *child = &mChildren[i]; + uint8_t version; if (child->GetState() != Neighbor::kStateValid || child->IsRxOnWhenIdle()) { continue; } - memset(&destination, 0, sizeof(destination)); - destination.mFields.m16[0] = HostSwap16(0xfe80); - destination.SetIid(child->GetExtAddress()); - if (child->IsFullNetworkData()) { - if (child->GetNetworkDataVersion() != netif.GetNetworkDataLeader().GetVersion()) - { - SendDataResponse(destination, tlvs, sizeof(tlvs), 0); - } + version = netif.GetNetworkDataLeader().GetVersion(); } else { - if (child->GetNetworkDataVersion() != netif.GetNetworkDataLeader().GetStableVersion()) - { - SendDataResponse(destination, tlvs, sizeof(tlvs), 0); - } + version = netif.GetNetworkDataLeader().GetStableVersion(); } + + if (child->GetNetworkDataVersion() == version) + { + continue; + } + + SuccessOrExit(SendChildUpdateRequest(child)); } exit: - return OT_ERROR_NONE; + return; } #if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index 87d52f5f5..f16ed10b9 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -753,6 +753,7 @@ private: otError SetStateRouter(uint16_t aRloc16); otError SetStateLeader(uint16_t aRloc16); void StopLeader(void); + void SynchronizeChildNetworkData(void); otError UpdateChildAddresses(const AddressRegistrationTlv &aTlv, Child &aChild); void UpdateRoutes(const RouteTlv &aTlv, uint8_t aRouterId);