Restrict the condition to SendAddressRelease (#1013)

* Restrict the condition to SendAddressRelease

* some enhancement for AttachSamePartition feature

* code cleanup and implement PARENT_PARTITION_CHANGE
This commit is contained in:
rongli
2016-11-29 12:14:54 -08:00
committed by Jonathan Hui
parent 24b98dbb85
commit 2fec3abdb0
7 changed files with 150 additions and 53 deletions
+12 -12
View File
@@ -287,6 +287,7 @@ ThreadError Mle::Restore()
else if (networkInfo.mDeviceState == kDeviceStateRouter || networkInfo.mDeviceState == kDeviceStateLeader) else if (networkInfo.mDeviceState == kDeviceStateRouter || networkInfo.mDeviceState == kDeviceStateLeader)
{ {
mMleRouter.SetRouterId(GetRouterId(GetRloc16())); mMleRouter.SetRouterId(GetRouterId(GetRloc16()));
mMleRouter.SetPreviousPartitionId(networkInfo.mPreviousPartitionId);
mMleRouter.RestoreChildren(); mMleRouter.RestoreChildren();
} }
@@ -315,6 +316,7 @@ ThreadError Mle::Store()
networkInfo.mKeySequence = mKeyManager.GetCurrentKeySequence(); networkInfo.mKeySequence = mKeyManager.GetCurrentKeySequence();
networkInfo.mMleFrameCounter = mKeyManager.GetMleFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD; networkInfo.mMleFrameCounter = mKeyManager.GetMleFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD;
networkInfo.mMacFrameCounter = mKeyManager.GetMacFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD; networkInfo.mMacFrameCounter = mKeyManager.GetMacFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD;
networkInfo.mPreviousPartitionId = mLeaderData.GetPartitionId();
memcpy(networkInfo.mExtAddress.m8, mMac.GetExtAddress(), sizeof(networkInfo.mExtAddress)); memcpy(networkInfo.mExtAddress.m8, mMac.GetExtAddress(), sizeof(networkInfo.mExtAddress));
if (mDeviceState == kDeviceStateChild) if (mDeviceState == kDeviceStateChild)
@@ -2523,15 +2525,6 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa
mMesh.SetRxOnWhenIdle(true); mMesh.SetRxOnWhenIdle(true);
} }
mParent.mValid.mRloc16 = sourceAddress.GetRloc16();
SuccessOrExit(error = SetStateChild(shortAddress.GetRloc16()));
mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
(mDeviceMode & ModeTlv::kModeFullNetworkData) == 0,
networkData.GetNetworkData(), networkData.GetLength());
mNetif.GetActiveDataset().ApplyConfiguration();
// Route // Route
if ((Tlv::GetTlv(aMessage, Tlv::kRoute, sizeof(route), route) == kThreadError_None) && if ((Tlv::GetTlv(aMessage, Tlv::kRoute, sizeof(route), route) == kThreadError_None) &&
(mDeviceMode & ModeTlv::kModeFFD)) (mDeviceMode & ModeTlv::kModeFFD))
@@ -2546,14 +2539,21 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa
} }
} }
if (mRouterSelectionJitterTimeout == 0 && if (mRouterSelectionJitterTimeout == 0 && numRouters < mMleRouter.GetRouterUpgradeThreshold())
(mDeviceMode & ModeTlv::kModeFFD) &&
(numRouters < mMleRouter.GetRouterUpgradeThreshold()))
{ {
mRouterSelectionJitterTimeout = (otPlatRandomGet() % mRouterSelectionJitter) + 1; mRouterSelectionJitterTimeout = (otPlatRandomGet() % mRouterSelectionJitter) + 1;
} }
} }
mParent.mValid.mRloc16 = sourceAddress.GetRloc16();
SuccessOrExit(error = SetStateChild(shortAddress.GetRloc16()));
mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
(mDeviceMode & ModeTlv::kModeFullNetworkData) == 0,
networkData.GetNetworkData(), networkData.GetLength());
mNetif.GetActiveDataset().ApplyConfiguration();
exit: exit:
if (error != kThreadError_None) if (error != kThreadError_None)
+1
View File
@@ -1263,6 +1263,7 @@ private:
uint32_t mKeySequence; ///< Key Sequence uint32_t mKeySequence; ///< Key Sequence
uint32_t mMleFrameCounter; ///< MLE Frame Counter uint32_t mMleFrameCounter; ///< MLE Frame Counter
uint32_t mMacFrameCounter; ///< MAC Frame Counter uint32_t mMacFrameCounter; ///< MAC Frame Counter
uint32_t mPreviousPartitionId; ///< PartitionId
Mac::ExtAddress mExtAddress; ///< Extended Address Mac::ExtAddress mExtAddress; ///< Extended Address
} NetworkInfo; } NetworkInfo;
+121 -39
View File
@@ -75,8 +75,9 @@ MleRouter::MleRouter(ThreadNetif &aThreadNetif):
mLeaderWeight = kLeaderWeight; mLeaderWeight = kLeaderWeight;
mFixedLeaderPartitionId = 0; mFixedLeaderPartitionId = 0;
mMaxChildrenAllowed = kMaxChildren; mMaxChildrenAllowed = kMaxChildren;
mRouterId = kInvalidRouterId;
mPreviousRouterId = kInvalidRouterId; SetRouterId(kInvalidRouterId);
mPreviousPartitionId = 0;
mRouterIdSequenceLastUpdated = 0; mRouterIdSequenceLastUpdated = 0;
mRouterRoleEnabled = true; mRouterRoleEnabled = true;
} }
@@ -221,6 +222,7 @@ ThreadError MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus)
mAdvertiseTimer.Stop(); mAdvertiseTimer.Stop();
mAddressResolver.Clear(); mAddressResolver.Clear();
mRouterSelectionJitterTimeout = 0;
switch (mDeviceState) switch (mDeviceState)
{ {
@@ -268,8 +270,7 @@ ThreadError MleRouter::BecomeLeader(void)
router = GetRouter(routerId); router = GetRouter(routerId);
VerifyOrExit(router != NULL, error = kThreadError_NoBufs); VerifyOrExit(router != NULL, error = kThreadError_NoBufs);
mRouterId = routerId; SetRouterId(routerId);
mPreviousRouterId = mRouterId;
memcpy(&router->mMacAddr, mMac.GetExtAddress(), sizeof(router->mMacAddr)); memcpy(&router->mMacAddr, mMac.GetExtAddress(), sizeof(router->mMacAddr));
@@ -329,32 +330,57 @@ ThreadError MleRouter::HandleChildStart(otMleAttachFilter aFilter)
StopLeader(); StopLeader();
mStateUpdateTimer.Start(kStateUpdatePeriod); mStateUpdateTimer.Start(kStateUpdatePeriod);
mAdvertiseTimer.Start(
Timer::SecToMsec(kReedAdvertiseInterval),
Timer::SecToMsec(kReedAdvertiseInterval + kReedAdvertiseJitter),
TrickleTimer::kModePlainTimer);
mNetif.SubscribeAllRoutersMulticast();
VerifyOrExit(IsRouterIdValid(mPreviousRouterId), ;);
switch (aFilter) switch (aFilter)
{ {
case kMleAttachAnyPartition:
break;
case kMleAttachSamePartition: case kMleAttachSamePartition:
SendAddressRelease();
// downgrade
if (GetActiveRouterCount() > mRouterDowngradeThreshold)
{
SendAddressRelease();
// reset children info if any
if (HasChildren())
{
RemoveChildren();
}
// reset routerId info
SetRouterId(kInvalidRouterId);
}
else if (HasChildren())
{
BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest);
}
break; break;
case kMleAttachAnyPartition:
case kMleAttachBetterPartition: case kMleAttachBetterPartition:
// BecomeRouter(); if (HasChildren() &&
mPreviousPartitionId != mLeaderData.GetPartitionId())
{
BecomeRouter(ThreadStatusTlv::kParentPartitionChange);
}
break; break;
} }
if (mDeviceMode & ModeTlv::kModeFFD) exit:
{
mAdvertiseTimer.Start(
Timer::SecToMsec(kReedAdvertiseInterval),
Timer::SecToMsec(kReedAdvertiseInterval + kReedAdvertiseJitter),
TrickleTimer::kModePlainTimer);
mNetif.SubscribeAllRoutersMulticast();
if (GetActiveRouterCount() >= mRouterUpgradeThreshold) if (GetActiveRouterCount() >= mRouterUpgradeThreshold &&
{ (!IsRouterIdValid(mPreviousRouterId) || !HasChildren()))
SendAdvertisement(); {
} SetRouterId(kInvalidRouterId);
SendAdvertisement();
} }
return kThreadError_None; return kThreadError_None;
@@ -374,6 +400,7 @@ ThreadError MleRouter::SetStateRouter(uint16_t aRloc16)
mNetif.SubscribeAllRoutersMulticast(); mNetif.SubscribeAllRoutersMulticast();
mRouters[mRouterId].mNextHop = mRouterId; mRouters[mRouterId].mNextHop = mRouterId;
mPreviousPartitionId = mLeaderData.GetPartitionId();
mNetworkData.Stop(); mNetworkData.Stop();
mStateUpdateTimer.Start(kStateUpdatePeriod); mStateUpdateTimer.Start(kStateUpdatePeriod);
mNetif.GetIp6().SetForwardingEnabled(true); mNetif.GetIp6().SetForwardingEnabled(true);
@@ -406,6 +433,7 @@ ThreadError MleRouter::SetStateLeader(uint16_t aRloc16)
mNetif.SubscribeAllRoutersMulticast(); mNetif.SubscribeAllRoutersMulticast();
mRouters[mRouterId].mNextHop = mRouterId; mRouters[mRouterId].mNextHop = mRouterId;
mPreviousPartitionId = mLeaderData.GetPartitionId();
mRouters[mRouterId].mLastHeard = Timer::GetNow(); mRouters[mRouterId].mLastHeard = Timer::GetNow();
mNetworkData.Start(); mNetworkData.Start();
@@ -1257,7 +1285,7 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M
mLeaderData.GetWeighting(), mLeaderData.GetPartitionId()); mLeaderData.GetWeighting(), mLeaderData.GetPartitionId());
if (GetDeviceState() == kDeviceStateChild && if (GetDeviceState() == kDeviceStateChild &&
memcmp(&mParent.mMacAddr, &macAddr, sizeof(mParent.mMacAddr)) == 0) (memcmp(&mParent.mMacAddr, &macAddr, sizeof(mParent.mMacAddr)) == 0 || !(mDeviceMode & ModeTlv::kModeFFD)))
{ {
ExitNow(); ExitNow();
} }
@@ -1693,6 +1721,7 @@ void MleRouter::HandleStateUpdateTimer(void)
{ {
// upgrade to Router // upgrade to Router
BecomeRouter(ThreadStatusTlv::kTooFewRouters); BecomeRouter(ThreadStatusTlv::kTooFewRouters);
ExitNow();
} }
case kDeviceStateRouter: case kDeviceStateRouter:
@@ -3240,9 +3269,15 @@ exit:
return error; return error;
} }
void MleRouter::SetPreviousPartitionId(uint32_t aPartitionId)
{
mPreviousPartitionId = aPartitionId;
}
void MleRouter::SetRouterId(uint8_t aRouterId) void MleRouter::SetRouterId(uint8_t aRouterId)
{ {
mRouterId = aRouterId; mRouterId = aRouterId;
mPreviousRouterId = mRouterId;
} }
Router *MleRouter::GetRouters(uint8_t *aNumRouters) Router *MleRouter::GetRouters(uint8_t *aNumRouters)
@@ -3652,7 +3687,22 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe
otLogInfoMle("Received address reply"); otLogInfoMle("Received address reply");
SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kStatus, sizeof(statusTlv), statusTlv)); SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kStatus, sizeof(statusTlv), statusTlv));
VerifyOrExit(statusTlv.IsValid() && statusTlv.GetStatus() == statusTlv.kSuccess, ;); VerifyOrExit(statusTlv.IsValid(), ;);
if (statusTlv.GetStatus() != statusTlv.kSuccess)
{
if (IsRouterIdValid(mPreviousRouterId))
{
if (HasChildren())
{
RemoveChildren();
}
SetRouterId(kInvalidRouterId);
}
ExitNow();
}
SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kRloc16, sizeof(rlocTlv), rlocTlv)); SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kRloc16, sizeof(rlocTlv), rlocTlv));
VerifyOrExit(rlocTlv.IsValid(), ;); VerifyOrExit(rlocTlv.IsValid(), ;);
@@ -3661,10 +3711,21 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe
SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kRouterMask, sizeof(routerMaskTlv), routerMaskTlv)); SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kRouterMask, sizeof(routerMaskTlv), routerMaskTlv));
VerifyOrExit(routerMaskTlv.IsValid(), ;); VerifyOrExit(routerMaskTlv.IsValid(), ;);
// if allocated routerId is different from previous routerId
if (IsRouterIdValid(mPreviousRouterId) && routerId != mPreviousRouterId)
{
// reset children info if any
if (HasChildren())
{
RemoveChildren();
}
}
// assign short address // assign short address
mRouterId = routerId; SetRouterId(routerId);
mPreviousRouterId = mRouterId;
SuccessOrExit(SetStateRouter(GetRloc16(mRouterId))); SuccessOrExit(SetStateRouter(GetRloc16(mRouterId)));
mRouters[mRouterId].mCost = 0; mRouters[mRouterId].mCost = 0;
// copy router id information // copy router id information
@@ -3691,10 +3752,6 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe
{ {
switch (mChildren[i].mState) switch (mChildren[i].mState)
{ {
case Neighbor::kStateInvalid:
case Neighbor::kStateParentRequest:
break;
case Neighbor::kStateChildIdRequest: case Neighbor::kStateChildIdRequest:
SendChildIdResponse(&mChildren[i]); SendChildIdResponse(&mChildren[i]);
break; break;
@@ -3703,14 +3760,11 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe
assert(false); assert(false);
break; break;
case Neighbor::kStateInvalid:
case Neighbor::kStateParentRequest:
case Neighbor::kStateValid: case Neighbor::kStateValid:
case Neighbor::kStateRestored: case Neighbor::kStateRestored:
case Neighbor::kStateChildUpdateRequest: case Neighbor::kStateChildUpdateRequest:
if (GetRouterId(mChildren[i].mValid.mRloc16) != mRouterId)
{
RemoveNeighbor(mChildren[i]);
}
break; break;
} }
} }
@@ -3765,6 +3819,7 @@ void MleRouter::HandleAddressSolicit(Coap::Header &aHeader, Message &aMessage, c
break; break;
case ThreadStatusTlv::kHaveChildIdRequest: case ThreadStatusTlv::kHaveChildIdRequest:
case ThreadStatusTlv::kParentPartitionChange:
break; break;
default: default:
@@ -4280,20 +4335,47 @@ exit:
return rval; return rval;
} }
bool MleRouter::HasChildren(void)
{
bool hasChildren = false;
for (uint8_t i = 0; i < mMaxChildrenAllowed; i++)
{
if (mChildren[i].mState == Neighbor::kStateRestored || mChildren[i].mState >= Neighbor::kStateChildIdRequest)
{
ExitNow(hasChildren = true);
}
}
exit:
return hasChildren;
}
void MleRouter::RemoveChildren(void)
{
for (uint8_t i = 0; i < mMaxChildrenAllowed; i++)
{
if (mChildren[i].mState == Neighbor::kStateRestored ||
mChildren[i].mState == Neighbor::kStateChildUpdateRequest ||
mChildren[i].mState == Neighbor::kStateValid)
{
RemoveStoredChild(mChildren[i].mValid.mRloc16);
}
mChildren[i].mState = Neighbor::kStateInvalid;
}
}
bool MleRouter::HasSmallNumberOfChildren(void) bool MleRouter::HasSmallNumberOfChildren(void)
{ {
Child *children;
uint8_t maxChildCount = 0;
uint8_t numChildren = 0; uint8_t numChildren = 0;
uint8_t routerCount = GetActiveRouterCount(); uint8_t routerCount = GetActiveRouterCount();
VerifyOrExit(routerCount > mRouterDowngradeThreshold, ;); VerifyOrExit(routerCount > mRouterDowngradeThreshold, ;);
children = GetChildren(&maxChildCount); for (uint8_t i = 0; i < mMaxChildrenAllowed; i++)
for (uint8_t i = 0; i < maxChildCount; i++)
{ {
if (children[i].mState == Neighbor::kStateValid) if (mChildren[i].mState == Neighbor::kStateValid)
{ {
numChildren++; numChildren++;
} }
+12 -1
View File
@@ -299,7 +299,15 @@ public:
ThreadError SetPreferredRouterId(uint8_t aRouterId); ThreadError SetPreferredRouterId(uint8_t aRouterId);
/** /**
* This method sets the Router Id from the stored network information. * This method sets the Partition Id which the device joins successfully.
*
* @param[in] aPartitionId The Partition Id.
*
*/
void SetPreviousPartitionId(uint32_t aPartitionId);
/**
* This method sets the Router Id.
* *
* @param[in] aRouterId The Router Id. * @param[in] aRouterId The Router Id.
* *
@@ -764,6 +772,8 @@ private:
Child *FindChild(uint16_t aChildId); Child *FindChild(uint16_t aChildId);
Child *FindChild(const Mac::ExtAddress &aMacAddr); Child *FindChild(const Mac::ExtAddress &aMacAddr);
bool HasChildren(void);
void RemoveChildren(void);
bool HasMinDowngradeNeighborRouters(void); bool HasMinDowngradeNeighborRouters(void);
bool HasOneNeighborwithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId); bool HasOneNeighborwithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId);
bool HasSmallNumberOfChildren(void); bool HasSmallNumberOfChildren(void);
@@ -812,6 +822,7 @@ private:
uint8_t mRouterId; uint8_t mRouterId;
uint8_t mPreviousRouterId; uint8_t mPreviousRouterId;
uint32_t mPreviousPartitionId;
Coap::Server &mCoapServer; Coap::Server &mCoapServer;
Coap::Client &mCoapClient; Coap::Client &mCoapClient;
+1
View File
@@ -69,6 +69,7 @@ public:
void SetLeaderPartitionId(uint32_t) { } void SetLeaderPartitionId(uint32_t) { }
ThreadError SetPreferredRouterId(uint8_t) { return kThreadError_NotImplemented; } ThreadError SetPreferredRouterId(uint8_t) { return kThreadError_NotImplemented; }
void SetPreviousPartitionId(uint32_t) { }
void SetRouterId(uint8_t) { } void SetRouterId(uint8_t) { }
uint16_t GetNextHop(uint16_t aDestination) const { return Mle::GetNextHop(aDestination); } uint16_t GetNextHop(uint16_t aDestination) const { return Mle::GetNextHop(aDestination); }
+1
View File
@@ -329,6 +329,7 @@ public:
kNoAddressAvailable = 1, ///< No address available. kNoAddressAvailable = 1, ///< No address available.
kTooFewRouters = 2, ///< Address Solicit due to too few routers. kTooFewRouters = 2, ///< Address Solicit due to too few routers.
kHaveChildIdRequest = 3, ///< Address Solicit due to child ID request. kHaveChildIdRequest = 3, ///< Address Solicit due to child ID request.
kParentPartitionChange = 4, ///< Address Solicit due to parent partition change
}; };
/** /**
+2 -1
View File
@@ -2485,7 +2485,8 @@ class ARM(IThci):
"""force update to router as if there is child id request""" """force update to router as if there is child id request"""
print '%s call updateRouterStatus' % self.port print '%s call updateRouterStatus' % self.port
cmd = 'state' cmd = 'state'
while state = self.__sendCommand(cmd)[0]: while True:
state = self.__sendCommand(cmd)[0]
if state == 'detached': if state == 'detached':
continue continue
elif state == 'child': elif state == 'child':