1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for MLE functionality required by the Thread Router and Leader roles.
32  */
33 
34 #ifndef MLE_ROUTER_HPP_
35 #define MLE_ROUTER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/thread_ftd.h>
40 
41 #include "coap/coap_message.hpp"
42 #include "common/callback.hpp"
43 #include "common/time_ticker.hpp"
44 #include "common/timer.hpp"
45 #include "common/trickle_timer.hpp"
46 #include "mac/mac_types.hpp"
47 #include "meshcop/meshcop_tlvs.hpp"
48 #include "net/icmp6.hpp"
49 #include "net/udp6.hpp"
50 #include "thread/child.hpp"
51 #include "thread/child_table.hpp"
52 #include "thread/mle.hpp"
53 #include "thread/mle_tlvs.hpp"
54 #include "thread/router.hpp"
55 #include "thread/router_table.hpp"
56 #include "thread/thread_tlvs.hpp"
57 #include "thread/tmf.hpp"
58 
59 namespace ot {
60 namespace Mle {
61 
62 /**
63  * @addtogroup core-mle-router
64  *
65  * @brief
66  *   This module includes definitions for MLE functionality required by the Thread Router and Leader roles.
67  *
68  * @{
69  */
70 
71 #if OPENTHREAD_FTD
72 
73 /**
74  * Implements MLE functionality required by the Thread Router and Leader roles.
75  *
76  */
77 class MleRouter : public Mle
78 {
79     friend class Mle;
80     friend class ot::Instance;
81     friend class ot::TimeTicker;
82     friend class Tmf::Agent;
83 
84 public:
85     /**
86      * Initializes the object.
87      *
88      * @param[in]  aInstance     A reference to the OpenThread instance.
89      *
90      */
91     explicit MleRouter(Instance &aInstance);
92 
93     /**
94      * Indicates whether or not the device is router-eligible.
95      *
96      * @retval true   If device is router-eligible.
97      * @retval false  If device is not router-eligible.
98      *
99      */
100     bool IsRouterEligible(void) const;
101 
102     /**
103      * Sets whether or not the device is router-eligible.
104      *
105      * If @p aEligible is false and the device is currently operating as a router, this call will cause the device to
106      * detach and attempt to reattach as a child.
107      *
108      * @param[in]  aEligible  TRUE to configure device router-eligible, FALSE otherwise.
109      *
110      * @retval kErrorNone         Successfully set the router-eligible configuration.
111      * @retval kErrorNotCapable   The device is not capable of becoming a router.
112      *
113      */
114     Error SetRouterEligible(bool aEligible);
115 
116     /**
117      * Indicates whether a node is the only router on the network.
118      *
119      * @retval TRUE   It is the only router in the network.
120      * @retval FALSE  It is a child or is not a single router in the network.
121      *
122      */
123     bool IsSingleton(void) const;
124 
125     /**
126      * Generates an Address Solicit request for a Router ID.
127      *
128      * @param[in]  aStatus  The reason for requesting a Router ID.
129      *
130      * @retval kErrorNone           Successfully generated an Address Solicit message.
131      * @retval kErrorNotCapable     Device is not capable of becoming a router
132      * @retval kErrorInvalidState   Thread is not enabled
133      *
134      */
135     Error BecomeRouter(ThreadStatusTlv::Status aStatus);
136 
137     /**
138      * Becomes a leader and starts a new partition.
139      *
140      * If the device is already attached, this method can be used to attempt to take over as the leader, creating a new
141      * partition. For this to work, the local leader weight must be greater than the weight of the current leader. The
142      * @p aCheckWeight can be used to ensure that this check is performed.
143      *
144      * @param[in] aCheckWeight      Check that the local leader weight is larger than the weight of the current leader.
145      *
146      * @retval kErrorNone           Successfully become a Leader and started a new partition.
147      * @retval kErrorInvalidState   Thread is not enabled.
148      * @retval kErrorNotCapable     Device is not capable of becoming a leader (not router eligible), or
149      *                              @p aCheckWeight is true and cannot override the current leader due to its local
150      *                              leader weight being same or smaller than current leader's weight.
151      *
152      */
153     Error BecomeLeader(bool aCheckWeight);
154 
155 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
156     /**
157      * Gets the device properties which are used to determine the Leader Weight.
158      *
159      * @returns The current device properties.
160      *
161      */
GetDeviceProperties(void) const162     const DeviceProperties &GetDeviceProperties(void) const { return mDeviceProperties; }
163 
164     /**
165      * Sets the device properties which are then used to determine and set the Leader Weight.
166      *
167      * @param[in]  aDeviceProperties    The device properties.
168      *
169      */
170     void SetDeviceProperties(const DeviceProperties &aDeviceProperties);
171 #endif
172 
173     /**
174      * Returns the Leader Weighting value for this Thread interface.
175      *
176      * @returns The Leader Weighting value for this Thread interface.
177      *
178      */
GetLeaderWeight(void) const179     uint8_t GetLeaderWeight(void) const { return mLeaderWeight; }
180 
181     /**
182      * Sets the Leader Weighting value for this Thread interface.
183      *
184      * Directly sets the Leader Weight to the new value replacing its previous value (which may have been
185      * determined from a previous call to `SetDeviceProperties()`).
186      *
187      * @param[in]  aWeight  The Leader Weighting value.
188      *
189      */
SetLeaderWeight(uint8_t aWeight)190     void SetLeaderWeight(uint8_t aWeight) { mLeaderWeight = aWeight; }
191 
192 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
193 
194     /**
195      * Returns the preferred Partition Id when operating in the Leader role for certification testing.
196      *
197      * @returns The preferred Partition Id value.
198      *
199      */
GetPreferredLeaderPartitionId(void) const200     uint32_t GetPreferredLeaderPartitionId(void) const { return mPreferredLeaderPartitionId; }
201 
202     /**
203      * Sets the preferred Partition Id when operating in the Leader role for certification testing.
204      *
205      * @param[in]  aPartitionId  The preferred Leader Partition Id.
206      *
207      */
SetPreferredLeaderPartitionId(uint32_t aPartitionId)208     void SetPreferredLeaderPartitionId(uint32_t aPartitionId) { mPreferredLeaderPartitionId = aPartitionId; }
209 #endif
210 
211     /**
212      * Sets the preferred Router Id. Upon becoming a router/leader the node
213      * attempts to use this Router Id. If the preferred Router Id is not set or if it
214      * can not be used, a randomly generated router Id is picked.
215      * This property can be set when he device role is detached or disabled.
216      *
217      * @param[in]  aRouterId             The preferred Router Id.
218      *
219      * @retval kErrorNone          Successfully set the preferred Router Id.
220      * @retval kErrorInvalidState  Could not set (role is other than detached and disabled)
221      *
222      */
223     Error SetPreferredRouterId(uint8_t aRouterId);
224 
225     /**
226      * Gets the Partition Id which the device joined successfully once.
227      *
228      */
GetPreviousPartitionId(void) const229     uint32_t GetPreviousPartitionId(void) const { return mPreviousPartitionId; }
230 
231     /**
232      * Sets the Partition Id which the device joins successfully.
233      *
234      * @param[in]  aPartitionId   The Partition Id.
235      *
236      */
SetPreviousPartitionId(uint32_t aPartitionId)237     void SetPreviousPartitionId(uint32_t aPartitionId) { mPreviousPartitionId = aPartitionId; }
238 
239     /**
240      * Sets the Router Id.
241      *
242      * @param[in]  aRouterId   The Router Id.
243      *
244      */
245     void SetRouterId(uint8_t aRouterId);
246 
247     /**
248      * Returns the NETWORK_ID_TIMEOUT value.
249      *
250      * @returns The NETWORK_ID_TIMEOUT value.
251      *
252      */
GetNetworkIdTimeout(void) const253     uint8_t GetNetworkIdTimeout(void) const { return mNetworkIdTimeout; }
254 
255     /**
256      * Sets the NETWORK_ID_TIMEOUT value.
257      *
258      * @param[in]  aTimeout  The NETWORK_ID_TIMEOUT value.
259      *
260      */
SetNetworkIdTimeout(uint8_t aTimeout)261     void SetNetworkIdTimeout(uint8_t aTimeout) { mNetworkIdTimeout = aTimeout; }
262 
263     /**
264      * Returns the ROUTER_SELECTION_JITTER value.
265      *
266      * @returns The ROUTER_SELECTION_JITTER value in seconds.
267      *
268      */
GetRouterSelectionJitter(void) const269     uint8_t GetRouterSelectionJitter(void) const { return mRouterRoleTransition.GetJitter(); }
270 
271     /**
272      * Sets the ROUTER_SELECTION_JITTER value.
273      *
274      * @param[in] aRouterJitter  The router selection jitter value (in seconds).
275      *
276      */
SetRouterSelectionJitter(uint8_t aRouterJitter)277     void SetRouterSelectionJitter(uint8_t aRouterJitter) { mRouterRoleTransition.SetJitter(aRouterJitter); }
278 
279     /**
280      * Indicates whether or not router role transition (upgrade from REED or downgrade to REED) is pending.
281      *
282      * @retval TRUE    Router role transition is pending.
283      * @retval FALSE   Router role transition is not pending
284      *
285      */
IsRouterRoleTransitionPending(void) const286     bool IsRouterRoleTransitionPending(void) const { return mRouterRoleTransition.IsPending(); }
287 
288     /**
289      * Returns the current timeout delay in seconds till router role transition (upgrade from REED or downgrade to
290      * REED).
291      *
292      * @returns The timeout in seconds till router role transition, or zero if not pending role transition.
293      *
294      */
GetRouterRoleTransitionTimeout(void) const295     uint8_t GetRouterRoleTransitionTimeout(void) const { return mRouterRoleTransition.GetTimeout(); }
296 
297     /**
298      * Returns the ROUTER_UPGRADE_THRESHOLD value.
299      *
300      * @returns The ROUTER_UPGRADE_THRESHOLD value.
301      *
302      */
GetRouterUpgradeThreshold(void) const303     uint8_t GetRouterUpgradeThreshold(void) const { return mRouterUpgradeThreshold; }
304 
305     /**
306      * Sets the ROUTER_UPGRADE_THRESHOLD value.
307      *
308      * @param[in]  aThreshold  The ROUTER_UPGRADE_THRESHOLD value.
309      *
310      */
SetRouterUpgradeThreshold(uint8_t aThreshold)311     void SetRouterUpgradeThreshold(uint8_t aThreshold) { mRouterUpgradeThreshold = aThreshold; }
312 
313     /**
314      * Returns the ROUTER_DOWNGRADE_THRESHOLD value.
315      *
316      * @returns The ROUTER_DOWNGRADE_THRESHOLD value.
317      *
318      */
GetRouterDowngradeThreshold(void) const319     uint8_t GetRouterDowngradeThreshold(void) const { return mRouterDowngradeThreshold; }
320 
321     /**
322      * Sets the ROUTER_DOWNGRADE_THRESHOLD value.
323      *
324      * @param[in]  aThreshold  The ROUTER_DOWNGRADE_THRESHOLD value.
325      *
326      */
SetRouterDowngradeThreshold(uint8_t aThreshold)327     void SetRouterDowngradeThreshold(uint8_t aThreshold) { mRouterDowngradeThreshold = aThreshold; }
328 
329     /**
330      * Returns the MLE_CHILD_ROUTER_LINKS value.
331      *
332      * @returns The MLE_CHILD_ROUTER_LINKS value.
333      *
334      */
GetChildRouterLinks(void) const335     uint8_t GetChildRouterLinks(void) const { return mChildRouterLinks; }
336 
337     /**
338      * Sets the MLE_CHILD_ROUTER_LINKS value.
339      *
340      * @param[in]  aChildRouterLinks  The MLE_CHILD_ROUTER_LINKS value.
341      *
342      * @retval kErrorNone          Successfully set the value.
343      * @retval kErrorInvalidState  Thread protocols are enabled.
344      */
345     Error SetChildRouterLinks(uint8_t aChildRouterLinks);
346 
347     /**
348      * Returns if the REED is expected to become Router soon.
349      *
350      * @retval TRUE   If the REED is going to become a Router soon.
351      * @retval FALSE  If the REED is not going to become a Router soon.
352      *
353      */
354     bool IsExpectedToBecomeRouterSoon(void) const;
355 
356     /**
357      * Removes a link to a neighbor.
358      *
359      * @param[in]  aNeighbor  A reference to the neighbor object.
360      *
361      */
362     void RemoveNeighbor(Neighbor &aNeighbor);
363 
364     /**
365      * Invalidates a direct link to a neighboring router (due to failed link-layer acks).
366      *
367      * @param[in]  aRouter  A reference to the router object.
368      *
369      */
370     void RemoveRouterLink(Router &aRouter);
371 
372     /**
373      * Indicates whether or not the given Thread partition attributes are preferred.
374      *
375      * @param[in]  aSingletonA   Whether or not the Thread Partition A has a single router.
376      * @param[in]  aLeaderDataA  A reference to Thread Partition A's Leader Data.
377      * @param[in]  aSingletonB   Whether or not the Thread Partition B has a single router.
378      * @param[in]  aLeaderDataB  A reference to Thread Partition B's Leader Data.
379      *
380      * @retval 1   If partition A is preferred.
381      * @retval 0   If partition A and B have equal preference.
382      * @retval -1  If partition B is preferred.
383      *
384      */
385     static int ComparePartitions(bool              aSingletonA,
386                                  const LeaderData &aLeaderDataA,
387                                  bool              aSingletonB,
388                                  const LeaderData &aLeaderDataB);
389 
390     /**
391      * Fills an ConnectivityTlv.
392      *
393      * @param[out]  aTlv  A reference to the tlv to be filled.
394      *
395      */
396     void FillConnectivityTlv(ConnectivityTlv &aTlv);
397 
398     /**
399      * Generates an MLE Child Update Request message to be sent to the parent.
400      *
401      * @retval kErrorNone     Successfully generated an MLE Child Update Request message.
402      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Child Update Request message.
403      *
404      */
SendChildUpdateRequest(void)405     Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
406 
407     Error SendLinkRequest(Neighbor *aNeighbor);
408 
409 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
410     /**
411      * Sets steering data out of band
412      *
413      * @param[in]  aExtAddress  Value used to set steering data
414      *                          All zeros clears steering data
415      *                          All 0xFFs sets steering data to 0xFF
416      *                          Anything else is used to compute the bloom filter
417      *
418      */
419     void SetSteeringData(const Mac::ExtAddress *aExtAddress);
420 #endif
421 
422     /**
423      * Gets the assigned parent priority.
424      *
425      * @returns The assigned parent priority value, -2 means not assigned.
426      *
427      */
GetAssignParentPriority(void) const428     int8_t GetAssignParentPriority(void) const { return mParentPriority; }
429 
430     /**
431      * Sets the parent priority.
432      *
433      * @param[in]  aParentPriority  The parent priority value.
434      *
435      * @retval kErrorNone           Successfully set the parent priority.
436      * @retval kErrorInvalidArgs    If the parent priority value is not among 1, 0, -1 and -2.
437      *
438      */
439     Error SetAssignParentPriority(int8_t aParentPriority);
440 
441     /**
442      * Gets the longest MLE Timeout TLV for all active MTD children.
443      *
444      * @param[out]  aTimeout  A reference to where the information is placed.
445      *
446      * @retval kErrorNone           Successfully get the max child timeout
447      * @retval kErrorInvalidState   Not an active router
448      * @retval kErrorNotFound       NO MTD child
449      *
450      */
451     Error GetMaxChildTimeout(uint32_t &aTimeout) const;
452 
453     /**
454      * Sets the callback that is called when processing an MLE Discovery Request message.
455      *
456      * @param[in]  aCallback A pointer to a function that is called to deliver MLE Discovery Request data.
457      * @param[in]  aContext  A pointer to application-specific context.
458      *
459      */
SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback,void * aContext)460     void SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback, void *aContext)
461     {
462         mDiscoveryRequestCallback.Set(aCallback, aContext);
463     }
464 
465     /**
466      * Resets the MLE Advertisement Trickle timer interval.
467      *
468      */
469     void ResetAdvertiseInterval(void);
470 
471     /**
472      * Updates the MLE Advertisement Trickle timer max interval (if timer is running).
473      *
474      * This is called when there is change in router table.
475      *
476      */
477     void UpdateAdvertiseInterval(void);
478 
479 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
480     /**
481      * Generates an MLE Time Synchronization message.
482      *
483      * @retval kErrorNone     Successfully sent an MLE Time Synchronization message.
484      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Time Synchronization message.
485      *
486      */
487     Error SendTimeSync(void);
488 #endif
489 
490     /**
491      * Gets the maximum number of IP addresses that each MTD child may register with this device as parent.
492      *
493      * @returns The maximum number of IP addresses that each MTD child may register with this device as parent.
494      *
495      */
496     uint8_t GetMaxChildIpAddresses(void) const;
497 
498 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
499 
500     /**
501      * Sets/restores the maximum number of IP addresses that each MTD child may register with this
502      * device as parent.
503      *
504      * @param[in]  aMaxIpAddresses  The maximum number of IP addresses that each MTD child may register with this
505      *                              device as parent. 0 to clear the setting and restore the default.
506      *
507      * @retval kErrorNone           Successfully set/cleared the number.
508      * @retval kErrorInvalidArgs    If exceeds the allowed maximum number.
509      *
510      */
511     Error SetMaxChildIpAddresses(uint8_t aMaxIpAddresses);
512 
513     /**
514      * Sets whether the device was commissioned using CCM.
515      *
516      * @param[in]  aEnabled  TRUE if the device was commissioned using CCM, FALSE otherwise.
517      *
518      */
SetCcmEnabled(bool aEnabled)519     void SetCcmEnabled(bool aEnabled) { mCcmEnabled = aEnabled; }
520 
521     /**
522      * Sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
523      *
524      * @param[in]  aEnabled  TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
525      *
526      */
SetThreadVersionCheckEnabled(bool aEnabled)527     void SetThreadVersionCheckEnabled(bool aEnabled) { mThreadVersionCheckEnabled = aEnabled; }
528 
529     /**
530      * Gets the current Interval Max value used by Advertisement trickle timer.
531      *
532      * @returns The Interval Max of Advertisement trickle timer in milliseconds.
533      *
534      */
GetAdvertisementTrickleIntervalMax(void) const535     uint32_t GetAdvertisementTrickleIntervalMax(void) const { return mAdvertiseTrickleTimer.GetIntervalMax(); }
536 
537 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
538 
539 private:
540     // Advertisement trickle timer constants - all times are in milliseconds.
541     static constexpr uint32_t kAdvIntervalMin                = 1000;  // I_MIN
542     static constexpr uint32_t kAdvIntervalNeighborMultiplier = 4000;  // Multiplier for I_MAX per router neighbor
543     static constexpr uint32_t kAdvIntervalMaxLowerBound      = 12000; // Lower bound for I_MAX
544     static constexpr uint32_t kAdvIntervalMaxUpperBound      = 32000; // Upper bound for I_MAX
545     static constexpr uint32_t kReedAdvIntervalMin            = 570000;
546     static constexpr uint32_t kReedAdvIntervalMax            = 630000;
547 #if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
548     static constexpr uint32_t kAdvIntervalMaxLogRoutes = 5000;
549 #endif
550 
551     static constexpr uint32_t kMaxNeighborAge                = 100000; // Max neighbor age (in msec)
552     static constexpr uint32_t kMaxLeaderToRouterTimeout      = 90000;  // (in msec)
553     static constexpr uint8_t  kMinDowngradeNeighbors         = 7;
554     static constexpr uint8_t  kNetworkIdTimeout              = 120; // (in sec)
555     static constexpr uint8_t  kRouterSelectionJitter         = 120; // (in sec)
556     static constexpr uint8_t  kRouterDowngradeThreshold      = 23;
557     static constexpr uint8_t  kRouterUpgradeThreshold        = 16;
558     static constexpr uint16_t kDiscoveryMaxJitter            = 250; // Max jitter delay Discovery Responses (in msec).
559     static constexpr uint16_t kChallengeTimeout              = 2;   // Challenge timeout (in sec).
560     static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
561     static constexpr uint8_t  kLeaderDowngradeExtraDelay     = 10;  // Extra delay to downgrade leader (in sec).
562     static constexpr uint8_t  kDefaultLeaderWeight           = 64;
563 
564     // Threshold to accept a router upgrade request with reason
565     // `kBorderRouterRequest` (number of BRs acting as router in
566     // Network Data).
567     static constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
568 
569     static constexpr uint8_t kLinkRequestMinMargin    = OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN;
570     static constexpr uint8_t kPartitionMergeMinMargin = OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN;
571     static constexpr uint8_t kChildRouterLinks        = OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS;
572     static constexpr uint8_t kMaxChildIpAddresses     = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
573 
574     static constexpr uint8_t kMinCriticalChildrenCount = 6;
575 
576     static constexpr uint16_t kChildSupervisionDefaultIntervalForOlderVersion =
577         OPENTHREAD_CONFIG_CHILD_SUPERVISION_OLDER_VERSION_CHILD_DEFAULT_INTERVAL;
578 
579     static constexpr int8_t kParentPriorityHigh        = 1;
580     static constexpr int8_t kParentPriorityMedium      = 0;
581     static constexpr int8_t kParentPriorityLow         = -1;
582     static constexpr int8_t kParentPriorityUnspecified = -2;
583 
584     class RouterRoleTransition
585     {
586     public:
587         RouterRoleTransition(void);
588 
IsPending(void) const589         bool    IsPending(void) const { return (mTimeout != 0); }
590         void    StartTimeout(void);
StopTimeout(void)591         void    StopTimeout(void) { mTimeout = 0; }
IncreaseTimeout(uint8_t aIncrement)592         void    IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
GetTimeout(void) const593         uint8_t GetTimeout(void) const { return mTimeout; }
594         bool    HandleTimeTick(void);
GetJitter(void) const595         uint8_t GetJitter(void) const { return mJitter; }
SetJitter(uint8_t aJitter)596         void    SetJitter(uint8_t aJitter) { mJitter = aJitter; }
597 
598     private:
599         uint8_t mTimeout;
600         uint8_t mJitter;
601     };
602 
603     void  HandleDetachStart(void);
604     void  HandleChildStart(AttachMode aMode);
605     void  HandleSecurityPolicyChanged(void);
606     void  HandleLinkRequest(RxInfo &aRxInfo);
607     void  HandleLinkAccept(RxInfo &aRxInfo);
608     Error HandleLinkAccept(RxInfo &aRxInfo, bool aRequest);
609     void  HandleLinkAcceptAndRequest(RxInfo &aRxInfo);
610     Error HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData);
611     void  HandleParentRequest(RxInfo &aRxInfo);
612     void  HandleChildIdRequest(RxInfo &aRxInfo);
613     void  HandleChildUpdateRequest(RxInfo &aRxInfo);
614     void  HandleChildUpdateResponse(RxInfo &aRxInfo);
615     void  HandleDataRequest(RxInfo &aRxInfo);
616     void  HandleNetworkDataUpdateRouter(void);
617     void  HandleDiscoveryRequest(RxInfo &aRxInfo);
618 
619     static bool IsMessageMleSubType(const Message &aMessage);
620     static bool IsMessageChildUpdateRequest(const Message &aMessage);
621 
622     Error ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo);
623     Error ReadAndProcessRouteTlvOnFed(RxInfo &aRxInfo, uint8_t aParentId);
624 
625     void     StopAdvertiseTrickleTimer(void);
626     uint32_t DetermineAdvertiseIntervalMax(void) const;
627 
628     Error SendAddressSolicit(ThreadStatusTlv::Status aStatus);
629     void  SendAddressSolicitResponse(const Coap::Message    &aRequest,
630                                      ThreadStatusTlv::Status aResponseStatus,
631                                      const Router           *aRouter,
632                                      const Ip6::MessageInfo &aMessageInfo);
633     void  SendAddressRelease(void);
634     void  SendAdvertisement(void);
635     Error SendLinkAccept(const RxInfo      &aRxInfo,
636                          Neighbor          *aNeighbor,
637                          const TlvList     &aRequestedTlvList,
638                          const RxChallenge &aChallenge);
639     void  SendParentResponse(Child *aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest);
640     Error SendChildIdResponse(Child &aChild);
641     Error SendChildUpdateRequest(Child &aChild);
642     void  SendChildUpdateResponse(Child                  *aChild,
643                                   const Ip6::MessageInfo &aMessageInfo,
644                                   const TlvList          &aTlvList,
645                                   const RxChallenge      &aChallenge);
646     void  SendDataResponse(const Ip6::Address &aDestination,
647                            const TlvList      &aTlvList,
648                            uint16_t            aDelay,
649                            const Message      *aRequestMessage = nullptr);
650     Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
651     void  SetStateRouter(uint16_t aRloc16);
652     void  SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode);
653     void  SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
654     void  StopLeader(void);
655     void  SynchronizeChildNetworkData(void);
656     Error ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild);
657     bool  HasNeighborWithGoodLinkQuality(void) const;
658 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
659     void SignalDuaAddressEvent(const Child &aChild, const Ip6::Address &aOldDua) const;
660 #endif
661 
662     static void HandleAddressSolicitResponse(void                *aContext,
663                                              otMessage           *aMessage,
664                                              const otMessageInfo *aMessageInfo,
665                                              Error                aResult);
666     void HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
667 
668     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
669 
670     void HandlePartitionChange(void);
671 
672     void SetChildStateToValid(Child &aChild);
673     bool HasChildren(void);
674     void RemoveChildren(void);
675     bool ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
676     bool NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
677 
678     static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
679     void        HandleAdvertiseTrickleTimer(void);
680     void        HandleTimeTick(void);
681 
682     TrickleTimer mAdvertiseTrickleTimer;
683 
684 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
685     DeviceProperties mDeviceProperties;
686 #endif
687 
688     ChildTable  mChildTable;
689     RouterTable mRouterTable;
690 
691     uint8_t     mChallengeTimeout;
692     TxChallenge mChallenge;
693 
694     uint16_t mNextChildId;
695     uint8_t  mNetworkIdTimeout;
696     uint8_t  mRouterUpgradeThreshold;
697     uint8_t  mRouterDowngradeThreshold;
698     uint8_t  mLeaderWeight;
699 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
700     uint32_t mPreferredLeaderPartitionId; ///< only for certification testing
701     bool     mCcmEnabled : 1;
702     bool     mThreadVersionCheckEnabled : 1;
703 #endif
704     bool mRouterEligible : 1;
705     bool mAddressSolicitPending : 1;
706     bool mAddressSolicitRejected : 1;
707 
708     uint8_t mRouterId;
709     uint8_t mPreviousRouterId;
710 
711     uint32_t mPreviousPartitionIdRouter;         ///< The partition ID when last operating as a router
712     uint32_t mPreviousPartitionId;               ///< The partition ID when last attached
713     uint8_t  mPreviousPartitionRouterIdSequence; ///< The router ID sequence when last attached
714     uint8_t  mPreviousPartitionIdTimeout;        ///< The partition ID timeout when last attached
715 
716     RouterRoleTransition mRouterRoleTransition;
717 
718     uint8_t mChildRouterLinks;
719 
720     int8_t mParentPriority; ///< The assigned parent priority value, -2 means not assigned.
721 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
722     uint8_t mMaxChildIpAddresses;
723 #endif
724 
725 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
726     MeshCoP::SteeringData mSteeringData;
727 #endif
728 
729     Ip6::Netif::UnicastAddress mLeaderAloc;
730 
731     Callback<otThreadDiscoveryRequestCallback> mDiscoveryRequestCallback;
732 };
733 
734 DeclareTmfHandler(MleRouter, kUriAddressSolicit);
735 DeclareTmfHandler(MleRouter, kUriAddressRelease);
736 
737 #endif // OPENTHREAD_FTD
738 
739 #if OPENTHREAD_MTD
740 
741 typedef Mle MleRouter;
742 
743 #endif
744 
745 } // namespace Mle
746 
747 /**
748  * @}
749  */
750 
751 } // namespace ot
752 
753 #endif // MLE_ROUTER_HPP_
754