mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 15:47:46 +00:00
[mle] add TlvList to track list of TLV types (#8008)
This commit adds `Mle::TlvList` type which represents a list of MLE TLV types. It provides helper methods to `Add()` TLVs to the list ensuring that any TLV type is included only once. The `TlvList` is used when parsing "TLV Request TLV" or preparing which TLVs to include in an MLE message.
This commit is contained in:
@@ -186,6 +186,30 @@ public:
|
||||
*/
|
||||
IndexType GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* This methods sets the current length (number of elements) of the array.
|
||||
*
|
||||
* @param[in] aLength The array length.
|
||||
*
|
||||
*/
|
||||
void SetLength(IndexType aLength) { mLength = aLength; }
|
||||
|
||||
/**
|
||||
* This method returns the pointer to the start of underlying C array buffer serving as `Array` storage.
|
||||
*
|
||||
* @return The pointer to start of underlying C array buffer.
|
||||
*
|
||||
*/
|
||||
Type *GetArrayBuffer(void) { return mElements; }
|
||||
|
||||
/**
|
||||
* This method returns the pointer to the start of underlying C array buffer serving as `Array` storage.
|
||||
*
|
||||
* @return The pointer to start of underlying C array buffer.
|
||||
*
|
||||
*/
|
||||
const Type *GetArrayBuffer(void) const { return mElements; }
|
||||
|
||||
/**
|
||||
* This method overloads the `[]` operator to get the element at a given index.
|
||||
*
|
||||
|
||||
+45
-33
@@ -2056,7 +2056,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge)
|
||||
Error Mle::SendChildUpdateResponse(const TlvList &aTlvList, const Challenge &aChallenge)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Ip6::Address destination;
|
||||
@@ -2067,9 +2067,9 @@ Error Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const
|
||||
SuccessOrExit(error = message->AppendSourceAddressTlv());
|
||||
SuccessOrExit(error = message->AppendLeaderDataTlv());
|
||||
|
||||
for (int i = 0; i < aNumTlvs; i++)
|
||||
for (uint8_t tlvType : aTlvList)
|
||||
{
|
||||
switch (aTlvs[i])
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kTimeout:
|
||||
SuccessOrExit(error = message->AppendTimeoutTlv(mTimeout));
|
||||
@@ -3422,14 +3422,11 @@ exit:
|
||||
|
||||
void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
static const uint8_t kMaxResponseTlvs = 6;
|
||||
|
||||
Error error = kErrorNone;
|
||||
uint16_t sourceAddress;
|
||||
Challenge challenge;
|
||||
RequestedTlvs requestedTlvs;
|
||||
uint8_t tlvs[kMaxResponseTlvs];
|
||||
uint8_t numTlvs = 0;
|
||||
Error error = kErrorNone;
|
||||
uint16_t sourceAddress;
|
||||
Challenge challenge;
|
||||
TlvList requestedTlvList;
|
||||
TlvList tlvList;
|
||||
|
||||
// Source Address
|
||||
SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
|
||||
@@ -3440,9 +3437,9 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
switch (aRxInfo.mMessage.ReadChallengeTlv(challenge))
|
||||
{
|
||||
case kErrorNone:
|
||||
tlvs[numTlvs++] = Tlv::kResponse;
|
||||
tlvs[numTlvs++] = Tlv::kMleFrameCounter;
|
||||
tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
|
||||
tlvList.Add(Tlv::kResponse);
|
||||
tlvList.Add(Tlv::kMleFrameCounter);
|
||||
tlvList.Add(Tlv::kLinkFrameCounter);
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
challenge.mLength = 0;
|
||||
@@ -3480,30 +3477,21 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
if (Tlv::FindTlv(aRxInfo.mMessage, cslClockAccuracyTlv) == kErrorNone)
|
||||
{
|
||||
// MUST include CSL timeout TLV when request includes CSL accuracy
|
||||
tlvs[numTlvs++] = Tlv::kCslTimeout;
|
||||
tlvList.Add(Tlv::kCslTimeout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// this device is not a child of the Child Update Request source
|
||||
tlvs[numTlvs++] = Tlv::kStatus;
|
||||
tlvList.Add(Tlv::kStatus);
|
||||
}
|
||||
|
||||
// TLV Request
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
|
||||
{
|
||||
case kErrorNone:
|
||||
for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
|
||||
{
|
||||
if (numTlvs >= sizeof(tlvs))
|
||||
{
|
||||
LogWarn("Failed to respond with TLVs: %d of %d", i, requestedTlvs.mNumTlvs);
|
||||
break;
|
||||
}
|
||||
|
||||
tlvs[numTlvs++] = requestedTlvs.mTlvs[i];
|
||||
}
|
||||
tlvList.AddElementsFrom(requestedTlvList);
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
break;
|
||||
@@ -3520,7 +3508,7 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge));
|
||||
SuccessOrExit(error = SendChildUpdateResponse(tlvList, challenge));
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeChildUpdateRequestOfParent, error);
|
||||
@@ -4400,6 +4388,30 @@ void Mle::HandleDetachGracefullyAddressReleaseResponse(void)
|
||||
}
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// TlvList
|
||||
|
||||
void Mle::TlvList::Add(uint8_t aTlvType)
|
||||
{
|
||||
VerifyOrExit(!Contains(aTlvType));
|
||||
|
||||
if (PushBack(aTlvType) != kErrorNone)
|
||||
{
|
||||
LogWarn("Failed to include TLV %d", aTlvType);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::TlvList::AddElementsFrom(const TlvList &aTlvList)
|
||||
{
|
||||
for (uint8_t tlvType : aTlvList)
|
||||
{
|
||||
Add(tlvType);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Challenge
|
||||
|
||||
@@ -5031,7 +5043,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::RxMessage::ReadTlvRequestTlv(RequestedTlvs &aRequestedTlvs) const
|
||||
Error Mle::RxMessage::ReadTlvRequestTlv(TlvList &aTlvList) const
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
@@ -5039,13 +5051,13 @@ Error Mle::RxMessage::ReadTlvRequestTlv(RequestedTlvs &aRequestedTlvs) const
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, Tlv::kTlvRequest, offset, length));
|
||||
|
||||
if (length > sizeof(aRequestedTlvs.mTlvs))
|
||||
if (length > aTlvList.GetMaxSize())
|
||||
{
|
||||
length = sizeof(aRequestedTlvs.mTlvs);
|
||||
length = aTlvList.GetMaxSize();
|
||||
}
|
||||
|
||||
ReadBytes(offset, aRequestedTlvs.mTlvs, length);
|
||||
aRequestedTlvs.mNumTlvs = static_cast<uint8_t>(length);
|
||||
ReadBytes(offset, aTlvList.GetArrayBuffer(), length);
|
||||
aTlvList.SetLength(static_cast<uint8_t>(length));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
+38
-17
@@ -903,6 +903,40 @@ protected:
|
||||
#endif
|
||||
};
|
||||
|
||||
static constexpr uint8_t kMaxTlvListSize = 16; ///< Maximum number of TLVs in a `TlvList`.
|
||||
|
||||
/**
|
||||
* This type represents a list of TLVs (array of TLV types).
|
||||
*
|
||||
*/
|
||||
class TlvList : public Array<uint8_t, kMaxTlvListSize>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the `TlvList` as empty.
|
||||
*
|
||||
*/
|
||||
TlvList(void) = default;
|
||||
|
||||
/**
|
||||
* This method checks if a given TLV type is not already present in the list and adds it in the list.
|
||||
*
|
||||
* If the list is full, this method logs it as a warning.
|
||||
*
|
||||
* @param[in] aTlvType The TLV type to add to the list.
|
||||
*
|
||||
*/
|
||||
void Add(uint8_t aTlvType);
|
||||
|
||||
/**
|
||||
* This method adds elements from a given list to this TLV list (if not already present in the list).
|
||||
*
|
||||
* @param[in] aTlvList The TLV list to add elements from.
|
||||
*
|
||||
*/
|
||||
void AddElementsFrom(const TlvList &aTlvList);
|
||||
};
|
||||
|
||||
/**
|
||||
* This type represents a Challenge (or Response) data.
|
||||
*
|
||||
@@ -942,18 +976,6 @@ protected:
|
||||
bool operator==(const Challenge &aOther) const { return Matches(aOther.mBuffer, aOther.mLength); }
|
||||
};
|
||||
|
||||
/**
|
||||
* This type represents list of requested TLVs in a TLV Request TLV.
|
||||
*
|
||||
*/
|
||||
struct RequestedTlvs
|
||||
{
|
||||
static constexpr uint8_t kMaxNumTlvs = 16; ///< Maximum number of TLVs in request array.
|
||||
|
||||
uint8_t mTlvs[kMaxNumTlvs]; ///< Array of requested TLVs.
|
||||
uint8_t mNumTlvs; ///< Number of TLVs in the array.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents an MLE Tx message.
|
||||
*
|
||||
@@ -1360,14 +1382,14 @@ protected:
|
||||
/**
|
||||
* This method reads TLV Request TLV from the message.
|
||||
*
|
||||
* @param[out] aRequestedTlvs A reference to output the read list of requested TLVs.
|
||||
* @param[out] aTlvList A reference to output the read list of requested TLVs.
|
||||
*
|
||||
* @retval kErrorNone Successfully read the TLV.
|
||||
* @retval kErrorNotFound TLV was not found in the message.
|
||||
* @retval kErrorParse TLV was found but could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error ReadTlvRequestTlv(RequestedTlvs &aRequestedTlvs) const;
|
||||
Error ReadTlvRequestTlv(TlvList &aTlvList) const;
|
||||
|
||||
/**
|
||||
* This method reads Leader Data TLV from a message.
|
||||
@@ -1538,15 +1560,14 @@ protected:
|
||||
/**
|
||||
* This method generates an MLE Child Update Response message.
|
||||
*
|
||||
* @param[in] aTlvs A pointer to requested TLV types.
|
||||
* @param[in] aNumTlvs The number of TLV types in @p aTlvs.
|
||||
* @param[in] aTlvList A list of requested TLV types.
|
||||
* @param[in] aChallenge The Challenge for the response.
|
||||
*
|
||||
* @retval kErrorNone Successfully generated an MLE Child Update Response message.
|
||||
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Response message.
|
||||
*
|
||||
*/
|
||||
Error SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge);
|
||||
Error SendChildUpdateResponse(const TlvList &aTlvList, const Challenge &aChallenge);
|
||||
|
||||
/**
|
||||
* This method sets the RLOC16 assigned to the Thread interface.
|
||||
|
||||
+97
-102
@@ -631,13 +631,13 @@ exit:
|
||||
|
||||
void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Neighbor * neighbor = nullptr;
|
||||
Challenge challenge;
|
||||
uint16_t version;
|
||||
LeaderData leaderData;
|
||||
uint16_t sourceAddress;
|
||||
RequestedTlvs requestedTlvs;
|
||||
Error error = kErrorNone;
|
||||
Neighbor * neighbor = nullptr;
|
||||
Challenge challenge;
|
||||
uint16_t version;
|
||||
LeaderData leaderData;
|
||||
uint16_t sourceAddress;
|
||||
TlvList requestedTlvList;
|
||||
|
||||
Log(kMessageReceive, kTypeLinkRequest, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
@@ -708,12 +708,10 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
}
|
||||
|
||||
// TLV Request
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
|
||||
{
|
||||
case kErrorNone:
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
requestedTlvs.mNumTlvs = 0;
|
||||
break;
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
@@ -735,7 +733,7 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
|
||||
SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, neighbor, requestedTlvs, challenge));
|
||||
SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, neighbor, requestedTlvList, challenge));
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeLinkRequest, error);
|
||||
@@ -743,7 +741,7 @@ exit:
|
||||
|
||||
Error MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
|
||||
Neighbor * aNeighbor,
|
||||
const RequestedTlvs & aRequestedTlvs,
|
||||
const TlvList & aRequestedTlvList,
|
||||
const Challenge & aChallenge)
|
||||
{
|
||||
static const uint8_t kRouterTlvs[] = {Tlv::kLinkMargin};
|
||||
@@ -773,9 +771,9 @@ Error MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
|
||||
SuccessOrExit(error = message->AppendLeaderDataTlv());
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < aRequestedTlvs.mNumTlvs; i++)
|
||||
for (uint8_t tlvType : aRequestedTlvList)
|
||||
{
|
||||
switch (aRequestedTlvs.mTlvs[i])
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kRoute:
|
||||
SuccessOrExit(error = message->AppendRouteTlv(aNeighbor));
|
||||
@@ -1033,25 +1031,23 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
|
||||
if (aRequest)
|
||||
{
|
||||
Challenge challenge;
|
||||
RequestedTlvs requestedTlvs;
|
||||
Challenge challenge;
|
||||
TlvList requestedTlvList;
|
||||
|
||||
// Challenge
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
|
||||
|
||||
// TLV Request
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
|
||||
{
|
||||
case kErrorNone:
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
requestedTlvs.mNumTlvs = 0;
|
||||
break;
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, router, requestedTlvs, challenge));
|
||||
SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, router, requestedTlvList, challenge));
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -2347,7 +2343,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||
uint8_t modeBitmask;
|
||||
DeviceMode mode;
|
||||
uint32_t timeout;
|
||||
RequestedTlvs requestedTlvs;
|
||||
TlvList requestedTlvList;
|
||||
MeshCoP::Timestamp timestamp;
|
||||
bool needsActiveDatasetTlv;
|
||||
bool needsPendingDatasetTlv;
|
||||
@@ -2394,8 +2390,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||
SuccessOrExit(error = Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout));
|
||||
|
||||
// TLV Request
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs));
|
||||
VerifyOrExit(requestedTlvs.mNumTlvs <= Child::kMaxRequestTlvs, error = kErrorParse);
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList));
|
||||
|
||||
// Active Timestamp
|
||||
needsActiveDatasetTlv = true;
|
||||
@@ -2425,6 +2420,20 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
numTlvs = requestedTlvList.GetLength();
|
||||
|
||||
if (needsActiveDatasetTlv)
|
||||
{
|
||||
numTlvs++;
|
||||
}
|
||||
|
||||
if (needsPendingDatasetTlv)
|
||||
{
|
||||
numTlvs++;
|
||||
}
|
||||
|
||||
VerifyOrExit(numTlvs <= Child::kMaxRequestTlvs, error = kErrorParse);
|
||||
|
||||
if (!mode.IsFullThreadDevice())
|
||||
{
|
||||
SuccessOrExit(error =
|
||||
@@ -2465,9 +2474,9 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||
child->SetNetworkDataVersion(mLeaderData.GetDataVersion(mode.GetNetworkDataType()));
|
||||
child->ClearRequestTlvs();
|
||||
|
||||
for (numTlvs = 0; numTlvs < requestedTlvs.mNumTlvs; numTlvs++)
|
||||
for (numTlvs = 0; numTlvs < requestedTlvList.GetLength(); numTlvs++)
|
||||
{
|
||||
child->SetRequestTlv(numTlvs, requestedTlvs.mTlvs[numTlvs]);
|
||||
child->SetRequestTlv(numTlvs, requestedTlvList[numTlvs]);
|
||||
}
|
||||
|
||||
if (needsActiveDatasetTlv)
|
||||
@@ -2506,8 +2515,6 @@ exit:
|
||||
|
||||
void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
static const uint8_t kMaxResponseTlvs = 10;
|
||||
|
||||
Error error = kErrorNone;
|
||||
Mac::ExtAddress extAddr;
|
||||
uint8_t modeBitmask;
|
||||
@@ -2517,9 +2524,8 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
uint32_t timeout;
|
||||
Child * child;
|
||||
DeviceMode oldMode;
|
||||
RequestedTlvs requestedTlvs;
|
||||
uint8_t tlvs[kMaxResponseTlvs];
|
||||
uint8_t tlvslength = 0;
|
||||
TlvList requestedTlvList;
|
||||
TlvList tlvList;
|
||||
uint16_t addressRegistrationOffset = 0;
|
||||
bool childDidChange = false;
|
||||
|
||||
@@ -2533,7 +2539,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
switch (aRxInfo.mMessage.ReadChallengeTlv(challenge))
|
||||
{
|
||||
case kErrorNone:
|
||||
tlvs[tlvslength++] = Tlv::kResponse;
|
||||
tlvList.Add(Tlv::kResponse);
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
challenge.mLength = 0;
|
||||
@@ -2542,7 +2548,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
tlvs[tlvslength++] = Tlv::kSourceAddress;
|
||||
tlvList.Add(Tlv::kSourceAddress);
|
||||
|
||||
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
|
||||
child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
|
||||
@@ -2553,8 +2559,8 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
// Status TLV (error).
|
||||
if (mode.IsRxOnWhenIdle())
|
||||
{
|
||||
tlvs[tlvslength++] = Tlv::kStatus;
|
||||
SendChildUpdateResponse(nullptr, aRxInfo.mMessageInfo, tlvs, tlvslength, challenge);
|
||||
tlvList.Add(Tlv::kStatus);
|
||||
SendChildUpdateResponse(nullptr, aRxInfo.mMessageInfo, tlvList, challenge);
|
||||
}
|
||||
|
||||
ExitNow();
|
||||
@@ -2571,22 +2577,22 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
oldMode = child->GetDeviceMode();
|
||||
child->SetDeviceMode(mode);
|
||||
|
||||
tlvs[tlvslength++] = Tlv::kMode;
|
||||
tlvList.Add(Tlv::kMode);
|
||||
|
||||
// Parent MUST include Leader Data TLV in Child Update Response
|
||||
tlvs[tlvslength++] = Tlv::kLeaderData;
|
||||
tlvList.Add(Tlv::kLeaderData);
|
||||
|
||||
if (challenge.mLength != 0)
|
||||
{
|
||||
tlvs[tlvslength++] = Tlv::kMleFrameCounter;
|
||||
tlvs[tlvslength++] = Tlv::kLinkFrameCounter;
|
||||
tlvList.Add(Tlv::kMleFrameCounter);
|
||||
tlvList.Add(Tlv::kLinkFrameCounter);
|
||||
}
|
||||
|
||||
// IPv6 Address TLV
|
||||
if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
|
||||
{
|
||||
SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, addressRegistrationOffset, *child));
|
||||
tlvs[tlvslength++] = Tlv::kAddressRegistration;
|
||||
tlvList.Add(Tlv::kAddressRegistration);
|
||||
}
|
||||
|
||||
// Leader Data
|
||||
@@ -2611,7 +2617,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
childDidChange = true;
|
||||
}
|
||||
|
||||
tlvs[tlvslength++] = Tlv::kTimeout;
|
||||
tlvList.Add(Tlv::kTimeout);
|
||||
break;
|
||||
|
||||
case kErrorNotFound:
|
||||
@@ -2622,18 +2628,10 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
}
|
||||
|
||||
// TLV Request
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
|
||||
{
|
||||
case kErrorNone:
|
||||
VerifyOrExit(requestedTlvs.mNumTlvs <= (kMaxResponseTlvs - tlvslength), error = kErrorParse);
|
||||
for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
|
||||
{
|
||||
// Skip LeaderDataTlv since it is already included by default.
|
||||
if (requestedTlvs.mTlvs[i] != Tlv::kLeaderData)
|
||||
{
|
||||
tlvs[tlvslength++] = requestedTlvs.mTlvs[i];
|
||||
}
|
||||
}
|
||||
tlvList.AddElementsFrom(requestedTlvList);
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
break;
|
||||
@@ -2652,7 +2650,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
case kErrorNone:
|
||||
child->SetCslTimeout(cslTimeout);
|
||||
// MUST include CSL accuracy TLV when request includes CSL timeout
|
||||
tlvs[tlvslength++] = Tlv::kCslClockAccuracy;
|
||||
tlvList.Add(Tlv::kCslClockAccuracy);
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
break;
|
||||
@@ -2712,7 +2710,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
SendChildUpdateResponse(child, aRxInfo.mMessageInfo, tlvs, tlvslength, challenge);
|
||||
SendChildUpdateResponse(child, aRxInfo.mMessageInfo, tlvList, challenge);
|
||||
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
|
||||
@@ -2858,22 +2856,15 @@ exit:
|
||||
void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
RequestedTlvs requestedTlvs;
|
||||
TlvList tlvList;
|
||||
MeshCoP::Timestamp timestamp;
|
||||
uint8_t tlvs[4];
|
||||
uint8_t numTlvs;
|
||||
|
||||
Log(kMessageReceive, kTypeDataRequest, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid(), error = kErrorSecurity);
|
||||
|
||||
// TLV Request
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs));
|
||||
VerifyOrExit(requestedTlvs.mNumTlvs <= sizeof(tlvs), error = kErrorParse);
|
||||
|
||||
memset(tlvs, Tlv::kInvalid, sizeof(tlvs));
|
||||
memcpy(tlvs, requestedTlvs.mTlvs, requestedTlvs.mNumTlvs);
|
||||
numTlvs = requestedTlvs.mNumTlvs;
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(tlvList));
|
||||
|
||||
// Active Timestamp
|
||||
switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
|
||||
@@ -2887,10 +2878,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kErrorNotFound:
|
||||
if (numTlvs < sizeof(tlvs))
|
||||
{
|
||||
tlvs[numTlvs++] = Tlv::kActiveDataset;
|
||||
}
|
||||
tlvList.Add(Tlv::kActiveDataset);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2909,10 +2897,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kErrorNotFound:
|
||||
if (numTlvs < sizeof(tlvs))
|
||||
{
|
||||
tlvs[numTlvs++] = Tlv::kPendingDataset;
|
||||
}
|
||||
tlvList.Add(Tlv::kPendingDataset);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2921,7 +2906,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
|
||||
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
|
||||
SendDataResponse(aRxInfo.mMessageInfo.GetPeerAddr(), tlvs, numTlvs, 0, &aRxInfo.mMessage);
|
||||
SendDataResponse(aRxInfo.mMessageInfo.GetPeerAddr(), tlvList, /* aDelay */ 0, &aRxInfo.mMessage);
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeDataRequest, error);
|
||||
@@ -2929,17 +2914,17 @@ exit:
|
||||
|
||||
void MleRouter::HandleNetworkDataUpdateRouter(void)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kNetworkData};
|
||||
|
||||
Ip6::Address destination;
|
||||
uint16_t delay;
|
||||
TlvList tlvList;
|
||||
|
||||
VerifyOrExit(IsRouterOrLeader());
|
||||
|
||||
destination.SetToLinkLocalAllNodesMulticast();
|
||||
tlvList.Add(Tlv::kNetworkData);
|
||||
|
||||
delay = IsLeader() ? 0 : Random::NonCrypto::GetUint16InRange(0, kUnsolicitedDataResponseJitter);
|
||||
SendDataResponse(destination, kTlvs, sizeof(kTlvs), delay);
|
||||
SendDataResponse(destination, tlvList, delay);
|
||||
|
||||
SynchronizeChildNetworkData();
|
||||
|
||||
@@ -3329,8 +3314,7 @@ exit:
|
||||
|
||||
void MleRouter::SendChildUpdateResponse(Child * aChild,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
const TlvList & aTlvList,
|
||||
const Challenge & aChallenge)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -3338,22 +3322,51 @@ void MleRouter::SendChildUpdateResponse(Child * aChild,
|
||||
|
||||
VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
for (int i = 0; i < aTlvsLength; i++)
|
||||
for (uint8_t tlvType : aTlvList)
|
||||
{
|
||||
switch (aTlvs[i])
|
||||
// Add all TLV types that do not depend on `child`
|
||||
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kStatus:
|
||||
SuccessOrExit(error = message->AppendStatusTlv(StatusTlv::kError));
|
||||
break;
|
||||
|
||||
case Tlv::kAddressRegistration:
|
||||
SuccessOrExit(error = message->AppendAddresseRegisterationTlv(*aChild));
|
||||
break;
|
||||
|
||||
case Tlv::kLeaderData:
|
||||
SuccessOrExit(error = message->AppendLeaderDataTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kResponse:
|
||||
SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
|
||||
break;
|
||||
|
||||
case Tlv::kSourceAddress:
|
||||
SuccessOrExit(error = message->AppendSourceAddressTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kMleFrameCounter:
|
||||
SuccessOrExit(error = message->AppendMleFrameCounterTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kLinkFrameCounter:
|
||||
SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure `child` is not null before adding TLV types
|
||||
// that can depend on it.
|
||||
|
||||
if (aChild == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kAddressRegistration:
|
||||
SuccessOrExit(error = message->AppendAddresseRegisterationTlv(*aChild));
|
||||
break;
|
||||
|
||||
case Tlv::kMode:
|
||||
SuccessOrExit(error = message->AppendModeTlv(aChild->GetDeviceMode()));
|
||||
break;
|
||||
@@ -3364,26 +3377,9 @@ void MleRouter::SendChildUpdateResponse(Child * aChild,
|
||||
SuccessOrExit(error = message->AppendPendingTimestampTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kResponse:
|
||||
SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
|
||||
break;
|
||||
|
||||
case Tlv::kSourceAddress:
|
||||
SuccessOrExit(error = message->AppendSourceAddressTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kTimeout:
|
||||
SuccessOrExit(error = message->AppendTimeoutTlv(aChild->GetTimeout()));
|
||||
break;
|
||||
|
||||
case Tlv::kMleFrameCounter:
|
||||
SuccessOrExit(error = message->AppendMleFrameCounterTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kLinkFrameCounter:
|
||||
SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
case Tlv::kCslClockAccuracy:
|
||||
if (!aChild->IsRxOnWhenIdle())
|
||||
@@ -3411,8 +3407,7 @@ exit:
|
||||
}
|
||||
|
||||
void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
const TlvList & aTlvList,
|
||||
uint16_t aDelay,
|
||||
const Message * aRequestMessage)
|
||||
{
|
||||
@@ -3434,9 +3429,9 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
|
||||
SuccessOrExit(error = message->AppendActiveTimestampTlv());
|
||||
SuccessOrExit(error = message->AppendPendingTimestampTlv());
|
||||
|
||||
for (int i = 0; i < aTlvsLength; i++)
|
||||
for (uint8_t tlvType : aTlvList)
|
||||
{
|
||||
switch (aTlvs[i])
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kNetworkData:
|
||||
neighbor = mNeighborTable.FindNeighbor(aDestination);
|
||||
|
||||
@@ -618,19 +618,17 @@ private:
|
||||
void SendAdvertisement(void);
|
||||
Error SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
|
||||
Neighbor * aNeighbor,
|
||||
const RequestedTlvs & aRequestedTlvs,
|
||||
const TlvList & aRequestedTlvList,
|
||||
const Challenge & aChallenge);
|
||||
void SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest);
|
||||
Error SendChildIdResponse(Child &aChild);
|
||||
Error SendChildUpdateRequest(Child &aChild);
|
||||
void SendChildUpdateResponse(Child * aChild,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
const TlvList & aTlvList,
|
||||
const Challenge & aChallenge);
|
||||
void SendDataResponse(const Ip6::Address &aDestination,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
const TlvList & aTlvList,
|
||||
uint16_t aDelay,
|
||||
const Message * aRequestMessage = nullptr);
|
||||
Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
|
||||
|
||||
Reference in New Issue
Block a user