From f8de062657937a16dd96b1e532b38caa9d77acd3 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Mon, 30 Mar 2020 11:47:37 -0700 Subject: [PATCH] [mesh-forwarder] do not remove router on link failures (#4753) A router coming out of reset sends a Link Request to re-establish its router role and links to neighboring routers. The existing implementation only responds to such Link Requests when a valid neighbor entry is found. This check is too strict and can cause partitions to remain for a couple minutes. The Thread Specification only requires a router to check that the Router ID is currently allocated. This commit updates the implementation to be conformant with the Thread Specification and allows routers coming out of reset to resynchronize even when a neighboring router has detect a link failure. --- src/core/thread/mesh_forwarder.cpp | 2 +- src/core/thread/mle_router.cpp | 23 +++++++++++++++++++++++ src/core/thread/mle_router.hpp | 9 +++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index e6051232d..188840ec5 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -810,7 +810,7 @@ Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, otError if (neighbor->GetLinkFailures() >= Mle::kFailedRouterTransmissions) { - Get().RemoveNeighbor(*neighbor); + Get().RemoveRouterLink(*static_cast(neighbor)); } } diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index e0c6461e3..90cfb4517 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -3267,6 +3267,29 @@ bool MleRouter::IsMinimalChild(uint16_t aRloc16) return rval; } +void MleRouter::RemoveRouterLink(Router &aRouter) +{ + switch (mRole) + { + case OT_DEVICE_ROLE_CHILD: + if (&aRouter == &mParent) + { + BecomeDetached(); + } + break; + +#if OPENTHREAD_FTD + case OT_DEVICE_ROLE_ROUTER: + case OT_DEVICE_ROLE_LEADER: + mRouterTable.RemoveNeighbor(aRouter); + break; +#endif + + default: + break; + } +} + void MleRouter::RemoveNeighbor(Neighbor &aNeighbor) { if (&aNeighbor == &mParent) diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index fcc479120..0fa17b6ad 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -327,6 +327,14 @@ public: */ void RemoveNeighbor(Neighbor &aNeighbor); + /** + * This method invalidates a direct link to a neighboring router (due to failed link-layer acks). + * + * @param[in] aRouter A reference to the router object. + * + */ + void RemoveRouterLink(Router &aRouter); + /** * This method restores children information from non-volatile memory. * @@ -844,6 +852,7 @@ public: uint8_t GetCost(uint16_t) { return 0; } otError RemoveNeighbor(Neighbor &) { return BecomeDetached(); } + otError RemoveRouterLink(Router &) { return BecomeDetached(); } Neighbor *GetNeighbor(const Mac::ExtAddress &aAddress) { return Mle::GetNeighbor(aAddress); } Neighbor *GetNeighbor(const Mac::Address &aAddress) { return Mle::GetNeighbor(aAddress); }