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 class MleRouter : public Mle
77 {
78     friend class Mle;
79     friend class ot::Instance;
80     friend class ot::TimeTicker;
81     friend class Tmf::Agent;
82 
83 public:
84     /**
85      * Initializes the object.
86      *
87      * @param[in]  aInstance     A reference to the OpenThread instance.
88      */
89     explicit MleRouter(Instance &aInstance);
90 
91     /**
92      * Indicates whether or not the device is router-eligible.
93      *
94      * @retval true   If device is router-eligible.
95      * @retval false  If device is not router-eligible.
96      */
97     bool IsRouterEligible(void) const;
98 
99     /**
100      * Sets whether or not the device is router-eligible.
101      *
102      * If @p aEligible is false and the device is currently operating as a router, this call will cause the device to
103      * detach and attempt to reattach as a child.
104      *
105      * @param[in]  aEligible  TRUE to configure device router-eligible, FALSE otherwise.
106      *
107      * @retval kErrorNone         Successfully set the router-eligible configuration.
108      * @retval kErrorNotCapable   The device is not capable of becoming a router.
109      */
110     Error SetRouterEligible(bool aEligible);
111 
112     /**
113      * Indicates whether a node is the only router on the network.
114      *
115      * @retval TRUE   It is the only router in the network.
116      * @retval FALSE  It is a child or is not a single router in the network.
117      */
118     bool IsSingleton(void) const;
119 
120     /**
121      * Generates an Address Solicit request for a Router ID.
122      *
123      * @param[in]  aStatus  The reason for requesting a Router ID.
124      *
125      * @retval kErrorNone           Successfully generated an Address Solicit message.
126      * @retval kErrorNotCapable     Device is not capable of becoming a router
127      * @retval kErrorInvalidState   Thread is not enabled
128      */
129     Error BecomeRouter(ThreadStatusTlv::Status aStatus);
130 
131     /**
132      * Becomes a leader and starts a new partition.
133      *
134      * If the device is already attached, this method can be used to attempt to take over as the leader, creating a new
135      * partition. For this to work, the local leader weight must be greater than the weight of the current leader. The
136      * @p aCheckWeight can be used to ensure that this check is performed.
137      *
138      * @param[in] aCheckWeight      Check that the local leader weight is larger than the weight of the current leader.
139      *
140      * @retval kErrorNone           Successfully become a Leader and started a new partition.
141      * @retval kErrorInvalidState   Thread is not enabled.
142      * @retval kErrorNotCapable     Device is not capable of becoming a leader (not router eligible), or
143      *                              @p aCheckWeight is true and cannot override the current leader due to its local
144      *                              leader weight being same or smaller than current leader's weight.
145      */
146     Error BecomeLeader(bool aCheckWeight);
147 
148 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
149     /**
150      * Gets the device properties which are used to determine the Leader Weight.
151      *
152      * @returns The current device properties.
153      */
GetDeviceProperties(void) const154     const DeviceProperties &GetDeviceProperties(void) const { return mDeviceProperties; }
155 
156     /**
157      * Sets the device properties which are then used to determine and set the Leader Weight.
158      *
159      * @param[in]  aDeviceProperties    The device properties.
160      */
161     void SetDeviceProperties(const DeviceProperties &aDeviceProperties);
162 #endif
163 
164     /**
165      * Returns the Leader Weighting value for this Thread interface.
166      *
167      * @returns The Leader Weighting value for this Thread interface.
168      */
GetLeaderWeight(void) const169     uint8_t GetLeaderWeight(void) const { return mLeaderWeight; }
170 
171     /**
172      * Sets the Leader Weighting value for this Thread interface.
173      *
174      * Directly sets the Leader Weight to the new value replacing its previous value (which may have been
175      * determined from a previous call to `SetDeviceProperties()`).
176      *
177      * @param[in]  aWeight  The Leader Weighting value.
178      */
SetLeaderWeight(uint8_t aWeight)179     void SetLeaderWeight(uint8_t aWeight) { mLeaderWeight = aWeight; }
180 
181 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
182 
183     /**
184      * Returns the preferred Partition Id when operating in the Leader role for certification testing.
185      *
186      * @returns The preferred Partition Id value.
187      */
GetPreferredLeaderPartitionId(void) const188     uint32_t GetPreferredLeaderPartitionId(void) const { return mPreferredLeaderPartitionId; }
189 
190     /**
191      * Sets the preferred Partition Id when operating in the Leader role for certification testing.
192      *
193      * @param[in]  aPartitionId  The preferred Leader Partition Id.
194      */
SetPreferredLeaderPartitionId(uint32_t aPartitionId)195     void SetPreferredLeaderPartitionId(uint32_t aPartitionId) { mPreferredLeaderPartitionId = aPartitionId; }
196 #endif
197 
198     /**
199      * Sets the preferred Router Id. Upon becoming a router/leader the node
200      * attempts to use this Router Id. If the preferred Router Id is not set or if it
201      * can not be used, a randomly generated router Id is picked.
202      * This property can be set when he device role is detached or disabled.
203      *
204      * @param[in]  aRouterId             The preferred Router Id.
205      *
206      * @retval kErrorNone          Successfully set the preferred Router Id.
207      * @retval kErrorInvalidState  Could not set (role is other than detached and disabled)
208      */
209     Error SetPreferredRouterId(uint8_t aRouterId);
210 
211     /**
212      * Gets the Partition Id which the device joined successfully once.
213      */
GetPreviousPartitionId(void) const214     uint32_t GetPreviousPartitionId(void) const { return mPreviousPartitionId; }
215 
216     /**
217      * Sets the Partition Id which the device joins successfully.
218      *
219      * @param[in]  aPartitionId   The Partition Id.
220      */
SetPreviousPartitionId(uint32_t aPartitionId)221     void SetPreviousPartitionId(uint32_t aPartitionId) { mPreviousPartitionId = aPartitionId; }
222 
223     /**
224      * Sets the Router Id.
225      *
226      * @param[in]  aRouterId   The Router Id.
227      */
228     void SetRouterId(uint8_t aRouterId);
229 
230     /**
231      * Returns the NETWORK_ID_TIMEOUT value.
232      *
233      * @returns The NETWORK_ID_TIMEOUT value.
234      */
GetNetworkIdTimeout(void) const235     uint8_t GetNetworkIdTimeout(void) const { return mNetworkIdTimeout; }
236 
237     /**
238      * Sets the NETWORK_ID_TIMEOUT value.
239      *
240      * @param[in]  aTimeout  The NETWORK_ID_TIMEOUT value.
241      */
SetNetworkIdTimeout(uint8_t aTimeout)242     void SetNetworkIdTimeout(uint8_t aTimeout) { mNetworkIdTimeout = aTimeout; }
243 
244     /**
245      * Returns the ROUTER_SELECTION_JITTER value.
246      *
247      * @returns The ROUTER_SELECTION_JITTER value in seconds.
248      */
GetRouterSelectionJitter(void) const249     uint8_t GetRouterSelectionJitter(void) const { return mRouterRoleTransition.GetJitter(); }
250 
251     /**
252      * Sets the ROUTER_SELECTION_JITTER value.
253      *
254      * @param[in] aRouterJitter  The router selection jitter value (in seconds).
255      */
SetRouterSelectionJitter(uint8_t aRouterJitter)256     void SetRouterSelectionJitter(uint8_t aRouterJitter) { mRouterRoleTransition.SetJitter(aRouterJitter); }
257 
258     /**
259      * Indicates whether or not router role transition (upgrade from REED or downgrade to REED) is pending.
260      *
261      * @retval TRUE    Router role transition is pending.
262      * @retval FALSE   Router role transition is not pending
263      */
IsRouterRoleTransitionPending(void) const264     bool IsRouterRoleTransitionPending(void) const { return mRouterRoleTransition.IsPending(); }
265 
266     /**
267      * Returns the current timeout delay in seconds till router role transition (upgrade from REED or downgrade to
268      * REED).
269      *
270      * @returns The timeout in seconds till router role transition, or zero if not pending role transition.
271      */
GetRouterRoleTransitionTimeout(void) const272     uint8_t GetRouterRoleTransitionTimeout(void) const { return mRouterRoleTransition.GetTimeout(); }
273 
274     /**
275      * Returns the ROUTER_UPGRADE_THRESHOLD value.
276      *
277      * @returns The ROUTER_UPGRADE_THRESHOLD value.
278      */
GetRouterUpgradeThreshold(void) const279     uint8_t GetRouterUpgradeThreshold(void) const { return mRouterUpgradeThreshold; }
280 
281     /**
282      * Sets the ROUTER_UPGRADE_THRESHOLD value.
283      *
284      * @param[in]  aThreshold  The ROUTER_UPGRADE_THRESHOLD value.
285      */
SetRouterUpgradeThreshold(uint8_t aThreshold)286     void SetRouterUpgradeThreshold(uint8_t aThreshold) { mRouterUpgradeThreshold = aThreshold; }
287 
288     /**
289      * Returns the ROUTER_DOWNGRADE_THRESHOLD value.
290      *
291      * @returns The ROUTER_DOWNGRADE_THRESHOLD value.
292      */
GetRouterDowngradeThreshold(void) const293     uint8_t GetRouterDowngradeThreshold(void) const { return mRouterDowngradeThreshold; }
294 
295     /**
296      * Sets the ROUTER_DOWNGRADE_THRESHOLD value.
297      *
298      * @param[in]  aThreshold  The ROUTER_DOWNGRADE_THRESHOLD value.
299      */
SetRouterDowngradeThreshold(uint8_t aThreshold)300     void SetRouterDowngradeThreshold(uint8_t aThreshold) { mRouterDowngradeThreshold = aThreshold; }
301 
302     /**
303      * Returns the MLE_CHILD_ROUTER_LINKS value.
304      *
305      * @returns The MLE_CHILD_ROUTER_LINKS value.
306      */
GetChildRouterLinks(void) const307     uint8_t GetChildRouterLinks(void) const { return mChildRouterLinks; }
308 
309     /**
310      * Sets the MLE_CHILD_ROUTER_LINKS value.
311      *
312      * @param[in]  aChildRouterLinks  The MLE_CHILD_ROUTER_LINKS value.
313      *
314      * @retval kErrorNone          Successfully set the value.
315      * @retval kErrorInvalidState  Thread protocols are enabled.
316      */
317     Error SetChildRouterLinks(uint8_t aChildRouterLinks);
318 
319     /**
320      * Returns if the REED is expected to become Router soon.
321      *
322      * @retval TRUE   If the REED is going to become a Router soon.
323      * @retval FALSE  If the REED is not going to become a Router soon.
324      */
325     bool IsExpectedToBecomeRouterSoon(void) const;
326 
327     /**
328      * Removes a link to a neighbor.
329      *
330      * @param[in]  aNeighbor  A reference to the neighbor object.
331      */
332     void RemoveNeighbor(Neighbor &aNeighbor);
333 
334     /**
335      * Invalidates a direct link to a neighboring router (due to failed link-layer acks).
336      *
337      * @param[in]  aRouter  A reference to the router object.
338      */
339     void RemoveRouterLink(Router &aRouter);
340 
341     /**
342      * Indicates whether or not the given Thread partition attributes are preferred.
343      *
344      * @param[in]  aSingletonA   Whether or not the Thread Partition A has a single router.
345      * @param[in]  aLeaderDataA  A reference to Thread Partition A's Leader Data.
346      * @param[in]  aSingletonB   Whether or not the Thread Partition B has a single router.
347      * @param[in]  aLeaderDataB  A reference to Thread Partition B's Leader Data.
348      *
349      * @retval 1   If partition A is preferred.
350      * @retval 0   If partition A and B have equal preference.
351      * @retval -1  If partition B is preferred.
352      */
353     static int ComparePartitions(bool              aSingletonA,
354                                  const LeaderData &aLeaderDataA,
355                                  bool              aSingletonB,
356                                  const LeaderData &aLeaderDataB);
357 
358     /**
359      * Fills an ConnectivityTlv.
360      *
361      * @param[out]  aTlv  A reference to the tlv to be filled.
362      */
363     void FillConnectivityTlv(ConnectivityTlv &aTlv);
364 
365     /**
366      * Schedule tx of MLE Advertisement message (unicast) to the given neighboring router after a random delay.
367      *
368      * @param[in] aRouter  The router to send the Advertisement to.
369      *
370      */
371     void ScheduleUnicastAdvertisementTo(const Router &aRouter);
372 
373 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
374     /**
375      * Sets steering data out of band
376      *
377      * @param[in]  aExtAddress  Value used to set steering data
378      *                          All zeros clears steering data
379      *                          All 0xFFs sets steering data to 0xFF
380      *                          Anything else is used to compute the bloom filter
381      */
382     void SetSteeringData(const Mac::ExtAddress *aExtAddress);
383 #endif
384 
385     /**
386      * Gets the assigned parent priority.
387      *
388      * @returns The assigned parent priority value, -2 means not assigned.
389      */
GetAssignParentPriority(void) const390     int8_t GetAssignParentPriority(void) const { return mParentPriority; }
391 
392     /**
393      * Sets the parent priority.
394      *
395      * @param[in]  aParentPriority  The parent priority value.
396      *
397      * @retval kErrorNone           Successfully set the parent priority.
398      * @retval kErrorInvalidArgs    If the parent priority value is not among 1, 0, -1 and -2.
399      */
400     Error SetAssignParentPriority(int8_t aParentPriority);
401 
402     /**
403      * Gets the longest MLE Timeout TLV for all active MTD children.
404      *
405      * @param[out]  aTimeout  A reference to where the information is placed.
406      *
407      * @retval kErrorNone           Successfully get the max child timeout
408      * @retval kErrorInvalidState   Not an active router
409      * @retval kErrorNotFound       NO MTD child
410      */
411     Error GetMaxChildTimeout(uint32_t &aTimeout) const;
412 
413     /**
414      * Sets the callback that is called when processing an MLE Discovery Request message.
415      *
416      * @param[in]  aCallback A pointer to a function that is called to deliver MLE Discovery Request data.
417      * @param[in]  aContext  A pointer to application-specific context.
418      */
SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback,void * aContext)419     void SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback, void *aContext)
420     {
421         mDiscoveryRequestCallback.Set(aCallback, aContext);
422     }
423 
424     /**
425      * Resets the MLE Advertisement Trickle timer interval.
426      */
427     void ResetAdvertiseInterval(void);
428 
429     /**
430      * Updates the MLE Advertisement Trickle timer max interval (if timer is running).
431      *
432      * This is called when there is change in router table.
433      */
434     void UpdateAdvertiseInterval(void);
435 
436 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
437     /**
438      * Generates an MLE Time Synchronization message.
439      *
440      * @retval kErrorNone     Successfully sent an MLE Time Synchronization message.
441      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Time Synchronization message.
442      */
443     Error SendTimeSync(void);
444 #endif
445 
446     /**
447      * Gets the maximum number of IP addresses that each MTD child may register with this device as parent.
448      *
449      * @returns The maximum number of IP addresses that each MTD child may register with this device as parent.
450      */
451     uint8_t GetMaxChildIpAddresses(void) const;
452 
453 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
454 
455     /**
456      * Sets/restores the maximum number of IP addresses that each MTD child may register with this
457      * device as parent.
458      *
459      * @param[in]  aMaxIpAddresses  The maximum number of IP addresses that each MTD child may register with this
460      *                              device as parent. 0 to clear the setting and restore the default.
461      *
462      * @retval kErrorNone           Successfully set/cleared the number.
463      * @retval kErrorInvalidArgs    If exceeds the allowed maximum number.
464      */
465     Error SetMaxChildIpAddresses(uint8_t aMaxIpAddresses);
466 
467     /**
468      * Sets whether the device was commissioned using CCM.
469      *
470      * @param[in]  aEnabled  TRUE if the device was commissioned using CCM, FALSE otherwise.
471      */
SetCcmEnabled(bool aEnabled)472     void SetCcmEnabled(bool aEnabled) { mCcmEnabled = aEnabled; }
473 
474     /**
475      * Sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
476      *
477      * @param[in]  aEnabled  TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
478      */
SetThreadVersionCheckEnabled(bool aEnabled)479     void SetThreadVersionCheckEnabled(bool aEnabled) { mThreadVersionCheckEnabled = aEnabled; }
480 
481     /**
482      * Gets the current Interval Max value used by Advertisement trickle timer.
483      *
484      * @returns The Interval Max of Advertisement trickle timer in milliseconds.
485      */
GetAdvertisementTrickleIntervalMax(void) const486     uint32_t GetAdvertisementTrickleIntervalMax(void) const { return mAdvertiseTrickleTimer.GetIntervalMax(); }
487 
488 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
489 
490 private:
491     //------------------------------------------------------------------------------------------------------------------
492     // Constants
493 
494     // Advertisement trickle timer constants - all times are in milliseconds.
495     static constexpr uint32_t kAdvIntervalMin                = 1000;  // I_MIN
496     static constexpr uint32_t kAdvIntervalNeighborMultiplier = 4000;  // Multiplier for I_MAX per router neighbor
497     static constexpr uint32_t kAdvIntervalMaxLowerBound      = 12000; // Lower bound for I_MAX
498     static constexpr uint32_t kAdvIntervalMaxUpperBound      = 32000; // Upper bound for I_MAX
499     static constexpr uint32_t kReedAdvIntervalMin            = 570000;
500     static constexpr uint32_t kReedAdvIntervalMax            = 630000;
501 #if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
502     static constexpr uint32_t kAdvIntervalMaxLogRoutes = 5000;
503 #endif
504 
505     static constexpr uint32_t kMaxUnicastAdvertisementDelay  = 1000;   // Max random delay for unciast Adv tx
506     static constexpr uint32_t kMaxNeighborAge                = 100000; // Max neighbor age (in msec)
507     static constexpr uint32_t kMaxLeaderToRouterTimeout      = 90000;  // (in msec)
508     static constexpr uint8_t  kMinDowngradeNeighbors         = 7;
509     static constexpr uint8_t  kNetworkIdTimeout              = 120; // (in sec)
510     static constexpr uint8_t  kRouterSelectionJitter         = 120; // (in sec)
511     static constexpr uint8_t  kRouterDowngradeThreshold      = 23;
512     static constexpr uint8_t  kRouterUpgradeThreshold        = 16;
513     static constexpr uint16_t kDiscoveryMaxJitter            = 250; // Max jitter delay Discovery Responses (in msec).
514     static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
515     static constexpr uint8_t  kLeaderDowngradeExtraDelay     = 10;  // Extra delay to downgrade leader (in sec).
516     static constexpr uint8_t  kDefaultLeaderWeight           = 64;
517     static constexpr uint8_t  kAlternateRloc16Timeout        = 8; // Time to use alternate RLOC16 (in sec).
518 
519     // Threshold to accept a router upgrade request with reason
520     // `kBorderRouterRequest` (number of BRs acting as router in
521     // Network Data).
522     static constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
523 
524     static constexpr uint8_t kLinkRequestMinMargin    = OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN;
525     static constexpr uint8_t kPartitionMergeMinMargin = OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN;
526     static constexpr uint8_t kChildRouterLinks        = OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS;
527     static constexpr uint8_t kMaxChildIpAddresses     = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
528 
529     // Constants for gradual router link establishment (on FTD child)
530     struct GradualChildRouterLink
531     {
532         static constexpr uint8_t  kExtraChildRouterLinks   = OPENTHREAD_CONFIG_MLE_EXTRA_CHILD_ROUTER_LINKS_GRADUAL;
533         static constexpr uint32_t kWaitDurationAfterAttach = 300;   // in seconds (5 minutes)
534         static constexpr uint32_t kMinLinkRequestDelay     = 1500;  // in msec
535         static constexpr uint32_t kMaxLinkRequestDelay     = 10000; // in msec
536         static constexpr uint32_t kProbabilityPercentage   = 5;     // in percent
537     };
538 
539     static constexpr uint8_t kMinCriticalChildrenCount = 6;
540 
541     static constexpr uint16_t kChildSupervisionDefaultIntervalForOlderVersion =
542         OPENTHREAD_CONFIG_CHILD_SUPERVISION_OLDER_VERSION_CHILD_DEFAULT_INTERVAL;
543 
544     static constexpr int8_t kParentPriorityHigh        = 1;
545     static constexpr int8_t kParentPriorityMedium      = 0;
546     static constexpr int8_t kParentPriorityLow         = -1;
547     static constexpr int8_t kParentPriorityUnspecified = -2;
548 
549     //------------------------------------------------------------------------------------------------------------------
550     // Nested types
551 
552     class RouterRoleTransition
553     {
554     public:
555         RouterRoleTransition(void);
556 
IsPending(void) const557         bool    IsPending(void) const { return (mTimeout != 0); }
558         void    StartTimeout(void);
StopTimeout(void)559         void    StopTimeout(void) { mTimeout = 0; }
IncreaseTimeout(uint8_t aIncrement)560         void    IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
GetTimeout(void) const561         uint8_t GetTimeout(void) const { return mTimeout; }
562         bool    HandleTimeTick(void);
GetJitter(void) const563         uint8_t GetJitter(void) const { return mJitter; }
SetJitter(uint8_t aJitter)564         void    SetJitter(uint8_t aJitter) { mJitter = aJitter; }
565 
566     private:
567         uint8_t mTimeout;
568         uint8_t mJitter;
569     };
570 
571     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
572 
573     class RouterRoleRestorer : public InstanceLocator
574     {
575         // Attempts to restore the router or leader role after an MLE
576         // restart(e.g., after a device reboot) by sending multicast
577         // Link Requests.
578 
579     public:
580         RouterRoleRestorer(Instance &aInstance);
581 
IsActive(void) const582         bool IsActive(void) const { return mAttempts > 0; }
583         void Start(DeviceRole aPreviousRole);
Stop(void)584         void Stop(void) { mAttempts = 0; }
585         void HandleTimer(void);
586 
GenerateRandomChallenge(void)587         void               GenerateRandomChallenge(void) { mChallenge.GenerateRandom(); }
GetChallenge(void) const588         const TxChallenge &GetChallenge(void) const { return mChallenge; }
589 
590     private:
591         void SendMulticastLinkRequest(void);
592 
593         uint8_t     mAttempts;
594         TxChallenge mChallenge;
595     };
596 
597     //------------------------------------------------------------------------------------------------------------------
598     // Methods
599 
600     void     SetAlternateRloc16(uint16_t aRloc16);
601     void     ClearAlternateRloc16(void);
602     void     HandleDetachStart(void);
603     void     HandleChildStart(AttachMode aMode);
604     void     HandleSecurityPolicyChanged(void);
605     void     HandleLinkRequest(RxInfo &aRxInfo);
606     void     HandleLinkAccept(RxInfo &aRxInfo);
607     void     HandleLinkAcceptAndRequest(RxInfo &aRxInfo);
608     void     HandleLinkAcceptVariant(RxInfo &aRxInfo, MessageType aMessageType);
609     Error    HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData);
610     void     HandleParentRequest(RxInfo &aRxInfo);
611     void     HandleChildIdRequest(RxInfo &aRxInfo);
612     void     HandleChildUpdateRequestOnParent(RxInfo &aRxInfo);
613     void     HandleChildUpdateResponseOnParent(RxInfo &aRxInfo);
614     void     HandleDataRequest(RxInfo &aRxInfo);
615     void     HandleNetworkDataUpdateRouter(void);
616     void     HandleDiscoveryRequest(RxInfo &aRxInfo);
617     void     EstablishRouterLinkOnFtdChild(Router &aRouter, RxInfo &aRxInfo, uint8_t aLinkMargin);
618     Error    ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo);
619     Error    ReadAndProcessRouteTlvOnFtdChild(RxInfo &aRxInfo, uint8_t aParentId);
620     void     StopAdvertiseTrickleTimer(void);
621     uint32_t DetermineAdvertiseIntervalMax(void) const;
622     Error    SendAddressSolicit(ThreadStatusTlv::Status aStatus);
623     void     SendAddressSolicitResponse(const Coap::Message    &aRequest,
624                                         ThreadStatusTlv::Status aResponseStatus,
625                                         const Router           *aRouter,
626                                         const Ip6::MessageInfo &aMessageInfo);
627     void     SendAddressRelease(void);
628     void     SendMulticastAdvertisement(void);
629     void     SendAdvertisement(const Ip6::Address &aDestination);
630     void     SendLinkRequest(Router *aRouter);
631     Error    SendLinkAccept(const LinkAcceptInfo &aInfo);
632     void     SendParentResponse(const ParentResponseInfo &aInfo);
633     Error    SendChildIdResponse(Child &aChild);
634     Error    SendChildUpdateRequestToChild(Child &aChild);
635     void     SendChildUpdateResponseToChild(Child                  *aChild,
636                                             const Ip6::MessageInfo &aMessageInfo,
637                                             const TlvList          &aTlvList,
638                                             const RxChallenge      &aChallenge);
639     void     SendMulticastDataResponse(void);
640     void     SendDataResponse(const Ip6::Address &aDestination,
641                               const TlvList      &aTlvList,
642                               const Message      *aRequestMessage = nullptr);
643     Error    SendDiscoveryResponse(const Ip6::Address &aDestination, const DiscoveryResponseInfo &aInfo);
644     void     SetStateRouter(uint16_t aRloc16);
645     void     SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode);
646     void     SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
647     void     StopLeader(void);
648     void     SynchronizeChildNetworkData(void);
649     Error    ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild);
650     bool     HasNeighborWithGoodLinkQuality(void) const;
651     void     HandlePartitionChange(void);
652     void     SetChildStateToValid(Child &aChild);
653     bool     HasChildren(void);
654     void     RemoveChildren(void);
655     bool     ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
656     bool     NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
657     void     HandleAdvertiseTrickleTimer(void);
658     void     HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
659     void     HandleTimeTick(void);
660 
661     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
662 
663 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
664     void SignalDuaAddressEvent(const Child &aChild, const Ip6::Address &aOldDua) const;
665 #endif
666 
667     static bool IsMessageMleSubType(const Message &aMessage);
668     static bool IsMessageChildUpdateRequest(const Message &aMessage);
669     static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
670     static void HandleAddressSolicitResponse(void                *aContext,
671                                              otMessage           *aMessage,
672                                              const otMessageInfo *aMessageInfo,
673                                              otError              aResult);
674 
675     //------------------------------------------------------------------------------------------------------------------
676     // Variables
677 
678     bool mRouterEligible : 1;
679     bool mAddressSolicitPending : 1;
680     bool mAddressSolicitRejected : 1;
681 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
682     bool mCcmEnabled : 1;
683     bool mThreadVersionCheckEnabled : 1;
684 #endif
685 
686     uint8_t mRouterId;
687     uint8_t mPreviousRouterId;
688     uint8_t mNetworkIdTimeout;
689     uint8_t mRouterUpgradeThreshold;
690     uint8_t mRouterDowngradeThreshold;
691     uint8_t mLeaderWeight;
692     uint8_t mPreviousPartitionRouterIdSequence;
693     uint8_t mPreviousPartitionIdTimeout;
694     uint8_t mChildRouterLinks;
695     uint8_t mAlternateRloc16Timeout;
696 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
697     uint8_t mMaxChildIpAddresses;
698 #endif
699     int8_t   mParentPriority;
700     uint16_t mNextChildId;
701     uint32_t mPreviousPartitionIdRouter;
702     uint32_t mPreviousPartitionId;
703 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
704     uint32_t mPreferredLeaderPartitionId;
705 #endif
706 
707     TrickleTimer               mAdvertiseTrickleTimer;
708     ChildTable                 mChildTable;
709     RouterTable                mRouterTable;
710     RouterRoleRestorer         mRouterRoleRestorer;
711     RouterRoleTransition       mRouterRoleTransition;
712     Ip6::Netif::UnicastAddress mLeaderAloc;
713 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
714     DeviceProperties mDeviceProperties;
715 #endif
716 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
717     MeshCoP::SteeringData mSteeringData;
718 #endif
719     Callback<otThreadDiscoveryRequestCallback> mDiscoveryRequestCallback;
720 };
721 
722 DeclareTmfHandler(MleRouter, kUriAddressSolicit);
723 DeclareTmfHandler(MleRouter, kUriAddressRelease);
724 
725 #endif // OPENTHREAD_FTD
726 
727 #if OPENTHREAD_MTD
728 
729 typedef Mle MleRouter;
730 
731 #endif
732 
733 } // namespace Mle
734 
735 /**
736  * @}
737  */
738 
739 } // namespace ot
740 
741 #endif // MLE_ROUTER_HPP_
742