From 672fe3047f9e24426ff18cb16a0ddd4aaff9adb6 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Tue, 2 Aug 2016 09:12:41 -0700 Subject: [PATCH] Update Address Solicit. (#314) * Add Status TLV to Address Solicit message. * Process Status TLV when receiving Address Solicit message. --- src/core/openthread.cpp | 2 +- src/core/thread/mle.cpp | 4 +- src/core/thread/mle_router.cpp | 78 +++++++++++++------ src/core/thread/mle_router.hpp | 15 +++- src/core/thread/thread_tlvs.hpp | 2 + .../Cert_5_2_02_LeaderReject1Hop.py | 1 + .../Cert_5_2_03_LeaderReject2Hops.py | 1 + 7 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index eee7af671..23f8a7193 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -481,7 +481,7 @@ ThreadError otBecomeChild(otMleAttachFilter aFilter) ThreadError otBecomeRouter(void) { - return sThreadNetif->GetMle().BecomeRouter(); + return sThreadNetif->GetMle().BecomeRouter(ThreadStatusTlv::kTooFewRouters); } ThreadError otBecomeLeader(void) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index d521069d2..a159f5476 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -167,7 +167,7 @@ ThreadError Mle::Start(void) } else if (IsActiveRouter(GetRloc16())) { - mMleRouter.BecomeRouter(); + mMleRouter.BecomeRouter(ThreadStatusTlv::kTooFewRouters); } else { @@ -1783,7 +1783,7 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa if ((mDeviceMode & ModeTlv::kModeFFD) && (numRouters < mMleRouter.GetRouterUpgradeThreshold())) { - mMleRouter.BecomeRouter(); + mMleRouter.BecomeRouter(ThreadStatusTlv::kTooFewRouters); } } diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 5847fb552..593d479c9 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -177,7 +177,7 @@ uint32_t MleRouter::GetLeaderAge(void) const return Timer::MsecToSec(Timer::GetNow() - mRouterIdSequenceLastUpdated); } -ThreadError MleRouter::BecomeRouter(void) +ThreadError MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus) { ThreadError error = kThreadError_None; @@ -205,7 +205,7 @@ ThreadError MleRouter::BecomeRouter(void) break; case kDeviceStateChild: - SuccessOrExit(error = SendAddressSolicit()); + SuccessOrExit(error = SendAddressSolicit(aStatus)); break; default: @@ -1173,6 +1173,21 @@ exit: return rval; } +uint8_t MleRouter::GetActiveRouterCount(void) const +{ + uint8_t rval = 0; + + for (int i = 0; i < kMaxRouterId; i++) + { + if (mRouters[i].mAllocated) + { + rval++; + } + } + + return rval; +} + ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadError error = kThreadError_None; @@ -1269,19 +1284,9 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M ExitNow(); case kDeviceStateChild: - routerCount = 0; - - for (int i = 0; i < kMaxRouterId; i++) + if ((mDeviceMode & ModeTlv::kModeFFD) && (GetActiveRouterCount() < mRouterUpgradeThreshold)) { - if (mRouters[i].mAllocated) - { - routerCount++; - } - } - - if ((mDeviceMode & ModeTlv::kModeFFD) && (routerCount < mRouterUpgradeThreshold)) - { - BecomeRouter(); + BecomeRouter(ThreadStatusTlv::kTooFewRouters); ExitNow(); } @@ -1829,7 +1834,7 @@ ThreadError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6:: break; case kDeviceStateChild: - BecomeRouter(); + BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest); break; case kDeviceStateRouter: @@ -2525,12 +2530,13 @@ ThreadError MleRouter::CheckReachability(uint16_t aMeshSource, uint16_t aMeshDes return kThreadError_Drop; } -ThreadError MleRouter::SendAddressSolicit(void) +ThreadError MleRouter::SendAddressSolicit(ThreadStatusTlv::Status aStatus) { ThreadError error = kThreadError_None; Coap::Header header; ThreadExtMacAddressTlv macAddr64Tlv; ThreadRloc16Tlv rlocTlv; + ThreadStatusTlv statusTlv; Ip6::MessageInfo messageInfo; Message *message; @@ -2563,6 +2569,10 @@ ThreadError MleRouter::SendAddressSolicit(void) SuccessOrExit(error = message->Append(&rlocTlv, sizeof(rlocTlv))); } + statusTlv.Init(); + statusTlv.SetStatus(aStatus); + SuccessOrExit(error = message->Append(&statusTlv, sizeof(statusTlv))); + memset(&messageInfo, 0, sizeof(messageInfo)); SuccessOrExit(error = GetLeaderAddress(messageInfo.GetPeerAddr())); messageInfo.mPeerPort = kCoapUdpPort; @@ -2730,17 +2740,19 @@ void MleRouter::HandleAddressSolicit(Coap::Header &aHeader, Message &aMessage, c ThreadError error = kThreadError_None; ThreadExtMacAddressTlv macAddr64Tlv; ThreadRloc16Tlv rlocTlv; - int routerId; + ThreadStatusTlv statusTlv; + int routerId = -1; - VerifyOrExit(aHeader.GetType() == Coap::Header::kTypeConfirmable && - aHeader.GetCode() == Coap::Header::kCodePost, ;); + VerifyOrExit(aHeader.GetType() == Coap::Header::kTypeConfirmable && aHeader.GetCode() == Coap::Header::kCodePost, + error = kThreadError_Parse); otLogInfoMle("Received address solicit\n"); SuccessOrExit(error = ThreadTlv::GetTlv(aMessage, ThreadTlv::kExtMacAddress, sizeof(macAddr64Tlv), macAddr64Tlv)); VerifyOrExit(macAddr64Tlv.IsValid(), error = kThreadError_Parse); - routerId = -1; + SuccessOrExit(error = ThreadTlv::GetTlv(aMessage, ThreadTlv::kStatus, sizeof(statusTlv), statusTlv)); + VerifyOrExit(statusTlv.IsValid(), error = kThreadError_Parse); // see if allocation already exists for (int i = 0; i < kMaxRouterId; i++) @@ -2748,11 +2760,25 @@ void MleRouter::HandleAddressSolicit(Coap::Header &aHeader, Message &aMessage, c if (mRouters[i].mAllocated && memcmp(&mRouters[i].mMacAddr, macAddr64Tlv.GetMacAddr(), sizeof(mRouters[i].mMacAddr)) == 0) { - SendAddressSolicitResponse(aHeader, i, aMessageInfo); - ExitNow(); + ExitNow(routerId = i); } } + // check the request reason + switch (statusTlv.GetStatus()) + { + case ThreadStatusTlv::kTooFewRouters: + VerifyOrExit(GetActiveRouterCount() < mRouterUpgradeThreshold, ;); + break; + + case ThreadStatusTlv::kHaveChildIdRequest: + break; + + default: + ExitNow(error = kThreadError_Parse); + break; + } + if (ThreadTlv::GetTlv(aMessage, ThreadTlv::kRloc16, sizeof(rlocTlv), rlocTlv) == kThreadError_None) { // specific Router ID requested @@ -2801,10 +2827,12 @@ void MleRouter::HandleAddressSolicit(Coap::Header &aHeader, Message &aMessage, c otLogInfoMle("router address unavailable!\n"); } - SendAddressSolicitResponse(aHeader, routerId, aMessageInfo); - exit: - {} + + if (error == kThreadError_None) + { + SendAddressSolicitResponse(aHeader, routerId, aMessageInfo); + } } void MleRouter::SendAddressSolicitResponse(const Coap::Header &aRequestHeader, int aRouterId, diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 738ebac0c..9f909f87f 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -42,6 +42,7 @@ #include #include #include +#include #include namespace Thread { @@ -99,11 +100,13 @@ public: /** * This method generates an Address Solicit request for a Router ID. * + * @param[in] aStatus The reason for requesting a Router ID. + * * @retval kThreadError_None Successfully generated an Address Solicit message. * @retval kThreadError_InvalidState Not currently an End Device. * */ - ThreadError BecomeRouter(void); + ThreadError BecomeRouter(ThreadStatusTlv::Status aStatus); /** * This method causes the Thread interface to become a Leader and start a new partition. @@ -114,6 +117,14 @@ public: */ ThreadError BecomeLeader(void); + /** + * This method returns the number of active routers. + * + * @returns The number of active routers. + * + */ + uint8_t GetActiveRouterCount(void) const; + /** * This method returns the time in seconds since the last Router ID Sequence update. * @@ -414,7 +425,7 @@ private: ThreadError ProcessRouteTlv(const RouteTlv &aRoute); ThreadError ResetAdvertiseInterval(void); - ThreadError SendAddressSolicit(void); + ThreadError SendAddressSolicit(ThreadStatusTlv::Status aStatus); ThreadError SendAddressRelease(void); void SendAddressSolicitResponse(const Coap::Header &aRequest, int aRouterId, const Ip6::MessageInfo &aMessageInfo); void SendAddressReleaseResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo); diff --git a/src/core/thread/thread_tlvs.hpp b/src/core/thread/thread_tlvs.hpp index 593e0ef19..602930d27 100644 --- a/src/core/thread/thread_tlvs.hpp +++ b/src/core/thread/thread_tlvs.hpp @@ -324,6 +324,8 @@ public: { kSuccess = 0, ///< Success. kNoAddressAvailable = 1, ///< No address available. + kTooFewRouters = 2, ///< Address Solicit due to too few routers. + kHaveChildIdRequest = 3, ///< Address Solicit due to child ID request. }; /** diff --git a/tests/scripts/thread-cert/Cert_5_2_02_LeaderReject1Hop.py b/tests/scripts/thread-cert/Cert_5_2_02_LeaderReject1Hop.py index 01bd58d13..9533748ed 100755 --- a/tests/scripts/thread-cert/Cert_5_2_02_LeaderReject1Hop.py +++ b/tests/scripts/thread-cert/Cert_5_2_02_LeaderReject1Hop.py @@ -44,6 +44,7 @@ class Cert_5_2_2_LeaderReject1Hop(unittest.TestCase): self.nodes[LEADER].set_panid(0xface) self.nodes[LEADER].set_mode('rsdn') self.nodes[LEADER].enable_whitelist() + self.nodes[LEADER].set_router_upgrade_threshold(32) for i in range(2,34): self.nodes[i] = node.Node(i) diff --git a/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py b/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py index b15f20ba2..4f0138a8f 100755 --- a/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py +++ b/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py @@ -45,6 +45,7 @@ class Cert_5_2_3_LeaderReject2Hops(unittest.TestCase): self.nodes[LEADER].set_panid(0xface) self.nodes[LEADER].set_mode('rsdn') self.nodes[LEADER].enable_whitelist() + self.nodes[LEADER].set_router_upgrade_threshold(32) for i in range(2,33): self.nodes[i] = node.Node(i)