[mle] simplify HandleAdvertisement() (#8643)

This commit contains smaller enhancements in `MleRouter` method
`HandleAdvertisement()` processing received MLE Advertisement
message:
- We remove all the `IsFullThreadDevice()` checks in this method
  since it is only called from `Mle` when device is FTD (already
  checked by `Mle` before calling).
- Also this method is called only when device is attached (in child,
  router, or leader role). So we can simplify the checks related to
  the device's role.
- We pass the already read TLV values (e.g., `LeaderDataTlv`) to
  this method (to avoid re-reading the same TLVs from message).
This commit is contained in:
Abtin Keshavarzian
2023-01-11 06:15:50 -08:00
committed by GitHub
parent 1e5c664a9a
commit 7dd9543687
3 changed files with 59 additions and 83 deletions
+2 -2
View File
@@ -2714,12 +2714,12 @@ void Mle::HandleAdvertisement(RxInfo &aRxInfo)
// Leader Data
SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
if (!IsDetached())
if (IsAttached())
{
#if OPENTHREAD_FTD
if (IsFullThreadDevice())
{
SuccessOrExit(error = Get<MleRouter>().HandleAdvertisement(aRxInfo));
SuccessOrExit(error = Get<MleRouter>().HandleAdvertisement(aRxInfo, sourceAddress, leaderData));
}
else
#endif
+56 -80
View File
@@ -1129,60 +1129,55 @@ exit:
return rval;
}
Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData)
{
// This method processes a received MLE Advertisement message on
// an FTD device. It is called from `Mle::HandleAdvertisement()`
// only when device is attached (in child, router, or leader roles)
// and `IsFullThreadDevice()`.
//
// - `aSourceAdress` is the read value from `SourceAddressTlv`.
// - `aLeaderData` is the read value from `LeaderDataTlv`.
Error error = kErrorNone;
const ThreadLinkInfo *linkInfo = aRxInfo.mMessageInfo.GetThreadLinkInfo();
uint8_t linkMargin = Get<Mac::Mac>().ComputeLinkMargin(linkInfo->GetRss());
Mac::ExtAddress extAddr;
uint16_t sourceAddress = Mac::kShortAddrInvalid;
LeaderData leaderData;
RouteTlv routeTlv;
uint32_t partitionId;
Router *router;
uint8_t routerId;
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
// Source Address
SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
// Leader Data
SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
// Route Data (optional)
if (Tlv::FindTlv(aRxInfo.mMessage, routeTlv) == kErrorNone)
{
VerifyOrExit(routeTlv.IsValid(), error = kErrorParse);
}
else
{
// mark that a Route TLV was not included
routeTlv.SetLength(0);
routeTlv.SetLength(0); // Mark that a Route TLV was not included
}
partitionId = leaderData.GetPartitionId();
if (partitionId != mLeaderData.GetPartitionId())
if (aLeaderData.GetPartitionId() != mLeaderData.GetPartitionId())
{
LogNote("Different partition (peer:%lu, local:%lu)", ToUlong(partitionId),
LogNote("Different partition (peer:%lu, local:%lu)", ToUlong(aLeaderData.GetPartitionId()),
ToUlong(mLeaderData.GetPartitionId()));
VerifyOrExit(linkMargin >= kPartitionMergeMinMargin, error = kErrorLinkMarginLow);
if (routeTlv.IsValid() && IsFullThreadDevice() && (mPreviousPartitionIdTimeout > 0) &&
(partitionId == mPreviousPartitionId))
if (routeTlv.IsValid() && (mPreviousPartitionIdTimeout > 0) &&
(aLeaderData.GetPartitionId() == mPreviousPartitionId))
{
VerifyOrExit(SerialNumber::IsGreater(routeTlv.GetRouterIdSequence(), mPreviousPartitionRouterIdSequence),
error = kErrorDrop);
}
if (IsChild() && (aRxInfo.mNeighbor == &mParent || !IsFullThreadDevice()))
if (IsChild() && (aRxInfo.mNeighbor == &mParent))
{
ExitNow();
}
if (ComparePartitions(routeTlv.IsSingleton(), leaderData, IsSingleton(), mLeaderData) > 0
if (ComparePartitions(routeTlv.IsSingleton(), aLeaderData, IsSingleton(), mLeaderData) > 0
#if OPENTHREAD_CONFIG_TIME_SYNC_REQUIRED
// if time sync is required, it will only migrate to a better network which also enables time sync.
&& aRxInfo.mMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ
@@ -1194,7 +1189,7 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
ExitNow(error = kErrorDrop);
}
else if (leaderData.GetLeaderRouterId() != GetLeaderId())
else if (aLeaderData.GetLeaderRouterId() != GetLeaderId())
{
VerifyOrExit(aRxInfo.IsNeighborStateValid());
@@ -1208,27 +1203,22 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
ExitNow();
}
VerifyOrExit(IsActiveRouter(sourceAddress) && routeTlv.IsValid());
routerId = RouterIdFromRloc16(sourceAddress);
VerifyOrExit(IsActiveRouter(aSourceAddress) && routeTlv.IsValid());
routerId = RouterIdFromRloc16(aSourceAddress);
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
#endif
if (IsFullThreadDevice() && aRxInfo.IsNeighborStateValid() &&
if (aRxInfo.IsNeighborStateValid() &&
((mRouterTable.GetActiveRouterCount() == 0) ||
SerialNumber::IsGreater(routeTlv.GetRouterIdSequence(), mRouterTable.GetRouterIdSequence())))
{
bool processRouteTlv = false;
switch (mRole)
if (IsChild())
{
case kRoleDisabled:
case kRoleDetached:
break;
case kRoleChild:
if (sourceAddress == mParent.GetRloc16())
if (aSourceAddress == mParent.GetRloc16())
{
processRouteTlv = true;
}
@@ -1241,13 +1231,10 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
processRouteTlv = true;
}
}
break;
case kRoleRouter:
case kRoleLeader:
}
else // Device is router or leader
{
processRouteTlv = true;
break;
}
if (processRouteTlv)
@@ -1256,35 +1243,26 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
}
}
switch (mRole)
if (IsChild())
{
case kRoleDisabled:
case kRoleDetached:
ExitNow();
case kRoleChild:
if (aRxInfo.mNeighbor == &mParent)
{
// MLE Advertisement from parent
router = &mParent;
if (mParent.GetRloc16() != sourceAddress)
if (mParent.GetRloc16() != aSourceAddress)
{
IgnoreError(BecomeDetached());
ExitNow(error = kErrorDetached);
}
if (IsFullThreadDevice())
if ((mRouterSelectionJitterTimeout == 0) && (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold))
{
if ((mRouterSelectionJitterTimeout == 0) &&
(mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold))
{
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
ExitNow();
}
mRouterTable.UpdateRoutesOnFed(routeTlv, routerId);
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
ExitNow();
}
mRouterTable.UpdateRoutesOnFed(routeTlv, routerId);
}
else
{
@@ -1292,7 +1270,7 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
router = mRouterTable.FindRouterById(routerId);
VerifyOrExit(router != nullptr);
if (IsFullThreadDevice() && !router->IsStateValid() && !router->IsStateLinkRequest() &&
if (!router->IsStateValid() && !router->IsStateLinkRequest() &&
(mRouterTable.GetNeighborCount() < kChildRouterLinks))
{
router->SetExtAddress(extAddr);
@@ -1309,8 +1287,10 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
router->SetLastHeard(TimerMilli::GetNow());
ExitNow();
}
case kRoleRouter:
if (IsRouter())
{
if (mLinkRequestDelay > 0 && routeTlv.IsRouterIdSet(mRouterId))
{
mLinkRequestDelay = 0;
@@ -1321,35 +1301,31 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
{
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
}
OT_FALL_THROUGH;
case kRoleLeader:
router = mRouterTable.FindRouterById(routerId);
VerifyOrExit(router != nullptr);
// Send unicast link request if no link to router and no unicast/multicast link request in progress
if (!router->IsStateValid() && !router->IsStateLinkRequest() && (mChallengeTimeout == 0) &&
(linkMargin >= kLinkRequestMinMargin))
{
router->SetExtAddress(extAddr);
router->GetLinkInfo().Clear();
router->GetLinkInfo().AddRss(linkInfo->GetRss());
router->ResetLinkFailures();
router->SetLastHeard(TimerMilli::GetNow());
router->SetState(Neighbor::kStateLinkRequest);
IgnoreError(SendLinkRequest(router));
ExitNow(error = kErrorNoRoute);
}
router->SetLastHeard(TimerMilli::GetNow());
break;
}
router = mRouterTable.FindRouterById(routerId);
VerifyOrExit(router != nullptr);
// Send unicast link request if no link to router and no unicast/multicast link request in progress
if (!router->IsStateValid() && !router->IsStateLinkRequest() && (mChallengeTimeout == 0) &&
(linkMargin >= kLinkRequestMinMargin))
{
router->SetExtAddress(extAddr);
router->GetLinkInfo().Clear();
router->GetLinkInfo().AddRss(linkInfo->GetRss());
router->ResetLinkFailures();
router->SetLastHeard(TimerMilli::GetNow());
router->SetState(Neighbor::kStateLinkRequest);
IgnoreError(SendLinkRequest(router));
ExitNow(error = kErrorNoRoute);
}
router->SetLastHeard(TimerMilli::GetNow());
mRouterTable.UpdateRoutes(routeTlv, routerId);
exit:
if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != sourceAddress)
if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != aSourceAddress)
{
// Remove stale neighbors
RemoveNeighbor(*aRxInfo.mNeighbor);
+1 -1
View File
@@ -554,7 +554,7 @@ private:
void HandleLinkAccept(RxInfo &aRxInfo);
Error HandleLinkAccept(RxInfo &aRxInfo, bool aRequest);
void HandleLinkAcceptAndRequest(RxInfo &aRxInfo);
Error HandleAdvertisement(RxInfo &aRxInfo);
Error HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData);
void HandleParentRequest(RxInfo &aRxInfo);
void HandleChildIdRequest(RxInfo &aRxInfo);
void HandleChildUpdateRequest(RxInfo &aRxInfo);