diff --git a/src/core/openthread-core-default-config.h b/src/core/openthread-core-default-config.h index ca827c701..f5af07bf4 100644 --- a/src/core/openthread-core-default-config.h +++ b/src/core/openthread-core-default-config.h @@ -850,6 +850,19 @@ #define OPENTHREAD_CONFIG_SUPERVISION_MSG_NO_ACK_REQUEST 0 #endif +/** + * @def OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + * + * Define as 1 for a child to inform its previous parent when it attaches to a new parent. + * + * If this feature is enabled, when a device attaches to a new parent, it will send an IP message (with empty payload + * and mesh-local IP address as the source address) to its previous parent. + * + */ +#ifndef OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH +#define OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH 0 +#endif + /** * @def OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE * @@ -873,7 +886,6 @@ #define OPENTHREAD_CONFIG_STAY_AWAKE_BETWEEN_FRAGMENTS 0 #endif - /* * @def OPENTHREAD_CONFIG_ENABLE_DEBUG_UART * diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index ddad71321..144f570d9 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -87,6 +87,9 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mDiscoverContext(NULL), mIsDiscoverInProgress(false), mEnableEui64Filtering(false), +#if OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + mPreviousParentRloc(Mac::kShortAddrInvalid), +#endif mAnnounceChannel(OT_RADIO_CHANNEL_MIN), mPreviousChannel(0), mPreviousPanId(Mac::kPanIdBroadcast) @@ -315,6 +318,10 @@ otError Mle::Restore(void) ModeTlv::kModeSecureDataRequest); mParent.SetRloc16(GetRloc16(GetRouterId(networkInfo.mRloc16))); mParent.SetState(Neighbor::kStateRestored); + +#if OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + mPreviousParentRloc = mParent.GetRloc16(); +#endif } else { @@ -627,6 +634,11 @@ otError Mle::SetStateChild(uint16_t aRloc16) netif.GetAnnounceBeginServer().SendAnnounce(1 << mPreviousChannel); } +#if OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + InformPreviousParent(); + mPreviousParentRloc = mParent.GetRloc16(); +#endif + otLogInfoMle(GetInstance(), "Mode -> Child"); return OT_ERROR_NONE; } @@ -3267,6 +3279,45 @@ exit: return error; } +#if OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH +otError Mle::InformPreviousParent(void) +{ + ThreadNetif &netif = GetNetif(); + otError error = OT_ERROR_NONE; + Message *message = NULL; + Ip6::MessageInfo messageInfo; + + VerifyOrExit((mPreviousParentRloc != Mac::kShortAddrInvalid) && (mPreviousParentRloc != mParent.GetRloc16())); + + VerifyOrExit((message = netif.GetIp6().NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS); + SuccessOrExit(error = message->SetLength(0)); + + messageInfo.SetSockAddr(GetMeshLocal64()); + messageInfo.SetPeerAddr(GetMeshLocal16()); + messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(mPreviousParentRloc); + messageInfo.SetInterfaceId(netif.GetInterfaceId()); + + SuccessOrExit(error = netif.GetIp6().SendDatagram(*message, messageInfo, Ip6::kProtoNone)); + message = NULL; + + otLogInfoMle(GetInstance(), "Sending message to inform previous parent 0x%04x", mPreviousParentRloc); + +exit: + + if (message != NULL) + { + message->Free(); + } + + if (error != OT_ERROR_NONE) + { + otLogWarnMle(GetInstance(), "Failed to inform previous parent, error:%s", otThreadErrorToString(error)); + } + + return error; +} +#endif // OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + Mle &Mle::GetOwner(const Context &aContext) { #if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 74622d7c7..f5a599e80 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1371,6 +1371,10 @@ private: bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv); void ResetParentCandidate(void); +#if OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + otError InformPreviousParent(void); +#endif + static Mle &GetOwner(const Context &aContext); MessageQueue mDelayedResponses; @@ -1407,6 +1411,10 @@ private: bool mIsDiscoverInProgress; bool mEnableEui64Filtering; +#if OPENTHREAD_CONFIG_INFORM_PREVIOUS_PARENT_ON_REATTACH + uint16_t mPreviousParentRloc; +#endif + uint8_t mAnnounceChannel; uint8_t mPreviousChannel; uint16_t mPreviousPanId;