[mle] send a unicast MLE Announce in response to a received Announce (#2669)

This commit changes how MLE Announce messages are sent in response to
a received MLE Announce. In addition to a multicast MLE Announce
message, a unicast MLE Announce is also sent. This behavior can be
controlled using `OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE`
config option. By default this is enabled.

This commit also changes actions taken after receiving an MLE Announce
in `Mle::HandleAnnounce()` to handle the situation where a device may
receive multiple MLE Announce messages with same info. No action is
taken if the device is detached, and current channel and panid match
the values from the received MLE Announce message.
This commit is contained in:
Abtin Keshavarzian
2018-04-19 09:29:18 -07:00
committed by Jonathan Hui
parent 51d487ed57
commit dc16c5e694
3 changed files with 54 additions and 17 deletions
+13
View File
@@ -1327,6 +1327,19 @@
#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -65
#endif
/**
* @def OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE
*
* Define as 1 to enable sending of a unicast MLE Announce message in response to a received Announce message from
* a device.
*
* @note The unicast MLE announce message is sent in addition to (and after) the multicast MLE Announce.
*
*/
#ifndef OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE
#define OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE 1
#endif
/**
* @def OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
*
+40 -17
View File
@@ -1979,13 +1979,23 @@ exit:
}
otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce)
{
Ip6::Address destination;
memset(&destination, 0, sizeof(destination));
destination.mFields.m16[0] = HostSwap16(0xff02);
destination.mFields.m16[7] = HostSwap16(0x0001);
return SendAnnounce(aChannel, aOrphanAnnounce, destination);
}
otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Address &aDestination)
{
ThreadNetif & netif = GetNetif();
otError error = OT_ERROR_NONE;
ChannelTlv channel;
PanIdTlv panid;
ActiveTimestampTlv activeTimestamp;
Ip6::Address destination;
Message * message;
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
@@ -2016,11 +2026,7 @@ otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce)
panid.Init();
panid.SetPanId(netif.GetMac().GetPanId());
SuccessOrExit(error = message->Append(&panid, sizeof(panid)));
memset(&destination, 0, sizeof(destination));
destination.mFields.m16[0] = HostSwap16(0xff02);
destination.mFields.m16[7] = HostSwap16(0x0001);
SuccessOrExit(error = SendMessage(*message, destination));
SuccessOrExit(error = SendMessage(*message, aDestination));
otLogInfoMle(GetInstance(), "Send Announce on channel %d", aChannel);
@@ -3188,36 +3194,53 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
{
ThreadNetif & netif = GetNetif();
otError error = OT_ERROR_NONE;
ChannelTlv channel;
ChannelTlv channelTlv;
ActiveTimestampTlv timestamp;
const MeshCoP::Timestamp *localTimestamp;
PanIdTlv panid;
PanIdTlv panIdTlv;
uint8_t channel;
uint16_t panId;
LogMleMessage("Receive Announce", aMessageInfo.GetPeerAddr());
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kChannel, sizeof(channel), channel));
VerifyOrExit(channel.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kChannel, sizeof(channelTlv), channelTlv));
VerifyOrExit(channelTlv.IsValid(), error = OT_ERROR_PARSE);
channel = static_cast<uint8_t>(channelTlv.GetChannel());
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kActiveTimestamp, sizeof(timestamp), timestamp));
VerifyOrExit(timestamp.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kPanId, sizeof(panid), panid));
VerifyOrExit(panid.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kPanId, sizeof(panIdTlv), panIdTlv));
VerifyOrExit(panIdTlv.IsValid(), error = OT_ERROR_PARSE);
panId = panIdTlv.GetPanId();
localTimestamp = netif.GetActiveDataset().GetTimestamp();
if (localTimestamp == NULL || localTimestamp->Compare(timestamp) > 0)
{
uint8_t curChannel = netif.GetMac().GetChannel();
uint16_t curPanId = netif.GetMac().GetPanId();
// 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));
Stop(false);
mPreviousChannel = netif.GetMac().GetChannel();
mPreviousPanId = netif.GetMac().GetPanId();
netif.GetMac().SetChannel(static_cast<uint8_t>(channel.GetChannel()));
netif.GetMac().SetPanId(panid.GetPanId());
mPreviousChannel = curChannel;
mPreviousPanId = curPanId;
netif.GetMac().SetChannel(channel);
netif.GetMac().SetPanId(panId);
Start(false, true);
}
else if (localTimestamp->Compare(timestamp) < 0)
{
SendAnnounce(static_cast<uint8_t>(channel.GetChannel()), false);
SendAnnounce(channel, false);
#if OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE
SendAnnounce(channel, false, aMessageInfo.GetPeerAddr());
#endif
}
else
{
+1
View File
@@ -1483,6 +1483,7 @@ private:
otError SendParentRequest(void);
otError SendChildIdRequest(void);
void SendOrphanAnnounce(void);
otError SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Address &aDestination);
bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, uint8_t aLinkMargin, ConnectivityTlv &aConnectivityTlv);
void ResetParentCandidate(void);