[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:
Abtin Keshavarzian
2022-08-11 11:14:09 -07:00
committed by GitHub
parent 3120efb486
commit ea1b2292be
5 changed files with 207 additions and 157 deletions
+24
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+3 -5
View File
@@ -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);