fix RFD child reattach issue when the parent is in new partition without changing routerid (#161)

choose a random initial mRouterIdSequence when forming a new partition
This commit is contained in:
rongli
2016-06-21 08:48:53 -07:00
committed by Jonathan Hui
parent 02a889566d
commit 460e27fdcb
3 changed files with 55 additions and 16 deletions
+51 -7
View File
@@ -67,6 +67,7 @@ Mle::Mle(ThreadNetif &aThreadNetif) :
mParentRequestState = kParentIdle;
mParentRequestMode = kMleAttachAnyPartition;
mParentConnectivity = 0;
mRetrieveNewNetworkData = false;
mTimeout = kMaxNeighborAge;
memset(&mLeaderData, 0, sizeof(mLeaderData));
@@ -1415,10 +1416,21 @@ ThreadError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::Message
Mac::ExtAddress macAddr;
bool isNeighbor;
Neighbor *neighbor;
SourceAddressTlv sourceAddress;
LeaderDataTlv leaderData;
uint8_t tlvs[] = {Tlv::kLeaderData, Tlv::kNetworkData};
if (mDeviceState != kDeviceStateDetached)
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = kThreadError_Parse);
// Leader Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
otLogInfoMle("Received advertisement from %04x\n", sourceAddress.GetRloc16());
if ((mDeviceState != kDeviceStateDetached) && (mDeviceMode & ModeTlv::kModeFFD))
{
SuccessOrExit(error = mMleRouter.HandleAdvertisement(aMessage, aMessageInfo));
}
@@ -1439,6 +1451,21 @@ ThreadError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::Message
break;
}
if (mParent.mValid.mRloc16 != sourceAddress.GetRloc16())
{
SetStateDetached();
ExitNow(error = kThreadError_NoRoute);
}
else
{
if (leaderData.GetPartitionId() != mLeaderData.GetPartitionId() ||
leaderData.GetLeaderRouterId() != GetLeaderId())
{
SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
mRetrieveNewNetworkData = true;
}
}
isNeighbor = true;
mParent.mLastHeard = mParentRequestTimer.GetNow();
break;
@@ -1456,10 +1483,8 @@ ThreadError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::Message
if (isNeighbor)
{
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
if (static_cast<int8_t>(leaderData.GetDataVersion() - mNetworkData.GetVersion()) > 0)
if (mRetrieveNewNetworkData ||
(static_cast<int8_t>(leaderData.GetDataVersion() - mNetworkData.GetVersion()) > 0))
{
SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs));
}
@@ -1499,8 +1524,27 @@ ThreadError Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageI
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
diff = leaderData.GetDataVersion() - mNetworkData.GetVersion();
VerifyOrExit(diff > 0, ;);
if ((leaderData.GetPartitionId() != mLeaderData.GetPartitionId()) ||
(leaderData.GetLeaderRouterId() != GetLeaderId()))
{
if ((mDeviceMode & ModeTlv::kModeRxOnWhenIdle) == 0)
{
SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
}
else
{
ExitNow(error = kThreadError_Drop);
}
}
else if (mRetrieveNewNetworkData)
{
mRetrieveNewNetworkData = false;
}
else
{
diff = leaderData.GetDataVersion() - mNetworkData.GetVersion();
VerifyOrExit(diff > 0, ;);
}
mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
(mDeviceMode & ModeTlv::kModeFullNetworkData) == 0,
+1
View File
@@ -907,6 +907,7 @@ protected:
NetworkData::Leader &mNetworkData; ///< The Network Data object.
LeaderDataTlv mLeaderData; ///< Last received Leader Data TLV.
bool mRetrieveNewNetworkData; ///< Indicating new Network Data is needed if set.
DeviceState mDeviceState; ///< Current Thread interface state.
Router mParent; ///< Parent information.
+3 -9
View File
@@ -228,6 +228,7 @@ ThreadError MleRouter::BecomeLeader(void)
memcpy(&mRouters[mRouterId].mMacAddr, mMac.GetExtAddress(), sizeof(mRouters[mRouterId].mMacAddr));
SetLeaderData(otPlatRandomGet(), mLeaderWeight, mRouterId);
mRouterIdSequence = otPlatRandomGet();
mNetworkData.Reset();
@@ -1083,7 +1084,6 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = kThreadError_Parse);
// Remove stale neighbors
if ((neighbor = GetNeighbor(macAddr)) != NULL &&
@@ -1094,9 +1094,6 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M
// Leader Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
otLogInfoMle("Received advertisement from %04x\n", sourceAddress.GetRloc16());
peerParitionId = leaderData.GetPartitionId();
@@ -1128,10 +1125,7 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kRoute, sizeof(route), route));
VerifyOrExit(route.IsValid(), error = kThreadError_Parse);
if (mDeviceMode & ModeTlv::kModeFFD)
{
SuccessOrExit(error = ProcessRouteTlv(route));
}
SuccessOrExit(error = ProcessRouteTlv(route));
VerifyOrExit((routerId = GetRouterId(sourceAddress.GetRloc16())) < kMaxRouterId, error = kThreadError_Parse);
@@ -1154,7 +1148,7 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M
}
}
if ((mDeviceMode & ModeTlv::kModeFFD) && (routerCount < mRouterUpgradeThreshold))
if (routerCount < mRouterUpgradeThreshold)
{
BecomeRouter();
ExitNow();