mirror of
https://github.com/espressif/openthread.git
synced 2026-09-10 19:20:06 +00:00
[mle] send shorter "Child ID Request" if needed to avoid frag (#3813)
This commit addresses the attach failure issue by an SED child trying to register multiple IPv6 addresses in MLE "Child ID Request" message. If the MLE "Child ID Request" requires fragmentation at 6LoWPAN layer, this commit changes the code to abort the transmission and drop the message and instead signal to MLE layer to prepare a shorter "Child ID Request" by only including the mesh-local address in the `Address Registration TLV`. After the child attaches, the new code will ensure to trigger a "Child Update Request" exchange for the child to register the remaining IPv6 addresses with its parents.
This commit is contained in:
committed by
Jonathan Hui
parent
06197eb7f5
commit
0b396918c1
@@ -393,15 +393,23 @@ exit:
|
||||
|
||||
bool Message::IsSubTypeMle(void) const
|
||||
{
|
||||
bool rval = false;
|
||||
bool rval;
|
||||
|
||||
if (mBuffer.mHead.mInfo.mSubType == kSubTypeMleAnnounce ||
|
||||
mBuffer.mHead.mInfo.mSubType == kSubTypeMleDiscoverRequest ||
|
||||
mBuffer.mHead.mInfo.mSubType == kSubTypeMleDiscoverResponse ||
|
||||
mBuffer.mHead.mInfo.mSubType == kSubTypeMleChildUpdateRequest ||
|
||||
mBuffer.mHead.mInfo.mSubType == kSubTypeMleDataResponse || mBuffer.mHead.mInfo.mSubType == kSubTypeMleGeneral)
|
||||
switch (mBuffer.mHead.mInfo.mSubType)
|
||||
{
|
||||
case kSubTypeMleGeneral:
|
||||
case kSubTypeMleAnnounce:
|
||||
case kSubTypeMleDiscoverRequest:
|
||||
case kSubTypeMleDiscoverResponse:
|
||||
case kSubTypeMleChildUpdateRequest:
|
||||
case kSubTypeMleDataResponse:
|
||||
case kSubTypeMleChildIdRequest:
|
||||
rval = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return rval;
|
||||
|
||||
+11
-10
@@ -218,16 +218,17 @@ public:
|
||||
|
||||
enum
|
||||
{
|
||||
kSubTypeNone = 0, ///< None
|
||||
kSubTypeMleAnnounce = 1, ///< MLE Announce
|
||||
kSubTypeMleDiscoverRequest = 2, ///< MLE Discover Request
|
||||
kSubTypeMleDiscoverResponse = 3, ///< MLE Discover Response
|
||||
kSubTypeJoinerEntrust = 4, ///< Joiner Entrust
|
||||
kSubTypeMplRetransmission = 5, ///< MPL next retransmission message
|
||||
kSubTypeMleGeneral = 6, ///< General MLE
|
||||
kSubTypeJoinerFinalizeResponse = 7, ///< Joiner Finalize Response
|
||||
kSubTypeMleChildUpdateRequest = 8, ///< MLE Child Update Request
|
||||
kSubTypeMleDataResponse = 9, ///< MLE Data Response
|
||||
kSubTypeNone = 0, ///< None
|
||||
kSubTypeMleAnnounce = 1, ///< MLE Announce
|
||||
kSubTypeMleDiscoverRequest = 2, ///< MLE Discover Request
|
||||
kSubTypeMleDiscoverResponse = 3, ///< MLE Discover Response
|
||||
kSubTypeJoinerEntrust = 4, ///< Joiner Entrust
|
||||
kSubTypeMplRetransmission = 5, ///< MPL next retransmission message
|
||||
kSubTypeMleGeneral = 6, ///< General MLE
|
||||
kSubTypeJoinerFinalizeResponse = 7, ///< Joiner Finalize Response
|
||||
kSubTypeMleChildUpdateRequest = 8, ///< MLE Child Update Request
|
||||
kSubTypeMleDataResponse = 9, ///< MLE Data Response
|
||||
kSubTypeMleChildIdRequest = 10, ///< MLE Child ID Request
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -568,6 +568,15 @@ otError MeshForwarder::HandleFrameRequest(Mac::Frame &aFrame)
|
||||
{
|
||||
// Enable security and try again.
|
||||
mSendMessage->SetLinkSecurityEnabled(true);
|
||||
|
||||
if (mSendMessage->GetSubType() == Message::kSubTypeMleChildIdRequest)
|
||||
{
|
||||
otLogNoteMac("Child ID Request requires fragmentation, aborting tx");
|
||||
mMessageNextOffset = mSendMessage->GetLength();
|
||||
error = OT_ERROR_ABORT;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
error = SendFragment(*mSendMessage, aFrame);
|
||||
}
|
||||
|
||||
@@ -1136,6 +1145,18 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, otError aError)
|
||||
|
||||
if (mSendMessage->GetDirectTransmission() == false && mSendMessage->IsChildPending() == false)
|
||||
{
|
||||
if (mSendMessage->GetSubType() == Message::kSubTypeMleChildIdRequest && mSendMessage->IsLinkSecurityEnabled())
|
||||
{
|
||||
// If the Child ID Request requires fragmentation and therefore
|
||||
// link layer security, the frame transmission will be aborted.
|
||||
// When the message is being freed, we signal to MLE to prepare a
|
||||
// shorter Child ID Request message (by only including mesh-local
|
||||
// address in the Address Registration TLV).
|
||||
|
||||
otLogInfoMac("Requesting shorter `Child ID Request`");
|
||||
Get<Mle::Mle>().RequestShorterChildIdRequest();
|
||||
}
|
||||
|
||||
mSendQueue.Dequeue(*mSendMessage);
|
||||
mSendMessage->Free();
|
||||
mSendMessage = NULL;
|
||||
|
||||
+50
-6
@@ -85,6 +85,7 @@ Mle::Mle(Instance &aInstance)
|
||||
, mChildUpdateRequestState(kChildUpdateRequestNone)
|
||||
, mDataRequestAttempts(0)
|
||||
, mDataRequestState(kDataRequestNone)
|
||||
, mAddressRegistrationMode(kAppendAllAddresses)
|
||||
, mParentLinkMargin(0)
|
||||
, mParentIsSingleton(false)
|
||||
, mReceivedResponseFromParent(false)
|
||||
@@ -1302,12 +1303,13 @@ otError Mle::AppendVersion(Message &aMessage)
|
||||
return aMessage.AppendTlv(tlv);
|
||||
}
|
||||
|
||||
otError Mle::AppendAddressRegistration(Message &aMessage)
|
||||
otError Mle::AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Tlv tlv;
|
||||
AddressRegistrationEntry entry;
|
||||
Lowpan::Context context;
|
||||
bool done = false;
|
||||
uint8_t length = 0;
|
||||
uint8_t counter = 0;
|
||||
uint16_t startOffset = aMessage.GetLength();
|
||||
@@ -1315,7 +1317,6 @@ otError Mle::AppendAddressRegistration(Message &aMessage)
|
||||
tlv.SetType(Tlv::kAddressRegistration);
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
|
||||
|
||||
// write entries to message
|
||||
for (const Ip6::NetifUnicastAddress *addr = Get<ThreadNetif>().GetUnicastAddresses(); addr; addr = addr->GetNext())
|
||||
{
|
||||
if (addr->GetAddress().IsLinkLocal() || IsRoutingLocator(addr->GetAddress()) ||
|
||||
@@ -1324,6 +1325,17 @@ otError Mle::AppendAddressRegistration(Message &aMessage)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aMode == kAppendMeshLocalOnly)
|
||||
{
|
||||
if (addr->GetAddress() != GetMeshLocal64())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set `done` to `true` to exit after the address is appended.
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (Get<NetworkData::Leader>().GetContext(addr->GetAddress(), context) == OT_ERROR_NONE)
|
||||
{
|
||||
// compressed entry
|
||||
@@ -1341,7 +1353,7 @@ otError Mle::AppendAddressRegistration(Message &aMessage)
|
||||
length += entry.GetLength();
|
||||
counter++;
|
||||
// only continue to append if there is available entry.
|
||||
VerifyOrExit(counter < OPENTHREAD_CONFIG_IP_ADDRS_TO_REGISTER);
|
||||
VerifyOrExit(!done && (counter < OPENTHREAD_CONFIG_IP_ADDRS_TO_REGISTER));
|
||||
}
|
||||
|
||||
// For sleepy end device, register external multicast addresses to the parent for indirect transmission
|
||||
@@ -1450,6 +1462,21 @@ void Mle::HandleStateChanged(otChangedFlags aFlags)
|
||||
{
|
||||
VerifyOrExit(mRole != OT_DEVICE_ROLE_DISABLED);
|
||||
|
||||
if (aFlags & OT_CHANGED_THREAD_ROLE)
|
||||
{
|
||||
if (mRole == OT_DEVICE_ROLE_CHILD && !IsFullThreadDevice() && mAddressRegistrationMode == kAppendMeshLocalOnly)
|
||||
{
|
||||
// If only mesh-local address was registered in the "Child
|
||||
// ID Request" message, after device is attached, trigger a
|
||||
// "Child Update Request" to register the remaining
|
||||
// addresses.
|
||||
|
||||
mAddressRegistrationMode = kAppendAllAddresses;
|
||||
mChildUpdateRequestState = kChildUpdateRequestPending;
|
||||
ScheduleMessageTransmissionTimer();
|
||||
}
|
||||
}
|
||||
|
||||
if ((aFlags & (OT_CHANGED_IP6_ADDRESS_ADDED | OT_CHANGED_IP6_ADDRESS_REMOVED)) != 0)
|
||||
{
|
||||
if (!Get<ThreadNetif>().IsUnicastAddress(mMeshLocal64.GetAddress()))
|
||||
@@ -1954,6 +1981,15 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Mle::RequestShorterChildIdRequest(void)
|
||||
{
|
||||
if (mAttachState == kAttachStateChildIdRequest)
|
||||
{
|
||||
mAddressRegistrationMode = kAppendMeshLocalOnly;
|
||||
SendChildIdRequest();
|
||||
}
|
||||
}
|
||||
|
||||
otError Mle::SendChildIdRequest(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -1981,6 +2017,7 @@ otError Mle::SendChildIdRequest(void)
|
||||
}
|
||||
|
||||
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
message->SetSubType(Message::kSubTypeMleChildIdRequest);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildIdRequest));
|
||||
SuccessOrExit(error = AppendResponse(*message, mChildIdRequest.mChallenge, mChildIdRequest.mChallengeLength));
|
||||
SuccessOrExit(error = AppendLinkFrameCounter(*message));
|
||||
@@ -1991,7 +2028,7 @@ otError Mle::SendChildIdRequest(void)
|
||||
|
||||
if (!IsFullThreadDevice())
|
||||
{
|
||||
SuccessOrExit(error = AppendAddressRegistration(*message));
|
||||
SuccessOrExit(error = AppendAddressRegistration(*message, mAddressRegistrationMode));
|
||||
|
||||
// no need to request the last Route64 TLV for MTD
|
||||
tlvsLen -= 1;
|
||||
@@ -2007,8 +2044,15 @@ otError Mle::SendChildIdRequest(void)
|
||||
destination.mFields.m16[0] = HostSwap16(0xfe80);
|
||||
destination.SetIid(mParentCandidate.GetExtAddress());
|
||||
SuccessOrExit(error = SendMessage(*message, destination));
|
||||
LogMleMessage("Send Child ID Request", destination);
|
||||
;
|
||||
|
||||
if (mAddressRegistrationMode == kAppendMeshLocalOnly)
|
||||
{
|
||||
LogMleMessage("Send Child ID Request - short", destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMleMessage("Send Child ID Request", destination);
|
||||
}
|
||||
|
||||
if (!IsRxOnWhenIdle())
|
||||
{
|
||||
|
||||
+25
-1
@@ -1072,6 +1072,16 @@ public:
|
||||
*/
|
||||
void RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* This method requests MLE layer to prepare and send a shorter version of Child ID Request message by only
|
||||
* including the mesh-local IPv6 address in the Address Registration TLV.
|
||||
*
|
||||
* This method should be called when a previous MLE Child ID Request message would require fragmentation at 6LoWPAN
|
||||
* layer.
|
||||
*
|
||||
*/
|
||||
void RequestShorterChildIdRequest(void);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* States during attach (when searching for a parent).
|
||||
@@ -1105,6 +1115,17 @@ protected:
|
||||
kMleMaxResponseDelay = 1000u, ///< Maximum delay before responding to a multicast request.
|
||||
};
|
||||
|
||||
/**
|
||||
* This enumeration type is used in `AppendAddressRegistration()` to determine which addresses to include in the
|
||||
* appended Address Registration TLV.
|
||||
*
|
||||
*/
|
||||
enum AddressRegistrationMode
|
||||
{
|
||||
kAppendAllAddresses, ///< Append all addresses (unicast/multicast) in Address Registration TLV.
|
||||
kAppendMeshLocalOnly, ///< Only append the Mesh Local (ML-EID) address in Address Registration TLV.
|
||||
};
|
||||
|
||||
/**
|
||||
* This method allocates a new message buffer for preparing an MLE message.
|
||||
*
|
||||
@@ -1323,12 +1344,13 @@ protected:
|
||||
* This method appends an Address Registration TLV to a message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aMode Determines which addresses to include in the TLV (see `AddressRegistrationMode`).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully appended the Address Registration TLV.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Address Registration TLV.
|
||||
*
|
||||
*/
|
||||
otError AppendAddressRegistration(Message &aMessage);
|
||||
otError AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode = kAppendAllAddresses);
|
||||
|
||||
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
|
||||
/**
|
||||
@@ -1755,6 +1777,8 @@ private:
|
||||
uint8_t mDataRequestAttempts;
|
||||
DataRequestState mDataRequestState;
|
||||
|
||||
AddressRegistrationMode mAddressRegistrationMode;
|
||||
|
||||
uint8_t mParentLinkMargin;
|
||||
bool mParentIsSingleton;
|
||||
bool mReceivedResponseFromParent;
|
||||
|
||||
@@ -2089,6 +2089,7 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
|
||||
|
||||
// Remove existing MLE messages
|
||||
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleGeneral);
|
||||
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleChildIdRequest);
|
||||
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleChildUpdateRequest);
|
||||
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleDataResponse);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user