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