1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.  All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions are met:
6  *  1. Redistributions of source code must retain the above copyright
7  *     notice, this list of conditions and the following disclaimer.
8  *  2. Redistributions in binary form must reproduce the above copyright
9  *     notice, this list of conditions and the following disclaimer in the
10  *     documentation and/or other materials provided with the distribution.
11  *  3. Neither the name of the copyright holder nor the
12  *     names of its contributors may be used to endorse or promote products
13  *     derived from this software without specific prior written permission.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * @file
30  *   This file implements MLE functionality required for the Thread Router and Leader roles.
31  */
32 
33 #include "mle_router.hpp"
34 
35 #if OPENTHREAD_FTD
36 
37 #include "common/as_core_type.hpp"
38 #include "common/code_utils.hpp"
39 #include "common/debug.hpp"
40 #include "common/encoding.hpp"
41 #include "common/locator_getters.hpp"
42 #include "common/num_utils.hpp"
43 #include "common/random.hpp"
44 #include "common/serial_number.hpp"
45 #include "common/settings.hpp"
46 #include "instance/instance.hpp"
47 #include "mac/mac_types.hpp"
48 #include "meshcop/meshcop.hpp"
49 #include "net/icmp6.hpp"
50 #include "thread/key_manager.hpp"
51 #include "thread/thread_netif.hpp"
52 #include "thread/thread_tlvs.hpp"
53 #include "thread/time_sync_service.hpp"
54 #include "thread/uri_paths.hpp"
55 #include "thread/version.hpp"
56 #include "utils/otns.hpp"
57 
58 namespace ot {
59 namespace Mle {
60 
61 RegisterLogModule("Mle");
62 
MleRouter(Instance & aInstance)63 MleRouter::MleRouter(Instance &aInstance)
64     : Mle(aInstance)
65     , mAdvertiseTrickleTimer(aInstance, MleRouter::HandleAdvertiseTrickleTimer)
66     , mChildTable(aInstance)
67     , mRouterTable(aInstance)
68     , mChallengeTimeout(0)
69     , mNextChildId(kMaxChildId)
70     , mNetworkIdTimeout(kNetworkIdTimeout)
71     , mRouterUpgradeThreshold(kRouterUpgradeThreshold)
72     , mRouterDowngradeThreshold(kRouterDowngradeThreshold)
73 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
74     , mPreferredLeaderPartitionId(0)
75     , mCcmEnabled(false)
76     , mThreadVersionCheckEnabled(true)
77 #endif
78     , mRouterEligible(true)
79     , mAddressSolicitPending(false)
80     , mAddressSolicitRejected(false)
81     , mPreviousPartitionIdRouter(0)
82     , mPreviousPartitionId(0)
83     , mPreviousPartitionRouterIdSequence(0)
84     , mPreviousPartitionIdTimeout(0)
85     , mChildRouterLinks(kChildRouterLinks)
86     , mParentPriority(kParentPriorityUnspecified)
87 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
88     , mMaxChildIpAddresses(0)
89 #endif
90 {
91     mDeviceMode.Set(mDeviceMode.Get() | DeviceMode::kModeFullThreadDevice | DeviceMode::kModeFullNetworkData);
92 
93 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
94     mLeaderWeight = mDeviceProperties.CalculateLeaderWeight();
95 #else
96     mLeaderWeight = kDefaultLeaderWeight;
97 #endif
98 
99     mLeaderAloc.InitAsThreadOriginMeshLocal();
100 
101     SetRouterId(kInvalidRouterId);
102 
103 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
104     mSteeringData.Clear();
105 #endif
106 }
107 
HandlePartitionChange(void)108 void MleRouter::HandlePartitionChange(void)
109 {
110     mPreviousPartitionId               = mLeaderData.GetPartitionId();
111     mPreviousPartitionRouterIdSequence = mRouterTable.GetRouterIdSequence();
112     mPreviousPartitionIdTimeout        = GetNetworkIdTimeout();
113 
114     Get<AddressResolver>().Clear();
115     IgnoreError(Get<Tmf::Agent>().AbortTransaction(&MleRouter::HandleAddressSolicitResponse, this));
116     mRouterTable.Clear();
117 }
118 
IsRouterEligible(void) const119 bool MleRouter::IsRouterEligible(void) const
120 {
121     bool                  rval      = false;
122     const SecurityPolicy &secPolicy = Get<KeyManager>().GetSecurityPolicy();
123 
124     VerifyOrExit(mRouterEligible && IsFullThreadDevice());
125 
126 #if OPENTHREAD_CONFIG_THREAD_VERSION == OT_THREAD_VERSION_1_1
127     VerifyOrExit(secPolicy.mRoutersEnabled);
128 #else
129     if (secPolicy.mCommercialCommissioningEnabled)
130     {
131 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
132         VerifyOrExit(mCcmEnabled || secPolicy.mNonCcmRoutersEnabled);
133 #else
134         VerifyOrExit(secPolicy.mNonCcmRoutersEnabled);
135 #endif
136     }
137     if (!secPolicy.mRoutersEnabled)
138     {
139 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
140         VerifyOrExit(!mThreadVersionCheckEnabled ||
141                      secPolicy.mVersionThresholdForRouting + SecurityPolicy::kVersionThresholdOffsetVersion <=
142                          kThreadVersion);
143 #else
144         VerifyOrExit(secPolicy.mVersionThresholdForRouting + SecurityPolicy::kVersionThresholdOffsetVersion <=
145                      kThreadVersion);
146 #endif
147     }
148 #endif
149 
150     rval = true;
151 
152 exit:
153     return rval;
154 }
155 
SetRouterEligible(bool aEligible)156 Error MleRouter::SetRouterEligible(bool aEligible)
157 {
158     Error error = kErrorNone;
159 
160     VerifyOrExit(IsFullThreadDevice() || !aEligible, error = kErrorNotCapable);
161 
162     mRouterEligible = aEligible;
163 
164     switch (mRole)
165     {
166     case kRoleDisabled:
167     case kRoleDetached:
168         break;
169 
170     case kRoleChild:
171         Get<Mac::Mac>().SetBeaconEnabled(mRouterEligible);
172         break;
173 
174     case kRoleRouter:
175     case kRoleLeader:
176         if (!mRouterEligible)
177         {
178             IgnoreError(BecomeDetached());
179         }
180 
181         break;
182     }
183 
184 exit:
185     return error;
186 }
187 
HandleSecurityPolicyChanged(void)188 void MleRouter::HandleSecurityPolicyChanged(void)
189 {
190     // If we are currently router or leader and no longer eligible to
191     // be a router (due to security policy change), we start jitter
192     // timeout to downgrade.
193 
194     VerifyOrExit(IsRouterOrLeader() && !IsRouterEligible());
195 
196     VerifyOrExit(!mRouterRoleTransition.IsPending());
197 
198     mRouterRoleTransition.StartTimeout();
199 
200     if (IsLeader())
201     {
202         mRouterRoleTransition.IncreaseTimeout(kLeaderDowngradeExtraDelay);
203     }
204 
205 exit:
206     return;
207 }
208 
209 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
SetDeviceProperties(const DeviceProperties & aDeviceProperties)210 void MleRouter::SetDeviceProperties(const DeviceProperties &aDeviceProperties)
211 {
212     mDeviceProperties = aDeviceProperties;
213     mDeviceProperties.ClampWeightAdjustment();
214     SetLeaderWeight(mDeviceProperties.CalculateLeaderWeight());
215 }
216 #endif
217 
BecomeRouter(ThreadStatusTlv::Status aStatus)218 Error MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus)
219 {
220     Error error = kErrorNone;
221 
222     VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
223     VerifyOrExit(!IsRouter(), error = kErrorNone);
224     VerifyOrExit(IsRouterEligible(), error = kErrorNotCapable);
225 
226     LogInfo("Attempt to become router");
227 
228     Get<MeshForwarder>().SetRxOnWhenIdle(true);
229     mRouterRoleTransition.StopTimeout();
230 
231     switch (mRole)
232     {
233     case kRoleDetached:
234         // If router had more than `kMinCriticalChildrenCount` children
235         // or was a leader prior to reset we treat the multicast Link
236         // Request as a critical message.
237         mLinkRequestAttempts =
238             (mWasLeader || mChildTable.GetNumChildren(Child::kInStateValidOrRestoring) >= kMinCriticalChildrenCount)
239                 ? kMaxCriticalTxCount
240                 : kMaxTxCount;
241 
242         SuccessOrExit(error = SendLinkRequest(nullptr));
243         mLinkRequestAttempts--;
244         ScheduleMessageTransmissionTimer();
245         Get<TimeTicker>().RegisterReceiver(TimeTicker::kMleRouter);
246         break;
247 
248     case kRoleChild:
249         SuccessOrExit(error = SendAddressSolicit(aStatus));
250         break;
251 
252     default:
253         OT_ASSERT(false);
254     }
255 
256 exit:
257     return error;
258 }
259 
BecomeLeader(void)260 Error MleRouter::BecomeLeader(void)
261 {
262     Error    error = kErrorNone;
263     Router  *router;
264     uint32_t partitionId;
265     uint8_t  leaderId;
266 
267 #if OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT
268     VerifyOrExit(!Get<MeshCoP::ActiveDatasetManager>().IsPartiallyComplete(), error = kErrorInvalidState);
269 #else
270     VerifyOrExit(Get<MeshCoP::ActiveDatasetManager>().IsComplete(), error = kErrorInvalidState);
271 #endif
272     VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
273     VerifyOrExit(!IsLeader(), error = kErrorNone);
274     VerifyOrExit(IsRouterEligible(), error = kErrorNotCapable);
275 
276     mRouterTable.Clear();
277 
278 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
279     {
280         uint8_t minId;
281         uint8_t maxId;
282 
283         mRouterTable.GetRouterIdRange(minId, maxId);
284         partitionId = mPreferredLeaderPartitionId ? mPreferredLeaderPartitionId : Random::NonCrypto::GetUint32();
285         leaderId    = (IsRouterIdValid(mPreviousRouterId) && minId <= mPreviousRouterId && mPreviousRouterId <= maxId)
286                           ? mPreviousRouterId
287                           : Random::NonCrypto::GetUint8InRange(minId, maxId + 1);
288     }
289 #else
290     partitionId = Random::NonCrypto::GetUint32();
291     leaderId    = IsRouterIdValid(mPreviousRouterId) ? mPreviousRouterId
292                                                      : Random::NonCrypto::GetUint8InRange(0, kMaxRouterId + 1);
293 #endif
294 
295     SetLeaderData(partitionId, mLeaderWeight, leaderId);
296 
297     router = mRouterTable.Allocate(leaderId);
298     OT_ASSERT(router != nullptr);
299 
300     SetRouterId(leaderId);
301     router->SetExtAddress(Get<Mac::Mac>().GetExtAddress());
302 
303     Get<NetworkData::Leader>().Reset();
304     Get<MeshCoP::Leader>().SetEmptyCommissionerData();
305 
306     SetStateLeader(Rloc16FromRouterId(leaderId), kStartingAsLeader);
307 
308 exit:
309     return error;
310 }
311 
StopLeader(void)312 void MleRouter::StopLeader(void)
313 {
314     StopAdvertiseTrickleTimer();
315     Get<ThreadNetif>().UnsubscribeAllRoutersMulticast();
316 }
317 
HandleDetachStart(void)318 void MleRouter::HandleDetachStart(void)
319 {
320     mRouterTable.ClearNeighbors();
321     StopLeader();
322     Get<TimeTicker>().UnregisterReceiver(TimeTicker::kMleRouter);
323 }
324 
HandleChildStart(AttachMode aMode)325 void MleRouter::HandleChildStart(AttachMode aMode)
326 {
327     mAddressSolicitRejected = false;
328 
329     mRouterRoleTransition.StartTimeout();
330 
331     StopLeader();
332     Get<TimeTicker>().RegisterReceiver(TimeTicker::kMleRouter);
333 
334     if (mRouterEligible)
335     {
336         Get<Mac::Mac>().SetBeaconEnabled(true);
337     }
338 
339     Get<ThreadNetif>().SubscribeAllRoutersMulticast();
340 
341     VerifyOrExit(IsRouterIdValid(mPreviousRouterId));
342 
343     switch (aMode)
344     {
345     case kDowngradeToReed:
346         SendAddressRelease();
347 
348         if (HasChildren())
349         {
350             RemoveChildren();
351         }
352 
353         SetRouterId(kInvalidRouterId);
354         break;
355 
356     case kSamePartition:
357         if (HasChildren())
358         {
359             IgnoreError(BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest));
360         }
361 
362         break;
363 
364     case kAnyPartition:
365     case kBetterParent:
366         // If attach was started due to receiving MLE Announce Messages, all rx-on-when-idle devices would
367         // start attach immediately when receiving such Announce message as in Thread 1.1 specification,
368         // Section 4.8.1,
369         // "If the received value is newer and the channel and/or PAN ID in the Announce message differ
370         //  from those currently in use, the receiving device attempts to attach using the channel and
371         //  PAN ID received from the Announce message."
372         //
373         // That is, Parent-child relationship is highly unlikely to be kept in the new partition, so here
374         // removes all children, leaving whether to become router according to the new partition status.
375         if (IsAnnounceAttach() && HasChildren())
376         {
377             RemoveChildren();
378         }
379 
380         OT_FALL_THROUGH;
381 
382     case kBetterPartition:
383         if (HasChildren() && mPreviousPartitionIdRouter != mLeaderData.GetPartitionId())
384         {
385             IgnoreError(BecomeRouter(ThreadStatusTlv::kParentPartitionChange));
386         }
387 
388         break;
389     }
390 
391 exit:
392 
393     if (mRouterTable.GetActiveRouterCount() >= mRouterUpgradeThreshold &&
394         (!IsRouterIdValid(mPreviousRouterId) || !HasChildren()))
395     {
396         SetRouterId(kInvalidRouterId);
397     }
398 }
399 
SetStateRouter(uint16_t aRloc16)400 void MleRouter::SetStateRouter(uint16_t aRloc16)
401 {
402     // The `aStartMode` is ignored when used with `kRoleRouter`
403     SetStateRouterOrLeader(kRoleRouter, aRloc16, /* aStartMode */ kStartingAsLeader);
404 }
405 
SetStateLeader(uint16_t aRloc16,LeaderStartMode aStartMode)406 void MleRouter::SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode)
407 {
408     SetStateRouterOrLeader(kRoleLeader, aRloc16, aStartMode);
409 }
410 
SetStateRouterOrLeader(DeviceRole aRole,uint16_t aRloc16,LeaderStartMode aStartMode)411 void MleRouter::SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode)
412 {
413     if (aRole == kRoleLeader)
414     {
415         IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
416         IgnoreError(Get<MeshCoP::PendingDatasetManager>().Restore());
417     }
418 
419     SetRloc16(aRloc16);
420 
421     SetRole(aRole);
422 
423     SetAttachState(kAttachStateIdle);
424     mAttachCounter = 0;
425     mAttachTimer.Stop();
426     mMessageTransmissionTimer.Stop();
427     StopAdvertiseTrickleTimer();
428     ResetAdvertiseInterval();
429 
430     Get<ThreadNetif>().SubscribeAllRoutersMulticast();
431     mPreviousPartitionIdRouter = mLeaderData.GetPartitionId();
432     Get<Mac::Mac>().SetBeaconEnabled(true);
433 
434     if (aRole == kRoleLeader)
435     {
436         IgnoreError(GetLeaderAloc(mLeaderAloc.GetAddress()));
437         Get<ThreadNetif>().AddUnicastAddress(mLeaderAloc);
438         Get<TimeTicker>().RegisterReceiver(TimeTicker::kMleRouter);
439         Get<NetworkData::Leader>().Start(aStartMode);
440         Get<MeshCoP::ActiveDatasetManager>().StartLeader();
441         Get<MeshCoP::PendingDatasetManager>().StartLeader();
442         Get<AddressResolver>().Clear();
443     }
444 
445     // Remove children that do not have matching RLOC16
446     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
447     {
448         if (RouterIdFromRloc16(child.GetRloc16()) != mRouterId)
449         {
450             RemoveNeighbor(child);
451         }
452     }
453 
454 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
455     Get<Mac::Mac>().UpdateCsl();
456 #endif
457 
458     LogNote("Partition ID 0x%lx", ToUlong(mLeaderData.GetPartitionId()));
459 }
460 
HandleAdvertiseTrickleTimer(TrickleTimer & aTimer)461 void MleRouter::HandleAdvertiseTrickleTimer(TrickleTimer &aTimer)
462 {
463     aTimer.Get<MleRouter>().HandleAdvertiseTrickleTimer();
464 }
465 
HandleAdvertiseTrickleTimer(void)466 void MleRouter::HandleAdvertiseTrickleTimer(void)
467 {
468     VerifyOrExit(IsRouterEligible(), mAdvertiseTrickleTimer.Stop());
469 
470     SendAdvertisement();
471 
472 exit:
473     return;
474 }
475 
StopAdvertiseTrickleTimer(void)476 void MleRouter::StopAdvertiseTrickleTimer(void) { mAdvertiseTrickleTimer.Stop(); }
477 
DetermineAdvertiseIntervalMax(void) const478 uint32_t MleRouter::DetermineAdvertiseIntervalMax(void) const
479 {
480     uint32_t interval;
481 
482 #if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
483     interval = kAdvIntervalMaxLogRoutes;
484 #else
485     // Determine the interval based on the number of router neighbors
486     // with link quality 2 or higher.
487 
488     interval = (Get<RouterTable>().GetNeighborCount(kLinkQuality2) + 1) * kAdvIntervalNeighborMultiplier;
489     interval = Clamp(interval, kAdvIntervalMaxLowerBound, kAdvIntervalMaxUpperBound);
490 #endif
491 
492     return interval;
493 }
494 
UpdateAdvertiseInterval(void)495 void MleRouter::UpdateAdvertiseInterval(void)
496 {
497     if (IsRouterOrLeader() && mAdvertiseTrickleTimer.IsRunning())
498     {
499         mAdvertiseTrickleTimer.SetIntervalMax(DetermineAdvertiseIntervalMax());
500     }
501 }
502 
ResetAdvertiseInterval(void)503 void MleRouter::ResetAdvertiseInterval(void)
504 {
505     VerifyOrExit(IsRouterOrLeader());
506 
507     if (!mAdvertiseTrickleTimer.IsRunning())
508     {
509         mAdvertiseTrickleTimer.Start(TrickleTimer::kModeTrickle, kAdvIntervalMin, DetermineAdvertiseIntervalMax());
510     }
511 
512     mAdvertiseTrickleTimer.IndicateInconsistent();
513 
514 exit:
515     return;
516 }
517 
SendAdvertisement(void)518 void MleRouter::SendAdvertisement(void)
519 {
520     Error        error = kErrorNone;
521     Ip6::Address destination;
522     TxMessage   *message = nullptr;
523 
524     // Suppress MLE Advertisements when trying to attach to a better partition.
525     //
526     // Without this suppression, a device may send an MLE Advertisement before receiving the MLE Child ID Response.
527     // The candidate parent then removes the attaching device because the Source Address TLV includes an RLOC16 that
528     // indicates a Router role (i.e. a Child ID equal to zero).
529     VerifyOrExit(!IsAttaching());
530 
531     // Suppress MLE Advertisements when transitioning to the router role.
532     //
533     // When trying to attach to a new partition, sending out advertisements as a REED can cause already-attached
534     // children to detach.
535     VerifyOrExit(!mAddressSolicitPending);
536 
537     VerifyOrExit((message = NewMleMessage(kCommandAdvertisement)) != nullptr, error = kErrorNoBufs);
538     SuccessOrExit(error = message->AppendSourceAddressTlv());
539     SuccessOrExit(error = message->AppendLeaderDataTlv());
540 
541     switch (mRole)
542     {
543     case kRoleChild:
544         break;
545 
546     case kRoleRouter:
547     case kRoleLeader:
548         SuccessOrExit(error = message->AppendRouteTlv());
549         break;
550 
551     case kRoleDisabled:
552     case kRoleDetached:
553         OT_ASSERT(false);
554     }
555 
556     destination.SetToLinkLocalAllNodesMulticast();
557     SuccessOrExit(error = message->SendTo(destination));
558 
559     Log(kMessageSend, kTypeAdvertisement, destination);
560 
561 exit:
562     FreeMessageOnError(message, error);
563     LogSendError(kTypeAdvertisement, error);
564 }
565 
SendLinkRequest(Neighbor * aNeighbor)566 Error MleRouter::SendLinkRequest(Neighbor *aNeighbor)
567 {
568     static const uint8_t kDetachedTlvs[]      = {Tlv::kAddress16, Tlv::kRoute};
569     static const uint8_t kRouterTlvs[]        = {Tlv::kLinkMargin};
570     static const uint8_t kValidNeighborTlvs[] = {Tlv::kLinkMargin, Tlv::kRoute};
571 
572     Error        error   = kErrorNone;
573     TxMessage   *message = nullptr;
574     Ip6::Address destination;
575 
576     VerifyOrExit(mChallengeTimeout == 0);
577 
578     destination.Clear();
579 
580     VerifyOrExit((message = NewMleMessage(kCommandLinkRequest)) != nullptr, error = kErrorNoBufs);
581     SuccessOrExit(error = message->AppendVersionTlv());
582 
583     switch (mRole)
584     {
585     case kRoleDetached:
586         SuccessOrExit(error = message->AppendTlvRequestTlv(kDetachedTlvs));
587         break;
588 
589     case kRoleChild:
590         SuccessOrExit(error = message->AppendSourceAddressTlv());
591         SuccessOrExit(error = message->AppendLeaderDataTlv());
592         break;
593 
594     case kRoleRouter:
595     case kRoleLeader:
596         if (aNeighbor == nullptr || !aNeighbor->IsStateValid())
597         {
598             SuccessOrExit(error = message->AppendTlvRequestTlv(kRouterTlvs));
599         }
600         else
601         {
602             SuccessOrExit(error = message->AppendTlvRequestTlv(kValidNeighborTlvs));
603         }
604 
605         SuccessOrExit(error = message->AppendSourceAddressTlv());
606         SuccessOrExit(error = message->AppendLeaderDataTlv());
607         break;
608 
609     case kRoleDisabled:
610         OT_ASSERT(false);
611     }
612 
613 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
614     SuccessOrExit(error = message->AppendTimeRequestTlv());
615 #endif
616 
617     if (aNeighbor == nullptr)
618     {
619         mChallenge.GenerateRandom();
620         mChallengeTimeout = kChallengeTimeout;
621 
622         SuccessOrExit(error = message->AppendChallengeTlv(mChallenge));
623         destination.SetToLinkLocalAllRoutersMulticast();
624     }
625     else
626     {
627         if (!aNeighbor->IsStateValid())
628         {
629             aNeighbor->GenerateChallenge();
630             SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge()));
631         }
632         else
633         {
634             TxChallenge challenge;
635 
636             challenge.GenerateRandom();
637             SuccessOrExit(error = message->AppendChallengeTlv(challenge));
638         }
639 
640         destination.SetToLinkLocalAddress(aNeighbor->GetExtAddress());
641     }
642 
643     SuccessOrExit(error = message->SendTo(destination));
644 
645     Log(kMessageSend, kTypeLinkRequest, destination);
646 
647 exit:
648     FreeMessageOnError(message, error);
649     return error;
650 }
651 
HandleLinkRequest(RxInfo & aRxInfo)652 void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
653 {
654     Error       error    = kErrorNone;
655     Neighbor   *neighbor = nullptr;
656     RxChallenge challenge;
657     uint16_t    version;
658     LeaderData  leaderData;
659     uint16_t    sourceAddress;
660     TlvList     requestedTlvList;
661 
662     Log(kMessageReceive, kTypeLinkRequest, aRxInfo.mMessageInfo.GetPeerAddr());
663 
664     VerifyOrExit(IsRouterOrLeader(), error = kErrorInvalidState);
665 
666     VerifyOrExit(!IsAttaching(), error = kErrorInvalidState);
667 
668     // Challenge
669     SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
670 
671     // Version
672     SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
673     VerifyOrExit(version >= kThreadVersion1p1, error = kErrorParse);
674 
675     // Leader Data
676     switch (aRxInfo.mMessage.ReadLeaderDataTlv(leaderData))
677     {
678     case kErrorNone:
679         VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId(), error = kErrorInvalidState);
680         break;
681     case kErrorNotFound:
682         break;
683     default:
684         ExitNow(error = kErrorParse);
685     }
686 
687     // Source Address
688     switch (Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress))
689     {
690     case kErrorNone:
691         if (IsActiveRouter(sourceAddress))
692         {
693             neighbor = mRouterTable.FindRouterByRloc16(sourceAddress);
694             VerifyOrExit(neighbor != nullptr, error = kErrorParse);
695             VerifyOrExit(!neighbor->IsStateLinkRequest(), error = kErrorAlready);
696 
697             if (!neighbor->IsStateValid())
698             {
699                 InitNeighbor(*neighbor, aRxInfo);
700                 neighbor->SetState(Neighbor::kStateLinkRequest);
701             }
702             else
703             {
704                 Mac::ExtAddress extAddr;
705 
706                 aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
707                 VerifyOrExit(neighbor->GetExtAddress() == extAddr);
708             }
709         }
710 
711         break;
712 
713     case kErrorNotFound:
714         // lack of source address indicates router coming out of reset
715         VerifyOrExit(aRxInfo.IsNeighborStateValid() && IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()),
716                      error = kErrorDrop);
717         neighbor = aRxInfo.mNeighbor;
718         break;
719 
720     default:
721         ExitNow(error = kErrorParse);
722     }
723 
724     // TLV Request
725     switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
726     {
727     case kErrorNone:
728     case kErrorNotFound:
729         break;
730     default:
731         ExitNow(error = kErrorParse);
732     }
733 
734 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
735     if (neighbor != nullptr)
736     {
737         neighbor->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aRxInfo.mMessage, nullptr, 0) == kErrorNone);
738     }
739 #endif
740 
741 #if OPENTHREAD_CONFIG_MULTI_RADIO
742     if (neighbor != nullptr)
743     {
744         neighbor->ClearLastRxFragmentTag();
745     }
746 #endif
747 
748     aRxInfo.mClass = RxInfo::kPeerMessage;
749     ProcessKeySequence(aRxInfo);
750 
751     SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, neighbor, requestedTlvList, challenge));
752 
753 exit:
754     LogProcessError(kTypeLinkRequest, error);
755 }
756 
SendLinkAccept(const Ip6::MessageInfo & aMessageInfo,Neighbor * aNeighbor,const TlvList & aRequestedTlvList,const RxChallenge & aChallenge)757 Error MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
758                                 Neighbor               *aNeighbor,
759                                 const TlvList          &aRequestedTlvList,
760                                 const RxChallenge      &aChallenge)
761 {
762     static const uint8_t kRouterTlvs[] = {Tlv::kLinkMargin};
763 
764     Error      error = kErrorNone;
765     TxMessage *message;
766     Command    command;
767     uint8_t    linkMargin;
768 
769     command = (aNeighbor == nullptr || aNeighbor->IsStateValid()) ? kCommandLinkAccept : kCommandLinkAcceptAndRequest;
770 
771     VerifyOrExit((message = NewMleMessage(command)) != nullptr, error = kErrorNoBufs);
772     SuccessOrExit(error = message->AppendVersionTlv());
773     SuccessOrExit(error = message->AppendSourceAddressTlv());
774     SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
775     SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
776     SuccessOrExit(error = message->AppendMleFrameCounterTlv());
777 
778     // always append a link margin, regardless of whether or not it was requested
779     linkMargin = Get<Mac::Mac>().ComputeLinkMargin(aMessageInfo.GetThreadLinkInfo()->GetRss());
780 
781     SuccessOrExit(error = message->AppendLinkMarginTlv(linkMargin));
782 
783     if (aNeighbor != nullptr && IsActiveRouter(aNeighbor->GetRloc16()))
784     {
785         SuccessOrExit(error = message->AppendLeaderDataTlv());
786     }
787 
788     for (uint8_t tlvType : aRequestedTlvList)
789     {
790         switch (tlvType)
791         {
792         case Tlv::kRoute:
793             SuccessOrExit(error = message->AppendRouteTlv(aNeighbor));
794             break;
795 
796         case Tlv::kAddress16:
797             VerifyOrExit(aNeighbor != nullptr, error = kErrorDrop);
798             SuccessOrExit(error = message->AppendAddress16Tlv(aNeighbor->GetRloc16()));
799             break;
800 
801         case Tlv::kLinkMargin:
802             break;
803 
804         default:
805             ExitNow(error = kErrorDrop);
806         }
807     }
808 
809     if (aNeighbor != nullptr && !aNeighbor->IsStateValid())
810     {
811         aNeighbor->GenerateChallenge();
812 
813         SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge()));
814         SuccessOrExit(error = message->AppendTlvRequestTlv(kRouterTlvs));
815         aNeighbor->SetLastHeard(TimerMilli::GetNow());
816         aNeighbor->SetState(Neighbor::kStateLinkRequest);
817     }
818 
819 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
820     if (aNeighbor != nullptr && aNeighbor->IsTimeSyncEnabled())
821     {
822         message->SetTimeSync(true);
823     }
824 #endif
825 
826     if (aMessageInfo.GetSockAddr().IsMulticast())
827     {
828         SuccessOrExit(error = message->SendAfterDelay(aMessageInfo.GetPeerAddr(),
829                                                       1 + Random::NonCrypto::GetUint16InRange(0, kMaxLinkAcceptDelay)));
830 
831         Log(kMessageDelay, (command == kCommandLinkAccept) ? kTypeLinkAccept : kTypeLinkAcceptAndRequest,
832             aMessageInfo.GetPeerAddr());
833     }
834     else
835     {
836         SuccessOrExit(error = message->SendTo(aMessageInfo.GetPeerAddr()));
837 
838         Log(kMessageSend, (command == kCommandLinkAccept) ? kTypeLinkAccept : kTypeLinkAcceptAndRequest,
839             aMessageInfo.GetPeerAddr());
840     }
841 
842 exit:
843     FreeMessageOnError(message, error);
844     return error;
845 }
846 
HandleLinkAccept(RxInfo & aRxInfo)847 void MleRouter::HandleLinkAccept(RxInfo &aRxInfo)
848 {
849     Error error = HandleLinkAccept(aRxInfo, false);
850 
851     LogProcessError(kTypeLinkAccept, error);
852 }
853 
HandleLinkAcceptAndRequest(RxInfo & aRxInfo)854 void MleRouter::HandleLinkAcceptAndRequest(RxInfo &aRxInfo)
855 {
856     Error error = HandleLinkAccept(aRxInfo, true);
857 
858     LogProcessError(kTypeLinkAcceptAndRequest, error);
859 }
860 
HandleLinkAccept(RxInfo & aRxInfo,bool aRequest)861 Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
862 {
863     Error           error = kErrorNone;
864     Router         *router;
865     Neighbor::State neighborState;
866     uint16_t        version;
867     RxChallenge     response;
868     uint16_t        sourceAddress;
869     uint32_t        linkFrameCounter;
870     uint32_t        mleFrameCounter;
871     uint8_t         routerId;
872     uint16_t        address16;
873     RouteTlv        routeTlv;
874     LeaderData      leaderData;
875     uint8_t         linkMargin;
876 
877     // Source Address
878     SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
879 
880     Log(kMessageReceive, aRequest ? kTypeLinkAcceptAndRequest : kTypeLinkAccept, aRxInfo.mMessageInfo.GetPeerAddr(),
881         sourceAddress);
882 
883     VerifyOrExit(IsActiveRouter(sourceAddress), error = kErrorParse);
884 
885     routerId      = RouterIdFromRloc16(sourceAddress);
886     router        = mRouterTable.FindRouterById(routerId);
887     neighborState = (router != nullptr) ? router->GetState() : Neighbor::kStateInvalid;
888 
889     // Response
890     SuccessOrExit(error = aRxInfo.mMessage.ReadResponseTlv(response));
891 
892     // verify response
893     switch (neighborState)
894     {
895     case Neighbor::kStateLinkRequest:
896         VerifyOrExit(response == router->GetChallenge(), error = kErrorSecurity);
897         break;
898 
899     case Neighbor::kStateInvalid:
900         VerifyOrExit((mLinkRequestAttempts > 0 || mChallengeTimeout > 0) && (response == mChallenge),
901                      error = kErrorSecurity);
902 
903         OT_FALL_THROUGH;
904 
905     case Neighbor::kStateValid:
906         break;
907 
908     default:
909         ExitNow(error = kErrorSecurity);
910     }
911 
912     // Remove stale neighbors
913     if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != sourceAddress)
914     {
915         RemoveNeighbor(*aRxInfo.mNeighbor);
916     }
917 
918     // Version
919     SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
920     VerifyOrExit(version >= kThreadVersion1p1, error = kErrorParse);
921 
922     // Link and MLE Frame Counters
923     SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
924 
925     // Link Margin
926     switch (Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMargin))
927     {
928     case kErrorNone:
929         break;
930     case kErrorNotFound:
931         // Link Margin TLV may be skipped in Router Synchronization process after Reset
932         VerifyOrExit(IsDetached(), error = kErrorNotFound);
933         // Wait for an MLE Advertisement to establish a routing cost to the neighbor
934         linkMargin = 0;
935         break;
936     default:
937         ExitNow(error = kErrorParse);
938     }
939 
940     switch (mRole)
941     {
942     case kRoleDetached:
943         // Address16
944         SuccessOrExit(error = Tlv::Find<Address16Tlv>(aRxInfo.mMessage, address16));
945         VerifyOrExit(GetRloc16() == address16, error = kErrorDrop);
946 
947         // Leader Data
948         SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
949         SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
950 
951         // Route
952         mRouterTable.Clear();
953         SuccessOrExit(error = aRxInfo.mMessage.ReadRouteTlv(routeTlv));
954         SuccessOrExit(error = ProcessRouteTlv(routeTlv, aRxInfo));
955         router = mRouterTable.FindRouterById(routerId);
956         VerifyOrExit(router != nullptr);
957 
958         if (mLeaderData.GetLeaderRouterId() == RouterIdFromRloc16(GetRloc16()))
959         {
960             SetStateLeader(GetRloc16(), kRestoringLeaderRoleAfterReset);
961         }
962         else
963         {
964             SetStateRouter(GetRloc16());
965         }
966 
967         mLinkRequestAttempts    = 0; // completed router sync after reset, no more link request to retransmit
968         mRetrieveNewNetworkData = true;
969         IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr()));
970 
971 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
972         Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
973 #endif
974         break;
975 
976     case kRoleChild:
977         VerifyOrExit(router != nullptr);
978         break;
979 
980     case kRoleRouter:
981     case kRoleLeader:
982         VerifyOrExit(router != nullptr);
983 
984         // Leader Data
985         SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
986         VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
987 
988         if (mRetrieveNewNetworkData ||
989             SerialNumber::IsGreater(leaderData.GetDataVersion(NetworkData::kFullSet),
990                                     Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet)))
991         {
992             IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr()));
993         }
994 
995         // Route (optional)
996         switch (aRxInfo.mMessage.ReadRouteTlv(routeTlv))
997         {
998         case kErrorNone:
999             VerifyOrExit(routeTlv.IsRouterIdSet(routerId), error = kErrorParse);
1000 
1001             if (mRouterTable.IsRouteTlvIdSequenceMoreRecent(routeTlv))
1002             {
1003                 SuccessOrExit(error = ProcessRouteTlv(routeTlv, aRxInfo));
1004                 router = mRouterTable.FindRouterById(routerId);
1005                 OT_ASSERT(router != nullptr);
1006             }
1007 
1008             mRouterTable.UpdateRoutes(routeTlv, routerId);
1009             break;
1010 
1011         case kErrorNotFound:
1012             break;
1013 
1014         default:
1015             ExitNow(error = kErrorParse);
1016         }
1017 
1018         if (routerId != mRouterId && !IsRouterIdValid(router->GetNextHop()))
1019         {
1020             ResetAdvertiseInterval();
1021         }
1022 
1023         break;
1024 
1025     case kRoleDisabled:
1026         OT_ASSERT(false);
1027     }
1028 
1029     // finish link synchronization
1030     InitNeighbor(*router, aRxInfo);
1031     router->SetRloc16(sourceAddress);
1032     router->GetLinkFrameCounters().SetAll(linkFrameCounter);
1033     router->SetLinkAckFrameCounter(linkFrameCounter);
1034     router->SetMleFrameCounter(mleFrameCounter);
1035     router->SetVersion(version);
1036     router->SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
1037                                      DeviceMode::kModeFullNetworkData));
1038     router->SetLinkQualityOut(LinkQualityForLinkMargin(linkMargin));
1039     router->SetState(Neighbor::kStateValid);
1040     router->SetKeySequence(aRxInfo.mKeySequence);
1041 
1042     mNeighborTable.Signal(NeighborTable::kRouterAdded, *router);
1043 
1044     aRxInfo.mClass = RxInfo::kAuthoritativeMessage;
1045     ProcessKeySequence(aRxInfo);
1046 
1047     if (aRequest)
1048     {
1049         RxChallenge challenge;
1050         TlvList     requestedTlvList;
1051 
1052         // Challenge
1053         SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
1054 
1055         // TLV Request
1056         switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
1057         {
1058         case kErrorNone:
1059         case kErrorNotFound:
1060             break;
1061         default:
1062             ExitNow(error = kErrorParse);
1063         }
1064 
1065         SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, router, requestedTlvList, challenge));
1066     }
1067 
1068 exit:
1069     return error;
1070 }
1071 
ProcessRouteTlv(const RouteTlv & aRouteTlv,RxInfo & aRxInfo)1072 Error MleRouter::ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo)
1073 {
1074     // This method processes `aRouteTlv` read from an MLE message.
1075     //
1076     // During processing of Route TLV, the entries in the router table
1077     // may shuffle. This method ensures that the `aRxInfo.mNeighbor`
1078     // (which indicates the neighbor from which the MLE message was
1079     // received) is correctly updated to point to the same neighbor
1080     // (in case `mNeighbor` was pointing to a router entry from the
1081     // `RouterTable`).
1082 
1083     Error    error          = kErrorNone;
1084     uint16_t neighborRloc16 = Mac::kShortAddrInvalid;
1085 
1086     if ((aRxInfo.mNeighbor != nullptr) && Get<RouterTable>().Contains(*aRxInfo.mNeighbor))
1087     {
1088         neighborRloc16 = aRxInfo.mNeighbor->GetRloc16();
1089     }
1090 
1091     mRouterTable.UpdateRouterIdSet(aRouteTlv.GetRouterIdSequence(), aRouteTlv.GetRouterIdMask());
1092 
1093     if (IsRouter() && !mRouterTable.IsAllocated(mRouterId))
1094     {
1095         IgnoreError(BecomeDetached());
1096         error = kErrorNoRoute;
1097     }
1098 
1099     if (neighborRloc16 != Mac::kShortAddrInvalid)
1100     {
1101         aRxInfo.mNeighbor = Get<NeighborTable>().FindNeighbor(neighborRloc16);
1102     }
1103 
1104     return error;
1105 }
1106 
ReadAndProcessRouteTlvOnFed(RxInfo & aRxInfo,uint8_t aParentId)1107 Error MleRouter::ReadAndProcessRouteTlvOnFed(RxInfo &aRxInfo, uint8_t aParentId)
1108 {
1109     // This method reads and processes Route TLV from message on an
1110     // FED if message contains one. It returns `kErrorNone` when
1111     // successfully processed or if there is no Route TLV in the
1112     // message.
1113     //
1114     // It MUST be used only when device is acting as a child and
1115     // for a message received from device's current parent.
1116 
1117     Error    error = kErrorNone;
1118     RouteTlv routeTlv;
1119 
1120     VerifyOrExit(IsFullThreadDevice());
1121 
1122     switch (aRxInfo.mMessage.ReadRouteTlv(routeTlv))
1123     {
1124     case kErrorNone:
1125         SuccessOrExit(error = ProcessRouteTlv(routeTlv, aRxInfo));
1126         mRouterTable.UpdateRoutesOnFed(routeTlv, aParentId);
1127         mRequestRouteTlv = false;
1128         break;
1129     case kErrorNotFound:
1130         break;
1131     default:
1132         ExitNow(error = kErrorParse);
1133     }
1134 
1135 exit:
1136     return error;
1137 }
1138 
IsSingleton(void) const1139 bool MleRouter::IsSingleton(void) const
1140 {
1141     bool isSingleton = true;
1142 
1143     VerifyOrExit(IsAttached() && IsRouterEligible());
1144     isSingleton = (mRouterTable.GetActiveRouterCount() <= 1);
1145 
1146 exit:
1147     return isSingleton;
1148 }
1149 
ComparePartitions(bool aSingletonA,const LeaderData & aLeaderDataA,bool aSingletonB,const LeaderData & aLeaderDataB)1150 int MleRouter::ComparePartitions(bool              aSingletonA,
1151                                  const LeaderData &aLeaderDataA,
1152                                  bool              aSingletonB,
1153                                  const LeaderData &aLeaderDataB)
1154 {
1155     int rval = 0;
1156 
1157     rval = ThreeWayCompare(aLeaderDataA.GetWeighting(), aLeaderDataB.GetWeighting());
1158     VerifyOrExit(rval == 0);
1159 
1160     // Not being a singleton is better.
1161     rval = ThreeWayCompare(!aSingletonA, !aSingletonB);
1162     VerifyOrExit(rval == 0);
1163 
1164     rval = ThreeWayCompare(aLeaderDataA.GetPartitionId(), aLeaderDataB.GetPartitionId());
1165 
1166 exit:
1167     return rval;
1168 }
1169 
HandleAdvertisement(RxInfo & aRxInfo,uint16_t aSourceAddress,const LeaderData & aLeaderData)1170 Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData)
1171 {
1172     // This method processes a received MLE Advertisement message on
1173     // an FTD device. It is called from `Mle::HandleAdvertisement()`
1174     // only when device is attached (in child, router, or leader roles)
1175     // and `IsFullThreadDevice()`.
1176     //
1177     // - `aSourceAddress` is the read value from `SourceAddressTlv`.
1178     // - `aLeaderData` is the read value from `LeaderDataTlv`.
1179 
1180     Error    error      = kErrorNone;
1181     uint8_t  linkMargin = Get<Mac::Mac>().ComputeLinkMargin(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
1182     RouteTlv routeTlv;
1183     Router  *router;
1184     uint8_t  routerId;
1185 
1186     switch (aRxInfo.mMessage.ReadRouteTlv(routeTlv))
1187     {
1188     case kErrorNone:
1189         break;
1190     case kErrorNotFound:
1191         routeTlv.SetLength(0); // Mark that a Route TLV was not included.
1192         break;
1193     default:
1194         ExitNow(error = kErrorParse);
1195     }
1196 
1197     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1198     // Handle Partition ID mismatch
1199 
1200     if (aLeaderData.GetPartitionId() != mLeaderData.GetPartitionId())
1201     {
1202         LogNote("Different partition (peer:%lu, local:%lu)", ToUlong(aLeaderData.GetPartitionId()),
1203                 ToUlong(mLeaderData.GetPartitionId()));
1204 
1205         VerifyOrExit(linkMargin >= kPartitionMergeMinMargin, error = kErrorLinkMarginLow);
1206 
1207         if (routeTlv.IsValid() && (mPreviousPartitionIdTimeout > 0) &&
1208             (aLeaderData.GetPartitionId() == mPreviousPartitionId))
1209         {
1210             VerifyOrExit(SerialNumber::IsGreater(routeTlv.GetRouterIdSequence(), mPreviousPartitionRouterIdSequence),
1211                          error = kErrorDrop);
1212         }
1213 
1214         if (IsChild() && (aRxInfo.mNeighbor == &mParent))
1215         {
1216             ExitNow();
1217         }
1218 
1219         if (ComparePartitions(routeTlv.IsSingleton(), aLeaderData, IsSingleton(), mLeaderData) > 0
1220 #if OPENTHREAD_CONFIG_TIME_SYNC_REQUIRED
1221             // if time sync is required, it will only migrate to a better network which also enables time sync.
1222             && aRxInfo.mMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ
1223 #endif
1224         )
1225         {
1226             Attach(kBetterPartition);
1227         }
1228 
1229         ExitNow(error = kErrorDrop);
1230     }
1231 
1232     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1233     // Handle Leader Router ID mismatch
1234 
1235     if (aLeaderData.GetLeaderRouterId() != GetLeaderId())
1236     {
1237         VerifyOrExit(aRxInfo.IsNeighborStateValid());
1238 
1239         if (!IsChild())
1240         {
1241             LogInfo("Leader ID mismatch");
1242             IgnoreError(BecomeDetached());
1243             error = kErrorDrop;
1244         }
1245 
1246         ExitNow();
1247     }
1248 
1249     VerifyOrExit(IsActiveRouter(aSourceAddress) && routeTlv.IsValid());
1250     routerId = RouterIdFromRloc16(aSourceAddress);
1251 
1252 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1253     Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
1254 #endif
1255 
1256     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1257     // Process `RouteTlv`
1258 
1259     if (aRxInfo.IsNeighborStateValid() && mRouterTable.IsRouteTlvIdSequenceMoreRecent(routeTlv))
1260     {
1261         SuccessOrExit(error = ProcessRouteTlv(routeTlv, aRxInfo));
1262     }
1263 
1264     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1265     // Update routers as a child
1266 
1267     if (IsChild())
1268     {
1269         if (aRxInfo.mNeighbor == &mParent)
1270         {
1271             // MLE Advertisement from parent
1272             router = &mParent;
1273 
1274             if (mParent.GetRloc16() != aSourceAddress)
1275             {
1276                 IgnoreError(BecomeDetached());
1277                 ExitNow(error = kErrorDetached);
1278             }
1279 
1280             if (!mRouterRoleTransition.IsPending() && (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold))
1281             {
1282                 mRouterRoleTransition.StartTimeout();
1283             }
1284 
1285             mRouterTable.UpdateRoutesOnFed(routeTlv, routerId);
1286         }
1287         else
1288         {
1289             // MLE Advertisement not from parent, but from some other neighboring router
1290             router = mRouterTable.FindRouterById(routerId);
1291             VerifyOrExit(router != nullptr);
1292 
1293             if (!router->IsStateValid() && !router->IsStateLinkRequest() &&
1294                 (mRouterTable.GetNeighborCount(kLinkQuality1) < mChildRouterLinks))
1295             {
1296                 InitNeighbor(*router, aRxInfo);
1297                 router->SetState(Neighbor::kStateLinkRequest);
1298                 IgnoreError(SendLinkRequest(router));
1299                 ExitNow(error = kErrorNoRoute);
1300             }
1301         }
1302 
1303         router->SetLastHeard(TimerMilli::GetNow());
1304 
1305         ExitNow();
1306     }
1307 
1308     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1309     // Update routers as a router or leader.
1310 
1311     if (IsRouter() && ShouldDowngrade(routerId, routeTlv))
1312     {
1313         mRouterRoleTransition.StartTimeout();
1314     }
1315 
1316     router = mRouterTable.FindRouterById(routerId);
1317     VerifyOrExit(router != nullptr);
1318 
1319     if (!router->IsStateValid() && aRxInfo.IsNeighborStateValid() && Get<ChildTable>().Contains(*aRxInfo.mNeighbor))
1320     {
1321         // The Adv is from a former child that is now acting as a router,
1322         // we copy the info from child entry and update the RLOC16.
1323 
1324         *static_cast<Neighbor *>(router) = *aRxInfo.mNeighbor;
1325         router->SetRloc16(Rloc16FromRouterId(routerId));
1326         router->SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
1327                                          DeviceMode::kModeFullNetworkData));
1328 
1329         mNeighborTable.Signal(NeighborTable::kRouterAdded, *router);
1330 
1331         // Change the cache entries associated with the former child
1332         // from using the old RLOC16 to its new RLOC16.
1333         Get<AddressResolver>().ReplaceEntriesForRloc16(aRxInfo.mNeighbor->GetRloc16(), router->GetRloc16());
1334     }
1335 
1336     // Send unicast link request if no link to router and no unicast/multicast link request in progress
1337     if (!router->IsStateValid() && !router->IsStateLinkRequest() && (mChallengeTimeout == 0) &&
1338         (linkMargin >= kLinkRequestMinMargin))
1339     {
1340         InitNeighbor(*router, aRxInfo);
1341         router->SetState(Neighbor::kStateLinkRequest);
1342         IgnoreError(SendLinkRequest(router));
1343         ExitNow(error = kErrorNoRoute);
1344     }
1345 
1346     router->SetLastHeard(TimerMilli::GetNow());
1347 
1348     mRouterTable.UpdateRoutes(routeTlv, routerId);
1349 
1350 exit:
1351     if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != aSourceAddress)
1352     {
1353         // Remove stale neighbors
1354         RemoveNeighbor(*aRxInfo.mNeighbor);
1355     }
1356 
1357     return error;
1358 }
1359 
HandleParentRequest(RxInfo & aRxInfo)1360 void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
1361 {
1362     Error           error = kErrorNone;
1363     Mac::ExtAddress extAddr;
1364     uint16_t        version;
1365     uint8_t         scanMask;
1366     RxChallenge     challenge;
1367     Child          *child;
1368     uint8_t         modeBitmask;
1369     DeviceMode      mode;
1370 
1371     Log(kMessageReceive, kTypeParentRequest, aRxInfo.mMessageInfo.GetPeerAddr());
1372 
1373     VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
1374 
1375     // A Router/REED MUST NOT send an MLE Parent Response if:
1376 
1377     // 0. It is detached or attempting to another partition
1378     VerifyOrExit(!IsDetached() && !IsAttaching(), error = kErrorDrop);
1379 
1380     // 1. It has no available Child capacity (if Max Child Count minus
1381     // Child Count would be equal to zero)
1382     // ==> verified below when allocating a child entry
1383 
1384     // 2. It is disconnected from its Partition (that is, it has not
1385     // received an updated ID sequence number within LEADER_TIMEOUT
1386     // seconds)
1387     VerifyOrExit(mRouterTable.GetLeaderAge() < mNetworkIdTimeout, error = kErrorDrop);
1388 
1389     // 3. Its current routing path cost to the Leader is infinite.
1390     VerifyOrExit(mRouterTable.GetPathCostToLeader() < kMaxRouteCost, error = kErrorDrop);
1391 
1392     // 4. It is a REED and there are already `kMaxRouters` active routers in
1393     // the network (because Leader would reject any further address solicit).
1394     // ==> Verified below when checking the scan mask.
1395 
1396     aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
1397 
1398     // Version
1399     SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
1400     VerifyOrExit(version >= kThreadVersion1p1, error = kErrorParse);
1401 
1402     // Scan Mask
1403     SuccessOrExit(error = Tlv::Find<ScanMaskTlv>(aRxInfo.mMessage, scanMask));
1404 
1405     switch (mRole)
1406     {
1407     case kRoleDisabled:
1408     case kRoleDetached:
1409         ExitNow();
1410 
1411     case kRoleChild:
1412         VerifyOrExit(ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
1413         VerifyOrExit(mRouterTable.GetActiveRouterCount() < kMaxRouters, error = kErrorDrop);
1414         break;
1415 
1416     case kRoleRouter:
1417     case kRoleLeader:
1418         VerifyOrExit(ScanMaskTlv::IsRouterFlagSet(scanMask));
1419         break;
1420     }
1421 
1422     // Challenge
1423     SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
1424 
1425     child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
1426 
1427     if (child == nullptr)
1428     {
1429         VerifyOrExit((child = mChildTable.GetNewChild()) != nullptr, error = kErrorNoBufs);
1430 
1431         // MAC Address
1432         InitNeighbor(*child, aRxInfo);
1433         child->SetState(Neighbor::kStateParentRequest);
1434 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1435         child->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aRxInfo.mMessage, nullptr, 0) == kErrorNone);
1436 #endif
1437         if (Tlv::Find<ModeTlv>(aRxInfo.mMessage, modeBitmask) == kErrorNone)
1438         {
1439             mode.Set(modeBitmask);
1440             child->SetDeviceMode(mode);
1441             child->SetVersion(version);
1442         }
1443     }
1444     else if (TimerMilli::GetNow() - child->GetLastHeard() < kParentRequestRouterTimeout - kParentRequestDuplicateMargin)
1445     {
1446         ExitNow(error = kErrorDuplicated);
1447     }
1448 
1449     if (!child->IsStateValidOrRestoring())
1450     {
1451         child->SetLastHeard(TimerMilli::GetNow());
1452         child->SetTimeout(Time::MsecToSec(kChildIdRequestTimeout));
1453     }
1454 
1455     aRxInfo.mClass = RxInfo::kPeerMessage;
1456     ProcessKeySequence(aRxInfo);
1457 
1458     SendParentResponse(child, challenge, !ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
1459 
1460 exit:
1461     LogProcessError(kTypeParentRequest, error);
1462 }
1463 
HasNeighborWithGoodLinkQuality(void) const1464 bool MleRouter::HasNeighborWithGoodLinkQuality(void) const
1465 {
1466     bool    haveNeighbor = true;
1467     uint8_t linkMargin;
1468 
1469     linkMargin = Get<Mac::Mac>().ComputeLinkMargin(mParent.GetLinkInfo().GetLastRss());
1470 
1471     if (linkMargin >= kLinkRequestMinMargin)
1472     {
1473         ExitNow();
1474     }
1475 
1476     for (const Router &router : Get<RouterTable>())
1477     {
1478         if (!router.IsStateValid())
1479         {
1480             continue;
1481         }
1482 
1483         linkMargin = Get<Mac::Mac>().ComputeLinkMargin(router.GetLinkInfo().GetLastRss());
1484 
1485         if (linkMargin >= kLinkRequestMinMargin)
1486         {
1487             ExitNow();
1488         }
1489     }
1490 
1491     haveNeighbor = false;
1492 
1493 exit:
1494     return haveNeighbor;
1495 }
1496 
HandleTimeTick(void)1497 void MleRouter::HandleTimeTick(void)
1498 {
1499     bool roleTransitionTimeoutExpired = false;
1500 
1501     VerifyOrExit(IsFullThreadDevice(), Get<TimeTicker>().UnregisterReceiver(TimeTicker::kMleRouter));
1502 
1503     if (mChallengeTimeout > 0)
1504     {
1505         mChallengeTimeout--;
1506     }
1507 
1508     if (mPreviousPartitionIdTimeout > 0)
1509     {
1510         mPreviousPartitionIdTimeout--;
1511     }
1512 
1513     roleTransitionTimeoutExpired = mRouterRoleTransition.HandleTimeTick();
1514 
1515     switch (mRole)
1516     {
1517     case kRoleDetached:
1518         if (mChallengeTimeout == 0 && mLinkRequestAttempts == 0)
1519         {
1520             IgnoreError(BecomeDetached());
1521             ExitNow();
1522         }
1523 
1524         break;
1525 
1526     case kRoleChild:
1527         if (roleTransitionTimeoutExpired)
1528         {
1529             if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold && HasNeighborWithGoodLinkQuality())
1530             {
1531                 IgnoreError(BecomeRouter(ThreadStatusTlv::kTooFewRouters));
1532             }
1533             else
1534             {
1535                 // send announce after decided to stay in REED if needed
1536                 InformPreviousChannel();
1537             }
1538 
1539             if (!mAdvertiseTrickleTimer.IsRunning())
1540             {
1541                 SendAdvertisement();
1542 
1543                 mAdvertiseTrickleTimer.Start(TrickleTimer::kModePlainTimer, kReedAdvIntervalMin, kReedAdvIntervalMax);
1544             }
1545 
1546             ExitNow();
1547         }
1548 
1549         OT_FALL_THROUGH;
1550 
1551     case kRoleRouter:
1552         LogDebg("network id timeout = %lu", ToUlong(mRouterTable.GetLeaderAge()));
1553 
1554         if ((mRouterTable.GetActiveRouterCount() > 0) && (mRouterTable.GetLeaderAge() >= mNetworkIdTimeout))
1555         {
1556             LogInfo("Router ID Sequence timeout");
1557             Attach(kSamePartition);
1558         }
1559 
1560         if (roleTransitionTimeoutExpired && mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold)
1561         {
1562             LogNote("Downgrade to REED");
1563             Attach(kDowngradeToReed);
1564         }
1565 
1566         OT_FALL_THROUGH;
1567 
1568     case kRoleLeader:
1569         if (roleTransitionTimeoutExpired && !IsRouterEligible())
1570         {
1571             LogInfo("No longer router eligible");
1572             IgnoreError(BecomeDetached());
1573         }
1574 
1575         break;
1576 
1577     case kRoleDisabled:
1578         OT_ASSERT(false);
1579     }
1580 
1581     // update children state
1582     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
1583     {
1584         uint32_t timeout = 0;
1585 
1586         switch (child.GetState())
1587         {
1588         case Neighbor::kStateInvalid:
1589         case Neighbor::kStateChildIdRequest:
1590             continue;
1591 
1592         case Neighbor::kStateParentRequest:
1593         case Neighbor::kStateValid:
1594         case Neighbor::kStateRestored:
1595         case Neighbor::kStateChildUpdateRequest:
1596             timeout = Time::SecToMsec(child.GetTimeout());
1597             break;
1598 
1599         case Neighbor::kStateParentResponse:
1600         case Neighbor::kStateLinkRequest:
1601             OT_ASSERT(false);
1602         }
1603 
1604 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1605         if (child.IsCslSynchronized() &&
1606             TimerMilli::GetNow() - child.GetCslLastHeard() >= Time::SecToMsec(child.GetCslTimeout()))
1607         {
1608             LogInfo("Child CSL synchronization expired");
1609             child.SetCslSynchronized(false);
1610             Get<CslTxScheduler>().Update();
1611         }
1612 #endif
1613 
1614         if (TimerMilli::GetNow() - child.GetLastHeard() >= timeout)
1615         {
1616             LogInfo("Child timeout expired");
1617             RemoveNeighbor(child);
1618         }
1619         else if (IsRouterOrLeader() && child.IsStateRestored())
1620         {
1621             IgnoreError(SendChildUpdateRequest(child));
1622         }
1623     }
1624 
1625     // update router state
1626     for (Router &router : Get<RouterTable>())
1627     {
1628         uint32_t age;
1629 
1630         if (router.GetRloc16() == GetRloc16())
1631         {
1632             router.SetLastHeard(TimerMilli::GetNow());
1633             continue;
1634         }
1635 
1636         age = TimerMilli::GetNow() - router.GetLastHeard();
1637 
1638         if (router.IsStateValid())
1639         {
1640 #if OPENTHREAD_CONFIG_MLE_SEND_LINK_REQUEST_ON_ADV_TIMEOUT == 0
1641 
1642             if (age >= kMaxNeighborAge)
1643             {
1644                 LogInfo("Router timeout expired");
1645                 RemoveNeighbor(router);
1646                 continue;
1647             }
1648 
1649 #else
1650 
1651             if (age >= kMaxNeighborAge)
1652             {
1653                 if (age < kMaxNeighborAge + kMaxTxCount * kUnicastRetxDelay)
1654                 {
1655                     LogInfo("Router timeout expired");
1656                     IgnoreError(SendLinkRequest(&router));
1657                 }
1658                 else
1659                 {
1660                     RemoveNeighbor(router);
1661                     continue;
1662                 }
1663             }
1664 
1665 #endif
1666         }
1667         else if (router.IsStateLinkRequest())
1668         {
1669             if (age >= kLinkRequestTimeout)
1670             {
1671                 LogInfo("Link Request timeout expired");
1672                 RemoveNeighbor(router);
1673                 continue;
1674             }
1675         }
1676 
1677         if (IsLeader())
1678         {
1679             if (mRouterTable.FindNextHopOf(router) == nullptr && mRouterTable.GetLinkCost(router) >= kMaxRouteCost &&
1680                 age >= kMaxLeaderToRouterTimeout)
1681             {
1682                 LogInfo("Router ID timeout expired (no route)");
1683                 IgnoreError(mRouterTable.Release(router.GetRouterId()));
1684             }
1685         }
1686     }
1687 
1688     mRouterTable.HandleTimeTick();
1689 
1690     SynchronizeChildNetworkData();
1691 
1692 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1693     if (IsRouterOrLeader())
1694     {
1695         Get<TimeSync>().ProcessTimeSync();
1696     }
1697 #endif
1698 
1699 exit:
1700     return;
1701 }
1702 
SendParentResponse(Child * aChild,const RxChallenge & aChallenge,bool aRoutersOnlyRequest)1703 void MleRouter::SendParentResponse(Child *aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest)
1704 {
1705     Error        error = kErrorNone;
1706     Ip6::Address destination;
1707     TxMessage   *message;
1708     uint16_t     delay;
1709 
1710     VerifyOrExit((message = NewMleMessage(kCommandParentResponse)) != nullptr, error = kErrorNoBufs);
1711     message->SetDirectTransmission();
1712 
1713     SuccessOrExit(error = message->AppendSourceAddressTlv());
1714     SuccessOrExit(error = message->AppendLeaderDataTlv());
1715     SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
1716     SuccessOrExit(error = message->AppendMleFrameCounterTlv());
1717     SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
1718 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1719     if (aChild->IsTimeSyncEnabled())
1720     {
1721         SuccessOrExit(error = message->AppendTimeParameterTlv());
1722     }
1723 #endif
1724 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1725     if (aChild->IsThreadVersionCslCapable())
1726     {
1727         SuccessOrExit(error = message->AppendCslClockAccuracyTlv());
1728     }
1729 #endif
1730 
1731     aChild->GenerateChallenge();
1732     SuccessOrExit(error = message->AppendChallengeTlv(aChild->GetChallenge()));
1733     SuccessOrExit(error = message->AppendLinkMarginTlv(aChild->GetLinkInfo().GetLinkMargin()));
1734     SuccessOrExit(error = message->AppendConnectivityTlv());
1735     SuccessOrExit(error = message->AppendVersionTlv());
1736 
1737     destination.SetToLinkLocalAddress(aChild->GetExtAddress());
1738 
1739     delay = 1 + Random::NonCrypto::GetUint16InRange(0, aRoutersOnlyRequest ? kParentResponseMaxDelayRouters
1740                                                                            : kParentResponseMaxDelayAll);
1741 
1742     SuccessOrExit(error = message->SendAfterDelay(destination, delay));
1743 
1744     Log(kMessageDelay, kTypeParentResponse, destination);
1745 
1746 exit:
1747     FreeMessageOnError(message, error);
1748     LogSendError(kTypeParentResponse, error);
1749 }
1750 
GetMaxChildIpAddresses(void) const1751 uint8_t MleRouter::GetMaxChildIpAddresses(void) const
1752 {
1753     uint8_t num = kMaxChildIpAddresses;
1754 
1755 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
1756     if (mMaxChildIpAddresses != 0)
1757     {
1758         num = mMaxChildIpAddresses;
1759     }
1760 #endif
1761 
1762     return num;
1763 }
1764 
1765 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
SetMaxChildIpAddresses(uint8_t aMaxIpAddresses)1766 Error MleRouter::SetMaxChildIpAddresses(uint8_t aMaxIpAddresses)
1767 {
1768     Error error = kErrorNone;
1769 
1770     VerifyOrExit(aMaxIpAddresses <= kMaxChildIpAddresses, error = kErrorInvalidArgs);
1771 
1772     mMaxChildIpAddresses = aMaxIpAddresses;
1773 
1774 exit:
1775     return error;
1776 }
1777 #endif
1778 
ProcessAddressRegistrationTlv(RxInfo & aRxInfo,Child & aChild)1779 Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
1780 {
1781     Error    error;
1782     uint16_t offset;
1783     uint16_t endOffset;
1784     uint8_t  count       = 0;
1785     uint8_t  storedCount = 0;
1786 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
1787     bool         hasOldDua = false;
1788     bool         hasNewDua = false;
1789     Ip6::Address oldDua;
1790 #endif
1791 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
1792     MlrManager::MlrAddressArray oldMlrRegisteredAddresses;
1793 #endif
1794 
1795     SuccessOrExit(error =
1796                       Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kAddressRegistration, offset, endOffset));
1797 
1798 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
1799     {
1800         const Ip6::Address *duaAddress = aChild.GetDomainUnicastAddress();
1801 
1802         if (duaAddress != nullptr)
1803         {
1804             oldDua    = *duaAddress;
1805             hasOldDua = true;
1806         }
1807     }
1808 #endif
1809 
1810 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
1811     // Retrieve registered multicast addresses of the Child
1812     if (aChild.HasAnyMlrRegisteredAddress())
1813     {
1814         OT_ASSERT(aChild.IsStateValid());
1815 
1816         for (const Ip6::Address &childAddress :
1817              aChild.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
1818         {
1819             if (aChild.GetAddressMlrState(childAddress) == kMlrStateRegistered)
1820             {
1821                 IgnoreError(oldMlrRegisteredAddresses.PushBack(childAddress));
1822             }
1823         }
1824     }
1825 #endif
1826 
1827     aChild.ClearIp6Addresses();
1828 
1829     while (offset < endOffset)
1830     {
1831         uint8_t      controlByte;
1832         Ip6::Address address;
1833 
1834         // Read out the control byte (first byte in entry)
1835         SuccessOrExit(error = aRxInfo.mMessage.Read(offset, controlByte));
1836         offset++;
1837         count++;
1838 
1839         address.Clear();
1840 
1841         if (AddressRegistrationTlv::IsEntryCompressed(controlByte))
1842         {
1843             // Compressed entry contains IID with the 64-bit prefix
1844             // determined from 6LoWPAN context identifier (from
1845             // the control byte).
1846 
1847             uint8_t         contextId = AddressRegistrationTlv::GetContextId(controlByte);
1848             Lowpan::Context context;
1849 
1850             VerifyOrExit(offset + sizeof(Ip6::InterfaceIdentifier) <= endOffset, error = kErrorParse);
1851             IgnoreError(aRxInfo.mMessage.Read(offset, address.GetIid()));
1852             offset += sizeof(Ip6::InterfaceIdentifier);
1853 
1854             if (Get<NetworkData::Leader>().GetContext(contextId, context) != kErrorNone)
1855             {
1856                 LogWarn("Failed to get context %u for compressed address from child 0x%04x", contextId,
1857                         aChild.GetRloc16());
1858                 continue;
1859             }
1860 
1861             address.SetPrefix(context.mPrefix);
1862         }
1863         else
1864         {
1865             // Uncompressed entry contains the full IPv6 address.
1866 
1867             VerifyOrExit(offset + sizeof(Ip6::Address) <= endOffset, error = kErrorParse);
1868             IgnoreError(aRxInfo.mMessage.Read(offset, address));
1869             offset += sizeof(Ip6::Address);
1870         }
1871 
1872 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
1873         if (mMaxChildIpAddresses > 0 && storedCount >= mMaxChildIpAddresses)
1874         {
1875             // Skip remaining address registration entries but keep logging skipped addresses.
1876             error = kErrorNoBufs;
1877         }
1878         else
1879 #endif
1880         {
1881             // We try to accept/add as many IPv6 addresses as possible.
1882             // "Child ID/Update Response" will indicate the accepted
1883             // addresses.
1884             error = aChild.AddIp6Address(address);
1885         }
1886 
1887         if (error == kErrorNone)
1888         {
1889             storedCount++;
1890             LogInfo("Child 0x%04x IPv6 address[%u]=%s", aChild.GetRloc16(), storedCount,
1891                     address.ToString().AsCString());
1892         }
1893         else
1894         {
1895             LogWarn("Error %s adding IPv6 address %s to child 0x%04x", ErrorToString(error),
1896                     address.ToString().AsCString(), aChild.GetRloc16());
1897         }
1898 
1899 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
1900         if (Get<BackboneRouter::Leader>().IsDomainUnicast(address))
1901         {
1902             if (error == kErrorNone)
1903             {
1904                 DuaManager::ChildDuaAddressEvent event;
1905 
1906                 hasNewDua = true;
1907 
1908                 if (hasOldDua)
1909                 {
1910                     event = (oldDua != address) ? DuaManager::kAddressChanged : DuaManager::kAddressUnchanged;
1911                 }
1912                 else
1913                 {
1914                     event = DuaManager::kAddressAdded;
1915                 }
1916 
1917                 Get<DuaManager>().HandleChildDuaAddressEvent(aChild, event);
1918             }
1919             else
1920             {
1921                 // if not able to store DUA, then assume child does not have one
1922                 hasNewDua = false;
1923             }
1924         }
1925 #endif
1926 
1927         if (address.IsMulticast())
1928         {
1929             continue;
1930         }
1931 
1932         // We check if the same address is in-use by another child, if so
1933         // remove it. This implements "last-in wins" duplicate address
1934         // resolution policy.
1935         //
1936         // Duplicate addresses can occur if a previously attached child
1937         // attaches to same parent again (after a reset, memory wipe) using
1938         // a new random extended address before the old entry in the child
1939         // table is timed out and then trying to register its globally unique
1940         // IPv6 address as the new child.
1941 
1942         for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
1943         {
1944             if (&child == &aChild)
1945             {
1946                 continue;
1947             }
1948 
1949             IgnoreError(child.RemoveIp6Address(address));
1950         }
1951 
1952         // Clear EID-to-RLOC cache for the unicast address registered by the child.
1953         Get<AddressResolver>().RemoveEntryForAddress(address);
1954     }
1955 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
1956     if (hasOldDua && !hasNewDua)
1957     {
1958         Get<DuaManager>().HandleChildDuaAddressEvent(aChild, DuaManager::kAddressRemoved);
1959     }
1960 #endif
1961 
1962 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
1963     Get<MlrManager>().UpdateProxiedSubscriptions(aChild, oldMlrRegisteredAddresses);
1964 #endif
1965 
1966     if (count == 0)
1967     {
1968         LogInfo("Child 0x%04x has no registered IPv6 address", aChild.GetRloc16());
1969     }
1970     else
1971     {
1972         LogInfo("Child 0x%04x has %u registered IPv6 address%s, %u address%s stored", aChild.GetRloc16(), count,
1973                 (count == 1) ? "" : "es", storedCount, (storedCount == 1) ? "" : "es");
1974     }
1975 
1976     error = kErrorNone;
1977 
1978 exit:
1979     return error;
1980 }
1981 
HandleChildIdRequest(RxInfo & aRxInfo)1982 void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
1983 {
1984     Error              error = kErrorNone;
1985     Mac::ExtAddress    extAddr;
1986     uint16_t           version;
1987     RxChallenge        response;
1988     uint32_t           linkFrameCounter;
1989     uint32_t           mleFrameCounter;
1990     uint8_t            modeBitmask;
1991     DeviceMode         mode;
1992     uint32_t           timeout;
1993     TlvList            tlvList;
1994     MeshCoP::Timestamp timestamp;
1995     Child             *child;
1996     Router            *router;
1997     uint16_t           supervisionInterval;
1998 
1999     Log(kMessageReceive, kTypeChildIdRequest, aRxInfo.mMessageInfo.GetPeerAddr());
2000 
2001     VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
2002 
2003     // only process message when operating as a child, router, or leader
2004     VerifyOrExit(IsAttached(), error = kErrorInvalidState);
2005 
2006     // Find Child
2007     aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
2008 
2009     child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
2010     VerifyOrExit(child != nullptr, error = kErrorAlready);
2011 
2012     // Version
2013     SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
2014     VerifyOrExit(version >= kThreadVersion1p1, error = kErrorParse);
2015 
2016     // Response
2017     SuccessOrExit(error = aRxInfo.mMessage.ReadResponseTlv(response));
2018     VerifyOrExit(response == child->GetChallenge(), error = kErrorSecurity);
2019 
2020     // Remove existing MLE messages
2021     Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleGeneral);
2022     Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleChildIdRequest);
2023     Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleChildUpdateRequest);
2024     Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleDataResponse);
2025 
2026     // Link-Layer and MLE Frame Counters
2027     SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
2028 
2029     // Mode
2030     SuccessOrExit(error = Tlv::Find<ModeTlv>(aRxInfo.mMessage, modeBitmask));
2031     mode.Set(modeBitmask);
2032 
2033     // Timeout
2034     SuccessOrExit(error = Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout));
2035 
2036     // Requested TLVs
2037     SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(tlvList));
2038 
2039     // Supervision interval
2040     switch (Tlv::Find<SupervisionIntervalTlv>(aRxInfo.mMessage, supervisionInterval))
2041     {
2042     case kErrorNone:
2043         tlvList.Add(Tlv::kSupervisionInterval);
2044         break;
2045     case kErrorNotFound:
2046         supervisionInterval = (version <= kThreadVersion1p3) ? kChildSupervisionDefaultIntervalForOlderVersion : 0;
2047         break;
2048     default:
2049         ExitNow(error = kErrorParse);
2050     }
2051 
2052     // Active Timestamp
2053     switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
2054     {
2055     case kErrorNone:
2056         if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) == 0)
2057         {
2058             break;
2059         }
2060 
2061         OT_FALL_THROUGH;
2062 
2063     case kErrorNotFound:
2064         tlvList.Add(Tlv::kActiveDataset);
2065         break;
2066 
2067     default:
2068         ExitNow(error = kErrorParse);
2069     }
2070 
2071     // Pending Timestamp
2072     switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
2073     {
2074     case kErrorNone:
2075         if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDatasetManager>().GetTimestamp()) == 0)
2076         {
2077             break;
2078         }
2079 
2080         OT_FALL_THROUGH;
2081 
2082     case kErrorNotFound:
2083         tlvList.Add(Tlv::kPendingDataset);
2084         break;
2085 
2086     default:
2087         ExitNow(error = kErrorParse);
2088     }
2089 
2090     VerifyOrExit(tlvList.GetLength() <= Child::kMaxRequestTlvs, error = kErrorParse);
2091 
2092     if (!mode.IsFullThreadDevice())
2093     {
2094         SuccessOrExit(error = ProcessAddressRegistrationTlv(aRxInfo, *child));
2095     }
2096 
2097     // Remove from router table
2098     router = mRouterTable.FindRouter(extAddr);
2099 
2100     if (router != nullptr)
2101     {
2102         // The `router` here can be invalid
2103         RemoveNeighbor(*router);
2104     }
2105 
2106     if (!child->IsStateValid())
2107     {
2108         child->SetState(Neighbor::kStateChildIdRequest);
2109     }
2110     else
2111     {
2112         RemoveNeighbor(*child);
2113     }
2114 
2115     child->SetLastHeard(TimerMilli::GetNow());
2116     child->GetLinkFrameCounters().SetAll(linkFrameCounter);
2117     child->SetLinkAckFrameCounter(linkFrameCounter);
2118     child->SetMleFrameCounter(mleFrameCounter);
2119     child->SetKeySequence(aRxInfo.mKeySequence);
2120     child->SetDeviceMode(mode);
2121     child->SetVersion(version);
2122     child->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
2123     child->SetTimeout(timeout);
2124     child->SetSupervisionInterval(supervisionInterval);
2125 #if OPENTHREAD_CONFIG_MULTI_RADIO
2126     child->ClearLastRxFragmentTag();
2127 #endif
2128 
2129     child->SetNetworkDataVersion(mLeaderData.GetDataVersion(mode.GetNetworkDataType()));
2130 
2131     // We already checked above that `tlvList` will fit in
2132     // `child` entry (with `Child::kMaxRequestTlvs` TLVs).
2133 
2134     child->ClearRequestTlvs();
2135 
2136     for (uint8_t index = 0; index < tlvList.GetLength(); index++)
2137     {
2138         child->SetRequestTlv(index, tlvList[index]);
2139     }
2140 
2141     aRxInfo.mClass = RxInfo::kAuthoritativeMessage;
2142     ProcessKeySequence(aRxInfo);
2143 
2144     switch (mRole)
2145     {
2146     case kRoleChild:
2147         child->SetState(Neighbor::kStateChildIdRequest);
2148         IgnoreError(BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest));
2149         break;
2150 
2151     case kRoleRouter:
2152     case kRoleLeader:
2153         SuccessOrExit(error = SendChildIdResponse(*child));
2154         break;
2155 
2156     case kRoleDisabled:
2157     case kRoleDetached:
2158         OT_ASSERT(false);
2159     }
2160 
2161 exit:
2162     LogProcessError(kTypeChildIdRequest, error);
2163 }
2164 
HandleChildUpdateRequest(RxInfo & aRxInfo)2165 void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
2166 {
2167     Error           error = kErrorNone;
2168     Mac::ExtAddress extAddr;
2169     uint8_t         modeBitmask;
2170     DeviceMode      mode;
2171     RxChallenge     challenge;
2172     LeaderData      leaderData;
2173     uint32_t        timeout;
2174     uint16_t        supervisionInterval;
2175     Child          *child;
2176     DeviceMode      oldMode;
2177     TlvList         requestedTlvList;
2178     TlvList         tlvList;
2179     bool            childDidChange = false;
2180 
2181     Log(kMessageReceive, kTypeChildUpdateRequestOfChild, aRxInfo.mMessageInfo.GetPeerAddr());
2182 
2183     // Mode
2184     SuccessOrExit(error = Tlv::Find<ModeTlv>(aRxInfo.mMessage, modeBitmask));
2185     mode.Set(modeBitmask);
2186 
2187     // Challenge
2188     switch (aRxInfo.mMessage.ReadChallengeTlv(challenge))
2189     {
2190     case kErrorNone:
2191         tlvList.Add(Tlv::kResponse);
2192         break;
2193     case kErrorNotFound:
2194         challenge.Clear();
2195         break;
2196     default:
2197         ExitNow(error = kErrorParse);
2198     }
2199 
2200     tlvList.Add(Tlv::kSourceAddress);
2201 
2202     aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
2203     child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
2204 
2205     if (child == nullptr)
2206     {
2207         // For invalid non-sleepy child, send Child Update Response with
2208         // Status TLV (error).
2209         if (mode.IsRxOnWhenIdle())
2210         {
2211             tlvList.Add(Tlv::kStatus);
2212             SendChildUpdateResponse(nullptr, aRxInfo.mMessageInfo, tlvList, challenge);
2213         }
2214 
2215         ExitNow();
2216     }
2217 
2218     // Ignore "Child Update Request" from a child that is present in the
2219     // child table but it is not yet in valid state. For example, a
2220     // child which is being restored (due to parent reset) or is in the
2221     // middle of the attach process (in `kStateParentRequest` or
2222     // `kStateChildIdRequest`).
2223 
2224     VerifyOrExit(child->IsStateValid());
2225 
2226     oldMode = child->GetDeviceMode();
2227     child->SetDeviceMode(mode);
2228 
2229     tlvList.Add(Tlv::kMode);
2230 
2231     // Parent MUST include Leader Data TLV in Child Update Response
2232     tlvList.Add(Tlv::kLeaderData);
2233 
2234     if (!challenge.IsEmpty())
2235     {
2236         tlvList.Add(Tlv::kMleFrameCounter);
2237         tlvList.Add(Tlv::kLinkFrameCounter);
2238     }
2239 
2240     // IPv6 Address TLV
2241     switch (ProcessAddressRegistrationTlv(aRxInfo, *child))
2242     {
2243     case kErrorNone:
2244         tlvList.Add(Tlv::kAddressRegistration);
2245         break;
2246     case kErrorNotFound:
2247         break;
2248     default:
2249         ExitNow(error = kErrorParse);
2250     }
2251 
2252     // Leader Data
2253     switch (aRxInfo.mMessage.ReadLeaderDataTlv(leaderData))
2254     {
2255     case kErrorNone:
2256         child->SetNetworkDataVersion(leaderData.GetDataVersion(child->GetNetworkDataType()));
2257         break;
2258     case kErrorNotFound:
2259         break;
2260     default:
2261         ExitNow(error = kErrorParse);
2262     }
2263 
2264     // Timeout
2265     switch (Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout))
2266     {
2267     case kErrorNone:
2268         if (child->GetTimeout() != timeout)
2269         {
2270             child->SetTimeout(timeout);
2271             childDidChange = true;
2272         }
2273 
2274         tlvList.Add(Tlv::kTimeout);
2275         break;
2276 
2277     case kErrorNotFound:
2278         break;
2279 
2280     default:
2281         ExitNow(error = kErrorParse);
2282     }
2283 
2284     // Supervision interval
2285     switch (Tlv::Find<SupervisionIntervalTlv>(aRxInfo.mMessage, supervisionInterval))
2286     {
2287     case kErrorNone:
2288         tlvList.Add(Tlv::kSupervisionInterval);
2289         break;
2290 
2291     case kErrorNotFound:
2292         supervisionInterval =
2293             (child->GetVersion() <= kThreadVersion1p3) ? kChildSupervisionDefaultIntervalForOlderVersion : 0;
2294         break;
2295 
2296     default:
2297         ExitNow(error = kErrorParse);
2298     }
2299 
2300     child->SetSupervisionInterval(supervisionInterval);
2301 
2302     // TLV Request
2303     switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
2304     {
2305     case kErrorNone:
2306         tlvList.AddElementsFrom(requestedTlvList);
2307         break;
2308     case kErrorNotFound:
2309         break;
2310     default:
2311         ExitNow(error = kErrorParse);
2312     }
2313 
2314 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
2315     if (child->IsCslSynchronized())
2316     {
2317         ChannelTlvValue cslChannelTlvValue;
2318         uint32_t        cslTimeout;
2319 
2320         switch (Tlv::Find<CslTimeoutTlv>(aRxInfo.mMessage, cslTimeout))
2321         {
2322         case kErrorNone:
2323             child->SetCslTimeout(cslTimeout);
2324             // MUST include CSL accuracy TLV when request includes CSL timeout
2325             tlvList.Add(Tlv::kCslClockAccuracy);
2326             break;
2327         case kErrorNotFound:
2328             break;
2329         default:
2330             ExitNow(error = kErrorNone);
2331         }
2332 
2333         if (Tlv::Find<CslChannelTlv>(aRxInfo.mMessage, cslChannelTlvValue) == kErrorNone)
2334         {
2335             // Special value of zero is used to indicate that
2336             // CSL channel is not specified.
2337             child->SetCslChannel(static_cast<uint8_t>(cslChannelTlvValue.GetChannel()));
2338         }
2339     }
2340 #endif // OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
2341 
2342     child->SetLastHeard(TimerMilli::GetNow());
2343 
2344     if (oldMode != child->GetDeviceMode())
2345     {
2346         LogNote("Child 0x%04x mode change 0x%02x -> 0x%02x [%s]", child->GetRloc16(), oldMode.Get(),
2347                 child->GetDeviceMode().Get(), child->GetDeviceMode().ToString().AsCString());
2348 
2349         childDidChange = true;
2350 
2351 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
2352         if (child->IsRxOnWhenIdle())
2353         {
2354             // Clear CSL synchronization state
2355             child->SetCslSynchronized(false);
2356         }
2357 #endif
2358 
2359         // The `IndirectSender::HandleChildModeChange()` needs to happen
2360         // after "Child Update" message is fully parsed to ensure that
2361         // any registered IPv6 addresses included in the "Child Update"
2362         // are added to the child.
2363 
2364         Get<IndirectSender>().HandleChildModeChange(*child, oldMode);
2365     }
2366 
2367     if (childDidChange)
2368     {
2369         IgnoreError(mChildTable.StoreChild(*child));
2370     }
2371 
2372 #if OPENTHREAD_CONFIG_MULTI_RADIO
2373     // We clear the fragment tag only if the "Child Update Request" is
2374     // from a detached child trying to restore its link with its
2375     // parent which is indicated by the presence of Challenge TLV in
2376     // the message.
2377     if (!challenge.IsEmpty())
2378     {
2379         child->ClearLastRxFragmentTag();
2380     }
2381 #endif
2382 
2383     SendChildUpdateResponse(child, aRxInfo.mMessageInfo, tlvList, challenge);
2384 
2385     aRxInfo.mClass = RxInfo::kPeerMessage;
2386 
2387 exit:
2388     LogProcessError(kTypeChildUpdateRequestOfChild, error);
2389 }
2390 
HandleChildUpdateResponse(RxInfo & aRxInfo)2391 void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo)
2392 {
2393     Error       error = kErrorNone;
2394     uint16_t    sourceAddress;
2395     uint32_t    timeout;
2396     RxChallenge response;
2397     uint8_t     status;
2398     uint32_t    linkFrameCounter;
2399     uint32_t    mleFrameCounter;
2400     LeaderData  leaderData;
2401     Child      *child;
2402 
2403     if ((aRxInfo.mNeighbor == nullptr) || IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()) ||
2404         !Get<ChildTable>().Contains(*aRxInfo.mNeighbor))
2405     {
2406         Log(kMessageReceive, kTypeChildUpdateResponseOfUnknownChild, aRxInfo.mMessageInfo.GetPeerAddr());
2407         ExitNow(error = kErrorNotFound);
2408     }
2409 
2410     child = static_cast<Child *>(aRxInfo.mNeighbor);
2411 
2412     // Response
2413     switch (aRxInfo.mMessage.ReadResponseTlv(response))
2414     {
2415     case kErrorNone:
2416         VerifyOrExit(response == child->GetChallenge(), error = kErrorSecurity);
2417         break;
2418     case kErrorNotFound:
2419         VerifyOrExit(child->IsStateValid(), error = kErrorSecurity);
2420         response.Clear();
2421         break;
2422     default:
2423         ExitNow(error = kErrorNone);
2424     }
2425 
2426     Log(kMessageReceive, kTypeChildUpdateResponseOfChild, aRxInfo.mMessageInfo.GetPeerAddr(), child->GetRloc16());
2427 
2428     // Source Address
2429     switch (Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress))
2430     {
2431     case kErrorNone:
2432         if (child->GetRloc16() != sourceAddress)
2433         {
2434             RemoveNeighbor(*child);
2435             ExitNow();
2436         }
2437 
2438         break;
2439 
2440     case kErrorNotFound:
2441         break;
2442 
2443     default:
2444         ExitNow(error = kErrorParse);
2445     }
2446 
2447     // Status
2448     switch (Tlv::Find<StatusTlv>(aRxInfo.mMessage, status))
2449     {
2450     case kErrorNone:
2451         VerifyOrExit(status != StatusTlv::kError, RemoveNeighbor(*child));
2452         break;
2453     case kErrorNotFound:
2454         break;
2455     default:
2456         ExitNow(error = kErrorParse);
2457     }
2458 
2459     // Link-Layer Frame Counter
2460 
2461     switch (Tlv::Find<LinkFrameCounterTlv>(aRxInfo.mMessage, linkFrameCounter))
2462     {
2463     case kErrorNone:
2464         child->GetLinkFrameCounters().SetAll(linkFrameCounter);
2465         child->SetLinkAckFrameCounter(linkFrameCounter);
2466         break;
2467     case kErrorNotFound:
2468         break;
2469     default:
2470         ExitNow(error = kErrorParse);
2471     }
2472 
2473     // MLE Frame Counter
2474     switch (Tlv::Find<MleFrameCounterTlv>(aRxInfo.mMessage, mleFrameCounter))
2475     {
2476     case kErrorNone:
2477         child->SetMleFrameCounter(mleFrameCounter);
2478         break;
2479     case kErrorNotFound:
2480         break;
2481     default:
2482         ExitNow(error = kErrorNone);
2483     }
2484 
2485     // Timeout
2486     switch (Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout))
2487     {
2488     case kErrorNone:
2489         child->SetTimeout(timeout);
2490         break;
2491     case kErrorNotFound:
2492         break;
2493     default:
2494         ExitNow(error = kErrorParse);
2495     }
2496 
2497     {
2498         uint16_t supervisionInterval;
2499 
2500         switch (Tlv::Find<SupervisionIntervalTlv>(aRxInfo.mMessage, supervisionInterval))
2501         {
2502         case kErrorNone:
2503             child->SetSupervisionInterval(supervisionInterval);
2504             break;
2505         case kErrorNotFound:
2506             break;
2507         default:
2508             ExitNow(error = kErrorParse);
2509         }
2510     }
2511 
2512     // IPv6 Address
2513     switch (ProcessAddressRegistrationTlv(aRxInfo, *child))
2514     {
2515     case kErrorNone:
2516     case kErrorNotFound:
2517         break;
2518     default:
2519         ExitNow(error = kErrorParse);
2520     }
2521 
2522     // Leader Data
2523     switch (aRxInfo.mMessage.ReadLeaderDataTlv(leaderData))
2524     {
2525     case kErrorNone:
2526         child->SetNetworkDataVersion(leaderData.GetDataVersion(child->GetNetworkDataType()));
2527         break;
2528     case kErrorNotFound:
2529         break;
2530     default:
2531         ExitNow(error = kErrorParse);
2532     }
2533 
2534     SetChildStateToValid(*child);
2535     child->SetLastHeard(TimerMilli::GetNow());
2536     child->SetKeySequence(aRxInfo.mKeySequence);
2537     child->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
2538 
2539     aRxInfo.mClass = response.IsEmpty() ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage;
2540 
2541 exit:
2542     LogProcessError(kTypeChildUpdateResponseOfChild, error);
2543 }
2544 
HandleDataRequest(RxInfo & aRxInfo)2545 void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
2546 {
2547     Error              error = kErrorNone;
2548     TlvList            tlvList;
2549     MeshCoP::Timestamp timestamp;
2550 
2551     Log(kMessageReceive, kTypeDataRequest, aRxInfo.mMessageInfo.GetPeerAddr());
2552 
2553     VerifyOrExit(aRxInfo.IsNeighborStateValid(), error = kErrorSecurity);
2554 
2555     // TLV Request
2556     SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(tlvList));
2557 
2558     // Active Timestamp
2559     switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
2560     {
2561     case kErrorNone:
2562         if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) == 0)
2563         {
2564             break;
2565         }
2566 
2567         OT_FALL_THROUGH;
2568 
2569     case kErrorNotFound:
2570         tlvList.Add(Tlv::kActiveDataset);
2571         break;
2572 
2573     default:
2574         ExitNow(error = kErrorParse);
2575     }
2576 
2577     // Pending Timestamp
2578     switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
2579     {
2580     case kErrorNone:
2581         if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDatasetManager>().GetTimestamp()) == 0)
2582         {
2583             break;
2584         }
2585 
2586         OT_FALL_THROUGH;
2587 
2588     case kErrorNotFound:
2589         tlvList.Add(Tlv::kPendingDataset);
2590         break;
2591 
2592     default:
2593         ExitNow(error = kErrorParse);
2594     }
2595 
2596     aRxInfo.mClass = RxInfo::kPeerMessage;
2597     ProcessKeySequence(aRxInfo);
2598 
2599     SendDataResponse(aRxInfo.mMessageInfo.GetPeerAddr(), tlvList, /* aDelay */ 0, &aRxInfo.mMessage);
2600 
2601 exit:
2602     LogProcessError(kTypeDataRequest, error);
2603 }
2604 
HandleNetworkDataUpdateRouter(void)2605 void MleRouter::HandleNetworkDataUpdateRouter(void)
2606 {
2607     Ip6::Address destination;
2608     uint16_t     delay;
2609     TlvList      tlvList;
2610 
2611     VerifyOrExit(IsRouterOrLeader());
2612 
2613     destination.SetToLinkLocalAllNodesMulticast();
2614     tlvList.Add(Tlv::kNetworkData);
2615 
2616     delay = IsLeader() ? 0 : Random::NonCrypto::GetUint16InRange(0, kUnsolicitedDataResponseJitter);
2617     SendDataResponse(destination, tlvList, delay);
2618 
2619     SynchronizeChildNetworkData();
2620 
2621 exit:
2622     return;
2623 }
2624 
SynchronizeChildNetworkData(void)2625 void MleRouter::SynchronizeChildNetworkData(void)
2626 {
2627     VerifyOrExit(IsRouterOrLeader());
2628 
2629     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
2630     {
2631         if (child.IsRxOnWhenIdle())
2632         {
2633             continue;
2634         }
2635 
2636         if (child.GetNetworkDataVersion() == Get<NetworkData::Leader>().GetVersion(child.GetNetworkDataType()))
2637         {
2638             continue;
2639         }
2640 
2641         SuccessOrExit(SendChildUpdateRequest(child));
2642     }
2643 
2644 exit:
2645     return;
2646 }
2647 
2648 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
SetSteeringData(const Mac::ExtAddress * aExtAddress)2649 void MleRouter::SetSteeringData(const Mac::ExtAddress *aExtAddress)
2650 {
2651     Mac::ExtAddress nullExtAddr;
2652     Mac::ExtAddress allowAnyExtAddr;
2653 
2654     nullExtAddr.Clear();
2655     allowAnyExtAddr.Fill(0xff);
2656 
2657     if ((aExtAddress == nullptr) || (*aExtAddress == nullExtAddr))
2658     {
2659         mSteeringData.Clear();
2660     }
2661     else if (*aExtAddress == allowAnyExtAddr)
2662     {
2663         mSteeringData.SetToPermitAllJoiners();
2664     }
2665     else
2666     {
2667         Mac::ExtAddress joinerId;
2668 
2669         mSteeringData.Init();
2670         MeshCoP::ComputeJoinerId(*aExtAddress, joinerId);
2671         mSteeringData.UpdateBloomFilter(joinerId);
2672     }
2673 }
2674 #endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
2675 
HandleDiscoveryRequest(RxInfo & aRxInfo)2676 void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
2677 {
2678     Error                        error = kErrorNone;
2679     MeshCoP::Tlv                 meshcopTlv;
2680     MeshCoP::DiscoveryRequestTlv discoveryRequestTlv;
2681     MeshCoP::ExtendedPanId       extPanId;
2682     uint16_t                     offset;
2683     uint16_t                     end;
2684 
2685     Log(kMessageReceive, kTypeDiscoveryRequest, aRxInfo.mMessageInfo.GetPeerAddr());
2686 
2687     discoveryRequestTlv.SetLength(0);
2688 
2689     // only Routers and REEDs respond
2690     VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
2691 
2692     SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kDiscovery, offset, end));
2693 
2694     while (offset < end)
2695     {
2696         IgnoreError(aRxInfo.mMessage.Read(offset, meshcopTlv));
2697 
2698         switch (meshcopTlv.GetType())
2699         {
2700         case MeshCoP::Tlv::kDiscoveryRequest:
2701             IgnoreError(aRxInfo.mMessage.Read(offset, discoveryRequestTlv));
2702             VerifyOrExit(discoveryRequestTlv.IsValid(), error = kErrorParse);
2703 
2704             break;
2705 
2706         case MeshCoP::Tlv::kExtendedPanId:
2707             SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset, extPanId));
2708             VerifyOrExit(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId() != extPanId, error = kErrorDrop);
2709 
2710             break;
2711 
2712         default:
2713             break;
2714         }
2715 
2716         offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
2717     }
2718 
2719     if (discoveryRequestTlv.IsValid())
2720     {
2721         if (mDiscoveryRequestCallback.IsSet())
2722         {
2723             otThreadDiscoveryRequestInfo info;
2724 
2725             aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&info.mExtAddress));
2726             info.mVersion  = discoveryRequestTlv.GetVersion();
2727             info.mIsJoiner = discoveryRequestTlv.IsJoiner();
2728 
2729             mDiscoveryRequestCallback.Invoke(&info);
2730         }
2731 
2732         if (discoveryRequestTlv.IsJoiner())
2733         {
2734 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
2735             if (!mSteeringData.IsEmpty())
2736             {
2737             }
2738             else // if steering data is not set out of band, fall back to network data
2739 #endif
2740             {
2741                 VerifyOrExit(Get<NetworkData::Leader>().IsJoiningAllowed(), error = kErrorSecurity);
2742             }
2743         }
2744     }
2745 
2746     error = SendDiscoveryResponse(aRxInfo.mMessageInfo.GetPeerAddr(), aRxInfo.mMessage);
2747 
2748 exit:
2749     LogProcessError(kTypeDiscoveryRequest, error);
2750 }
2751 
SendDiscoveryResponse(const Ip6::Address & aDestination,const Message & aDiscoverRequestMessage)2752 Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage)
2753 {
2754     Error                         error = kErrorNone;
2755     TxMessage                    *message;
2756     uint16_t                      startOffset;
2757     Tlv                           tlv;
2758     MeshCoP::DiscoveryResponseTlv discoveryResponseTlv;
2759     MeshCoP::NetworkNameTlv       networkNameTlv;
2760     uint16_t                      delay;
2761 
2762     VerifyOrExit((message = NewMleMessage(kCommandDiscoveryResponse)) != nullptr, error = kErrorNoBufs);
2763     message->SetDirectTransmission();
2764     message->SetPanId(aDiscoverRequestMessage.GetPanId());
2765 #if OPENTHREAD_CONFIG_MULTI_RADIO
2766     // Send the MLE Discovery Response message on same radio link
2767     // from which the "MLE Discover Request" message was received.
2768     message->SetRadioType(aDiscoverRequestMessage.GetRadioType());
2769 #endif
2770 
2771     // Discovery TLV
2772     tlv.SetType(Tlv::kDiscovery);
2773     SuccessOrExit(error = message->Append(tlv));
2774 
2775     startOffset = message->GetLength();
2776 
2777     // Discovery Response TLV
2778     discoveryResponseTlv.Init();
2779     discoveryResponseTlv.SetVersion(kThreadVersion);
2780 
2781 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
2782     if (Get<KeyManager>().GetSecurityPolicy().mNativeCommissioningEnabled)
2783     {
2784         SuccessOrExit(
2785             error = Tlv::Append<MeshCoP::CommissionerUdpPortTlv>(*message, Get<MeshCoP::BorderAgent>().GetUdpPort()));
2786 
2787         discoveryResponseTlv.SetNativeCommissioner(true);
2788     }
2789     else
2790 #endif
2791     {
2792         discoveryResponseTlv.SetNativeCommissioner(false);
2793     }
2794 
2795     if (Get<KeyManager>().GetSecurityPolicy().mCommercialCommissioningEnabled)
2796     {
2797         discoveryResponseTlv.SetCommercialCommissioningMode(true);
2798     }
2799 
2800     SuccessOrExit(error = discoveryResponseTlv.AppendTo(*message));
2801 
2802     // Extended PAN ID TLV
2803     SuccessOrExit(
2804         error = Tlv::Append<MeshCoP::ExtendedPanIdTlv>(*message, Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId()));
2805 
2806     // Network Name TLV
2807     networkNameTlv.Init();
2808     networkNameTlv.SetNetworkName(Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsData());
2809     SuccessOrExit(error = networkNameTlv.AppendTo(*message));
2810 
2811     SuccessOrExit(error = message->AppendSteeringDataTlv());
2812 
2813     SuccessOrExit(
2814         error = Tlv::Append<MeshCoP::JoinerUdpPortTlv>(*message, Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort()));
2815 
2816     tlv.SetLength(static_cast<uint8_t>(message->GetLength() - startOffset));
2817     message->Write(startOffset - sizeof(tlv), tlv);
2818 
2819     delay = Random::NonCrypto::GetUint16InRange(0, kDiscoveryMaxJitter + 1);
2820 
2821     SuccessOrExit(error = message->SendAfterDelay(aDestination, delay));
2822 
2823     Log(kMessageDelay, kTypeDiscoveryResponse, aDestination);
2824 
2825 exit:
2826     FreeMessageOnError(message, error);
2827     LogProcessError(kTypeDiscoveryResponse, error);
2828     return error;
2829 }
2830 
SendChildIdResponse(Child & aChild)2831 Error MleRouter::SendChildIdResponse(Child &aChild)
2832 {
2833     Error        error = kErrorNone;
2834     Ip6::Address destination;
2835     TxMessage   *message;
2836 
2837     VerifyOrExit((message = NewMleMessage(kCommandChildIdResponse)) != nullptr, error = kErrorNoBufs);
2838     SuccessOrExit(error = message->AppendSourceAddressTlv());
2839     SuccessOrExit(error = message->AppendLeaderDataTlv());
2840     SuccessOrExit(error = message->AppendActiveTimestampTlv());
2841     SuccessOrExit(error = message->AppendPendingTimestampTlv());
2842 
2843     if ((aChild.GetRloc16() == 0) || !RouterIdMatch(aChild.GetRloc16(), GetRloc16()))
2844     {
2845         uint16_t rloc16;
2846 
2847         // pick next Child ID that is not being used
2848         do
2849         {
2850             mNextChildId++;
2851 
2852             if (mNextChildId > kMaxChildId)
2853             {
2854                 mNextChildId = kMinChildId;
2855             }
2856 
2857             rloc16 = Get<Mac::Mac>().GetShortAddress() | mNextChildId;
2858 
2859         } while (mChildTable.FindChild(rloc16, Child::kInStateAnyExceptInvalid) != nullptr);
2860 
2861         // allocate Child ID
2862         aChild.SetRloc16(rloc16);
2863     }
2864 
2865     SuccessOrExit(error = message->AppendAddress16Tlv(aChild.GetRloc16()));
2866 
2867     for (uint8_t i = 0; i < Child::kMaxRequestTlvs; i++)
2868     {
2869         switch (aChild.GetRequestTlv(i))
2870         {
2871         case Tlv::kNetworkData:
2872             SuccessOrExit(error = message->AppendNetworkDataTlv(aChild.GetNetworkDataType()));
2873             break;
2874 
2875         case Tlv::kRoute:
2876             SuccessOrExit(error = message->AppendRouteTlv());
2877             break;
2878 
2879         case Tlv::kActiveDataset:
2880             SuccessOrExit(error = message->AppendActiveDatasetTlv());
2881             break;
2882 
2883         case Tlv::kPendingDataset:
2884             SuccessOrExit(error = message->AppendPendingDatasetTlv());
2885             break;
2886 
2887         case Tlv::kSupervisionInterval:
2888             SuccessOrExit(error = message->AppendSupervisionIntervalTlv(aChild.GetSupervisionInterval()));
2889             break;
2890 
2891         default:
2892             break;
2893         }
2894     }
2895 
2896     if (!aChild.IsFullThreadDevice())
2897     {
2898         SuccessOrExit(error = message->AppendAddressRegistrationTlv(aChild));
2899     }
2900 
2901     SetChildStateToValid(aChild);
2902 
2903     if (!aChild.IsRxOnWhenIdle())
2904     {
2905         Get<IndirectSender>().SetChildUseShortAddress(aChild, false);
2906     }
2907 
2908 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
2909     if (aChild.IsTimeSyncEnabled())
2910     {
2911         message->SetTimeSync(true);
2912     }
2913 #endif
2914 
2915     destination.SetToLinkLocalAddress(aChild.GetExtAddress());
2916     SuccessOrExit(error = message->SendTo(destination));
2917 
2918     Log(kMessageSend, kTypeChildIdResponse, destination, aChild.GetRloc16());
2919 
2920 exit:
2921     FreeMessageOnError(message, error);
2922     return error;
2923 }
2924 
SendChildUpdateRequest(Child & aChild)2925 Error MleRouter::SendChildUpdateRequest(Child &aChild)
2926 {
2927     static const uint8_t kTlvs[] = {Tlv::kTimeout, Tlv::kAddressRegistration};
2928 
2929     Error        error = kErrorNone;
2930     Ip6::Address destination;
2931     TxMessage   *message = nullptr;
2932 
2933     if (!aChild.IsRxOnWhenIdle())
2934     {
2935         uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
2936 
2937         for (const Message &msg : Get<MeshForwarder>().GetSendQueue())
2938         {
2939             if (msg.GetChildMask(childIndex) && msg.GetSubType() == Message::kSubTypeMleChildUpdateRequest)
2940             {
2941                 // No need to send the resync "Child Update Request" to the sleepy child
2942                 // if there is one already queued.
2943                 if (aChild.IsStateRestoring())
2944                 {
2945                     ExitNow();
2946                 }
2947 
2948                 // Remove queued outdated "Child Update Request" when there is newer Network Data is to send.
2949                 Get<MeshForwarder>().RemoveMessages(aChild, Message::kSubTypeMleChildUpdateRequest);
2950                 break;
2951             }
2952         }
2953     }
2954 
2955     VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
2956     SuccessOrExit(error = message->AppendSourceAddressTlv());
2957     SuccessOrExit(error = message->AppendLeaderDataTlv());
2958     SuccessOrExit(error = message->AppendNetworkDataTlv(aChild.GetNetworkDataType()));
2959     SuccessOrExit(error = message->AppendActiveTimestampTlv());
2960     SuccessOrExit(error = message->AppendPendingTimestampTlv());
2961 
2962     if (!aChild.IsStateValid())
2963     {
2964         SuccessOrExit(error = message->AppendTlvRequestTlv(kTlvs));
2965         aChild.GenerateChallenge();
2966         SuccessOrExit(error = message->AppendChallengeTlv(aChild.GetChallenge()));
2967     }
2968 
2969     destination.SetToLinkLocalAddress(aChild.GetExtAddress());
2970     SuccessOrExit(error = message->SendTo(destination));
2971 
2972     if (aChild.IsRxOnWhenIdle())
2973     {
2974         // only try to send a single Child Update Request message to an rx-on-when-idle child
2975         aChild.SetState(Child::kStateChildUpdateRequest);
2976     }
2977 
2978     Log(kMessageSend, kTypeChildUpdateRequestOfChild, destination, aChild.GetRloc16());
2979 
2980 exit:
2981     FreeMessageOnError(message, error);
2982     return error;
2983 }
2984 
SendChildUpdateResponse(Child * aChild,const Ip6::MessageInfo & aMessageInfo,const TlvList & aTlvList,const RxChallenge & aChallenge)2985 void MleRouter::SendChildUpdateResponse(Child                  *aChild,
2986                                         const Ip6::MessageInfo &aMessageInfo,
2987                                         const TlvList          &aTlvList,
2988                                         const RxChallenge      &aChallenge)
2989 {
2990     Error      error = kErrorNone;
2991     TxMessage *message;
2992 
2993     VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs);
2994 
2995     for (uint8_t tlvType : aTlvList)
2996     {
2997         // Add all TLV types that do not depend on `child`
2998 
2999         switch (tlvType)
3000         {
3001         case Tlv::kStatus:
3002             SuccessOrExit(error = message->AppendStatusTlv(StatusTlv::kError));
3003             break;
3004 
3005         case Tlv::kLeaderData:
3006             SuccessOrExit(error = message->AppendLeaderDataTlv());
3007             break;
3008 
3009         case Tlv::kResponse:
3010             SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
3011             break;
3012 
3013         case Tlv::kSourceAddress:
3014             SuccessOrExit(error = message->AppendSourceAddressTlv());
3015             break;
3016 
3017         case Tlv::kMleFrameCounter:
3018             SuccessOrExit(error = message->AppendMleFrameCounterTlv());
3019             break;
3020 
3021         case Tlv::kLinkFrameCounter:
3022             SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
3023             break;
3024         }
3025 
3026         // Make sure `child` is not null before adding TLV types
3027         // that can depend on it.
3028 
3029         if (aChild == nullptr)
3030         {
3031             continue;
3032         }
3033 
3034         switch (tlvType)
3035         {
3036         case Tlv::kAddressRegistration:
3037             SuccessOrExit(error = message->AppendAddressRegistrationTlv(*aChild));
3038             break;
3039 
3040         case Tlv::kMode:
3041             SuccessOrExit(error = message->AppendModeTlv(aChild->GetDeviceMode()));
3042             break;
3043 
3044         case Tlv::kNetworkData:
3045             SuccessOrExit(error = message->AppendNetworkDataTlv(aChild->GetNetworkDataType()));
3046             SuccessOrExit(error = message->AppendActiveTimestampTlv());
3047             SuccessOrExit(error = message->AppendPendingTimestampTlv());
3048             break;
3049 
3050         case Tlv::kTimeout:
3051             SuccessOrExit(error = message->AppendTimeoutTlv(aChild->GetTimeout()));
3052             break;
3053 
3054         case Tlv::kSupervisionInterval:
3055             SuccessOrExit(error = message->AppendSupervisionIntervalTlv(aChild->GetSupervisionInterval()));
3056             break;
3057 
3058 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
3059         case Tlv::kCslClockAccuracy:
3060             if (!aChild->IsRxOnWhenIdle())
3061             {
3062                 SuccessOrExit(error = message->AppendCslClockAccuracyTlv());
3063             }
3064             break;
3065 #endif
3066         }
3067     }
3068 
3069     SuccessOrExit(error = message->SendTo(aMessageInfo.GetPeerAddr()));
3070 
3071     if (aChild == nullptr)
3072     {
3073         Log(kMessageSend, kTypeChildUpdateResponseOfChild, aMessageInfo.GetPeerAddr());
3074     }
3075     else
3076     {
3077         Log(kMessageSend, kTypeChildUpdateResponseOfChild, aMessageInfo.GetPeerAddr(), aChild->GetRloc16());
3078     }
3079 
3080 exit:
3081     FreeMessageOnError(message, error);
3082 }
3083 
SendDataResponse(const Ip6::Address & aDestination,const TlvList & aTlvList,uint16_t aDelay,const Message * aRequestMessage)3084 void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
3085                                  const TlvList      &aTlvList,
3086                                  uint16_t            aDelay,
3087                                  const Message      *aRequestMessage)
3088 {
3089     OT_UNUSED_VARIABLE(aRequestMessage);
3090 
3091     Error      error   = kErrorNone;
3092     TxMessage *message = nullptr;
3093     Neighbor  *neighbor;
3094 
3095     if (mRetrieveNewNetworkData)
3096     {
3097         LogInfo("Suppressing Data Response - waiting for new network data");
3098         ExitNow();
3099     }
3100 
3101     VerifyOrExit((message = NewMleMessage(kCommandDataResponse)) != nullptr, error = kErrorNoBufs);
3102     SuccessOrExit(error = message->AppendSourceAddressTlv());
3103     SuccessOrExit(error = message->AppendLeaderDataTlv());
3104     SuccessOrExit(error = message->AppendActiveTimestampTlv());
3105     SuccessOrExit(error = message->AppendPendingTimestampTlv());
3106 
3107     for (uint8_t tlvType : aTlvList)
3108     {
3109         switch (tlvType)
3110         {
3111         case Tlv::kNetworkData:
3112             neighbor = mNeighborTable.FindNeighbor(aDestination);
3113             SuccessOrExit(error = message->AppendNetworkDataTlv((neighbor != nullptr) ? neighbor->GetNetworkDataType()
3114                                                                                       : NetworkData::kFullSet));
3115             break;
3116 
3117         case Tlv::kActiveDataset:
3118             SuccessOrExit(error = message->AppendActiveDatasetTlv());
3119             break;
3120 
3121         case Tlv::kPendingDataset:
3122             SuccessOrExit(error = message->AppendPendingDatasetTlv());
3123             break;
3124 
3125         case Tlv::kRoute:
3126             SuccessOrExit(error = message->AppendRouteTlv());
3127             break;
3128 
3129 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
3130         case Tlv::kLinkMetricsReport:
3131             OT_ASSERT(aRequestMessage != nullptr);
3132             neighbor = mNeighborTable.FindNeighbor(aDestination);
3133             VerifyOrExit(neighbor != nullptr, error = kErrorInvalidState);
3134             SuccessOrExit(error = Get<LinkMetrics::Subject>().AppendReport(*message, *aRequestMessage, *neighbor));
3135             break;
3136 #endif
3137         }
3138     }
3139 
3140     if (aDelay)
3141     {
3142         // Remove MLE Data Responses from Send Message Queue.
3143         Get<MeshForwarder>().RemoveDataResponseMessages();
3144 
3145         // Remove multicast MLE Data Response from Delayed Message Queue.
3146         RemoveDelayedDataResponseMessage();
3147 
3148         SuccessOrExit(error = message->SendAfterDelay(aDestination, aDelay));
3149         Log(kMessageDelay, kTypeDataResponse, aDestination);
3150     }
3151     else
3152     {
3153         SuccessOrExit(error = message->SendTo(aDestination));
3154         Log(kMessageSend, kTypeDataResponse, aDestination);
3155     }
3156 
3157 exit:
3158     FreeMessageOnError(message, error);
3159     LogSendError(kTypeDataResponse, error);
3160 }
3161 
IsMinimalChild(uint16_t aRloc16)3162 bool MleRouter::IsMinimalChild(uint16_t aRloc16)
3163 {
3164     bool rval = false;
3165 
3166     if (RouterIdFromRloc16(aRloc16) == RouterIdFromRloc16(Get<Mac::Mac>().GetShortAddress()))
3167     {
3168         Neighbor *neighbor;
3169 
3170         neighbor = mNeighborTable.FindNeighbor(aRloc16);
3171 
3172         rval = (neighbor != nullptr) && (!neighbor->IsFullThreadDevice());
3173     }
3174 
3175     return rval;
3176 }
3177 
RemoveRouterLink(Router & aRouter)3178 void MleRouter::RemoveRouterLink(Router &aRouter)
3179 {
3180     switch (mRole)
3181     {
3182     case kRoleChild:
3183         if (&aRouter == &mParent)
3184         {
3185             IgnoreError(BecomeDetached());
3186         }
3187         break;
3188 
3189     case kRoleRouter:
3190     case kRoleLeader:
3191         mRouterTable.RemoveRouterLink(aRouter);
3192         break;
3193 
3194     default:
3195         break;
3196     }
3197 }
3198 
RemoveNeighbor(Neighbor & aNeighbor)3199 void MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
3200 {
3201     VerifyOrExit(!aNeighbor.IsStateInvalid());
3202 
3203     if (&aNeighbor == &mParent)
3204     {
3205         if (IsChild())
3206         {
3207             IgnoreError(BecomeDetached());
3208         }
3209     }
3210     else if (&aNeighbor == &GetParentCandidate())
3211     {
3212         ClearParentCandidate();
3213     }
3214     else if (!IsActiveRouter(aNeighbor.GetRloc16()))
3215     {
3216         OT_ASSERT(mChildTable.Contains(aNeighbor));
3217 
3218         if (aNeighbor.IsStateValidOrRestoring())
3219         {
3220             mNeighborTable.Signal(NeighborTable::kChildRemoved, aNeighbor);
3221         }
3222 
3223         Get<IndirectSender>().ClearAllMessagesForSleepyChild(static_cast<Child &>(aNeighbor));
3224 
3225         if (aNeighbor.IsFullThreadDevice())
3226         {
3227             // Clear all EID-to-RLOC entries associated with the child.
3228             Get<AddressResolver>().RemoveEntriesForRloc16(aNeighbor.GetRloc16());
3229         }
3230 
3231         mChildTable.RemoveStoredChild(static_cast<Child &>(aNeighbor));
3232     }
3233     else if (aNeighbor.IsStateValid())
3234     {
3235         OT_ASSERT(mRouterTable.Contains(aNeighbor));
3236 
3237         mNeighborTable.Signal(NeighborTable::kRouterRemoved, aNeighbor);
3238         mRouterTable.RemoveRouterLink(static_cast<Router &>(aNeighbor));
3239     }
3240 
3241     aNeighbor.GetLinkInfo().Clear();
3242     aNeighbor.SetState(Neighbor::kStateInvalid);
3243 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
3244     aNeighbor.RemoveAllForwardTrackingSeriesInfo();
3245 #endif
3246 
3247 exit:
3248     return;
3249 }
3250 
SetPreferredRouterId(uint8_t aRouterId)3251 Error MleRouter::SetPreferredRouterId(uint8_t aRouterId)
3252 {
3253     Error error = kErrorNone;
3254 
3255     VerifyOrExit(IsDetached() || IsDisabled(), error = kErrorInvalidState);
3256 
3257     mPreviousRouterId = aRouterId;
3258 
3259 exit:
3260     return error;
3261 }
3262 
SetRouterId(uint8_t aRouterId)3263 void MleRouter::SetRouterId(uint8_t aRouterId)
3264 {
3265     mRouterId         = aRouterId;
3266     mPreviousRouterId = mRouterId;
3267 }
3268 
ResolveRoutingLoops(uint16_t aSourceMac,uint16_t aDestRloc16)3269 void MleRouter::ResolveRoutingLoops(uint16_t aSourceMac, uint16_t aDestRloc16)
3270 {
3271     Router *router;
3272 
3273     if (aSourceMac != GetNextHop(aDestRloc16))
3274     {
3275         ExitNow();
3276     }
3277 
3278     // loop exists
3279     router = mRouterTable.FindRouterByRloc16(aDestRloc16);
3280     VerifyOrExit(router != nullptr);
3281 
3282     // invalidate next hop
3283     router->SetNextHopToInvalid();
3284     ResetAdvertiseInterval();
3285 
3286 exit:
3287     return;
3288 }
3289 
CheckReachability(uint16_t aMeshDest,const Ip6::Header & aIp6Header)3290 Error MleRouter::CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header)
3291 {
3292     Error error = kErrorNone;
3293 
3294     if (IsChild())
3295     {
3296         error = Mle::CheckReachability(aMeshDest, aIp6Header);
3297         ExitNow();
3298     }
3299 
3300     if (aMeshDest == Get<Mac::Mac>().GetShortAddress())
3301     {
3302         // mesh destination is this device
3303         if (Get<ThreadNetif>().HasUnicastAddress(aIp6Header.GetDestination()))
3304         {
3305             // IPv6 destination is this device
3306             ExitNow();
3307         }
3308         else if (mNeighborTable.FindNeighbor(aIp6Header.GetDestination()) != nullptr)
3309         {
3310             // IPv6 destination is an RFD child
3311             ExitNow();
3312         }
3313     }
3314     else if (RouterIdFromRloc16(aMeshDest) == mRouterId)
3315     {
3316         // mesh destination is a child of this device
3317         if (mChildTable.FindChild(aMeshDest, Child::kInStateValidOrRestoring))
3318         {
3319             ExitNow();
3320         }
3321     }
3322     else if (GetNextHop(aMeshDest) != Mac::kShortAddrInvalid)
3323     {
3324         // forwarding to another router and route is known
3325         ExitNow();
3326     }
3327 
3328     error = kErrorNoRoute;
3329 
3330 exit:
3331     return error;
3332 }
3333 
SendAddressSolicit(ThreadStatusTlv::Status aStatus)3334 Error MleRouter::SendAddressSolicit(ThreadStatusTlv::Status aStatus)
3335 {
3336     Error            error = kErrorNone;
3337     Tmf::MessageInfo messageInfo(GetInstance());
3338     Coap::Message   *message = nullptr;
3339 
3340     VerifyOrExit(!mAddressSolicitPending);
3341 
3342     message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(kUriAddressSolicit);
3343     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
3344 
3345     SuccessOrExit(error = Tlv::Append<ThreadExtMacAddressTlv>(*message, Get<Mac::Mac>().GetExtAddress()));
3346 
3347     if (IsRouterIdValid(mPreviousRouterId))
3348     {
3349         SuccessOrExit(error = Tlv::Append<ThreadRloc16Tlv>(*message, Rloc16FromRouterId(mPreviousRouterId)));
3350     }
3351 
3352     SuccessOrExit(error = Tlv::Append<ThreadStatusTlv>(*message, aStatus));
3353 
3354 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
3355     SuccessOrExit(error = Tlv::Append<XtalAccuracyTlv>(*message, otPlatTimeGetXtalAccuracy()));
3356 #endif
3357 
3358     SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderRloc());
3359 
3360     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &HandleAddressSolicitResponse, this));
3361     mAddressSolicitPending = true;
3362 
3363     Log(kMessageSend, kTypeAddressSolicit, messageInfo.GetPeerAddr());
3364 
3365 exit:
3366     FreeMessageOnError(message, error);
3367     return error;
3368 }
3369 
SendAddressRelease(void)3370 void MleRouter::SendAddressRelease(void)
3371 {
3372     Error            error = kErrorNone;
3373     Tmf::MessageInfo messageInfo(GetInstance());
3374     Coap::Message   *message;
3375 
3376     message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(kUriAddressRelease);
3377     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
3378 
3379     SuccessOrExit(error = Tlv::Append<ThreadRloc16Tlv>(*message, Rloc16FromRouterId(mRouterId)));
3380     SuccessOrExit(error = Tlv::Append<ThreadExtMacAddressTlv>(*message, Get<Mac::Mac>().GetExtAddress()));
3381 
3382     SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderRloc());
3383 
3384     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
3385 
3386     Log(kMessageSend, kTypeAddressRelease, messageInfo.GetPeerAddr());
3387 
3388 exit:
3389     FreeMessageOnError(message, error);
3390     LogSendError(kTypeAddressRelease, error);
3391 }
3392 
HandleAddressSolicitResponse(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo,Error aResult)3393 void MleRouter::HandleAddressSolicitResponse(void                *aContext,
3394                                              otMessage           *aMessage,
3395                                              const otMessageInfo *aMessageInfo,
3396                                              Error                aResult)
3397 {
3398     static_cast<MleRouter *>(aContext)->HandleAddressSolicitResponse(AsCoapMessagePtr(aMessage),
3399                                                                      AsCoreTypePtr(aMessageInfo), aResult);
3400 }
3401 
HandleAddressSolicitResponse(Coap::Message * aMessage,const Ip6::MessageInfo * aMessageInfo,Error aResult)3402 void MleRouter::HandleAddressSolicitResponse(Coap::Message          *aMessage,
3403                                              const Ip6::MessageInfo *aMessageInfo,
3404                                              Error                   aResult)
3405 {
3406     uint8_t             status;
3407     uint16_t            rloc16;
3408     ThreadRouterMaskTlv routerMaskTlv;
3409     uint8_t             routerId;
3410     Router             *router;
3411 
3412     mAddressSolicitPending = false;
3413 
3414     VerifyOrExit(aResult == kErrorNone && aMessage != nullptr && aMessageInfo != nullptr);
3415 
3416     VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
3417 
3418     Log(kMessageReceive, kTypeAddressReply, aMessageInfo->GetPeerAddr());
3419 
3420     SuccessOrExit(Tlv::Find<ThreadStatusTlv>(*aMessage, status));
3421 
3422     if (status != ThreadStatusTlv::kSuccess)
3423     {
3424         mAddressSolicitRejected = true;
3425 
3426         if (IsRouterIdValid(mPreviousRouterId))
3427         {
3428             if (HasChildren())
3429             {
3430                 RemoveChildren();
3431             }
3432 
3433             SetRouterId(kInvalidRouterId);
3434         }
3435 
3436         ExitNow();
3437     }
3438 
3439     SuccessOrExit(Tlv::Find<ThreadRloc16Tlv>(*aMessage, rloc16));
3440     routerId = RouterIdFromRloc16(rloc16);
3441 
3442     SuccessOrExit(Tlv::FindTlv(*aMessage, routerMaskTlv));
3443     VerifyOrExit(routerMaskTlv.IsValid());
3444 
3445     // assign short address
3446     SetRouterId(routerId);
3447 
3448     SetStateRouter(Rloc16FromRouterId(mRouterId));
3449 
3450     // We keep the router table next hop and cost as what we had as a
3451     // REED, i.e., our parent was the next hop towards all other
3452     // routers and we tracked its cost towards them. As FED, we may
3453     // have established links with a subset of neighboring routers.
3454     // We ensure to clear these links to avoid using them (since will
3455     // be rejected by the neighbor).
3456 
3457     mRouterTable.ClearNeighbors();
3458 
3459     mRouterTable.UpdateRouterIdSet(routerMaskTlv.GetIdSequence(), routerMaskTlv.GetAssignedRouterIdMask());
3460 
3461     router = mRouterTable.FindRouterById(routerId);
3462     VerifyOrExit(router != nullptr);
3463     router->SetExtAddress(Get<Mac::Mac>().GetExtAddress());
3464     router->SetNextHopToInvalid();
3465 
3466     // Ensure we have our parent as a neighboring router, copying the
3467     // `mParent` entry.
3468 
3469     router = mRouterTable.FindRouterById(mParent.GetRouterId());
3470     VerifyOrExit(router != nullptr);
3471     router->SetFrom(mParent);
3472     router->SetState(Neighbor::kStateValid);
3473     router->SetNextHopToInvalid();
3474 
3475     // Ensure we have a next hop and cost towards leader.
3476     if (mRouterTable.GetPathCostToLeader() >= kMaxRouteCost)
3477     {
3478         Router *leader = mRouterTable.GetLeader();
3479 
3480         OT_ASSERT(leader != nullptr);
3481         leader->SetNextHopAndCost(RouterIdFromRloc16(mParent.GetRloc16()), mParent.GetLeaderCost());
3482     }
3483 
3484     // We send a unicast Link Request to our former parent if its
3485     // version is earlier than 1.3. This is to address a potential
3486     // compatibility issue with some non-OpenThread stacks which may
3487     // ignore MLE Advertisements from a former/existing child.
3488 
3489     if (mParent.GetVersion() < kThreadVersion1p3)
3490     {
3491         IgnoreError(SendLinkRequest(&mParent));
3492     }
3493 
3494     // We send an Advertisement to inform our former parent of our
3495     // newly allocated Router ID. This will cause the parent to
3496     // reset its advertisement trickle timer which can help speed
3497     // up the dissemination of the new Router ID to other routers.
3498     // This can also help with quicker link establishment with our
3499     // former parent and other routers.
3500     SendAdvertisement();
3501 
3502     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateChildIdRequest))
3503     {
3504         IgnoreError(SendChildIdResponse(child));
3505     }
3506 
3507 exit:
3508     // Send announce after received address solicit reply if needed
3509     InformPreviousChannel();
3510 }
3511 
SetChildRouterLinks(uint8_t aChildRouterLinks)3512 Error MleRouter::SetChildRouterLinks(uint8_t aChildRouterLinks)
3513 {
3514     Error error = kErrorNone;
3515 
3516     VerifyOrExit(IsDisabled(), error = kErrorInvalidState);
3517     mChildRouterLinks = aChildRouterLinks;
3518 exit:
3519     return error;
3520 }
3521 
IsExpectedToBecomeRouterSoon(void) const3522 bool MleRouter::IsExpectedToBecomeRouterSoon(void) const
3523 {
3524     static constexpr uint8_t kMaxDelay = 10;
3525 
3526     return IsRouterEligible() && IsChild() && !mAddressSolicitRejected &&
3527            ((mRouterRoleTransition.IsPending() && mRouterRoleTransition.GetTimeout() <= kMaxDelay) ||
3528             mAddressSolicitPending);
3529 }
3530 
HandleTmf(Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)3531 template <> void MleRouter::HandleTmf<kUriAddressSolicit>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
3532 {
3533     Error                   error          = kErrorNone;
3534     ThreadStatusTlv::Status responseStatus = ThreadStatusTlv::kNoAddressAvailable;
3535     Router                 *router         = nullptr;
3536     Mac::ExtAddress         extAddress;
3537     uint16_t                rloc16;
3538     uint8_t                 status;
3539 
3540     VerifyOrExit(mRole == kRoleLeader, error = kErrorInvalidState);
3541 
3542     VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
3543 
3544     Log(kMessageReceive, kTypeAddressSolicit, aMessageInfo.GetPeerAddr());
3545 
3546     SuccessOrExit(error = Tlv::Find<ThreadExtMacAddressTlv>(aMessage, extAddress));
3547     SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(aMessage, status));
3548 
3549     switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
3550     {
3551     case kErrorNone:
3552         break;
3553     case kErrorNotFound:
3554         rloc16 = Mac::kShortAddrInvalid;
3555         break;
3556     default:
3557         ExitNow(error = kErrorParse);
3558     }
3559 
3560 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
3561     {
3562         uint16_t xtalAccuracy;
3563 
3564         SuccessOrExit(Tlv::Find<XtalAccuracyTlv>(aMessage, xtalAccuracy));
3565         VerifyOrExit(xtalAccuracy <= Get<TimeSync>().GetXtalThreshold());
3566     }
3567 #endif
3568 
3569     // Check if allocation already exists
3570     router = mRouterTable.FindRouter(extAddress);
3571 
3572     if (router != nullptr)
3573     {
3574         responseStatus = ThreadStatusTlv::kSuccess;
3575         ExitNow();
3576     }
3577 
3578     switch (status)
3579     {
3580     case ThreadStatusTlv::kTooFewRouters:
3581         VerifyOrExit(mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold);
3582         break;
3583 
3584     case ThreadStatusTlv::kHaveChildIdRequest:
3585     case ThreadStatusTlv::kParentPartitionChange:
3586         break;
3587 
3588     case ThreadStatusTlv::kBorderRouterRequest:
3589         if ((mRouterTable.GetActiveRouterCount() >= mRouterUpgradeThreshold) &&
3590             (Get<NetworkData::Leader>().CountBorderRouters(NetworkData::kRouterRoleOnly) >=
3591              kRouterUpgradeBorderRouterRequestThreshold))
3592         {
3593             LogInfo("Rejecting BR %s router role req - have %u BR routers", extAddress.ToString().AsCString(),
3594                     kRouterUpgradeBorderRouterRequestThreshold);
3595             ExitNow();
3596         }
3597         break;
3598 
3599     default:
3600         responseStatus = ThreadStatusTlv::kUnrecognizedStatus;
3601         ExitNow();
3602     }
3603 
3604     if (rloc16 != Mac::kShortAddrInvalid)
3605     {
3606         router = mRouterTable.Allocate(RouterIdFromRloc16(rloc16));
3607 
3608         if (router != nullptr)
3609         {
3610             LogInfo("Router id %u requested and provided!", RouterIdFromRloc16(rloc16));
3611         }
3612     }
3613 
3614     if (router == nullptr)
3615     {
3616         router = mRouterTable.Allocate();
3617         VerifyOrExit(router != nullptr);
3618     }
3619 
3620     router->SetExtAddress(extAddress);
3621     responseStatus = ThreadStatusTlv::kSuccess;
3622 
3623 exit:
3624     if (error == kErrorNone)
3625     {
3626         SendAddressSolicitResponse(aMessage, responseStatus, router, aMessageInfo);
3627     }
3628 }
3629 
SendAddressSolicitResponse(const Coap::Message & aRequest,ThreadStatusTlv::Status aResponseStatus,const Router * aRouter,const Ip6::MessageInfo & aMessageInfo)3630 void MleRouter::SendAddressSolicitResponse(const Coap::Message    &aRequest,
3631                                            ThreadStatusTlv::Status aResponseStatus,
3632                                            const Router           *aRouter,
3633                                            const Ip6::MessageInfo &aMessageInfo)
3634 {
3635     Coap::Message *message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
3636 
3637     VerifyOrExit(message != nullptr);
3638 
3639     SuccessOrExit(Tlv::Append<ThreadStatusTlv>(*message, aResponseStatus));
3640 
3641     if (aRouter != nullptr)
3642     {
3643         ThreadRouterMaskTlv routerMaskTlv;
3644 
3645         SuccessOrExit(Tlv::Append<ThreadRloc16Tlv>(*message, aRouter->GetRloc16()));
3646 
3647         routerMaskTlv.Init();
3648         routerMaskTlv.SetIdSequence(mRouterTable.GetRouterIdSequence());
3649         mRouterTable.GetRouterIdSet(routerMaskTlv.GetAssignedRouterIdMask());
3650 
3651         SuccessOrExit(routerMaskTlv.AppendTo(*message));
3652     }
3653 
3654     SuccessOrExit(Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
3655     message = nullptr;
3656 
3657     Log(kMessageSend, kTypeAddressReply, aMessageInfo.GetPeerAddr());
3658 
3659     // If assigning a new RLOC16 (e.g., on promotion of a child to
3660     // router role) we clear any address cache entries associated
3661     // with the old RLOC16.
3662 
3663     if ((aResponseStatus == ThreadStatusTlv::kSuccess) && (aRouter != nullptr))
3664     {
3665         uint16_t oldRloc16;
3666 
3667         VerifyOrExit(IsRoutingLocator(aMessageInfo.GetPeerAddr()));
3668         oldRloc16 = aMessageInfo.GetPeerAddr().GetIid().GetLocator();
3669 
3670         VerifyOrExit(oldRloc16 != aRouter->GetRloc16());
3671         Get<AddressResolver>().RemoveEntriesForRloc16(oldRloc16);
3672     }
3673 
3674 exit:
3675     FreeMessage(message);
3676 }
3677 
HandleTmf(Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)3678 template <> void MleRouter::HandleTmf<kUriAddressRelease>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
3679 {
3680     uint16_t        rloc16;
3681     Mac::ExtAddress extAddress;
3682     uint8_t         routerId;
3683     Router         *router;
3684 
3685     VerifyOrExit(mRole == kRoleLeader);
3686 
3687     VerifyOrExit(aMessage.IsConfirmablePostRequest());
3688 
3689     Log(kMessageReceive, kTypeAddressRelease, aMessageInfo.GetPeerAddr());
3690 
3691     SuccessOrExit(Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16));
3692     SuccessOrExit(Tlv::Find<ThreadExtMacAddressTlv>(aMessage, extAddress));
3693 
3694     routerId = RouterIdFromRloc16(rloc16);
3695     router   = mRouterTable.FindRouterById(routerId);
3696 
3697     VerifyOrExit((router != nullptr) && (router->GetExtAddress() == extAddress));
3698 
3699     IgnoreError(mRouterTable.Release(routerId));
3700 
3701     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
3702 
3703     Log(kMessageSend, kTypeAddressReleaseReply, aMessageInfo.GetPeerAddr());
3704 
3705 exit:
3706     return;
3707 }
3708 
FillConnectivityTlv(ConnectivityTlv & aTlv)3709 void MleRouter::FillConnectivityTlv(ConnectivityTlv &aTlv)
3710 {
3711     int8_t parentPriority = kParentPriorityMedium;
3712 
3713     if (mParentPriority != kParentPriorityUnspecified)
3714     {
3715         parentPriority = mParentPriority;
3716     }
3717     else
3718     {
3719         uint16_t numChildren = mChildTable.GetNumChildren(Child::kInStateValid);
3720         uint16_t maxAllowed  = mChildTable.GetMaxChildrenAllowed();
3721 
3722         if ((maxAllowed - numChildren) < (maxAllowed / 3))
3723         {
3724             parentPriority = kParentPriorityLow;
3725         }
3726         else
3727         {
3728             parentPriority = kParentPriorityMedium;
3729         }
3730     }
3731 
3732     aTlv.SetParentPriority(parentPriority);
3733 
3734     aTlv.SetLinkQuality1(0);
3735     aTlv.SetLinkQuality2(0);
3736     aTlv.SetLinkQuality3(0);
3737 
3738     if (IsChild())
3739     {
3740         aTlv.IncrementLinkQuality(mParent.GetLinkQualityIn());
3741     }
3742 
3743     for (const Router &router : Get<RouterTable>())
3744     {
3745         if (router.GetRloc16() == GetRloc16())
3746         {
3747             // skip self
3748             continue;
3749         }
3750 
3751         if (!router.IsStateValid())
3752         {
3753             // skip non-neighbor routers
3754             continue;
3755         }
3756 
3757         aTlv.IncrementLinkQuality(router.GetTwoWayLinkQuality());
3758     }
3759 
3760     aTlv.SetActiveRouters(mRouterTable.GetActiveRouterCount());
3761     aTlv.SetLeaderCost(Min(mRouterTable.GetPathCostToLeader(), kMaxRouteCost));
3762     aTlv.SetIdSequence(mRouterTable.GetRouterIdSequence());
3763     aTlv.SetSedBufferSize(OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE);
3764     aTlv.SetSedDatagramCount(OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT);
3765 }
3766 
ShouldDowngrade(uint8_t aNeighborId,const RouteTlv & aRouteTlv) const3767 bool MleRouter::ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const
3768 {
3769     // Determine whether all conditions are satisfied for the router
3770     // to downgrade after receiving info for a neighboring router
3771     // with Router ID `aNeighborId` along with its `aRouteTlv`.
3772 
3773     bool    shouldDowngrade   = false;
3774     uint8_t activeRouterCount = mRouterTable.GetActiveRouterCount();
3775     uint8_t count;
3776 
3777     VerifyOrExit(IsRouter());
3778     VerifyOrExit(mRouterTable.IsAllocated(aNeighborId));
3779 
3780     VerifyOrExit(!mRouterRoleTransition.IsPending());
3781 
3782     VerifyOrExit(activeRouterCount > mRouterDowngradeThreshold);
3783 
3784     // Check that we have at least `kMinDowngradeNeighbors`
3785     // neighboring routers with two-way link quality of 2 or better.
3786 
3787     count = 0;
3788 
3789     for (const Router &router : mRouterTable)
3790     {
3791         if (!router.IsStateValid() || (router.GetTwoWayLinkQuality() < kLinkQuality2))
3792         {
3793             continue;
3794         }
3795 
3796         count++;
3797 
3798         if (count >= kMinDowngradeNeighbors)
3799         {
3800             break;
3801         }
3802     }
3803 
3804     VerifyOrExit(count >= kMinDowngradeNeighbors);
3805 
3806     // Check that we have fewer children than three times the number
3807     // of excess routers (defined as the difference between number of
3808     // active routers and `mRouterDowngradeThreshold`).
3809 
3810     count = activeRouterCount - mRouterDowngradeThreshold;
3811     VerifyOrExit(mChildTable.GetNumChildren(Child::kInStateValid) < count * 3);
3812 
3813     // Check that the neighbor has as good or better-quality links to
3814     // same routers.
3815 
3816     VerifyOrExit(NeighborHasComparableConnectivity(aRouteTlv, aNeighborId));
3817 
3818 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
3819     // Check if we are eligible to be router due to being a BR.
3820     VerifyOrExit(!Get<NetworkData::Notifier>().IsEligibleForRouterRoleUpgradeAsBorderRouter());
3821 #endif
3822 
3823     shouldDowngrade = true;
3824 
3825 exit:
3826     return shouldDowngrade;
3827 }
3828 
NeighborHasComparableConnectivity(const RouteTlv & aRouteTlv,uint8_t aNeighborId) const3829 bool MleRouter::NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const
3830 {
3831     // Check whether the neighboring router with Router ID `aNeighborId`
3832     // (along with its `aRouteTlv`) has as good or better-quality links
3833     // to all our neighboring routers which have a two-way link quality
3834     // of two or better.
3835 
3836     bool isComparable = true;
3837 
3838     for (uint8_t routerId = 0, index = 0; routerId <= kMaxRouterId;
3839          index += aRouteTlv.IsRouterIdSet(routerId) ? 1 : 0, routerId++)
3840     {
3841         const Router *router;
3842         LinkQuality   localLinkQuality;
3843         LinkQuality   peerLinkQuality;
3844 
3845         if ((routerId == mRouterId) || (routerId == aNeighborId))
3846         {
3847             continue;
3848         }
3849 
3850         router = mRouterTable.FindRouterById(routerId);
3851 
3852         if ((router == nullptr) || !router->IsStateValid())
3853         {
3854             continue;
3855         }
3856 
3857         localLinkQuality = router->GetTwoWayLinkQuality();
3858 
3859         if (localLinkQuality < kLinkQuality2)
3860         {
3861             continue;
3862         }
3863 
3864         // `router` is our neighbor with two-way link quality of
3865         // at least two. Check that `aRouteTlv` has as good or
3866         // better-quality link to it as well.
3867 
3868         if (!aRouteTlv.IsRouterIdSet(routerId))
3869         {
3870             ExitNow(isComparable = false);
3871         }
3872 
3873         peerLinkQuality = Min(aRouteTlv.GetLinkQualityIn(index), aRouteTlv.GetLinkQualityOut(index));
3874 
3875         if (peerLinkQuality < localLinkQuality)
3876         {
3877             ExitNow(isComparable = false);
3878         }
3879     }
3880 
3881 exit:
3882     return isComparable;
3883 }
3884 
SetChildStateToValid(Child & aChild)3885 void MleRouter::SetChildStateToValid(Child &aChild)
3886 {
3887     VerifyOrExit(!aChild.IsStateValid());
3888 
3889     aChild.SetState(Neighbor::kStateValid);
3890     IgnoreError(mChildTable.StoreChild(aChild));
3891 
3892 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
3893     Get<MlrManager>().UpdateProxiedSubscriptions(aChild, MlrManager::MlrAddressArray());
3894 #endif
3895 
3896     mNeighborTable.Signal(NeighborTable::kChildAdded, aChild);
3897 
3898 exit:
3899     return;
3900 }
3901 
HasChildren(void)3902 bool MleRouter::HasChildren(void) { return mChildTable.HasChildren(Child::kInStateValidOrAttaching); }
3903 
RemoveChildren(void)3904 void MleRouter::RemoveChildren(void)
3905 {
3906     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
3907     {
3908         RemoveNeighbor(child);
3909     }
3910 }
3911 
SetAssignParentPriority(int8_t aParentPriority)3912 Error MleRouter::SetAssignParentPriority(int8_t aParentPriority)
3913 {
3914     Error error = kErrorNone;
3915 
3916     VerifyOrExit(aParentPriority <= kParentPriorityHigh && aParentPriority >= kParentPriorityUnspecified,
3917                  error = kErrorInvalidArgs);
3918 
3919     mParentPriority = aParentPriority;
3920 
3921 exit:
3922     return error;
3923 }
3924 
GetMaxChildTimeout(uint32_t & aTimeout) const3925 Error MleRouter::GetMaxChildTimeout(uint32_t &aTimeout) const
3926 {
3927     Error error = kErrorNotFound;
3928 
3929     aTimeout = 0;
3930 
3931     VerifyOrExit(IsRouterOrLeader(), error = kErrorInvalidState);
3932 
3933     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
3934     {
3935         if (child.IsFullThreadDevice())
3936         {
3937             continue;
3938         }
3939 
3940         if (child.GetTimeout() > aTimeout)
3941         {
3942             aTimeout = child.GetTimeout();
3943         }
3944 
3945         error = kErrorNone;
3946     }
3947 
3948 exit:
3949     return error;
3950 }
3951 
3952 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
HandleTimeSync(RxInfo & aRxInfo)3953 void MleRouter::HandleTimeSync(RxInfo &aRxInfo)
3954 {
3955     Log(kMessageReceive, kTypeTimeSync, aRxInfo.mMessageInfo.GetPeerAddr());
3956 
3957     VerifyOrExit(aRxInfo.IsNeighborStateValid());
3958 
3959     aRxInfo.mClass = RxInfo::kPeerMessage;
3960 
3961     Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
3962 
3963 exit:
3964     return;
3965 }
3966 
SendTimeSync(void)3967 Error MleRouter::SendTimeSync(void)
3968 {
3969     Error        error = kErrorNone;
3970     Ip6::Address destination;
3971     TxMessage   *message = nullptr;
3972 
3973     VerifyOrExit((message = NewMleMessage(kCommandTimeSync)) != nullptr, error = kErrorNoBufs);
3974 
3975     message->SetTimeSync(true);
3976 
3977     destination.SetToLinkLocalAllNodesMulticast();
3978     SuccessOrExit(error = message->SendTo(destination));
3979 
3980     Log(kMessageSend, kTypeTimeSync, destination);
3981 
3982 exit:
3983     FreeMessageOnError(message, error);
3984     return error;
3985 }
3986 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
3987 
3988 //----------------------------------------------------------------------------------------------------------------------
3989 // RouterRoleTransition
3990 
RouterRoleTransition(void)3991 MleRouter::RouterRoleTransition::RouterRoleTransition(void)
3992     : mTimeout(0)
3993     , mJitter(kRouterSelectionJitter)
3994 {
3995 }
3996 
StartTimeout(void)3997 void MleRouter::RouterRoleTransition::StartTimeout(void)
3998 {
3999     mTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mJitter);
4000 }
4001 
HandleTimeTick(void)4002 bool MleRouter::RouterRoleTransition::HandleTimeTick(void)
4003 {
4004     bool expired = false;
4005 
4006     VerifyOrExit(mTimeout > 0);
4007     mTimeout--;
4008     expired = (mTimeout == 0);
4009 
4010 exit:
4011     return expired;
4012 }
4013 
4014 } // namespace Mle
4015 } // namespace ot
4016 
4017 #endif // OPENTHREAD_FTD
4018