From 33065099e1e67314b5a3e4b69f4a209f6e152269 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Mon, 15 Jan 2018 05:36:28 +0000 Subject: [PATCH] [mle] fix partition merging with REEDs (#2476) REEDs periodically transmit MLE Advertisement messages to support merging partitions. However, REEDs do not include Route64 TLVs in their MLE Advertisement messages. This commit removes the strict requirement check when handling MLE Advertisement messages, allowing such messages sent by REEDs to trigger the partition merging process. --- src/core/thread/mle_router.cpp | 54 +++++++++++++++++++++--------- src/core/thread/mle_router_ftd.hpp | 2 ++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index bf04bb4d6..962d46f48 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -1308,6 +1308,30 @@ uint8_t MleRouter::GetActiveNeighborRouterCount(void) const return rval; } +bool MleRouter::IsSingleton(const RouteTlv &aRouteTlv) +{ + bool rval = true; + uint8_t count = 0; + + // REEDs do not include a Route TLV and indicate not a singleton + if (!aRouteTlv.IsValid()) + { + ExitNow(rval = false); + } + + // Check if 2 or more active routers + for (uint8_t i = 0; i <= kMaxRouterId; i++) + { + if (aRouteTlv.IsRouterIdSet(i) && (++count >= 2)) + { + ExitNow(rval = false); + } + } + +exit: + return rval; +} + otError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif &netif = GetNetif(); @@ -1341,9 +1365,16 @@ otError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::Messa SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData)); VerifyOrExit(leaderData.IsValid(), error = OT_ERROR_PARSE); - // Route Data - SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kRoute, sizeof(route), route)); - VerifyOrExit(route.IsValid(), error = OT_ERROR_PARSE); + // Route Data (optional) + if (Tlv::GetTlv(aMessage, Tlv::kRoute, sizeof(route), route) == OT_ERROR_NONE) + { + VerifyOrExit(route.IsValid(), error = OT_ERROR_PARSE); + } + else + { + // mark that a Route TLV was not included + route.SetLength(0); + } partitionId = leaderData.GetPartitionId(); @@ -1354,7 +1385,8 @@ otError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::Messa VerifyOrExit(linkMargin >= OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN, error = OT_ERROR_LINK_MARGIN_LOW); - if ((mDeviceMode & ModeTlv::kModeFFD) && + if (route.IsValid() && + (mDeviceMode & ModeTlv::kModeFFD) && (mLastPartitionIdTimeout > 0) && (partitionId == mLastPartitionId)) { @@ -1368,17 +1400,7 @@ otError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::Messa ExitNow(); } - routerCount = 0; - - for (uint8_t i = 0; i <= kMaxRouterId; i++) - { - if (route.IsRouterIdSet(i)) - { - routerCount++; - } - } - - if (ComparePartitions(routerCount <= 1, leaderData, IsSingleton(), mLeaderData) > 0) + if (ComparePartitions(IsSingleton(route), leaderData, IsSingleton(), mLeaderData) > 0) { BecomeChild(kAttachBetter); } @@ -1397,7 +1419,7 @@ otError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::Messa ExitNow(); } - VerifyOrExit(IsActiveRouter(sourceAddress.GetRloc16())); + VerifyOrExit(IsActiveRouter(sourceAddress.GetRloc16()) && route.IsValid()); routerId = GetRouterId(sourceAddress.GetRloc16()); router = GetRouter(routerId); VerifyOrExit(router != NULL, error = OT_ERROR_PARSE); diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index 70beb7998..c088424dd 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -813,6 +813,8 @@ private: static uint8_t LinkQualityToCost(uint8_t aLinkQuality); + static bool IsSingleton(const RouteTlv &aRouteTlv); + Child *NewChild(void); Child *FindChild(uint16_t aChildId); Child *FindChild(const Mac::ExtAddress &aMacAddr);