From b3f60ff7138ba561dd8ca3f938f9bbbea0ab8295 Mon Sep 17 00:00:00 2001 From: Ciaran Woodward Date: Thu, 7 Sep 2017 16:37:13 +0100 Subject: [PATCH] [meshcop] implement a prioritized queue for Joiner Routers (#2152) --- src/core/meshcop/joiner.cpp | 148 ++++++++++++++-------- src/core/meshcop/joiner.hpp | 20 ++- src/core/openthread-core-default-config.h | 10 ++ 3 files changed, 122 insertions(+), 56 deletions(-) diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index ab46110ad..354f87947 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -67,11 +67,6 @@ Joiner::Joiner(ThreadNetif &aNetif): mContext(NULL), mCcitt(0), mAnsi(0), - mJoinerRouterIsSpecific(false), - mJoinerRouterChannel(0), - mJoinerRouterRssi(0), - mJoinerRouterPanId(0), - mJoinerUdpPort(0), mVendorName(NULL), mVendorModel(NULL), mVendorSwVersion(NULL), @@ -79,6 +74,7 @@ Joiner::Joiner(ThreadNetif &aNetif): mTimer(aNetif.GetInstance(), &Joiner::HandleTimer, this), mJoinerEntrust(OT_URI_PATH_JOINER_ENTRUST, &Joiner::HandleJoinerEntrust, this) { + memset(mJoinerRouters, 0, sizeof(mJoinerRouters)); aNetif.GetCoap().AddResource(mJoinerEntrust); } @@ -122,9 +118,8 @@ otError Joiner::Start(const char *aPSKd, const char *aProvisioningUrl, error = netif.GetCoapSecure().GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl); SuccessOrExit(error); - mJoinerRouterPanId = Mac::kPanIdBroadcast; - mJoinerRouterRssi = 0; - mJoinerRouterIsSpecific = false; + memset(mJoinerRouters, 0, sizeof(mJoinerRouters)); + SuccessOrExit(error = netif.GetMle().Discover(0, netif.GetMac().GetPanId(), true, false, HandleDiscoverResult, this)); @@ -169,13 +164,21 @@ void Joiner::Close(void) void Joiner::Complete(otError aError) { + ThreadNetif &netif = GetNetif(); mState = OT_JOINER_STATE_IDLE; + otError error = OT_ERROR_NOT_FOUND; GetNetif().SetStateChangedFlags(OT_CHANGED_JOINER_STATE); - GetNetif().GetCoapSecure().Stop(); + netif.GetCoapSecure().Disconnect(); - if (mCallback) + if (aError != OT_ERROR_NONE && aError != OT_ERROR_NOT_FOUND) { + error = TryNextJoin(); + } + + if (error == OT_ERROR_NOT_FOUND && mCallback) + { + netif.GetCoapSecure().Stop(); otJoinerCallback callback = mCallback; mCallback = NULL; callback(aError, mContext); @@ -189,13 +192,12 @@ void Joiner::HandleDiscoverResult(otActiveScanResult *aResult, void *aContext) void Joiner::HandleDiscoverResult(otActiveScanResult *aResult) { - ThreadNetif &netif = GetNetif(); - Ip6::MessageInfo messageInfo; - otLogFuncEntry(); if (aResult != NULL) { + JoinerRouter joinerRouter; + otLogFuncEntryMsg("aResult = %llX", HostSwap64(*reinterpret_cast(&aResult->mExtAddress))); // Joining is disabled if the Steering Data is not included @@ -209,59 +211,105 @@ void Joiner::HandleDiscoverResult(otActiveScanResult *aResult) steeringData.SetLength(aResult->mSteeringData.mLength); memcpy(steeringData.GetValue(), aResult->mSteeringData.m8, steeringData.GetLength()); - if (steeringData.DoesAllowAny()) - { - VerifyOrExit(!mJoinerRouterIsSpecific); - VerifyOrExit(aResult->mRssi > mJoinerRouterRssi); - } - else if (steeringData.GetBit(mCcitt % steeringData.GetNumBits()) && - steeringData.GetBit(mAnsi % steeringData.GetNumBits())) - { - if (mJoinerRouterIsSpecific) - { - VerifyOrExit(aResult->mRssi > mJoinerRouterRssi); - } - - mJoinerRouterIsSpecific = true; - } - else + if (!steeringData.GetBit(mCcitt % steeringData.GetNumBits()) || + !steeringData.GetBit(mAnsi % steeringData.GetNumBits())) { otLogDebgMeshCoP(GetInstance(), "Steering data does not include this device"); ExitNow(); } - mJoinerUdpPort = aResult->mJoinerUdpPort; - mJoinerRouterPanId = aResult->mPanId; - mJoinerRouterChannel = aResult->mChannel; - mJoinerRouterRssi = aResult->mRssi; - memcpy(&mJoinerRouter, &aResult->mExtAddress, sizeof(mJoinerRouter)); - } - else if (mJoinerRouterPanId != Mac::kPanIdBroadcast) - { - otLogFuncEntryMsg("aResult = NULL"); + joinerRouter.mPriority = static_cast(aResult->mRssi) + 0x80; - netif.GetMac().SetPanId(mJoinerRouterPanId); - netif.GetMac().SetChannel(mJoinerRouterChannel); - netif.GetIp6Filter().AddUnsecurePort(netif.GetCoapSecure().GetPort()); + if (!steeringData.DoesAllowAny()) + { + joinerRouter.mPriority += kSpecificPriorityBonus; + } - messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xfe80); - messageInfo.GetPeerAddr().SetIid(mJoinerRouter); - messageInfo.mPeerPort = mJoinerUdpPort; - messageInfo.mInterfaceId = OT_NETIF_INTERFACE_ID_THREAD; - - netif.GetCoapSecure().Connect(messageInfo, Joiner::HandleSecureCoapClientConnect, this); - mState = OT_JOINER_STATE_CONNECT; + joinerRouter.mJoinerUdpPort = aResult->mJoinerUdpPort; + joinerRouter.mPanId = aResult->mPanId; + joinerRouter.mChannel = aResult->mChannel; + memcpy(joinerRouter.mExtAddr.m8, &aResult->mExtAddress, sizeof(joinerRouter.mExtAddr)); + AddJoinerRouter(joinerRouter); } else { - otLogDebgMeshCoP(GetInstance(), "No joinable network found"); - Complete(OT_ERROR_NOT_FOUND); + otError error = TryNextJoin(); + + if (error != OT_ERROR_NONE) + { + Complete(error); + } } exit: otLogFuncExit(); } +void Joiner::AddJoinerRouter(JoinerRouter &aJoinerRouter) +{ + JoinerRouter *joinerRouter = &mJoinerRouters[0]; + + // Find the lowest priority + for (size_t i = 1; i < OPENTHREAD_CONFIG_MAX_JOINER_ROUTER_ENTRIES; i++) + { + if (mJoinerRouters[i].mPriority < joinerRouter->mPriority) + { + joinerRouter = &mJoinerRouters[i]; + } + + if (joinerRouter->mPriority == 0) + { + break; + } + } + + if (aJoinerRouter.mPriority > joinerRouter->mPriority) + { + memcpy(joinerRouter, &aJoinerRouter, sizeof(aJoinerRouter)); + } +} + +otError Joiner::TryNextJoin() +{ + ThreadNetif &netif = GetNetif(); + otError error = OT_ERROR_NOT_FOUND; + JoinerRouter *joinerRouter = &mJoinerRouters[0]; + + for (size_t i = 1; i < OPENTHREAD_CONFIG_MAX_JOINER_ROUTER_ENTRIES; i++) + { + if (mJoinerRouters[i].mPriority > joinerRouter->mPriority) + { + joinerRouter = &mJoinerRouters[i]; + } + } + + if (joinerRouter->mPriority > 0) + { + Ip6::MessageInfo messageInfo; + + joinerRouter->mPriority = 0; + + netif.GetMac().SetPanId(joinerRouter->mPanId); + netif.GetMac().SetChannel(joinerRouter->mChannel); + netif.GetIp6Filter().AddUnsecurePort(netif.GetCoapSecure().GetPort()); + + messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xfe80); + messageInfo.GetPeerAddr().SetIid(joinerRouter->mExtAddr); + messageInfo.mPeerPort = joinerRouter->mJoinerUdpPort; + messageInfo.mInterfaceId = OT_NETIF_INTERFACE_ID_THREAD; + + netif.GetCoapSecure().Connect(messageInfo, Joiner::HandleSecureCoapClientConnect, this); + mState = OT_JOINER_STATE_CONNECT; + error = OT_ERROR_NONE; + } + else + { + otLogDebgMeshCoP(GetInstance(), "No joinable networks remaining to try"); + } + + return error; +} + void Joiner::HandleSecureCoapClientConnect(bool aConnected, void *aContext) { static_cast(aContext)->HandleSecureCoapClientConnect(aConnected); diff --git a/src/core/meshcop/joiner.hpp b/src/core/meshcop/joiner.hpp index 5bddfcbe2..44f7474fb 100644 --- a/src/core/meshcop/joiner.hpp +++ b/src/core/meshcop/joiner.hpp @@ -111,6 +111,16 @@ private: { kConfigExtAddressDelay = 100, ///< milliseconds kTimeout = 4000, ///< milliseconds + kSpecificPriorityBonus = (1 << 9), + }; + + struct JoinerRouter + { + Mac::ExtAddress mExtAddr; + uint16_t mPriority; + uint16_t mPanId; + uint16_t mJoinerUdpPort; + uint8_t mChannel; }; static void HandleDiscoverResult(otActiveScanResult *aResult, void *aContext); @@ -122,6 +132,9 @@ private: void Close(void); void Complete(otError aError); + void AddJoinerRouter(JoinerRouter &aJoinerRouter); + otError TryNextJoin(); + static void HandleSecureCoapClientConnect(bool aConnected, void *aContext); void HandleSecureCoapClientConnect(bool aConnected); @@ -146,12 +159,7 @@ private: uint16_t mCcitt; uint16_t mAnsi; - bool mJoinerRouterIsSpecific; - uint8_t mJoinerRouterChannel; - int8_t mJoinerRouterRssi; - uint16_t mJoinerRouterPanId; - uint16_t mJoinerUdpPort; - Mac::ExtAddress mJoinerRouter; + JoinerRouter mJoinerRouters[OPENTHREAD_CONFIG_MAX_JOINER_ROUTER_ENTRIES]; const char *mVendorName; const char *mVendorModel; diff --git a/src/core/openthread-core-default-config.h b/src/core/openthread-core-default-config.h index 348d2e75a..ca827c701 100644 --- a/src/core/openthread-core-default-config.h +++ b/src/core/openthread-core-default-config.h @@ -305,6 +305,16 @@ #define OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES 2 #endif // OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES +/** + * @def OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES + * + * The maximum number of Joiner Router entries that can be queued by the Joiner. + * + */ +#ifndef OPENTHREAD_CONFIG_MAX_JOINER_ROUTER_ENTRIES +#define OPENTHREAD_CONFIG_MAX_JOINER_ROUTER_ENTRIES 2 +#endif // OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES + /** * @def OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS *