[mle] update processing of received MLE Announce messages (#2707)

This commit changes how the received MLE Announce messages are
processed.

The new implementation adds a delay before taking action when it
receives an MLE Announce message that has a more recent Active
timestamp (compared to device's current Active Dataset timestamp).  A
timeout interval of `kAnnounceProcessTimeout` (250ms) is used before
the device switches to the new channel or pan-id from the received MLE
Announce message. During the timeout interval, device can receive and
parse other MLE Announce messages and it will ignore any with the same
timestamp.
This commit is contained in:
Abtin Keshavarzian
2018-05-23 01:19:49 -07:00
committed by Jonathan Hui
parent c276d0776c
commit 38f206c670
3 changed files with 63 additions and 22 deletions
+57 -20
View File
@@ -101,8 +101,9 @@ Mle::Mle(Instance &aInstance)
, mParentSearchTimer(aInstance, &Mle::HandleParentSearchTimer, this)
#endif
, mAnnounceChannel(OT_RADIO_CHANNEL_MIN)
, mPreviousChannel(0)
, mPreviousPanId(Mac::kPanIdBroadcast)
, mAlternateChannel(0)
, mAlternatePanId(Mac::kPanIdBroadcast)
, mAlternateTimestamp(0)
, mNotifierCallback(&Mle::HandleStateChanged, this)
{
uint8_t meshLocalPrefix[8];
@@ -658,14 +659,14 @@ otError Mle::SetStateChild(uint16_t aRloc16)
void Mle::InformPreviousChannel(void)
{
VerifyOrExit(mPreviousPanId != Mac::kPanIdBroadcast);
VerifyOrExit(mAlternatePanId != Mac::kPanIdBroadcast);
VerifyOrExit(mRole == OT_DEVICE_ROLE_CHILD || mRole == OT_DEVICE_ROLE_ROUTER);
if (!IsFullThreadDevice() || mRole == OT_DEVICE_ROLE_ROUTER ||
GetNetif().GetMle().GetRouterSelectionJitterTimeout() == 0)
{
mPreviousPanId = Mac::kPanIdBroadcast;
GetNetif().GetAnnounceBeginServer().SendAnnounce(1 << mPreviousChannel);
mAlternatePanId = Mac::kPanIdBroadcast;
GetNetif().GetAnnounceBeginServer().SendAnnounce(1 << mAlternateChannel);
}
exit:
@@ -1478,6 +1479,10 @@ void Mle::HandleAttachTimer(void)
SendChildUpdateRequest();
break;
case kAttachStateProcessAnnounce:
ProcessAnnounce();
break;
case kAttachStateStart:
SetAttachState(kAttachStateParentRequestRouter);
mParentCandidate.SetState(Neighbor::kStateInvalid);
@@ -1615,11 +1620,11 @@ uint32_t Mle::Reattach(void)
case kAttachAny:
if (mRole != OT_DEVICE_ROLE_CHILD)
{
if (mPreviousPanId != Mac::kPanIdBroadcast)
if (mAlternatePanId != Mac::kPanIdBroadcast)
{
netif.GetMac().SetPanChannel(mPreviousChannel);
netif.GetMac().SetPanId(mPreviousPanId);
mPreviousPanId = Mac::kPanIdBroadcast;
netif.GetMac().SetPanChannel(mAlternateChannel);
netif.GetMac().SetPanId(mAlternatePanId);
mAlternatePanId = Mac::kPanIdBroadcast;
BecomeDetached();
}
else if (!IsFullThreadDevice())
@@ -3268,7 +3273,6 @@ exit:
otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
ThreadNetif & netif = GetNetif();
otError error = OT_ERROR_NONE;
ChannelTlv channelTlv;
ActiveTimestampTlv timestamp;
@@ -3290,25 +3294,31 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
VerifyOrExit(panIdTlv.IsValid(), error = OT_ERROR_PARSE);
panId = panIdTlv.GetPanId();
localTimestamp = netif.GetActiveDataset().GetTimestamp();
localTimestamp = GetNetif().GetActiveDataset().GetTimestamp();
if (localTimestamp == NULL || localTimestamp->Compare(timestamp) > 0)
{
uint8_t curChannel = netif.GetMac().GetPanChannel();
uint16_t curPanId = netif.GetMac().GetPanId();
Mac::Mac &mac = GetNetif().GetMac();
// No action is required if device is detached, and current
// channel and pan-id match the values from the received MLE
// Announce message.
VerifyOrExit((mRole != OT_DEVICE_ROLE_DETACHED) || (curChannel != channel) || (curPanId != panId));
VerifyOrExit((mRole != OT_DEVICE_ROLE_DETACHED) || (mac.GetPanChannel() != channel) ||
(mac.GetPanId() != panId));
Stop(false);
mPreviousChannel = curChannel;
mPreviousPanId = curPanId;
netif.GetMac().SetPanChannel(channel);
netif.GetMac().SetPanId(panId);
Start(false, true);
if (mAttachState == kAttachStateProcessAnnounce)
{
VerifyOrExit(mAlternateTimestamp < timestamp.GetSeconds());
}
mAlternateTimestamp = timestamp.GetSeconds();
mAlternateChannel = channel;
mAlternatePanId = panId;
SetAttachState(kAttachStateProcessAnnounce);
mAttachTimer.Start(kAnnounceProcessTimeout);
otLogInfoMle(GetInstance(), "Delay processing Announce - channel %d, panid 0x%02x", channel, panId);
}
else if (localTimestamp->Compare(timestamp) < 0)
{
@@ -3331,6 +3341,29 @@ exit:
return error;
}
void Mle::ProcessAnnounce(void)
{
Mac::Mac &mac = GetNetif().GetMac();
uint8_t newChannel = mAlternateChannel;
uint16_t newPanId = mAlternatePanId;
assert(mAttachState == kAttachStateProcessAnnounce);
otLogInfoMle(GetInstance(), "Processing Announce - channel %d, panid 0x%02x", newChannel, newPanId);
Stop(/* aClearNetworkDatasets */ false);
// Save the current/previous channel and pan-id
mAlternateChannel = mac.GetPanChannel();
mAlternatePanId = mac.GetPanId();
mAlternateTimestamp = 0;
mac.SetPanChannel(newChannel);
mac.SetPanId(newPanId);
Start(/* aEnableReattach */ false, /* aAnnounceAttach */ true);
}
otError Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
@@ -3820,6 +3853,10 @@ const char *Mle::AttachStateToString(AttachState aState)
str = "Sync";
break;
case kAttachStateProcessAnnounce:
str = "ProcessAnnounce";
break;
case kAttachStateStart:
str = "Start";
break;
+5 -2
View File
@@ -998,6 +998,7 @@ protected:
{
kAttachStateIdle, ///< Not currently searching for a parent.
kAttachStateSynchronize, ///< Looking to synchronize with a parent (after reset).
kAttachStateProcessAnnounce, ///< Waiting to process a received Announce (to switch channel/pan-id).
kAttachStateStart, ///< Starting to look for a parent.
kAttachStateParentRequestRouter, ///< Searching for a Router to attach to.
kAttachStateParentRequestReed, ///< Searching for Routers or REEDs to attach to.
@@ -1565,6 +1566,7 @@ private:
otError HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessAnnounce(void);
otError SendParentRequest(ParentRequestType aType);
otError SendChildIdRequest(void);
@@ -1644,8 +1646,9 @@ private:
#endif
uint8_t mAnnounceChannel;
uint8_t mPreviousChannel;
uint16_t mPreviousPanId;
uint8_t mAlternateChannel;
uint16_t mAlternatePanId;
uint64_t mAlternateTimestamp;
Ip6::NetifUnicastAddress mLeaderAloc;
+1
View File
@@ -62,6 +62,7 @@ enum
kParentRequestRouterTimeout = 750, ///< Router Parent Request timeout
kParentRequestReedTimeout = 1250, ///< Router and REEDs Parent Request timeout
kParentRequestJitter = 50, ///< Maximum jitter time added to Parent Request timeout
kAnnounceProcessTimeout = 250, ///< Timeout after receiving Announcement before channel/pan-id change
kAnnounceTimeout = 1400, ///< Total timeout used for sending Announcement messages
kMinAnnounceDelay = 80, ///< Minimum delay between Announcement messages
kParentResponseMaxDelayRouters = 500, ///< Maximum delay for response for Parent Request sent to routers only