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      * Causes the Thread interface to become a Leader and start a new partition.
139      *
140      * @retval kErrorNone           Successfully become a Leader and started a new partition.
141      * @retval kErrorNotCapable     Device is not capable of becoming a leader
142      * @retval kErrorInvalidState   Thread is not enabled
143      *
144      */
145     Error BecomeLeader(void);
146 
147 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
148     /**
149      * Gets the device properties which are used to determine the Leader Weight.
150      *
151      * @returns The current device properties.
152      *
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      */
162     void SetDeviceProperties(const DeviceProperties &aDeviceProperties);
163 #endif
164 
165     /**
166      * Returns the Leader Weighting value for this Thread interface.
167      *
168      * @returns The Leader Weighting value for this Thread interface.
169      *
170      */
GetLeaderWeight(void) const171     uint8_t GetLeaderWeight(void) const { return mLeaderWeight; }
172 
173     /**
174      * Sets the Leader Weighting value for this Thread interface.
175      *
176      * Directly sets the Leader Weight to the new value replacing its previous value (which may have been
177      * determined from a previous call to `SetDeviceProperties()`).
178      *
179      * @param[in]  aWeight  The Leader Weighting value.
180      *
181      */
SetLeaderWeight(uint8_t aWeight)182     void SetLeaderWeight(uint8_t aWeight) { mLeaderWeight = aWeight; }
183 
184 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
185 
186     /**
187      * Returns the preferred Partition Id when operating in the Leader role for certification testing.
188      *
189      * @returns The preferred Partition Id value.
190      *
191      */
GetPreferredLeaderPartitionId(void) const192     uint32_t GetPreferredLeaderPartitionId(void) const { return mPreferredLeaderPartitionId; }
193 
194     /**
195      * Sets the preferred Partition Id when operating in the Leader role for certification testing.
196      *
197      * @param[in]  aPartitionId  The preferred Leader Partition Id.
198      *
199      */
SetPreferredLeaderPartitionId(uint32_t aPartitionId)200     void SetPreferredLeaderPartitionId(uint32_t aPartitionId) { mPreferredLeaderPartitionId = aPartitionId; }
201 #endif
202 
203     /**
204      * Sets the preferred Router Id. Upon becoming a router/leader the node
205      * attempts to use this Router Id. If the preferred Router Id is not set or if it
206      * can not be used, a randomly generated router Id is picked.
207      * This property can be set when he device role is detached or disabled.
208      *
209      * @param[in]  aRouterId             The preferred Router Id.
210      *
211      * @retval kErrorNone          Successfully set the preferred Router Id.
212      * @retval kErrorInvalidState  Could not set (role is other than detached and disabled)
213      *
214      */
215     Error SetPreferredRouterId(uint8_t aRouterId);
216 
217     /**
218      * Gets the Partition Id which the device joined successfully once.
219      *
220      */
GetPreviousPartitionId(void) const221     uint32_t GetPreviousPartitionId(void) const { return mPreviousPartitionId; }
222 
223     /**
224      * Sets the Partition Id which the device joins successfully.
225      *
226      * @param[in]  aPartitionId   The Partition Id.
227      *
228      */
SetPreviousPartitionId(uint32_t aPartitionId)229     void SetPreviousPartitionId(uint32_t aPartitionId) { mPreviousPartitionId = aPartitionId; }
230 
231     /**
232      * Sets the Router Id.
233      *
234      * @param[in]  aRouterId   The Router Id.
235      *
236      */
237     void SetRouterId(uint8_t aRouterId);
238 
239     /**
240      * Returns the next hop towards an RLOC16 destination.
241      *
242      * @param[in]  aDestination  The RLOC16 of the destination.
243      *
244      * @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
245      *
246      */
GetNextHop(uint16_t aDestination)247     uint16_t GetNextHop(uint16_t aDestination) { return mRouterTable.GetNextHop(aDestination); }
248 
249     /**
250      * Returns the NETWORK_ID_TIMEOUT value.
251      *
252      * @returns The NETWORK_ID_TIMEOUT value.
253      *
254      */
GetNetworkIdTimeout(void) const255     uint8_t GetNetworkIdTimeout(void) const { return mNetworkIdTimeout; }
256 
257     /**
258      * Sets the NETWORK_ID_TIMEOUT value.
259      *
260      * @param[in]  aTimeout  The NETWORK_ID_TIMEOUT value.
261      *
262      */
SetNetworkIdTimeout(uint8_t aTimeout)263     void SetNetworkIdTimeout(uint8_t aTimeout) { mNetworkIdTimeout = aTimeout; }
264 
265     /**
266      * Returns the ROUTER_SELECTION_JITTER value.
267      *
268      * @returns The ROUTER_SELECTION_JITTER value in seconds.
269      *
270      */
GetRouterSelectionJitter(void) const271     uint8_t GetRouterSelectionJitter(void) const { return mRouterRoleTransition.GetJitter(); }
272 
273     /**
274      * Sets the ROUTER_SELECTION_JITTER value.
275      *
276      * @param[in] aRouterJitter  The router selection jitter value (in seconds).
277      *
278      */
SetRouterSelectionJitter(uint8_t aRouterJitter)279     void SetRouterSelectionJitter(uint8_t aRouterJitter) { mRouterRoleTransition.SetJitter(aRouterJitter); }
280 
281     /**
282      * Indicates whether or not router role transition (upgrade from REED or downgrade to REED) is pending.
283      *
284      * @retval TRUE    Router role transition is pending.
285      * @retval FALSE   Router role transition is not pending
286      *
287      */
IsRouterRoleTransitionPending(void) const288     bool IsRouterRoleTransitionPending(void) const { return mRouterRoleTransition.IsPending(); }
289 
290     /**
291      * Returns the current timeout delay in seconds till router role transition (upgrade from REED or downgrade to
292      * REED).
293      *
294      * @returns The timeout in seconds till router role transition, or zero if not pending role transition.
295      *
296      */
GetRouterRoleTransitionTimeout(void) const297     uint8_t GetRouterRoleTransitionTimeout(void) const { return mRouterRoleTransition.GetTimeout(); }
298 
299     /**
300      * Returns the ROUTER_UPGRADE_THRESHOLD value.
301      *
302      * @returns The ROUTER_UPGRADE_THRESHOLD value.
303      *
304      */
GetRouterUpgradeThreshold(void) const305     uint8_t GetRouterUpgradeThreshold(void) const { return mRouterUpgradeThreshold; }
306 
307     /**
308      * Sets the ROUTER_UPGRADE_THRESHOLD value.
309      *
310      * @param[in]  aThreshold  The ROUTER_UPGRADE_THRESHOLD value.
311      *
312      */
SetRouterUpgradeThreshold(uint8_t aThreshold)313     void SetRouterUpgradeThreshold(uint8_t aThreshold) { mRouterUpgradeThreshold = aThreshold; }
314 
315     /**
316      * Returns the ROUTER_DOWNGRADE_THRESHOLD value.
317      *
318      * @returns The ROUTER_DOWNGRADE_THRESHOLD value.
319      *
320      */
GetRouterDowngradeThreshold(void) const321     uint8_t GetRouterDowngradeThreshold(void) const { return mRouterDowngradeThreshold; }
322 
323     /**
324      * Sets the ROUTER_DOWNGRADE_THRESHOLD value.
325      *
326      * @param[in]  aThreshold  The ROUTER_DOWNGRADE_THRESHOLD value.
327      *
328      */
SetRouterDowngradeThreshold(uint8_t aThreshold)329     void SetRouterDowngradeThreshold(uint8_t aThreshold) { mRouterDowngradeThreshold = aThreshold; }
330 
331     /**
332      * Returns the MLE_CHILD_ROUTER_LINKS value.
333      *
334      * @returns The MLE_CHILD_ROUTER_LINKS value.
335      *
336      */
GetChildRouterLinks(void) const337     uint8_t GetChildRouterLinks(void) const { return mChildRouterLinks; }
338 
339     /**
340      * Sets the MLE_CHILD_ROUTER_LINKS value.
341      *
342      * @param[in]  aChildRouterLinks  The MLE_CHILD_ROUTER_LINKS value.
343      *
344      * @retval kErrorNone          Successfully set the value.
345      * @retval kErrorInvalidState  Thread protocols are enabled.
346      */
347     Error SetChildRouterLinks(uint8_t aChildRouterLinks);
348 
349     /**
350      * Returns if the REED is expected to become Router soon.
351      *
352      * @retval TRUE   If the REED is going to become a Router soon.
353      * @retval FALSE  If the REED is not going to become a Router soon.
354      *
355      */
356     bool IsExpectedToBecomeRouterSoon(void) const;
357 
358     /**
359      * Removes a link to a neighbor.
360      *
361      * @param[in]  aNeighbor  A reference to the neighbor object.
362      *
363      */
364     void RemoveNeighbor(Neighbor &aNeighbor);
365 
366     /**
367      * Invalidates a direct link to a neighboring router (due to failed link-layer acks).
368      *
369      * @param[in]  aRouter  A reference to the router object.
370      *
371      */
372     void RemoveRouterLink(Router &aRouter);
373 
374     /**
375      * Indicates whether or not the RLOC16 is an MTD child of this device.
376      *
377      * @param[in]  aRloc16  The RLOC16.
378      *
379      * @retval TRUE if @p aRloc16 is an MTD child of this device.
380      * @retval FALSE if @p aRloc16 is not an MTD child of this device.
381      *
382      */
383     bool IsMinimalChild(uint16_t aRloc16);
384 
385     /**
386      * Indicates whether or not the given Thread partition attributes are preferred.
387      *
388      * @param[in]  aSingletonA   Whether or not the Thread Partition A has a single router.
389      * @param[in]  aLeaderDataA  A reference to Thread Partition A's Leader Data.
390      * @param[in]  aSingletonB   Whether or not the Thread Partition B has a single router.
391      * @param[in]  aLeaderDataB  A reference to Thread Partition B's Leader Data.
392      *
393      * @retval 1   If partition A is preferred.
394      * @retval 0   If partition A and B have equal preference.
395      * @retval -1  If partition B is preferred.
396      *
397      */
398     static int ComparePartitions(bool              aSingletonA,
399                                  const LeaderData &aLeaderDataA,
400                                  bool              aSingletonB,
401                                  const LeaderData &aLeaderDataB);
402 
403     /**
404      * Checks if the destination is reachable.
405      *
406      * @param[in]  aMeshDest   The RLOC16 of the destination.
407      * @param[in]  aIp6Header  A reference to the IPv6 header of the message.
408      *
409      * @retval kErrorNone      The destination is reachable.
410      * @retval kErrorNoRoute   The destination is not reachable and the message should be dropped.
411      *
412      */
413     Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header);
414 
415     /**
416      * Resolves 2-hop routing loops.
417      *
418      * @param[in]  aSourceMac   The RLOC16 of the previous hop.
419      * @param[in]  aDestRloc16  The RLOC16 of the final destination.
420      *
421      */
422     void ResolveRoutingLoops(uint16_t aSourceMac, uint16_t aDestRloc16);
423 
424     /**
425      * Fills an ConnectivityTlv.
426      *
427      * @param[out]  aTlv  A reference to the tlv to be filled.
428      *
429      */
430     void FillConnectivityTlv(ConnectivityTlv &aTlv);
431 
432     /**
433      * Generates an MLE Child Update Request message to be sent to the parent.
434      *
435      * @retval kErrorNone     Successfully generated an MLE Child Update Request message.
436      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Child Update Request message.
437      *
438      */
SendChildUpdateRequest(void)439     Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
440 
441     Error SendLinkRequest(Neighbor *aNeighbor);
442 
443 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
444     /**
445      * Sets steering data out of band
446      *
447      * @param[in]  aExtAddress  Value used to set steering data
448      *                          All zeros clears steering data
449      *                          All 0xFFs sets steering data to 0xFF
450      *                          Anything else is used to compute the bloom filter
451      *
452      */
453     void SetSteeringData(const Mac::ExtAddress *aExtAddress);
454 #endif
455 
456     /**
457      * Gets the assigned parent priority.
458      *
459      * @returns The assigned parent priority value, -2 means not assigned.
460      *
461      */
GetAssignParentPriority(void) const462     int8_t GetAssignParentPriority(void) const { return mParentPriority; }
463 
464     /**
465      * Sets the parent priority.
466      *
467      * @param[in]  aParentPriority  The parent priority value.
468      *
469      * @retval kErrorNone           Successfully set the parent priority.
470      * @retval kErrorInvalidArgs    If the parent priority value is not among 1, 0, -1 and -2.
471      *
472      */
473     Error SetAssignParentPriority(int8_t aParentPriority);
474 
475     /**
476      * Gets the longest MLE Timeout TLV for all active MTD children.
477      *
478      * @param[out]  aTimeout  A reference to where the information is placed.
479      *
480      * @retval kErrorNone           Successfully get the max child timeout
481      * @retval kErrorInvalidState   Not an active router
482      * @retval kErrorNotFound       NO MTD child
483      *
484      */
485     Error GetMaxChildTimeout(uint32_t &aTimeout) const;
486 
487     /**
488      * Sets the callback that is called when processing an MLE Discovery Request message.
489      *
490      * @param[in]  aCallback A pointer to a function that is called to deliver MLE Discovery Request data.
491      * @param[in]  aContext  A pointer to application-specific context.
492      *
493      */
SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback,void * aContext)494     void SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback, void *aContext)
495     {
496         mDiscoveryRequestCallback.Set(aCallback, aContext);
497     }
498 
499     /**
500      * Resets the MLE Advertisement Trickle timer interval.
501      *
502      */
503     void ResetAdvertiseInterval(void);
504 
505     /**
506      * Updates the MLE Advertisement Trickle timer max interval (if timer is running).
507      *
508      * This is called when there is change in router table.
509      *
510      */
511     void UpdateAdvertiseInterval(void);
512 
513 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
514     /**
515      * Generates an MLE Time Synchronization message.
516      *
517      * @retval kErrorNone     Successfully sent an MLE Time Synchronization message.
518      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Time Synchronization message.
519      *
520      */
521     Error SendTimeSync(void);
522 #endif
523 
524     /**
525      * Gets the maximum number of IP addresses that each MTD child may register with this device as parent.
526      *
527      * @returns The maximum number of IP addresses that each MTD child may register with this device as parent.
528      *
529      */
530     uint8_t GetMaxChildIpAddresses(void) const;
531 
532 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
533 
534     /**
535      * Sets/restores the maximum number of IP addresses that each MTD child may register with this
536      * device as parent.
537      *
538      * @param[in]  aMaxIpAddresses  The maximum number of IP addresses that each MTD child may register with this
539      *                              device as parent. 0 to clear the setting and restore the default.
540      *
541      * @retval kErrorNone           Successfully set/cleared the number.
542      * @retval kErrorInvalidArgs    If exceeds the allowed maximum number.
543      *
544      */
545     Error SetMaxChildIpAddresses(uint8_t aMaxIpAddresses);
546 
547     /**
548      * Sets whether the device was commissioned using CCM.
549      *
550      * @param[in]  aEnabled  TRUE if the device was commissioned using CCM, FALSE otherwise.
551      *
552      */
SetCcmEnabled(bool aEnabled)553     void SetCcmEnabled(bool aEnabled) { mCcmEnabled = aEnabled; }
554 
555     /**
556      * Sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
557      *
558      * @param[in]  aEnabled  TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
559      *
560      */
SetThreadVersionCheckEnabled(bool aEnabled)561     void SetThreadVersionCheckEnabled(bool aEnabled) { mThreadVersionCheckEnabled = aEnabled; }
562 
563     /**
564      * Gets the current Interval Max value used by Advertisement trickle timer.
565      *
566      * @returns The Interval Max of Advertisement trickle timer in milliseconds.
567      *
568      */
GetAdvertisementTrickleIntervalMax(void) const569     uint32_t GetAdvertisementTrickleIntervalMax(void) const { return mAdvertiseTrickleTimer.GetIntervalMax(); }
570 
571 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
572 
573 private:
574     // Advertisement trickle timer constants - all times are in milliseconds.
575     static constexpr uint32_t kAdvIntervalMin                = 1000;  // I_MIN
576     static constexpr uint32_t kAdvIntervalNeighborMultiplier = 4000;  // Multiplier for I_MAX per router neighbor
577     static constexpr uint32_t kAdvIntervalMaxLowerBound      = 12000; // Lower bound for I_MAX
578     static constexpr uint32_t kAdvIntervalMaxUpperBound      = 32000; // Upper bound for I_MAX
579     static constexpr uint32_t kReedAdvIntervalMin            = 570000;
580     static constexpr uint32_t kReedAdvIntervalMax            = 630000;
581 #if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
582     static constexpr uint32_t kAdvIntervalMaxLogRoutes = 5000;
583 #endif
584 
585     static constexpr uint32_t kMaxNeighborAge                = 100000; // Max neighbor age (in msec)
586     static constexpr uint32_t kMaxLeaderToRouterTimeout      = 90000;  // (in msec)
587     static constexpr uint8_t  kMinDowngradeNeighbors         = 7;
588     static constexpr uint8_t  kNetworkIdTimeout              = 120; // (in sec)
589     static constexpr uint8_t  kRouterSelectionJitter         = 120; // (in sec)
590     static constexpr uint8_t  kRouterDowngradeThreshold      = 23;
591     static constexpr uint8_t  kRouterUpgradeThreshold        = 16;
592     static constexpr uint16_t kDiscoveryMaxJitter            = 250; // Max jitter delay Discovery Responses (in msec).
593     static constexpr uint16_t kChallengeTimeout              = 2;   // Challenge timeout (in sec).
594     static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
595     static constexpr uint8_t  kLeaderDowngradeExtraDelay     = 10;  // Extra delay to downgrade leader (in sec).
596     static constexpr uint8_t  kDefaultLeaderWeight           = 64;
597 
598     // Threshold to accept a router upgrade request with reason
599     // `kBorderRouterRequest` (number of BRs acting as router in
600     // Network Data).
601     static constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
602 
603     static constexpr uint8_t kLinkRequestMinMargin    = OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN;
604     static constexpr uint8_t kPartitionMergeMinMargin = OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN;
605     static constexpr uint8_t kChildRouterLinks        = OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS;
606     static constexpr uint8_t kMaxChildIpAddresses     = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
607 
608     static constexpr uint8_t kMinCriticalChildrenCount = 6;
609 
610     static constexpr uint16_t kChildSupervisionDefaultIntervalForOlderVersion =
611         OPENTHREAD_CONFIG_CHILD_SUPERVISION_OLDER_VERSION_CHILD_DEFAULT_INTERVAL;
612 
613     static constexpr int8_t kParentPriorityHigh        = 1;
614     static constexpr int8_t kParentPriorityMedium      = 0;
615     static constexpr int8_t kParentPriorityLow         = -1;
616     static constexpr int8_t kParentPriorityUnspecified = -2;
617 
618     class RouterRoleTransition
619     {
620     public:
621         RouterRoleTransition(void);
622 
IsPending(void) const623         bool    IsPending(void) const { return (mTimeout != 0); }
624         void    StartTimeout(void);
StopTimeout(void)625         void    StopTimeout(void) { mTimeout = 0; }
IncreaseTimeout(uint8_t aIncrement)626         void    IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
GetTimeout(void) const627         uint8_t GetTimeout(void) const { return mTimeout; }
628         bool    HandleTimeTick(void);
GetJitter(void) const629         uint8_t GetJitter(void) const { return mJitter; }
SetJitter(uint8_t aJitter)630         void    SetJitter(uint8_t aJitter) { mJitter = aJitter; }
631 
632     private:
633         uint8_t mTimeout;
634         uint8_t mJitter;
635     };
636 
637     void  HandleDetachStart(void);
638     void  HandleChildStart(AttachMode aMode);
639     void  HandleSecurityPolicyChanged(void);
640     void  HandleLinkRequest(RxInfo &aRxInfo);
641     void  HandleLinkAccept(RxInfo &aRxInfo);
642     Error HandleLinkAccept(RxInfo &aRxInfo, bool aRequest);
643     void  HandleLinkAcceptAndRequest(RxInfo &aRxInfo);
644     Error HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData);
645     void  HandleParentRequest(RxInfo &aRxInfo);
646     void  HandleChildIdRequest(RxInfo &aRxInfo);
647     void  HandleChildUpdateRequest(RxInfo &aRxInfo);
648     void  HandleChildUpdateResponse(RxInfo &aRxInfo);
649     void  HandleDataRequest(RxInfo &aRxInfo);
650     void  HandleNetworkDataUpdateRouter(void);
651     void  HandleDiscoveryRequest(RxInfo &aRxInfo);
652 
653     Error ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo);
654     Error ReadAndProcessRouteTlvOnFed(RxInfo &aRxInfo, uint8_t aParentId);
655 
656     void     StopAdvertiseTrickleTimer(void);
657     uint32_t DetermineAdvertiseIntervalMax(void) const;
658 
659     Error SendAddressSolicit(ThreadStatusTlv::Status aStatus);
660     void  SendAddressSolicitResponse(const Coap::Message    &aRequest,
661                                      ThreadStatusTlv::Status aResponseStatus,
662                                      const Router           *aRouter,
663                                      const Ip6::MessageInfo &aMessageInfo);
664     void  SendAddressRelease(void);
665     void  SendAdvertisement(void);
666     Error SendLinkAccept(const RxInfo      &aRxInfo,
667                          Neighbor          *aNeighbor,
668                          const TlvList     &aRequestedTlvList,
669                          const RxChallenge &aChallenge);
670     void  SendParentResponse(Child *aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest);
671     Error SendChildIdResponse(Child &aChild);
672     Error SendChildUpdateRequest(Child &aChild);
673     void  SendChildUpdateResponse(Child                  *aChild,
674                                   const Ip6::MessageInfo &aMessageInfo,
675                                   const TlvList          &aTlvList,
676                                   const RxChallenge      &aChallenge);
677     void  SendDataResponse(const Ip6::Address &aDestination,
678                            const TlvList      &aTlvList,
679                            uint16_t            aDelay,
680                            const Message      *aRequestMessage = nullptr);
681     Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
682     void  SetStateRouter(uint16_t aRloc16);
683     void  SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode);
684     void  SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
685     void  StopLeader(void);
686     void  SynchronizeChildNetworkData(void);
687     Error ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild);
688     Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, uint16_t aLength, Child &aChild);
689     bool  HasNeighborWithGoodLinkQuality(void) const;
690 #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
691     void SignalDuaAddressEvent(const Child &aChild, const Ip6::Address &aOldDua) const;
692 #endif
693 
694     static void HandleAddressSolicitResponse(void                *aContext,
695                                              otMessage           *aMessage,
696                                              const otMessageInfo *aMessageInfo,
697                                              Error                aResult);
698     void HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
699 
700     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
701 
702     void HandlePartitionChange(void);
703 
704     void SetChildStateToValid(Child &aChild);
705     bool HasChildren(void);
706     void RemoveChildren(void);
707     bool ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
708     bool NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
709 
710     static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
711     void        HandleAdvertiseTrickleTimer(void);
712     void        HandleTimeTick(void);
713 
714     TrickleTimer mAdvertiseTrickleTimer;
715 
716 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
717     DeviceProperties mDeviceProperties;
718 #endif
719 
720     ChildTable  mChildTable;
721     RouterTable mRouterTable;
722 
723     uint8_t     mChallengeTimeout;
724     TxChallenge mChallenge;
725 
726     uint16_t mNextChildId;
727     uint8_t  mNetworkIdTimeout;
728     uint8_t  mRouterUpgradeThreshold;
729     uint8_t  mRouterDowngradeThreshold;
730     uint8_t  mLeaderWeight;
731 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
732     uint32_t mPreferredLeaderPartitionId; ///< only for certification testing
733     bool     mCcmEnabled : 1;
734     bool     mThreadVersionCheckEnabled : 1;
735 #endif
736     bool mRouterEligible : 1;
737     bool mAddressSolicitPending : 1;
738     bool mAddressSolicitRejected : 1;
739 
740     uint8_t mRouterId;
741     uint8_t mPreviousRouterId;
742 
743     uint32_t mPreviousPartitionIdRouter;         ///< The partition ID when last operating as a router
744     uint32_t mPreviousPartitionId;               ///< The partition ID when last attached
745     uint8_t  mPreviousPartitionRouterIdSequence; ///< The router ID sequence when last attached
746     uint8_t  mPreviousPartitionIdTimeout;        ///< The partition ID timeout when last attached
747 
748     RouterRoleTransition mRouterRoleTransition;
749 
750     uint8_t mChildRouterLinks;
751 
752     int8_t mParentPriority; ///< The assigned parent priority value, -2 means not assigned.
753 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
754     uint8_t mMaxChildIpAddresses;
755 #endif
756 
757 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
758     MeshCoP::SteeringData mSteeringData;
759 #endif
760 
761     Ip6::Netif::UnicastAddress mLeaderAloc;
762 
763     Callback<otThreadDiscoveryRequestCallback> mDiscoveryRequestCallback;
764 };
765 
766 DeclareTmfHandler(MleRouter, kUriAddressSolicit);
767 DeclareTmfHandler(MleRouter, kUriAddressRelease);
768 
769 #endif // OPENTHREAD_FTD
770 
771 #if OPENTHREAD_MTD
772 
773 typedef Mle MleRouter;
774 
775 #endif
776 
777 } // namespace Mle
778 
779 /**
780  * @}
781  */
782 
783 } // namespace ot
784 
785 #endif // MLE_ROUTER_HPP_
786