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_table.hpp"
51 #include "thread/mle.hpp"
52 #include "thread/mle_tlvs.hpp"
53 #include "thread/router_table.hpp"
54 #include "thread/thread_tlvs.hpp"
55 #include "thread/tmf.hpp"
56 #include "thread/topology.hpp"
57 
58 namespace ot {
59 namespace Mle {
60 
61 /**
62  * @addtogroup core-mle-router
63  *
64  * @brief
65  *   This module includes definitions for MLE functionality required by the Thread Router and Leader roles.
66  *
67  * @{
68  */
69 
70 #if OPENTHREAD_FTD
71 
72 /**
73  * This class implements MLE functionality required by the Thread Router and Leader roles.
74  *
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      * This constructor initializes the object.
86      *
87      * @param[in]  aInstance     A reference to the OpenThread instance.
88      *
89      */
90     explicit MleRouter(Instance &aInstance);
91 
92     /**
93      * This method indicates whether or not the device is router-eligible.
94      *
95      * @retval true   If device is router-eligible.
96      * @retval false  If device is not router-eligible.
97      *
98      */
99     bool IsRouterEligible(void) const;
100 
101     /**
102      * This method sets whether or not the device is router-eligible.
103      *
104      * If @p aEligible is false and the device is currently operating as a router, this call will cause the device to
105      * detach and attempt to reattach as a child.
106      *
107      * @param[in]  aEligible  TRUE to configure device router-eligible, FALSE otherwise.
108      *
109      * @retval kErrorNone         Successfully set the router-eligible configuration.
110      * @retval kErrorNotCapable   The device is not capable of becoming a router.
111      *
112      */
113     Error SetRouterEligible(bool aEligible);
114 
115     /**
116      * This method indicates whether a node is the only router on the network.
117      *
118      * @retval TRUE   It is the only router in the network.
119      * @retval FALSE  It is a child or is not a single router in the network.
120      *
121      */
122     bool IsSingleton(void) const;
123 
124     /**
125      * This method generates an Address Solicit request for a Router ID.
126      *
127      * @param[in]  aStatus  The reason for requesting a Router ID.
128      *
129      * @retval kErrorNone           Successfully generated an Address Solicit message.
130      * @retval kErrorNotCapable     Device is not capable of becoming a router
131      * @retval kErrorInvalidState   Thread is not enabled
132      *
133      */
134     Error BecomeRouter(ThreadStatusTlv::Status aStatus);
135 
136     /**
137      * This method causes the Thread interface to become a Leader and start a new partition.
138      *
139      * @retval kErrorNone           Successfully become a Leader and started a new partition.
140      * @retval kErrorNotCapable     Device is not capable of becoming a leader
141      * @retval kErrorInvalidState   Thread is not enabled
142      *
143      */
144     Error BecomeLeader(void);
145 
146     /**
147      * This method gets the device properties which are used to determine the Leader Weight.
148      *
149      * @returns The current device properties.
150      *
151      */
GetDeviceProperties(void) const152     const DeviceProperties &GetDeviceProperties(void) const { return mDeviceProperties; }
153 
154     /**
155      * This method sets the device properties which are then used to determine and set the Leader Weight.
156      *
157      * @param[in]  aDeviceProperties    The device properties.
158      *
159      */
160     void SetDeviceProperties(const DeviceProperties &aDeviceProperties);
161 
162     /**
163      * This method returns the Leader Weighting value for this Thread interface.
164      *
165      * @returns The Leader Weighting value for this Thread interface.
166      *
167      */
GetLeaderWeight(void) const168     uint8_t GetLeaderWeight(void) const { return mLeaderWeight; }
169 
170     /**
171      * This method sets the Leader Weighting value for this Thread interface.
172      *
173      * This method directly sets the Leader Weight to the new value replacing its previous value (which may have been
174      * determined from a previous call to `SetDeviceProperties()`).
175      *
176      * @param[in]  aWeight  The Leader Weighting value.
177      *
178      */
SetLeaderWeight(uint8_t aWeight)179     void SetLeaderWeight(uint8_t aWeight) { mLeaderWeight = aWeight; }
180 
181 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
182 
183     /**
184      * This method returns the preferred Partition Id when operating in the Leader role for certification testing.
185      *
186      * @returns The preferred Partition Id value.
187      *
188      */
GetPreferredLeaderPartitionId(void) const189     uint32_t GetPreferredLeaderPartitionId(void) const { return mPreferredLeaderPartitionId; }
190 
191     /**
192      * This method sets the preferred Partition Id when operating in the Leader role for certification testing.
193      *
194      * @param[in]  aPartitionId  The preferred Leader Partition Id.
195      *
196      */
SetPreferredLeaderPartitionId(uint32_t aPartitionId)197     void SetPreferredLeaderPartitionId(uint32_t aPartitionId) { mPreferredLeaderPartitionId = aPartitionId; }
198 #endif
199 
200     /**
201      * This method sets the preferred Router Id. Upon becoming a router/leader the node
202      * attempts to use this Router Id. If the preferred Router Id is not set or if it
203      * can not be used, a randomly generated router Id is picked.
204      * This property can be set when he device role is detached or disabled.
205      *
206      * @param[in]  aRouterId             The preferred Router Id.
207      *
208      * @retval kErrorNone          Successfully set the preferred Router Id.
209      * @retval kErrorInvalidState  Could not set (role is other than detached and disabled)
210      *
211      */
212     Error SetPreferredRouterId(uint8_t aRouterId);
213 
214     /**
215      * This method gets the Partition Id which the device joined successfully once.
216      *
217      */
GetPreviousPartitionId(void) const218     uint32_t GetPreviousPartitionId(void) const { return mPreviousPartitionId; }
219 
220     /**
221      * This method sets the Partition Id which the device joins successfully.
222      *
223      * @param[in]  aPartitionId   The Partition Id.
224      *
225      */
SetPreviousPartitionId(uint32_t aPartitionId)226     void SetPreviousPartitionId(uint32_t aPartitionId) { mPreviousPartitionId = aPartitionId; }
227 
228     /**
229      * This method sets the Router Id.
230      *
231      * @param[in]  aRouterId   The Router Id.
232      *
233      */
234     void SetRouterId(uint8_t aRouterId);
235 
236     /**
237      * This method returns the next hop towards an RLOC16 destination.
238      *
239      * @param[in]  aDestination  The RLOC16 of the destination.
240      *
241      * @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
242      *
243      */
GetNextHop(uint16_t aDestination)244     uint16_t GetNextHop(uint16_t aDestination) { return mRouterTable.GetNextHop(aDestination); }
245 
246     /**
247      * This method returns the NETWORK_ID_TIMEOUT value.
248      *
249      * @returns The NETWORK_ID_TIMEOUT value.
250      *
251      */
GetNetworkIdTimeout(void) const252     uint8_t GetNetworkIdTimeout(void) const { return mNetworkIdTimeout; }
253 
254     /**
255      * This method sets the NETWORK_ID_TIMEOUT value.
256      *
257      * @param[in]  aTimeout  The NETWORK_ID_TIMEOUT value.
258      *
259      */
SetNetworkIdTimeout(uint8_t aTimeout)260     void SetNetworkIdTimeout(uint8_t aTimeout) { mNetworkIdTimeout = aTimeout; }
261 
262     /**
263      * This method returns the ROUTER_SELECTION_JITTER value.
264      *
265      * @returns The ROUTER_SELECTION_JITTER value.
266      *
267      */
GetRouterSelectionJitter(void) const268     uint8_t GetRouterSelectionJitter(void) const { return mRouterSelectionJitter; }
269 
270     /**
271      * This method sets the ROUTER_SELECTION_JITTER value.
272      *
273      * @returns The ROUTER_SELECTION_JITTER value.
274      *
275      */
276     Error SetRouterSelectionJitter(uint8_t aRouterJitter);
277 
278     /**
279      * This method returns the current router selection jitter timeout value.
280      *
281      * @returns The current router selection jitter timeout value.
282      *
283      */
GetRouterSelectionJitterTimeout(void) const284     uint8_t GetRouterSelectionJitterTimeout(void) const { return mRouterSelectionJitterTimeout; }
285 
286     /**
287      * This method returns the ROUTER_UPGRADE_THRESHOLD value.
288      *
289      * @returns The ROUTER_UPGRADE_THRESHOLD value.
290      *
291      */
GetRouterUpgradeThreshold(void) const292     uint8_t GetRouterUpgradeThreshold(void) const { return mRouterUpgradeThreshold; }
293 
294     /**
295      * This method sets the ROUTER_UPGRADE_THRESHOLD value.
296      *
297      * @param[in]  aThreshold  The ROUTER_UPGRADE_THRESHOLD value.
298      *
299      */
SetRouterUpgradeThreshold(uint8_t aThreshold)300     void SetRouterUpgradeThreshold(uint8_t aThreshold) { mRouterUpgradeThreshold = aThreshold; }
301 
302     /**
303      * This method returns the ROUTER_DOWNGRADE_THRESHOLD value.
304      *
305      * @returns The ROUTER_DOWNGRADE_THRESHOLD value.
306      *
307      */
GetRouterDowngradeThreshold(void) const308     uint8_t GetRouterDowngradeThreshold(void) const { return mRouterDowngradeThreshold; }
309 
310     /**
311      * This method sets the ROUTER_DOWNGRADE_THRESHOLD value.
312      *
313      * @param[in]  aThreshold  The ROUTER_DOWNGRADE_THRESHOLD value.
314      *
315      */
SetRouterDowngradeThreshold(uint8_t aThreshold)316     void SetRouterDowngradeThreshold(uint8_t aThreshold) { mRouterDowngradeThreshold = aThreshold; }
317 
318     /**
319      * This method returns the MLE_CHILD_ROUTER_LINKS value.
320      *
321      * @returns The MLE_CHILD_ROUTER_LINKS value.
322      *
323      */
GetChildRouterLinks(void) const324     uint8_t GetChildRouterLinks(void) const { return mChildRouterLinks; }
325 
326     /**
327      * This method sets the MLE_CHILD_ROUTER_LINKS value.
328      *
329      * @param[in]  aChildRouterLinks  The MLE_CHILD_ROUTER_LINKS value.
330      *
331      * @retval kErrorNone          Successfully set the value.
332      * @retval kErrorInvalidState  Thread protocols are enabled.
333      */
334     Error SetChildRouterLinks(uint8_t aChildRouterLinks);
335 
336     /**
337      * This method returns if the REED is expected to become Router soon.
338      *
339      * @retval TRUE   If the REED is going to become a Router soon.
340      * @retval FALSE  If the REED is not going to become a Router soon.
341      *
342      */
343     bool IsExpectedToBecomeRouterSoon(void) const;
344 
345     /**
346      * This method removes a link to a neighbor.
347      *
348      * @param[in]  aNeighbor  A reference to the neighbor object.
349      *
350      */
351     void RemoveNeighbor(Neighbor &aNeighbor);
352 
353     /**
354      * This method invalidates a direct link to a neighboring router (due to failed link-layer acks).
355      *
356      * @param[in]  aRouter  A reference to the router object.
357      *
358      */
359     void RemoveRouterLink(Router &aRouter);
360 
361     /**
362      * This method indicates whether or not the RLOC16 is an MTD child of this device.
363      *
364      * @param[in]  aRloc16  The RLOC16.
365      *
366      * @retval TRUE if @p aRloc16 is an MTD child of this device.
367      * @retval FALSE if @p aRloc16 is not an MTD child of this device.
368      *
369      */
370     bool IsMinimalChild(uint16_t aRloc16);
371 
372     /**
373      * This method 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      * This method checks if the destination is reachable.
392      *
393      * @param[in]  aMeshDest   The RLOC16 of the destination.
394      * @param[in]  aIp6Header  A reference to the IPv6 header of the message.
395      *
396      * @retval kErrorNone      The destination is reachable.
397      * @retval kErrorNoRoute   The destination is not reachable and the message should be dropped.
398      *
399      */
400     Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header);
401 
402     /**
403      * This method resolves 2-hop routing loops.
404      *
405      * @param[in]  aSourceMac   The RLOC16 of the previous hop.
406      * @param[in]  aDestRloc16  The RLOC16 of the final destination.
407      *
408      */
409     void ResolveRoutingLoops(uint16_t aSourceMac, uint16_t aDestRloc16);
410 
411     /**
412      * This method checks if a given Router ID has correct value.
413      *
414      * @param[in]  aRouterId  The Router ID value.
415      *
416      * @retval TRUE   If @p aRouterId is in correct range [0..62].
417      * @retval FALSE  If @p aRouterId is not a valid Router ID.
418      *
419      */
IsRouterIdValid(uint8_t aRouterId)420     static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
421 
422     /**
423      * This method fills an ConnectivityTlv.
424      *
425      * @param[out]  aTlv  A reference to the tlv to be filled.
426      *
427      */
428     void FillConnectivityTlv(ConnectivityTlv &aTlv);
429 
430     /**
431      * This method generates an MLE Child Update Request message to be sent to the parent.
432      *
433      * @retval kErrorNone     Successfully generated an MLE Child Update Request message.
434      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Child Update Request message.
435      *
436      */
SendChildUpdateRequest(void)437     Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
438 
439     Error SendLinkRequest(Neighbor *aNeighbor);
440 
441 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
442     /**
443      * This method sets steering data out of band
444      *
445      * @param[in]  aExtAddress  Value used to set steering data
446      *                          All zeros clears steering data
447      *                          All 0xFFs sets steering data to 0xFF
448      *                          Anything else is used to compute the bloom filter
449      *
450      */
451     void SetSteeringData(const Mac::ExtAddress *aExtAddress);
452 #endif
453 
454     /**
455      * This method gets the assigned parent priority.
456      *
457      * @returns The assigned parent priority value, -2 means not assigned.
458      *
459      */
GetAssignParentPriority(void) const460     int8_t GetAssignParentPriority(void) const { return mParentPriority; }
461 
462     /**
463      * This method sets the parent priority.
464      *
465      * @param[in]  aParentPriority  The parent priority value.
466      *
467      * @retval kErrorNone           Successfully set the parent priority.
468      * @retval kErrorInvalidArgs    If the parent priority value is not among 1, 0, -1 and -2.
469      *
470      */
471     Error SetAssignParentPriority(int8_t aParentPriority);
472 
473     /**
474      * This method gets the longest MLE Timeout TLV for all active MTD children.
475      *
476      * @param[out]  aTimeout  A reference to where the information is placed.
477      *
478      * @retval kErrorNone           Successfully get the max child timeout
479      * @retval kErrorInvalidState   Not an active router
480      * @retval kErrorNotFound       NO MTD child
481      *
482      */
483     Error GetMaxChildTimeout(uint32_t &aTimeout) const;
484 
485     /**
486      * This function sets the callback that is called when processing an MLE Discovery Request message.
487      *
488      * @param[in]  aCallback A pointer to a function that is called to deliver MLE Discovery Request data.
489      * @param[in]  aContext  A pointer to application-specific context.
490      *
491      */
SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback,void * aContext)492     void SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback, void *aContext)
493     {
494         mDiscoveryRequestCallback.Set(aCallback, aContext);
495     }
496 
497     /**
498      * This method resets the MLE Advertisement Trickle timer interval.
499      *
500      */
501     void ResetAdvertiseInterval(void);
502 
503 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
504     /**
505      * This method generates an MLE Time Synchronization message.
506      *
507      * @retval kErrorNone     Successfully sent an MLE Time Synchronization message.
508      * @retval kErrorNoBufs   Insufficient buffers to generate the MLE Time Synchronization message.
509      *
510      */
511     Error SendTimeSync(void);
512 #endif
513 
514 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
515     /**
516      * This method sets the delay before registering Backbone Router service.
517      *
518      * @param[in]  aDelay  The delay before registering Backbone Router service.
519      *
520      */
SetBackboneRouterRegistrationDelay(uint8_t aDelay)521     void SetBackboneRouterRegistrationDelay(uint8_t aDelay) { mBackboneRouterRegistrationDelay = aDelay; }
522 #endif
523 
524     /**
525      * This method 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      * This method sets/restores the maximum number of IP addresses that each MTD child may register with this
535      * device as parent.
536      *
537      * @param[in]  aMaxIpAddresses  The maximum number of IP addresses that each MTD child may register with this
538      *                              device as parent. 0 to clear the setting and restore the default.
539      *
540      * @retval kErrorNone           Successfully set/cleared the number.
541      * @retval kErrorInvalidArgs    If exceeds the allowed maximum number.
542      *
543      */
544     Error SetMaxChildIpAddresses(uint8_t aMaxIpAddresses);
545 
546     /**
547      * This method sets whether the device was commissioned using CCM.
548      *
549      * @param[in]  aEnabled  TRUE if the device was commissioned using CCM, FALSE otherwise.
550      *
551      */
SetCcmEnabled(bool aEnabled)552     void SetCcmEnabled(bool aEnabled) { mCcmEnabled = aEnabled; }
553 
554     /**
555      * This function sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
556      *
557      * @param[in]  aEnabled  TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
558      *
559      */
SetThreadVersionCheckEnabled(bool aEnabled)560     void SetThreadVersionCheckEnabled(bool aEnabled) { mThreadVersionCheckEnabled = aEnabled; }
561 #endif
562 
563 private:
564     static constexpr uint16_t kDiscoveryMaxJitter            = 250; // Max jitter delay Discovery Responses (in msec).
565     static constexpr uint16_t kChallengeTimeout              = 2;   // Challenge timeout (in sec).
566     static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
567 
568     // Threshold to accept a router upgrade request with reason
569     // `kBorderRouterRequest` (number of BRs acting as router in
570     // Network Data).
571     static constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
572 
573     static constexpr uint8_t kLinkRequestMinMargin    = OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN;
574     static constexpr uint8_t kPartitionMergeMinMargin = OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN;
575     static constexpr uint8_t kChildRouterLinks        = OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS;
576     static constexpr uint8_t kMaxChildIpAddresses     = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
577 
578     static constexpr uint8_t kMinCriticalChildrenCount = 6;
579 
580     static constexpr uint16_t kChildSupervisionDefaultIntervalForOlderVersion =
581         OPENTHREAD_CONFIG_CHILD_SUPERVISION_OLDER_VERSION_CHILD_DEFAULT_INTERVAL;
582 
583     void  HandleDetachStart(void);
584     void  HandleChildStart(AttachMode aMode);
585     void  HandleLinkRequest(RxInfo &aRxInfo);
586     void  HandleLinkAccept(RxInfo &aRxInfo);
587     Error HandleLinkAccept(RxInfo &aRxInfo, bool aRequest);
588     void  HandleLinkAcceptAndRequest(RxInfo &aRxInfo);
589     Error HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, const LeaderData &aLeaderData);
590     void  HandleParentRequest(RxInfo &aRxInfo);
591     void  HandleChildIdRequest(RxInfo &aRxInfo);
592     void  HandleChildUpdateRequest(RxInfo &aRxInfo);
593     void  HandleChildUpdateResponse(RxInfo &aRxInfo);
594     void  HandleDataRequest(RxInfo &aRxInfo);
595     void  HandleNetworkDataUpdateRouter(void);
596     void  HandleDiscoveryRequest(RxInfo &aRxInfo);
597 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
598     void HandleTimeSync(RxInfo &aRxInfo);
599 #endif
600 
601     Error ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo);
602     Error ReadAndProcessRouteTlvOnFed(RxInfo &aRxInfo, uint8_t aParentId);
603 
604     void  StopAdvertiseTrickleTimer(void);
605     Error SendAddressSolicit(ThreadStatusTlv::Status aStatus);
606     void  SendAddressSolicitResponse(const Coap::Message    &aRequest,
607                                      ThreadStatusTlv::Status aResponseStatus,
608                                      const Router           *aRouter,
609                                      const Ip6::MessageInfo &aMessageInfo);
610     void  SendAddressRelease(void);
611     void  SendAdvertisement(void);
612     Error SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
613                          Neighbor               *aNeighbor,
614                          const TlvList          &aRequestedTlvList,
615                          const Challenge        &aChallenge);
616     void  SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest);
617     Error SendChildIdResponse(Child &aChild);
618     Error SendChildUpdateRequest(Child &aChild);
619     void  SendChildUpdateResponse(Child                  *aChild,
620                                   const Ip6::MessageInfo &aMessageInfo,
621                                   const TlvList          &aTlvList,
622                                   const Challenge        &aChallenge);
623     void  SendDataResponse(const Ip6::Address &aDestination,
624                            const TlvList      &aTlvList,
625                            uint16_t            aDelay,
626                            const Message      *aRequestMessage = nullptr);
627     Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
628     void  SetStateRouter(uint16_t aRloc16);
629     void  SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode);
630     void  SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
631     void  StopLeader(void);
632     void  SynchronizeChildNetworkData(void);
633     Error ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild);
634     Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, uint16_t aLength, Child &aChild);
635     bool  HasNeighborWithGoodLinkQuality(void) const;
636 
637     static void HandleAddressSolicitResponse(void                *aContext,
638                                              otMessage           *aMessage,
639                                              const otMessageInfo *aMessageInfo,
640                                              Error                aResult);
641     void HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
642 
643     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
644 
645     void HandlePartitionChange(void);
646 
647     void SetChildStateToValid(Child &aChild);
648     bool HasChildren(void);
649     void RemoveChildren(void);
650     bool ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
651     bool NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
652 
653     static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
654     void        HandleAdvertiseTrickleTimer(void);
655     void        HandleTimeTick(void);
656 
657     TrickleTimer mAdvertiseTrickleTimer;
658 
659     DeviceProperties mDeviceProperties;
660 
661     ChildTable  mChildTable;
662     RouterTable mRouterTable;
663 
664     uint8_t   mChallengeTimeout;
665     Challenge mChallenge;
666 
667     uint16_t mNextChildId;
668     uint8_t  mNetworkIdTimeout;
669     uint8_t  mRouterUpgradeThreshold;
670     uint8_t  mRouterDowngradeThreshold;
671     uint8_t  mLeaderWeight;
672 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
673     uint32_t mPreferredLeaderPartitionId; ///< only for certification testing
674     bool     mCcmEnabled : 1;
675     bool     mThreadVersionCheckEnabled : 1;
676 #endif
677     bool mRouterEligible : 1;
678     bool mAddressSolicitPending : 1;
679     bool mAddressSolicitRejected : 1;
680 
681     uint8_t mRouterId;
682     uint8_t mPreviousRouterId;
683 
684     uint32_t mPreviousPartitionIdRouter;         ///< The partition ID when last operating as a router
685     uint32_t mPreviousPartitionId;               ///< The partition ID when last attached
686     uint8_t  mPreviousPartitionRouterIdSequence; ///< The router ID sequence when last attached
687     uint8_t  mPreviousPartitionIdTimeout;        ///< The partition ID timeout when last attached
688 
689     uint8_t mRouterSelectionJitter;        ///< The variable to save the assigned jitter value.
690     uint8_t mRouterSelectionJitterTimeout; ///< The Timeout prior to request/release Router ID.
691 
692     uint8_t mChildRouterLinks;
693 
694     int8_t mParentPriority; ///< The assigned parent priority value, -2 means not assigned.
695 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
696     uint8_t mBackboneRouterRegistrationDelay; ///< Delay before registering Backbone Router service.
697 #endif
698 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
699     uint8_t mMaxChildIpAddresses;
700 #endif
701 
702 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
703     MeshCoP::SteeringData mSteeringData;
704 #endif
705 
706     Callback<otThreadDiscoveryRequestCallback> mDiscoveryRequestCallback;
707 };
708 
709 DeclareTmfHandler(MleRouter, kUriAddressSolicit);
710 DeclareTmfHandler(MleRouter, kUriAddressRelease);
711 
712 #endif // OPENTHREAD_FTD
713 
714 #if OPENTHREAD_MTD
715 
716 class MleRouter : public Mle
717 {
718     friend class Mle;
719     friend class ot::Instance;
720 
721 public:
MleRouter(Instance & aInstance)722     explicit MleRouter(Instance &aInstance)
723         : Mle(aInstance)
724     {
725     }
726 
IsSingleton(void) const727     bool IsSingleton(void) const { return false; }
728 
GetNextHop(uint16_t aDestination) const729     uint16_t GetNextHop(uint16_t aDestination) const { return Mle::GetNextHop(aDestination); }
730 
RemoveNeighbor(Neighbor &)731     Error RemoveNeighbor(Neighbor &) { return BecomeDetached(); }
RemoveRouterLink(Router &)732     void  RemoveRouterLink(Router &) { IgnoreError(BecomeDetached()); }
733 
IsRouterIdValid(uint8_t aRouterId)734     static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
735 
SendChildUpdateRequest(void)736     Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
737 
CheckReachability(uint16_t aMeshDest,Ip6::Header & aIp6Header)738     Error CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
739     {
740         return Mle::CheckReachability(aMeshDest, aIp6Header);
741     }
742 };
743 
744 #endif // OPENTHREAD_MTD
745 
746 } // namespace Mle
747 
748 /**
749  * @}
750  */
751 
752 } // namespace ot
753 
754 #endif // MLE_ROUTER_HPP_
755