mirror of
https://github.com/espressif/openthread.git
synced 2026-08-25 03:39:52 +00:00
[mle] request "Route TLV" after quick re-attach as FED (#8956)
This commit allows an FED child to request Route TLV (in "TLV Request TLV") in an MLE Data Request message. Parent will include the Route TLV when requested by the child. After successfully performing a quick re-attach upon reset, an FED child requests Route TLV when sending MLE Data Request to its parent. This is tracked by a newly added boolean `mRequestRouteTlv`, which is set after quick re-attach and cleared when Route TLV is successfully processed. This commit also simplifies methods related to sending Data Request.
This commit is contained in:
@@ -58,8 +58,6 @@ LinkMetrics::LinkMetrics(Instance &aInstance)
|
||||
|
||||
Error LinkMetrics::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Mle::Tlv::kLinkMetricsReport};
|
||||
|
||||
Error error;
|
||||
Neighbor *neighbor;
|
||||
QueryInfo info;
|
||||
@@ -79,7 +77,7 @@ Error LinkMetrics::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, co
|
||||
VerifyOrExit(info.mTypeIdCount == 0, error = kErrorInvalidArgs);
|
||||
}
|
||||
|
||||
error = Get<Mle::MleRouter>().SendDataRequest(aDestination, kTlvs, sizeof(kTlvs), /* aDelay */ 0, info);
|
||||
error = Get<Mle::MleRouter>().SendDataRequestForLinkMetricsReport(aDestination, info);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
+38
-9
@@ -73,6 +73,7 @@ const otMeshLocalPrefix Mle::sMeshLocalPrefixInit = {
|
||||
Mle::Mle(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mRetrieveNewNetworkData(false)
|
||||
, mRequestRouteTlv(false)
|
||||
, mRole(kRoleDisabled)
|
||||
, mNeighborTable(aInstance)
|
||||
, mDeviceMode(DeviceMode::kModeRxOnWhenIdle)
|
||||
@@ -1841,7 +1842,30 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination)
|
||||
{
|
||||
return SendDataRequestAfterDelay(aDestination, /* aDelay */ 0);
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kNetworkData, Tlv::kRoute};
|
||||
|
||||
// Based on `mRequestRouteTlv` include both Network Data and Route
|
||||
// TLVs or only Network Data TLV.
|
||||
|
||||
return SendDataRequest(aDestination, kTlvs, mRequestRouteTlv ? 2 : 1, aDelay);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
Error Mle::SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination,
|
||||
const LinkMetrics::LinkMetrics::QueryInfo &aQueryInfo)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kLinkMetricsReport};
|
||||
|
||||
return SendDataRequest(aDestination, kTlvs, sizeof(kTlvs), /* aDelay */ 0, &aQueryInfo);
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination,
|
||||
const uint8_t *aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
@@ -1987,15 +2011,13 @@ void Mle::HandleMessageTransmissionTimer(void)
|
||||
case kChildUpdateRequestNone:
|
||||
if (mDataRequestState == kDataRequestActive)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kNetworkData};
|
||||
|
||||
Ip6::Address destination;
|
||||
|
||||
VerifyOrExit(mDataRequestAttempts < kMaxChildKeepAliveAttempts, IgnoreError(BecomeDetached()));
|
||||
|
||||
destination.SetToLinkLocalAddress(mParent.GetExtAddress());
|
||||
|
||||
if (SendDataRequest(destination, kTlvs) == kErrorNone)
|
||||
if (SendDataRequest(destination) == kErrorNone)
|
||||
{
|
||||
mDataRequestAttempts++;
|
||||
}
|
||||
@@ -2741,8 +2763,6 @@ exit:
|
||||
|
||||
void Mle::HandleAdvertisement(RxInfo &aRxInfo)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kNetworkData};
|
||||
|
||||
Error error = kErrorNone;
|
||||
uint16_t sourceAddress;
|
||||
LeaderData leaderData;
|
||||
@@ -2796,7 +2816,7 @@ void Mle::HandleAdvertisement(RxInfo &aRxInfo)
|
||||
if (mRetrieveNewNetworkData || IsNetworkDataNewer(leaderData))
|
||||
{
|
||||
delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
|
||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), kTlvs, delay));
|
||||
IgnoreError(SendDataRequestAfterDelay(aRxInfo.mMessageInfo.GetPeerAddr(), delay));
|
||||
}
|
||||
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
@@ -2826,6 +2846,10 @@ void Mle::HandleDataResponse(RxInfo &aRxInfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
SuccessOrExit(error = Get<MleRouter>().ReadAndProcessRouteTlvOnFed(aRxInfo, mParent.GetRouterId()));
|
||||
#endif
|
||||
|
||||
error = HandleLeaderData(aRxInfo);
|
||||
|
||||
if (mDataRequestState == kDataRequestNone && !IsRxOnWhenIdle())
|
||||
@@ -2989,8 +3013,6 @@ exit:
|
||||
|
||||
if (dataRequest)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kNetworkData};
|
||||
|
||||
uint16_t delay;
|
||||
|
||||
if (aRxInfo.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
@@ -3005,7 +3027,7 @@ exit:
|
||||
delay = 10;
|
||||
}
|
||||
|
||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), kTlvs, delay));
|
||||
IgnoreError(SendDataRequestAfterDelay(aRxInfo.mMessageInfo.GetPeerAddr(), delay));
|
||||
}
|
||||
else if (error == kErrorNone)
|
||||
{
|
||||
@@ -3584,6 +3606,13 @@ void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo)
|
||||
|
||||
mRetrieveNewNetworkData = true;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
if (IsFullThreadDevice())
|
||||
{
|
||||
mRequestRouteTlv = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kRoleChild:
|
||||
|
||||
+30
-45
@@ -1525,49 +1525,32 @@ protected:
|
||||
*/
|
||||
Mac::ShortAddress GetNextHop(uint16_t aDestination) const;
|
||||
|
||||
/**
|
||||
* This method generates an MLE Data Request message.
|
||||
*
|
||||
* @param[in] aDestination The IPv6 destination address.
|
||||
*
|
||||
* @retval kErrorNone Successfully generated an MLE Data Request message.
|
||||
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
|
||||
*
|
||||
*/
|
||||
Error SendDataRequest(const Ip6::Address &aDestination);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
/**
|
||||
* This method generates an MLE Data Request message which includes a Link Metrics Query TLV.
|
||||
* This method generates an MLE Data Request message which request Link Metrics Report TLV.
|
||||
*
|
||||
* @param[in] aDestination A reference to the IPv6 address of the destination.
|
||||
* @param[in] aTlvs A pointer to requested TLV types.
|
||||
* @param[in] aTlvsLength The number of TLV types in @p aTlvs.
|
||||
* @param[in] aDelay Delay in milliseconds before the Data Request message is sent.
|
||||
* @param[in] aQueryInfo A Link Metrics query info.
|
||||
*
|
||||
* @retval kErrorNone Successfully generated an MLE Data Request message.
|
||||
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
|
||||
*
|
||||
*/
|
||||
Error SendDataRequest(const Ip6::Address &aDestination,
|
||||
const uint8_t *aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const LinkMetrics::LinkMetrics::QueryInfo &aQueryInfo)
|
||||
{
|
||||
return SendDataRequest(aDestination, aTlvs, aTlvsLength, aDelay, &aQueryInfo);
|
||||
}
|
||||
Error SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination,
|
||||
const LinkMetrics::LinkMetrics::QueryInfo &aQueryInfo);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method generates an MLE Data Request message.
|
||||
*
|
||||
* @tparam kArrayLength The TLV array length.
|
||||
*
|
||||
* @param[in] aDestination A reference to the IPv6 address of the destination.
|
||||
* @param[in] aTlvs An array of requested TLVs.
|
||||
* @param[in] aDelay Delay in milliseconds before the Data Request message is sent.
|
||||
*
|
||||
* @retval kErrorNone Successfully generated an MLE Data Request message.
|
||||
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
|
||||
*
|
||||
*/
|
||||
template <uint8_t kArrayLength>
|
||||
Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t (&aTlvs)[kArrayLength], uint16_t aDelay = 0)
|
||||
{
|
||||
return SendDataRequest(aDestination, aTlvs, kArrayLength, aDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method generates an MLE Child Update Request message.
|
||||
*
|
||||
@@ -1769,20 +1752,21 @@ protected:
|
||||
|
||||
Ip6::Netif::UnicastAddress mLeaderAloc; ///< Leader anycast locator
|
||||
|
||||
LeaderData mLeaderData; ///< Last received Leader Data TLV.
|
||||
bool mRetrieveNewNetworkData; ///< Indicating new Network Data is needed if set.
|
||||
DeviceRole mRole; ///< Current Thread role.
|
||||
Parent mParent; ///< Parent information.
|
||||
NeighborTable mNeighborTable; ///< The neighbor table.
|
||||
DeviceMode mDeviceMode; ///< Device mode setting.
|
||||
AttachState mAttachState; ///< The attach state.
|
||||
uint8_t mParentRequestCounter; ///< Number of parent requests while in `kAttachStateParentRequest`.
|
||||
ReattachState mReattachState; ///< Reattach state
|
||||
uint16_t mAttachCounter; ///< Attach attempt counter.
|
||||
uint16_t mAnnounceDelay; ///< Delay in between sending Announce messages during attach.
|
||||
AttachTimer mAttachTimer; ///< The timer for driving the attach process.
|
||||
DelayTimer mDelayedResponseTimer; ///< The timer to delay MLE responses.
|
||||
MsgTxTimer mMessageTransmissionTimer; ///< The timer for (re-)sending of MLE messages (e.g. Child Update).
|
||||
LeaderData mLeaderData; ///< Last received Leader Data TLV.
|
||||
bool mRetrieveNewNetworkData : 1; ///< Indicating new Network Data is needed if set.
|
||||
bool mRequestRouteTlv : 1; ///< Request Route TLV when sending Data Request.
|
||||
DeviceRole mRole; ///< Current Thread role.
|
||||
Parent mParent; ///< Parent information.
|
||||
NeighborTable mNeighborTable; ///< The neighbor table.
|
||||
DeviceMode mDeviceMode; ///< Device mode setting.
|
||||
AttachState mAttachState; ///< The attach state.
|
||||
uint8_t mParentRequestCounter; ///< Number of parent requests while in `kAttachStateParentRequest`.
|
||||
ReattachState mReattachState; ///< Reattach state
|
||||
uint16_t mAttachCounter; ///< Attach attempt counter.
|
||||
uint16_t mAnnounceDelay; ///< Delay in between sending Announce messages during attach.
|
||||
AttachTimer mAttachTimer; ///< The timer for driving the attach process.
|
||||
DelayTimer mDelayedResponseTimer; ///< The timer to delay MLE responses.
|
||||
MsgTxTimer mMessageTransmissionTimer; ///< The timer for (re-)sending of MLE messages (e.g. Child Update).
|
||||
#if OPENTHREAD_FTD
|
||||
uint8_t mLinkRequestAttempts; ///< Number of remaining link requests to send after reset.
|
||||
bool mWasLeader; ///< Indicating if device was leader before reset.
|
||||
@@ -1990,6 +1974,7 @@ private:
|
||||
void HandleDetachGracefullyTimer(void);
|
||||
bool IsDetachingGracefully(void) { return mDetachGracefullyTimer.IsRunning(); }
|
||||
Error SendChildUpdateRequest(ChildUpdateRequestMode aMode);
|
||||
Error SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
Error SendDataRequest(const Ip6::Address &aDestination,
|
||||
|
||||
@@ -808,8 +808,6 @@ void MleRouter::HandleLinkAcceptAndRequest(RxInfo &aRxInfo)
|
||||
|
||||
Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
{
|
||||
static const uint8_t kDataRequestTlvs[] = {Tlv::kNetworkData};
|
||||
|
||||
Error error = kErrorNone;
|
||||
Router *router;
|
||||
Neighbor::State neighborState;
|
||||
@@ -916,7 +914,7 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
|
||||
mLinkRequestAttempts = 0; // completed router sync after reset, no more link request to retransmit
|
||||
mRetrieveNewNetworkData = true;
|
||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), kDataRequestTlvs));
|
||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr()));
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
|
||||
@@ -939,7 +937,7 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
SerialNumber::IsGreater(leaderData.GetDataVersion(NetworkData::kFullSet),
|
||||
Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet)))
|
||||
{
|
||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), kDataRequestTlvs));
|
||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr()));
|
||||
}
|
||||
|
||||
// Route (optional)
|
||||
@@ -1085,6 +1083,7 @@ Error MleRouter::ReadAndProcessRouteTlvOnFed(RxInfo &aRxInfo, uint8_t aParentId)
|
||||
case kErrorNone:
|
||||
SuccessOrExit(error = ProcessRouteTlv(routeTlv, aRxInfo));
|
||||
mRouterTable.UpdateRoutesOnFed(routeTlv, aParentId);
|
||||
mRequestRouteTlv = false;
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
break;
|
||||
@@ -3159,6 +3158,10 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
|
||||
SuccessOrExit(error = message->AppendPendingDatasetTlv());
|
||||
break;
|
||||
|
||||
case Tlv::kRoute:
|
||||
SuccessOrExit(error = message->AppendRouteTlv());
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
case Tlv::kLinkMetricsReport:
|
||||
OT_ASSERT(aRequestMessage != nullptr);
|
||||
|
||||
@@ -55,7 +55,7 @@ child2 = cli.Node()
|
||||
# Form topology
|
||||
|
||||
leader.form('reset')
|
||||
child1.join(leader, cli.JOIN_TYPE_END_DEVICE)
|
||||
child1.join(leader, cli.JOIN_TYPE_REED)
|
||||
child2.join(leader, cli.JOIN_TYPE_END_DEVICE)
|
||||
|
||||
verify(leader.get_state() == 'leader')
|
||||
@@ -135,6 +135,24 @@ def check_leader_neighbor_table():
|
||||
|
||||
verify_within(check_leader_neighbor_table, 10)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Reset `child` and make sure it re-attaches successfully.
|
||||
|
||||
del child1
|
||||
child1 = cli.Node(index=3)
|
||||
child1.set_router_eligible('disable')
|
||||
child1.interface_up()
|
||||
child1.thread_start()
|
||||
|
||||
|
||||
def check_child1_state():
|
||||
verify(child1.get_state() == 'child')
|
||||
table = child1.get_router_table()
|
||||
verify(len(table) == 2)
|
||||
|
||||
|
||||
verify_within(check_child1_state, 10)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
|
||||
Reference in New Issue
Block a user