From b5d86fa319caebd69f640168cd939407432ca56f Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 15 May 2019 19:32:40 -0700 Subject: [PATCH] [mle] only include mesh-local address in Child Update Response (#3829) This commit changes preparation of "Child Update Response" (on a child) such that only the mesh-local address is included in Address Registration TLV. If the child has more addresses to register it follows up with its own "Child Update Request". --- src/core/thread/mle.cpp | 45 ++++++++++++++++++++++++++++++++++++++++- src/core/thread/mle.hpp | 1 + 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index c791fa049..9a78f87ff 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1303,6 +1303,37 @@ otError Mle::AppendVersion(Message &aMessage) return aMessage.AppendTlv(tlv); } +bool Mle::HasUnregisteredAddress(void) +{ + bool retval = false; + + // Checks whether there are any addresses in addition to the mesh-local + // address that need to be registered. + + for (const Ip6::NetifUnicastAddress *addr = Get().GetUnicastAddresses(); addr; addr = addr->GetNext()) + { + if (!addr->GetAddress().IsLinkLocal() && !IsRoutingLocator(addr->GetAddress()) && + !IsAnycastLocator(addr->GetAddress()) && addr->GetAddress() != GetMeshLocal64()) + { + ExitNow(retval = true); + } + } + + if (!IsRxOnWhenIdle()) + { + uint8_t iterator = 0; + Ip6::Address address; + + // For sleepy end-device, we register any external multicast + // addresses. + + retval = (Get().GetNextExternalMulticast(iterator, address) == OT_ERROR_NONE); + } + +exit: + return retval; +} + otError Mle::AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode) { otError error = OT_ERROR_NONE; @@ -2317,6 +2348,7 @@ otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, con otError error = OT_ERROR_NONE; Ip6::Address destination; Message * message; + bool checkAddress = false; VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS); SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildUpdateResponse)); @@ -2334,7 +2366,13 @@ otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, con case Tlv::kAddressRegistration: if (!IsFullThreadDevice()) { - SuccessOrExit(error = AppendAddressRegistration(*message)); + // We only register the mesh-local address in the "Child + // Update Response" message and if there are additional + // addresses to register we follow up with a "Child Update + // Request". + + SuccessOrExit(error = AppendAddressRegistration(*message, kAppendMeshLocalOnly)); + checkAddress = true; } break; @@ -2360,6 +2398,11 @@ otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, con LogMleMessage("Send Child Update Response to parent", destination); + if (checkAddress && HasUnregisteredAddress()) + { + SendChildUpdateRequest(); + } + exit: if (error != OT_ERROR_NONE && message != NULL) diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 52e879a6e..11ad8cd71 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1721,6 +1721,7 @@ private: otError HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); otError HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void ProcessAnnounce(void); + bool HasUnregisteredAddress(void); uint32_t GetAttachStartDelay(void) const; otError SendParentRequest(ParentRequestType aType);