[meshcop] implement a prioritized queue for Joiner Routers (#2152)

This commit is contained in:
Ciaran Woodward
2017-09-07 08:37:13 -07:00
committed by Jonathan Hui
parent cb03cd607a
commit b3f60ff713
3 changed files with 122 additions and 56 deletions
+98 -50
View File
@@ -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<uint64_t *>(&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<uint16_t>(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<Joiner *>(aContext)->HandleSecureCoapClientConnect(aConnected);
+14 -6
View File
@@ -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;
+10
View File
@@ -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
*