mirror of
https://github.com/espressif/openthread.git
synced 2026-10-09 17:27:41 +00:00
[mle] introduce AnnounceHandler class (#11558)
This commit introduces the `AnnounceHandler` class within `Mle` to encapsulate logic for handling Announce messages. This change simplifies the `Mle` module and makes the code easier to read and follow. The `AnnounceHandler` class handles received Announce messages with a newer timestamp and different channel and/or PAN ID. It can delay processing to collect and handle subsequent Announce messages. It also manages starting the "announce attach" process, where the device attempts to attach using the parameters from a processed Announce message. - If the attach is successful, this class sends an Announce on the old channel to inform other devices. This is done immediately after attaching as a MTD child or after a router transition attempt completes (on FTD). - If the attach fails, the class ensures the channel and PAN ID are restored to their original values. In particular, the new `AnnounceHandler` uses its own `Timer` to delay the start of an announce attach. Previously, the `AttachTimer` was repurposed for this, in addition to its use for attach state management.
This commit is contained in:
+79
-39
@@ -67,21 +67,19 @@ Mle::Mle(Instance &aInstance)
|
||||
, mChildUpdateAttempts(0)
|
||||
, mDataRequestAttempts(0)
|
||||
, mAnnounceChannel(0)
|
||||
, mAlternateChannel(0)
|
||||
, mRloc16(kInvalidRloc16)
|
||||
, mPreviousParentRloc(kInvalidRloc16)
|
||||
, mAttachCounter(0)
|
||||
, mAnnounceDelay(kAnnounceTimeout)
|
||||
, mAlternatePanId(Mac::kPanIdBroadcast)
|
||||
, mStoreFrameCounterAhead(kDefaultStoreFrameCounterAhead)
|
||||
, mTimeout(kDefaultChildTimeout)
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
, mCslTimeout(kDefaultCslTimeout)
|
||||
#endif
|
||||
, mAlternateTimestamp(0)
|
||||
, mNeighborTable(aInstance)
|
||||
, mDelayedSender(aInstance)
|
||||
, mSocket(aInstance, *this)
|
||||
, mAnnounceHandler(aInstance)
|
||||
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||
, mParentSearch(aInstance)
|
||||
#endif
|
||||
@@ -270,6 +268,7 @@ void Mle::Stop(StopMode aMode)
|
||||
VerifyOrExit(!IsDisabled());
|
||||
|
||||
mDelayedSender.Stop();
|
||||
mAnnounceHandler.Stop();
|
||||
Get<KeyManager>().Stop();
|
||||
SetStateDetached();
|
||||
Get<ThreadNetif>().UnsubscribeMulticast(mRealmLocalAllThreadNodes);
|
||||
@@ -793,8 +792,10 @@ void Mle::SetStateChild(uint16_t aRloc16)
|
||||
}
|
||||
#endif
|
||||
|
||||
// send announce after attached if needed
|
||||
InformPreviousChannel();
|
||||
if (mAnnounceHandler.IsAnnounceAttaching())
|
||||
{
|
||||
mAnnounceHandler.HandleAnnounceAttachSuccess();
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||
mParentSearch.UpdateState();
|
||||
@@ -812,16 +813,31 @@ void Mle::SetStateChild(uint16_t aRloc16)
|
||||
mPreviousParentRloc = mParent.GetRloc16();
|
||||
}
|
||||
|
||||
void Mle::InformPreviousChannel(void)
|
||||
void Mle::AnnounceHandler::HandleAnnounceAttachSuccess(void)
|
||||
{
|
||||
VerifyOrExit(mAlternatePanId != Mac::kPanIdBroadcast);
|
||||
VerifyOrExit(IsChild() || IsRouter());
|
||||
// Clear state and send announce on previous channel.
|
||||
|
||||
VerifyOrExit(mState == kStateAnnounceAttaching);
|
||||
mState = kStateToInformPreviousChannel;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
VerifyOrExit(!IsFullThreadDevice() || IsRouter() || !IsRouterRoleTransitionPending());
|
||||
if (Get<Mle>().IsFullThreadDevice() && !Get<Mle>().IsRouter() && Get<Mle>().IsRouterRoleTransitionPending())
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
#endif
|
||||
|
||||
mAlternatePanId = Mac::kPanIdBroadcast;
|
||||
InformPreviousChannel();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::AnnounceHandler::InformPreviousChannel(void)
|
||||
{
|
||||
VerifyOrExit(mState == kStateToInformPreviousChannel);
|
||||
|
||||
mState = kStateIdle;
|
||||
Get<AnnounceBeginServer>().SendAnnounce(1 << mAlternateChannel);
|
||||
|
||||
exit:
|
||||
@@ -1504,10 +1520,6 @@ void Mle::HandleAttachTimer(void)
|
||||
mAttachCounter = 0;
|
||||
break;
|
||||
|
||||
case kAttachStateProcessAnnounce:
|
||||
ProcessAnnounce();
|
||||
break;
|
||||
|
||||
case kAttachStateStart:
|
||||
LogNote("Attach attempt %d, %s %s", mAttachCounter, AttachModeToString(mAttachMode),
|
||||
ReattachStateToString(mReattachState));
|
||||
@@ -1640,11 +1652,9 @@ uint32_t Mle::Reattach(void)
|
||||
case kSelectedParent:
|
||||
if (!IsChild())
|
||||
{
|
||||
if (mAlternatePanId != Mac::kPanIdBroadcast)
|
||||
if (mAnnounceHandler.IsAnnounceAttaching())
|
||||
{
|
||||
IgnoreError(Get<Mac::Mac>().SetPanChannel(mAlternateChannel));
|
||||
Get<Mac::Mac>().SetPanId(mAlternatePanId);
|
||||
mAlternatePanId = Mac::kPanIdBroadcast;
|
||||
mAnnounceHandler.HandleAnnounceAttachFailure();
|
||||
IgnoreError(BecomeDetached());
|
||||
}
|
||||
#if OPENTHREAD_FTD
|
||||
@@ -2559,7 +2569,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
break;
|
||||
|
||||
case kCommandAnnounce:
|
||||
HandleAnnounce(rxInfo);
|
||||
mAnnounceHandler.HandleAnnounce(rxInfo);
|
||||
break;
|
||||
|
||||
case kCommandChildUpdateRequest:
|
||||
@@ -3678,7 +3688,7 @@ exit:
|
||||
LogProcessError(kTypeChildUpdateResponseAsChild, error);
|
||||
}
|
||||
|
||||
void Mle::HandleAnnounce(RxInfo &aRxInfo)
|
||||
void Mle::AnnounceHandler::HandleAnnounce(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
ChannelTlvValue channelTlvValue;
|
||||
@@ -3711,10 +3721,10 @@ void Mle::HandleAnnounce(RxInfo &aRxInfo)
|
||||
VerifyOrExit(!channelAndPanIdMatch);
|
||||
}
|
||||
|
||||
SendAnnounce(channel);
|
||||
Get<Mle>().SendAnnounce(channel);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_SEND_UNICAST_ANNOUNCE_RESPONSE
|
||||
SendAnnounce(channel, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
Get<Mle>().SendAnnounce(channel, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
#endif
|
||||
}
|
||||
else if (timestampCompare > 0)
|
||||
@@ -3723,7 +3733,7 @@ void Mle::HandleAnnounce(RxInfo &aRxInfo)
|
||||
// channel and pan-id match the values from the received MLE
|
||||
// Announce message.
|
||||
|
||||
if (IsDetached())
|
||||
if (Get<Mle>().IsDetached())
|
||||
{
|
||||
VerifyOrExit(!channelAndPanIdMatch);
|
||||
}
|
||||
@@ -3746,7 +3756,7 @@ void Mle::HandleAnnounce(RxInfo &aRxInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if (mAttachState == kAttachStateProcessAnnounce)
|
||||
if (mState == kStateToAnnounceAttach)
|
||||
{
|
||||
VerifyOrExit(mAlternateTimestamp < timestamp.GetSeconds());
|
||||
}
|
||||
@@ -3754,9 +3764,8 @@ void Mle::HandleAnnounce(RxInfo &aRxInfo)
|
||||
mAlternateTimestamp = timestamp.GetSeconds();
|
||||
mAlternateChannel = channel;
|
||||
mAlternatePanId = panId;
|
||||
SetAttachState(kAttachStateProcessAnnounce);
|
||||
mAttachTimer.Start(kAnnounceProcessTimeout);
|
||||
mAttachCounter = 0;
|
||||
mState = kStateToAnnounceAttach;
|
||||
mTimer.Start(kAnnounceProcessTimeout);
|
||||
|
||||
LogNote("Delay processing Announce - channel %d, panid 0x%02x", channel, panId);
|
||||
}
|
||||
@@ -3854,16 +3863,16 @@ exit:
|
||||
}
|
||||
#endif
|
||||
|
||||
void Mle::ProcessAnnounce(void)
|
||||
void Mle::AnnounceHandler::StartAnnounceAttach(void)
|
||||
{
|
||||
uint8_t newChannel = mAlternateChannel;
|
||||
uint16_t newPanId = mAlternatePanId;
|
||||
|
||||
OT_ASSERT(mAttachState == kAttachStateProcessAnnounce);
|
||||
VerifyOrExit(mState == kStateToAnnounceAttach);
|
||||
|
||||
LogNote("Processing Announce - channel %d, panid 0x%02x", newChannel, newPanId);
|
||||
LogNote("Starting Announce attach - channel %d, panid 0x%02x", newChannel, newPanId);
|
||||
|
||||
Stop(kKeepNetworkDatasets);
|
||||
Get<Mle>().Stop(kKeepNetworkDatasets);
|
||||
|
||||
// Save the current/previous channel and pan-id
|
||||
mAlternateChannel = Get<Mac::Mac>().GetPanChannel();
|
||||
@@ -3873,7 +3882,11 @@ void Mle::ProcessAnnounce(void)
|
||||
IgnoreError(Get<Mac::Mac>().SetPanChannel(newChannel));
|
||||
Get<Mac::Mac>().SetPanId(newPanId);
|
||||
|
||||
IgnoreError(Start(kAnnounceAttach));
|
||||
mState = kStateAnnounceAttaching;
|
||||
IgnoreError(Get<Mle>().Start(kAnnounceAttach));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t Mle::GetParentRloc16(void) const { return (mParent.IsStateValid() ? mParent.GetRloc16() : kInvalidRloc16); }
|
||||
@@ -4341,19 +4354,17 @@ const char *Mle::AttachModeToString(AttachMode aMode)
|
||||
const char *Mle::AttachStateToString(AttachState aState)
|
||||
{
|
||||
static const char *const kAttachStateStrings[] = {
|
||||
"Idle", // (0) kAttachStateIdle
|
||||
"ProcessAnnounce", // (1) kAttachStateProcessAnnounce
|
||||
"Start", // (2) kAttachStateStart
|
||||
"ParentReq", // (3) kAttachStateParent
|
||||
"Announce", // (4) kAttachStateAnnounce
|
||||
"ChildIdReq", // (5) kAttachStateChildIdRequest
|
||||
"Idle", // (0) kAttachStateIdle
|
||||
"Start", // (1) kAttachStateStart
|
||||
"ParentReq", // (2) kAttachStateParent
|
||||
"Announce", // (3) kAttachStateAnnounce
|
||||
"ChildIdReq", // (4) kAttachStateChildIdRequest
|
||||
};
|
||||
|
||||
struct EnumCheck
|
||||
{
|
||||
InitEnumValidatorCounter();
|
||||
ValidateNextEnum(kAttachStateIdle);
|
||||
ValidateNextEnum(kAttachStateProcessAnnounce);
|
||||
ValidateNextEnum(kAttachStateStart);
|
||||
ValidateNextEnum(kAttachStateParentRequest);
|
||||
ValidateNextEnum(kAttachStateAnnounce);
|
||||
@@ -5594,5 +5605,34 @@ void Mle::ParentCandidate::CopyTo(Parent &aParent) const
|
||||
aParent = *candidateAsParent;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// AnnounceHanlder
|
||||
|
||||
Mle::AnnounceHandler::AnnounceHandler(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mState(kStateIdle)
|
||||
, mTimer(aInstance)
|
||||
{
|
||||
}
|
||||
|
||||
void Mle::AnnounceHandler::Stop(void)
|
||||
{
|
||||
mTimer.Stop();
|
||||
mState = kStateIdle;
|
||||
}
|
||||
|
||||
void Mle::AnnounceHandler::HandleAnnounceAttachFailure(void)
|
||||
{
|
||||
VerifyOrExit(mState == kStateAnnounceAttaching);
|
||||
mState = kStateIdle;
|
||||
IgnoreError(Get<Mac::Mac>().SetPanChannel(mAlternateChannel));
|
||||
Get<Mac::Mac>().SetPanId(mAlternatePanId);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::AnnounceHandler::HandleTimer(void) { StartAnnounceAttach(); }
|
||||
|
||||
} // namespace Mle
|
||||
} // namespace ot
|
||||
|
||||
+63
-12
@@ -1318,12 +1318,11 @@ private:
|
||||
|
||||
enum AttachState : uint8_t
|
||||
{
|
||||
kAttachStateIdle, // Not currently searching for a parent.
|
||||
kAttachStateProcessAnnounce, // Waiting to process a received Announce (to switch channel/pan-id).
|
||||
kAttachStateStart, // Starting to look for a parent.
|
||||
kAttachStateParentRequest, // Send Parent Request (current number tracked by `mParentRequestCounter`).
|
||||
kAttachStateAnnounce, // Send Announce messages
|
||||
kAttachStateChildIdRequest, // Sending a Child ID Request message.
|
||||
kAttachStateIdle, // Not currently searching for a parent.
|
||||
kAttachStateStart, // Starting to look for a parent.
|
||||
kAttachStateParentRequest, // Send Parent Request (current number tracked by `mParentRequestCounter`).
|
||||
kAttachStateAnnounce, // Send Announce messages
|
||||
kAttachStateChildIdRequest, // Sending a Child ID Request message.
|
||||
};
|
||||
|
||||
enum ReattachState : uint8_t
|
||||
@@ -1733,6 +1732,63 @@ private:
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
void HandleAnnounceHandlerTimer(void) { mAnnounceHandler.HandleTimer(); }
|
||||
|
||||
class AnnounceHandler : public InstanceLocator
|
||||
{
|
||||
// Handles received Announce messages with a newer timestamp on
|
||||
// a different channel and/or PAN ID. It may delay processing
|
||||
// to collect and handle subsequent Announce messages.
|
||||
//
|
||||
// This class also manages an 'announce attach' process, where
|
||||
// the device tries to attach using the parameters (channel and
|
||||
// PAN ID) from a processed Announce message.
|
||||
//
|
||||
// If the 'announce attach' is successful, this class handles
|
||||
// sending an Announce on the old channel to inform other
|
||||
// devices. This is done immediately after attaching as a child
|
||||
// or after an attempt to transition to the router role is
|
||||
// complete (whether successful or not).
|
||||
//
|
||||
// If the 'announce attach' fails, the class ensures the channel
|
||||
// and PAN ID are restored to their original values.
|
||||
|
||||
public:
|
||||
explicit AnnounceHandler(Instance &aInstance);
|
||||
|
||||
void Stop(void);
|
||||
void HandleAnnounce(RxInfo &aRxInfo);
|
||||
bool IsAnnounceAttaching(void) const { return mState == kStateAnnounceAttaching; }
|
||||
void HandleAnnounceAttachSuccess(void);
|
||||
void HandleAnnounceAttachFailure(void);
|
||||
#if OPENTHREAD_FTD
|
||||
void HandleRouterRoleTransitionAttemptDone(void) { InformPreviousChannel(); }
|
||||
#endif
|
||||
void HandleTimer(void);
|
||||
|
||||
private:
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateIdle,
|
||||
kStateToAnnounceAttach,
|
||||
kStateAnnounceAttaching,
|
||||
kStateToInformPreviousChannel,
|
||||
};
|
||||
|
||||
void StartAnnounceAttach(void);
|
||||
void InformPreviousChannel(void);
|
||||
|
||||
using AnnouceTimer = TimerMilliIn<Mle, &Mle::HandleAnnounceHandlerTimer>;
|
||||
|
||||
State mState;
|
||||
uint8_t mAlternateChannel;
|
||||
uint16_t mAlternatePanId;
|
||||
uint64_t mAlternateTimestamp;
|
||||
AnnouceTimer mTimer;
|
||||
};
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||
void HandleParentSearchTimer(void) { mParentSearch.HandleTimer(); }
|
||||
|
||||
@@ -1865,7 +1921,6 @@ private:
|
||||
void SetLeaderData(const LeaderData &aLeaderData);
|
||||
void SetTimeout(uint32_t aTimeout, TimeoutAction aAction);
|
||||
void InformPreviousChannel(void);
|
||||
bool IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; }
|
||||
void ScheduleMessageTransmissionTimer(void);
|
||||
void HandleAttachTimer(void);
|
||||
void HandleMessageTransmissionTimer(void);
|
||||
@@ -1878,9 +1933,7 @@ private:
|
||||
void HandleChildUpdateResponseOnChild(RxInfo &aRxInfo);
|
||||
void HandleDataResponse(RxInfo &aRxInfo);
|
||||
void HandleParentResponse(RxInfo &aRxInfo);
|
||||
void HandleAnnounce(RxInfo &aRxInfo);
|
||||
Error HandleLeaderData(RxInfo &aRxInfo);
|
||||
void ProcessAnnounce(void);
|
||||
bool HasUnregisteredAddress(void);
|
||||
uint32_t GetAttachStartDelay(void) const;
|
||||
void SendParentRequest(ParentRequestType aType);
|
||||
@@ -2084,12 +2137,10 @@ private:
|
||||
uint8_t mChildUpdateAttempts;
|
||||
uint8_t mDataRequestAttempts;
|
||||
uint8_t mAnnounceChannel;
|
||||
uint8_t mAlternateChannel;
|
||||
uint16_t mRloc16;
|
||||
uint16_t mPreviousParentRloc;
|
||||
uint16_t mAttachCounter;
|
||||
uint16_t mAnnounceDelay;
|
||||
uint16_t mAlternatePanId;
|
||||
uint32_t mStoreFrameCounterAhead;
|
||||
uint32_t mTimeout;
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
@@ -2097,7 +2148,6 @@ private:
|
||||
#endif
|
||||
uint32_t mLastAttachTime;
|
||||
uint64_t mLastUpdatedTimestamp;
|
||||
uint64_t mAlternateTimestamp;
|
||||
|
||||
LeaderData mLeaderData;
|
||||
Parent mParent;
|
||||
@@ -2107,6 +2157,7 @@ private:
|
||||
ParentCandidate mParentCandidate;
|
||||
MleSocket mSocket;
|
||||
Counters mCounters;
|
||||
AnnounceHandler mAnnounceHandler;
|
||||
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||
ParentSearch mParentSearch;
|
||||
#endif
|
||||
|
||||
@@ -343,7 +343,7 @@ void Mle::HandleChildStart(AttachMode aMode)
|
||||
// decision to become router is determined based on the new
|
||||
// partition's status.
|
||||
|
||||
if (IsAnnounceAttach() && HasChildren())
|
||||
if (mAnnounceHandler.IsAnnounceAttaching() && HasChildren())
|
||||
{
|
||||
RemoveChildren();
|
||||
}
|
||||
@@ -1562,7 +1562,7 @@ void Mle::HandleTimeTick(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
InformPreviousChannel();
|
||||
mAnnounceHandler.HandleRouterRoleTransitionAttemptDone();
|
||||
}
|
||||
|
||||
if (!mAdvertiseTrickleTimer.IsRunning())
|
||||
@@ -3460,7 +3460,7 @@ void Mle::HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::Messa
|
||||
}
|
||||
|
||||
exit:
|
||||
InformPreviousChannel();
|
||||
mAnnounceHandler.HandleRouterRoleTransitionAttemptDone();
|
||||
}
|
||||
|
||||
Error Mle::SetChildRouterLinks(uint8_t aChildRouterLinks)
|
||||
|
||||
Reference in New Issue
Block a user