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 Child, Router, and Leader roles.
32  */
33 
34 #ifndef MLE_HPP_
35 #define MLE_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/callback.hpp"
40 #include "common/encoding.hpp"
41 #include "common/locator.hpp"
42 #include "common/log.hpp"
43 #include "common/non_copyable.hpp"
44 #include "common/notifier.hpp"
45 #include "common/timer.hpp"
46 #include "crypto/aes_ccm.hpp"
47 #include "mac/mac.hpp"
48 #include "meshcop/dataset.hpp"
49 #include "meshcop/joiner_router.hpp"
50 #include "meshcop/meshcop.hpp"
51 #include "net/udp6.hpp"
52 #include "thread/child.hpp"
53 #include "thread/link_metrics.hpp"
54 #include "thread/link_metrics_tlvs.hpp"
55 #include "thread/mle_tlvs.hpp"
56 #include "thread/mle_types.hpp"
57 #include "thread/neighbor_table.hpp"
58 #include "thread/network_data_types.hpp"
59 #include "thread/router.hpp"
60 
61 namespace ot {
62 
63 /**
64  * @addtogroup core-mle MLE
65  *
66  * @brief
67  *   This module includes definitions for the MLE protocol.
68  *
69  * @{
70  *
71  * @defgroup core-mle-core Core
72  * @defgroup core-mle-router Router
73  * @defgroup core-mle-tlvs TLVs
74  *
75  * @}
76  */
77 
78 class SupervisionListener;
79 class UnitTester;
80 
81 /**
82  * @namespace ot::Mle
83  *
84  * @brief
85  *   This namespace includes definitions for the MLE protocol.
86  */
87 
88 namespace Mle {
89 
90 /**
91  * @addtogroup core-mle-core
92  *
93  * @brief
94  *   This module includes definitions for MLE functionality required by the Thread Child, Router, and Leader roles.
95  *
96  * @{
97  *
98  */
99 
100 #if OPENTHREAD_FTD
101 class MleRouter;
102 #endif
103 
104 /**
105  * Implements MLE functionality required by the Thread EndDevices, Router, and Leader roles.
106  *
107  */
108 class Mle : public InstanceLocator, private NonCopyable
109 {
110 #if OPENTHREAD_FTD
111     friend class MleRouter;
112 #endif
113     friend class DiscoverScanner;
114     friend class ot::Instance;
115     friend class ot::Notifier;
116     friend class ot::SupervisionListener;
117 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
118     friend class ot::LinkMetrics::Initiator;
119 #endif
120     friend class ot::UnitTester;
121 
122 public:
123     /**
124      * Initializes the MLE object.
125      *
126      * @param[in]  aInstance     A reference to the OpenThread instance.
127      *
128      */
129     explicit Mle(Instance &aInstance);
130 
131     /**
132      * Enables MLE.
133      *
134      * @retval kErrorNone     Successfully enabled MLE.
135      * @retval kErrorAlready  MLE was already enabled.
136      *
137      */
138     Error Enable(void);
139 
140     /**
141      * Disables MLE.
142      *
143      * @retval kErrorNone     Successfully disabled MLE.
144      *
145      */
146     Error Disable(void);
147 
148     /**
149      * Starts the MLE protocol operation.
150      *
151      * @retval kErrorNone           Successfully started the protocol operation.
152      * @retval kErrorInvalidState   IPv6 interface is down or device is in raw-link mode.
153      *
154      */
Start(void)155     Error Start(void) { return Start(kNormalAttach); }
156 
157     /**
158      * Stops the MLE protocol operation.
159      *
160      */
Stop(void)161     void Stop(void) { Stop(kUpdateNetworkDatasets); }
162 
163     /**
164      * Restores network information from non-volatile memory (if any).
165      *
166      */
167     void Restore(void);
168 
169     /**
170      * Stores network information into non-volatile memory.
171      *
172      * @retval kErrorNone      Successfully store the network information.
173      * @retval kErrorNoBufs    Could not store the network information due to insufficient memory space.
174      *
175      */
176     Error Store(void);
177 
178     /**
179      * Generates an MLE Announce message.
180      *
181      * @param[in]  aChannel        The channel to use when transmitting.
182      *
183      */
SendAnnounce(uint8_t aChannel)184     void SendAnnounce(uint8_t aChannel) { SendAnnounce(aChannel, kNormalAnnounce); }
185 
186     /**
187      * Causes the Thread interface to detach from the Thread network.
188      *
189      * @retval kErrorNone          Successfully detached from the Thread network.
190      * @retval kErrorInvalidState  MLE is Disabled.
191      *
192      */
193     Error BecomeDetached(void);
194 
195     /**
196      * Causes the Thread interface to attempt an MLE attach.
197      *
198      * @retval kErrorNone          Successfully began the attach process.
199      * @retval kErrorInvalidState  MLE is Disabled.
200      * @retval kErrorBusy          An attach process is in progress.
201      *
202      */
203     Error BecomeChild(void);
204 
205     /**
206      * Notifies other nodes in the network (if any) and then stops Thread protocol operation.
207      *
208      * It sends an Address Release if it's a router, or sets its child timeout to 0 if it's a child.
209      *
210      * @param[in] aCallback A pointer to a function that is called upon finishing detaching.
211      * @param[in] aContext  A pointer to callback application-specific context.
212      *
213      * @retval kErrorNone   Successfully started detaching.
214      * @retval kErrorBusy   Detaching is already in progress.
215      *
216      */
217     Error DetachGracefully(otDetachGracefullyCallback aCallback, void *aContext);
218 
219     /**
220      * Indicates whether or not the Thread device is attached to a Thread network.
221      *
222      * @retval TRUE   Attached to a Thread network.
223      * @retval FALSE  Not attached to a Thread network.
224      *
225      */
226     bool IsAttached(void) const;
227 
228     /**
229      * Indicates whether device is currently attaching or not.
230      *
231      * Note that an already attached device may also be in attaching state. Examples of this include a leader/router
232      * trying to attach to a better partition, or a child trying to find a better parent (when feature
233      * `OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE` is enabled).
234      *
235      * @retval TRUE   Device is currently trying to attach.
236      * @retval FALSE  Device is not in middle of attach process.
237      *
238      */
IsAttaching(void) const239     bool IsAttaching(void) const { return (mAttachState != kAttachStateIdle); }
240 
241     /**
242      * Returns the current Thread device role.
243      *
244      * @returns The current Thread device role.
245      *
246      */
GetRole(void) const247     DeviceRole GetRole(void) const { return mRole; }
248 
249     /**
250      * Indicates whether device role is disabled.
251      *
252      * @retval TRUE   Device role is disabled.
253      * @retval FALSE  Device role is not disabled.
254      *
255      */
IsDisabled(void) const256     bool IsDisabled(void) const { return (mRole == kRoleDisabled); }
257 
258     /**
259      * Indicates whether device role is detached.
260      *
261      * @retval TRUE   Device role is detached.
262      * @retval FALSE  Device role is not detached.
263      *
264      */
IsDetached(void) const265     bool IsDetached(void) const { return (mRole == kRoleDetached); }
266 
267     /**
268      * Indicates whether device role is child.
269      *
270      * @retval TRUE   Device role is child.
271      * @retval FALSE  Device role is not child.
272      *
273      */
IsChild(void) const274     bool IsChild(void) const { return (mRole == kRoleChild); }
275 
276     /**
277      * Indicates whether device role is router.
278      *
279      * @retval TRUE   Device role is router.
280      * @retval FALSE  Device role is not router.
281      *
282      */
IsRouter(void) const283     bool IsRouter(void) const { return (mRole == kRoleRouter); }
284 
285     /**
286      * Indicates whether device role is leader.
287      *
288      * @retval TRUE   Device role is leader.
289      * @retval FALSE  Device role is not leader.
290      *
291      */
IsLeader(void) const292     bool IsLeader(void) const { return (mRole == kRoleLeader); }
293 
294     /**
295      * Indicates whether device role is either router or leader.
296      *
297      * @retval TRUE   Device role is either router or leader.
298      * @retval FALSE  Device role is neither router nor leader.
299      *
300      */
301     bool IsRouterOrLeader(void) const;
302 
303     /**
304      * Returns the Device Mode as reported in the Mode TLV.
305      *
306      * @returns The Device Mode as reported in the Mode TLV.
307      *
308      */
GetDeviceMode(void) const309     DeviceMode GetDeviceMode(void) const { return mDeviceMode; }
310 
311     /**
312      * Sets the Device Mode as reported in the Mode TLV.
313      *
314      * @param[in]  aDeviceMode  The device mode to set.
315      *
316      * @retval kErrorNone         Successfully set the Mode TLV.
317      * @retval kErrorInvalidArgs  The mode combination specified in @p aMode is invalid.
318      *
319      */
320     Error SetDeviceMode(DeviceMode aDeviceMode);
321 
322     /**
323      * Indicates whether or not the device is rx-on-when-idle.
324      *
325      * @returns TRUE if rx-on-when-idle, FALSE otherwise.
326      *
327      */
IsRxOnWhenIdle(void) const328     bool IsRxOnWhenIdle(void) const { return mDeviceMode.IsRxOnWhenIdle(); }
329 
330     /**
331      * Indicates whether or not the device is a Full Thread Device.
332      *
333      * @returns TRUE if a Full Thread Device, FALSE otherwise.
334      *
335      */
IsFullThreadDevice(void) const336     bool IsFullThreadDevice(void) const { return mDeviceMode.IsFullThreadDevice(); }
337 
338     /**
339      * Indicates whether or not the device is a Minimal End Device.
340      *
341      * @returns TRUE if the device is a Minimal End Device, FALSE otherwise.
342      *
343      */
IsMinimalEndDevice(void) const344     bool IsMinimalEndDevice(void) const { return mDeviceMode.IsMinimalEndDevice(); }
345 
346     /**
347      * Gets the Network Data type (full set or stable subset) that this device requests.
348      *
349      * @returns The Network Data type requested by this device.
350      *
351      */
GetNetworkDataType(void) const352     NetworkData::Type GetNetworkDataType(void) const { return mDeviceMode.GetNetworkDataType(); }
353 
354     /**
355      * Returns a pointer to the Mesh Local Prefix.
356      *
357      * @returns A reference to the Mesh Local Prefix.
358      *
359      */
GetMeshLocalPrefix(void) const360     const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; }
361 
362     /**
363      * Sets the Mesh Local Prefix.
364      *
365      * @param[in]  aMeshLocalPrefix  A reference to the Mesh Local Prefix.
366      *
367      */
368     void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix);
369 
370 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
371     /**
372      * Sets the Mesh Local IID.
373      *
374      * Available only when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
375      *
376      * @param[in] aMlIid  The Mesh Local IID.
377      *
378      * @retval kErrorNone           Successfully configured Mesh Local IID.
379      * @retval kErrorInvalidState   If the Thread stack is already enabled.
380      *
381      */
382     Error SetMeshLocalIid(const Ip6::InterfaceIdentifier &aMlIid);
383 #endif
384 
385     /**
386      * Returns a reference to the Thread link-local address.
387      *
388      * The Thread link local address is derived using IEEE802.15.4 Extended Address as Interface Identifier.
389      *
390      * @returns A reference to the Thread link local address.
391      *
392      */
GetLinkLocalAddress(void) const393     const Ip6::Address &GetLinkLocalAddress(void) const { return mLinkLocal64.GetAddress(); }
394 
395     /**
396      * Updates the link local address.
397      *
398      * Call this method when the IEEE 802.15.4 Extended Address has changed.
399      *
400      */
401     void UpdateLinkLocalAddress(void);
402 
403     /**
404      * Returns a reference to the link-local all Thread nodes multicast address.
405      *
406      * @returns A reference to the link-local all Thread nodes multicast address.
407      *
408      */
GetLinkLocalAllThreadNodesAddress(void) const409     const Ip6::Address &GetLinkLocalAllThreadNodesAddress(void) const { return mLinkLocalAllThreadNodes.GetAddress(); }
410 
411     /**
412      * Returns a reference to the realm-local all Thread nodes multicast address.
413      *
414      * @returns A reference to the realm-local all Thread nodes multicast address.
415      *
416      */
GetRealmLocalAllThreadNodesAddress(void) const417     const Ip6::Address &GetRealmLocalAllThreadNodesAddress(void) const
418     {
419         return mRealmLocalAllThreadNodes.GetAddress();
420     }
421 
422     /**
423      * Gets the parent when operating in End Device mode.
424      *
425      * @returns A reference to the parent.
426      *
427      */
GetParent(void)428     Parent &GetParent(void) { return mParent; }
429 
430     /**
431      * Gets the parent when operating in End Device mode.
432      *
433      * @returns A reference to the parent.
434      *
435      */
GetParent(void) const436     const Parent &GetParent(void) const { return mParent; }
437 
438     /**
439      * The method retrieves information about the parent.
440      *
441      * @param[out] aParentInfo     Reference to a parent information structure.
442      *
443      * @retval kErrorNone          Successfully retrieved the parent info and updated @p aParentInfo.
444      * @retval kErrorInvalidState  Device role is not child.
445      *
446      */
447     Error GetParentInfo(Router::Info &aParentInfo) const;
448 
449     /**
450      * Get the parent candidate.
451      *
452      * The parent candidate is valid when attempting to attach to a new parent.
453      *
454      */
GetParentCandidate(void)455     Parent &GetParentCandidate(void) { return mParentCandidate; }
456 
457     /**
458      * Starts the process for child to search for a better parent while staying attached to its current
459      * parent
460      *
461      * @retval kErrorNone          Successfully started the process to search for a better parent.
462      * @retval kErrorInvalidState  Device role is not child.
463      *
464      */
465     Error SearchForBetterParent(void);
466 
467     /**
468      * Indicates whether or not an IPv6 address is an RLOC.
469      *
470      * @retval TRUE   If @p aAddress is an RLOC.
471      * @retval FALSE  If @p aAddress is not an RLOC.
472      *
473      */
474     bool IsRoutingLocator(const Ip6::Address &aAddress) const;
475 
476     /**
477      * Indicates whether or not an IPv6 address is an ALOC.
478      *
479      * @retval TRUE   If @p aAddress is an ALOC.
480      * @retval FALSE  If @p aAddress is not an ALOC.
481      *
482      */
483     bool IsAnycastLocator(const Ip6::Address &aAddress) const;
484 
485     /**
486      * Indicates whether or not an IPv6 address is a Mesh Local Address.
487      *
488      * @retval TRUE   If @p aAddress is a Mesh Local Address.
489      * @retval FALSE  If @p aAddress is not a Mesh Local Address.
490      *
491      */
492     bool IsMeshLocalAddress(const Ip6::Address &aAddress) const;
493 
494     /**
495      * Returns the MLE Timeout value.
496      *
497      * @returns The MLE Timeout value in seconds.
498      *
499      */
GetTimeout(void) const500     uint32_t GetTimeout(void) const { return mTimeout; }
501 
502     /**
503      * Sets the MLE Timeout value.
504      *
505      * @param[in]  aTimeout  The Timeout value in seconds.
506      *
507      */
508     void SetTimeout(uint32_t aTimeout);
509 
510     /**
511      * Returns the RLOC16 assigned to the Thread interface.
512      *
513      * @returns The RLOC16 assigned to the Thread interface.
514      *
515      */
GetRloc16(void) const516     uint16_t GetRloc16(void) const { return mRloc16; }
517 
518     /**
519      * Returns a reference to the RLOC assigned to the Thread interface.
520      *
521      * @returns A reference to the RLOC assigned to the Thread interface.
522      *
523      */
GetMeshLocal16(void) const524     const Ip6::Address &GetMeshLocal16(void) const { return mMeshLocal16.GetAddress(); }
525 
526     /**
527      * Returns a reference to the ML-EID assigned to the Thread interface.
528      *
529      * @returns A reference to the ML-EID assigned to the Thread interface.
530      *
531      */
GetMeshLocal64(void) const532     const Ip6::Address &GetMeshLocal64(void) const { return mMeshLocal64.GetAddress(); }
533 
534     /**
535      * Returns a reference to the ML-EID as a `Netif::UnicastAddress`.
536      *
537      * @returns A reference to the ML-EID.
538      *
539      */
GetMeshLocal64UnicastAddress(void)540     Ip6::Netif::UnicastAddress &GetMeshLocal64UnicastAddress(void) { return mMeshLocal64; }
541 
542     /**
543      * Returns the Router ID of the Leader.
544      *
545      * @returns The Router ID of the Leader.
546      *
547      */
GetLeaderId(void) const548     uint8_t GetLeaderId(void) const { return mLeaderData.GetLeaderRouterId(); }
549 
550     /**
551      * Retrieves the Leader's RLOC.
552      *
553      * @param[out]  aAddress  A reference to the Leader's RLOC.
554      *
555      * @retval kErrorNone      Successfully retrieved the Leader's RLOC.
556      * @retval kErrorDetached  The Thread interface is not currently attached to a Thread Partition.
557      *
558      */
559     Error GetLeaderAddress(Ip6::Address &aAddress) const;
560 
561     /**
562      * Retrieves the Leader's ALOC.
563      *
564      * @param[out]  aAddress  A reference to the Leader's ALOC.
565      *
566      * @retval kErrorNone      Successfully retrieved the Leader's ALOC.
567      * @retval kErrorDetached  The Thread interface is not currently attached to a Thread Partition.
568      *
569      */
GetLeaderAloc(Ip6::Address & aAddress) const570     Error GetLeaderAloc(Ip6::Address &aAddress) const { return GetLocatorAddress(aAddress, kAloc16Leader); }
571 
572     /**
573      * Computes the Commissioner's ALOC.
574      *
575      * @param[out]  aAddress        A reference to the Commissioner's ALOC.
576      * @param[in]   aSessionId      Commissioner session id.
577      *
578      * @retval kErrorNone      Successfully retrieved the Commissioner's ALOC.
579      * @retval kErrorDetached  The Thread interface is not currently attached to a Thread Partition.
580      *
581      */
GetCommissionerAloc(Ip6::Address & aAddress,uint16_t aSessionId) const582     Error GetCommissionerAloc(Ip6::Address &aAddress, uint16_t aSessionId) const
583     {
584         return GetLocatorAddress(aAddress, CommissionerAloc16FromId(aSessionId));
585     }
586 
587     /**
588      * Retrieves the Service ALOC for given Service ID.
589      *
590      * @param[in]   aServiceId Service ID to get ALOC for.
591      * @param[out]  aAddress   A reference to the Service ALOC.
592      *
593      * @retval kErrorNone      Successfully retrieved the Service ALOC.
594      * @retval kErrorDetached  The Thread interface is not currently attached to a Thread Partition.
595      *
596      */
597     Error GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const;
598 
599     /**
600      * Returns the most recently received Leader Data.
601      *
602      * @returns  A reference to the most recently received Leader Data.
603      *
604      */
605     const LeaderData &GetLeaderData(void);
606 
607     /**
608      * Returns a reference to the send queue.
609      *
610      * @returns A reference to the send queue.
611      *
612      */
GetMessageQueue(void) const613     const MessageQueue &GetMessageQueue(void) const { return mDelayedResponses; }
614 
615     /**
616      * Frees multicast MLE Data Response from Delayed Message Queue if any.
617      *
618      */
619     void RemoveDelayedDataResponseMessage(void);
620 
621     /**
622      * Gets the MLE counters.
623      *
624      * @returns A reference to the MLE counters.
625      *
626      */
GetCounters(void)627     const Counters &GetCounters(void)
628     {
629 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
630         UpdateRoleTimeCounters(mRole);
631 #endif
632         return mCounters;
633     }
634 
635     /**
636      * Resets the MLE counters.
637      *
638      */
639     void ResetCounters(void);
640 
641 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
642     /**
643      * Registers the client callback that is called when processing an MLE Parent Response message.
644      *
645      * @param[in]  aCallback A pointer to a function that is called to deliver MLE Parent Response data.
646      * @param[in]  aContext  A pointer to application-specific context.
647      *
648      */
RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback,void * aContext)649     void RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext)
650     {
651         mParentResponseCallback.Set(aCallback, aContext);
652     }
653 #endif
654     /**
655      * Notifies MLE whether the Child ID Request message was transmitted successfully.
656      *
657      * @param[in]  aMessage  The transmitted message.
658      *
659      */
660     void HandleChildIdRequestTxDone(Message &aMessage);
661 
662     /**
663      * Requests MLE layer to prepare and send a shorter version of Child ID Request message by only
664      * including the mesh-local IPv6 address in the Address Registration TLV.
665      *
666      * Should be called when a previous MLE Child ID Request message would require fragmentation at 6LoWPAN
667      * layer.
668      *
669      */
670     void RequestShorterChildIdRequest(void);
671 
672     /**
673      * Gets the RLOC or ALOC of a given RLOC16 or ALOC16.
674      *
675      * @param[out]  aAddress  A reference to the RLOC or ALOC.
676      * @param[in]   aLocator  RLOC16 or ALOC16.
677      *
678      * @retval kErrorNone      If got the RLOC or ALOC successfully.
679      * @retval kErrorDetached  If device is detached.
680      *
681      */
682     Error GetLocatorAddress(Ip6::Address &aAddress, uint16_t aLocator) const;
683 
684     /**
685      * Schedules a Child Update Request.
686      *
687      */
688     void ScheduleChildUpdateRequest(void);
689 
690     /*
691      * Indicates whether or not the device has restored the network information from
692      * non-volatile settings after boot.
693      *
694      * @retval true  Successfully restored the network information.
695      * @retval false No valid network information was found.
696      *
697      */
HasRestored(void) const698     bool HasRestored(void) const { return mHasRestored; }
699 
700     /**
701      * Indicates whether or not a given netif multicast address instance is a prefix-based address added by MLE and
702      * uses the mesh local prefix.
703      *
704      * @param[in] aAddress   A `Netif::MulticastAddress` address instance.
705      *
706      * @retval TRUE   If @p aAddress is a prefix-based address which uses the mesh local prefix.
707      * @retval FALSE  If @p aAddress is not a prefix-based address which uses the mesh local prefix.
708      *
709      */
IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress & aAddress) const710     bool IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress &aAddress) const
711     {
712         return (&aAddress == &mLinkLocalAllThreadNodes) || (&aAddress == &mRealmLocalAllThreadNodes);
713     }
714 
715     /**
716      * Determines the next hop towards an RLOC16 destination.
717      *
718      * @param[in]  aDestination  The RLOC16 of the destination.
719      *
720      * @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
721      *
722      */
723     uint16_t GetNextHop(uint16_t aDestination) const;
724 
725 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
726     /**
727      * Gets the CSL timeout.
728      *
729      * @returns CSL timeout
730      *
731      */
GetCslTimeout(void) const732     uint32_t GetCslTimeout(void) const { return mCslTimeout; }
733 
734     /**
735      * Sets the CSL timeout.
736      *
737      * @param[in]  aTimeout  The CSL timeout in seconds.
738      *
739      */
740     void SetCslTimeout(uint32_t aTimeout);
741 
742     /**
743      * Calculates CSL metric of parent.
744      *
745      * @param[in] aCslAccuracy The CSL accuracy.
746      *
747      * @returns CSL metric.
748      *
749      */
750     uint64_t CalcParentCslMetric(const Mac::CslAccuracy &aCslAccuracy) const;
751 
752 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
753 
754 private:
755     //------------------------------------------------------------------------------------------------------------------
756     // Constants
757 
758     // All time intervals are in milliseconds
759     static constexpr uint32_t kParentRequestRouterTimeout     = 750;  // Wait time after tx of Parent Req to routers
760     static constexpr uint32_t kParentRequestReedTimeout       = 1250; // Wait timer after tx of Parent Req to REEDs
761     static constexpr uint32_t kParentRequestDuplicateMargin   = 50;   // Margin to detect duplicate received Parent Req
762     static constexpr uint32_t kChildIdResponseTimeout         = 1250; // Wait time to receive Child ID Response
763     static constexpr uint32_t kAttachStartJitter              = 50;   // Max jitter time added to start of attach
764     static constexpr uint32_t kAnnounceProcessTimeout         = 250;  // Delay after Announce rx before processing
765     static constexpr uint32_t kAnnounceTimeout                = 1400; // Total timeout for sending Announce messages
766     static constexpr uint16_t kMinAnnounceDelay               = 80;   // Min delay between Announcement messages
767     static constexpr uint32_t kParentResponseMaxDelayRouters  = 500;  // Max response delay for Parent Req to routers
768     static constexpr uint32_t kParentResponseMaxDelayAll      = 1000; // Max response delay for Parent Req to all
769     static constexpr uint32_t kChildUpdateRequestPendingDelay = 100;  // Delay for aggregating Child Update Req
770     static constexpr uint32_t kMaxLinkAcceptDelay             = 1000; // Max delay to tx Link Accept for multicast Req
771     static constexpr uint32_t kChildIdRequestTimeout          = 5000; // Max delay to rx a Child ID Req after Parent Res
772     static constexpr uint32_t kLinkRequestTimeout             = 2000; // Max delay to rx a Link Accept
773     static constexpr uint32_t kDetachGracefullyTimeout        = 1000; // Timeout for graceful detach
774     static constexpr uint32_t kUnicastRetxDelay               = 1000; // Base delay for MLE unicast retx
775     static constexpr uint32_t kMulticastRetxDelay             = 5000; // Base delay for MLE multicast retx
776     static constexpr uint32_t kMulticastRetxDelayMin          = kMulticastRetxDelay * 9 / 10;  // 0.9 * base delay
777     static constexpr uint32_t kMulticastRetxDelayMax          = kMulticastRetxDelay * 11 / 10; // 1.1 * base delay
778 
779     static constexpr uint8_t kMaxTxCount                = 3; // Max tx count for MLE message
780     static constexpr uint8_t kMaxCriticalTxCount        = 6; // Max tx count for critical MLE message
781     static constexpr uint8_t kMaxChildKeepAliveAttempts = 4; // Max keep alive attempts before reattach
782 
783     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
784     // Attach backoff feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds.
785 
786     static constexpr uint32_t kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL;
787     static constexpr uint32_t kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL;
788     static constexpr uint32_t kAttachBackoffJitter      = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL;
789     static constexpr uint32_t kAttachBackoffDelayToResetCounter =
790         OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL;
791 
792     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
793     // Number of Parent Requests in first and next attach cycles
794 
795 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3
796     // First attach cycle includes two Parent Requests to routers, followed by four to routers and REEDs.
797     static constexpr uint8_t kFirstAttachCycleTotalParentRequests       = 6;
798     static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 2;
799 #else
800     // First attach cycle in Thread 1.1/1.2 includes a Parent Requests to routers, followed by one to routers and REEDs.
801     static constexpr uint8_t kFirstAttachCycleTotalParentRequests       = 2;
802     static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 1;
803 #endif
804 
805     // Next attach cycles includes one Parent Request to routers, followed by one to routers and REEDs.
806     static constexpr uint8_t kNextAttachCycleTotalParentRequests       = 2;
807     static constexpr uint8_t kNextAttachCycleNumParentRequestToRouters = 1;
808 
809     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
810 
811 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
812     static constexpr uint8_t kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS + 1;
813 #else
814     static constexpr uint8_t kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS;
815 #endif
816 
817     static constexpr uint8_t  kMleHopLimit              = 255;
818     static constexpr uint8_t  kMleSecurityTagSize       = 4;
819     static constexpr uint32_t kStoreFrameCounterAhead   = OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD;
820     static constexpr uint8_t  kMaxIpAddressesToRegister = OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER;
821     static constexpr uint32_t kDefaultChildTimeout      = OPENTHREAD_CONFIG_MLE_CHILD_TIMEOUT_DEFAULT;
822     static constexpr uint32_t kDefaultCslTimeout        = OPENTHREAD_CONFIG_CSL_TIMEOUT;
823 
824     //------------------------------------------------------------------------------------------------------------------
825     // Enumerations
826 
827     enum Command : uint8_t
828     {
829         kCommandLinkRequest                   = 0,
830         kCommandLinkAccept                    = 1,
831         kCommandLinkAcceptAndRequest          = 2,
832         kCommandLinkReject                    = 3,
833         kCommandAdvertisement                 = 4,
834         kCommandUpdate                        = 5,
835         kCommandUpdateRequest                 = 6,
836         kCommandDataRequest                   = 7,
837         kCommandDataResponse                  = 8,
838         kCommandParentRequest                 = 9,
839         kCommandParentResponse                = 10,
840         kCommandChildIdRequest                = 11,
841         kCommandChildIdResponse               = 12,
842         kCommandChildUpdateRequest            = 13,
843         kCommandChildUpdateResponse           = 14,
844         kCommandAnnounce                      = 15,
845         kCommandDiscoveryRequest              = 16,
846         kCommandDiscoveryResponse             = 17,
847         kCommandLinkMetricsManagementRequest  = 18,
848         kCommandLinkMetricsManagementResponse = 19,
849         kCommandLinkProbe                     = 20,
850         kCommandTimeSync                      = 99,
851     };
852 
853     enum AttachMode : uint8_t
854     {
855         kAnyPartition,    // Attach to any Thread partition.
856         kSamePartition,   // Attach to the same Thread partition (when losing connectivity).
857         kBetterPartition, // Attach to a better (i.e. higher weight/partition id) Thread partition.
858         kDowngradeToReed, // Attach to the same Thread partition during downgrade process.
859         kBetterParent,    // Attach to a better parent.
860     };
861 
862     enum AttachState : uint8_t
863     {
864         kAttachStateIdle,            // Not currently searching for a parent.
865         kAttachStateProcessAnnounce, // Waiting to process a received Announce (to switch channel/pan-id).
866         kAttachStateStart,           // Starting to look for a parent.
867         kAttachStateParentRequest,   // Send Parent Request (current number tracked by `mParentRequestCounter`).
868         kAttachStateAnnounce,        // Send Announce messages
869         kAttachStateChildIdRequest,  // Sending a Child ID Request message.
870     };
871 
872     enum ReattachState : uint8_t
873     {
874         kReattachStop,    // Reattach process is disabled or finished
875         kReattachStart,   // Start reattach process
876         kReattachActive,  // Reattach using stored Active Dataset
877         kReattachPending, // Reattach using stored Pending Dataset
878     };
879 
880     static constexpr uint16_t kMleMaxResponseDelay = 1000u; // Max delay before responding to a multicast request.
881 
882     enum AddressRegistrationMode : uint8_t // Used by `AppendAddressRegistrationTlv()`
883     {
884         kAppendAllAddresses,  // Append all addresses (unicast/multicast) in Address Registration TLV.
885         kAppendMeshLocalOnly, // Only append the Mesh Local (ML-EID) address in Address Registration TLV.
886     };
887 
888     enum StartMode : uint8_t // Used in `Start()`.
889     {
890         kNormalAttach,
891         kAnnounceAttach, // Try to attach on the announced thread network with newer active timestamp.
892     };
893 
894     enum StopMode : uint8_t // Used in `Stop()`.
895     {
896         kKeepNetworkDatasets,
897         kUpdateNetworkDatasets,
898     };
899 
900     enum AnnounceMode : uint8_t // Used in `SendAnnounce()`
901     {
902         kNormalAnnounce,
903         kOrphanAnnounce,
904     };
905 
906     enum ParentRequestType : uint8_t
907     {
908         kToRouters,         // Parent Request to routers only.
909         kToRoutersAndReeds, // Parent Request to all routers and REEDs.
910     };
911 
912     enum ChildUpdateRequestState : uint8_t
913     {
914         kChildUpdateRequestNone,    // No pending or active Child Update Request.
915         kChildUpdateRequestPending, // Pending Child Update Request due to relative OT_CHANGED event.
916         kChildUpdateRequestActive,  // Child Update Request has been sent and Child Update Response is expected.
917     };
918 
919     enum ChildUpdateRequestMode : uint8_t // Used in `SendChildUpdateRequest()`
920     {
921         kNormalChildUpdateRequest, // Normal Child Update Request.
922         kAppendChallengeTlv,       // Append Challenge TLV to Child Update Request even if currently attached.
923         kAppendZeroTimeout,        // Use zero timeout when appending Timeout TLV (used for graceful detach).
924     };
925 
926     enum DataRequestState : uint8_t
927     {
928         kDataRequestNone,   // Not waiting for a Data Response.
929         kDataRequestActive, // Data Request has been sent, Data Response is expected.
930     };
931 
932     enum SecuritySuite : uint8_t
933     {
934         k154Security = 0,   // Security suite value indicating that MLE message is not secured.
935         kNoSecurity  = 255, // Security suite value indicating that MLE message is secured.
936     };
937 
938     enum MessageAction : uint8_t
939     {
940         kMessageSend,
941         kMessageReceive,
942         kMessageDelay,
943         kMessageRemoveDelayed,
944     };
945 
946     enum MessageType : uint8_t
947     {
948         kTypeAdvertisement,
949         kTypeAnnounce,
950         kTypeChildIdRequest,
951         kTypeChildIdRequestShort,
952         kTypeChildIdResponse,
953         kTypeChildUpdateRequestAsChild,
954         kTypeChildUpdateResponseAsChild,
955         kTypeDataRequest,
956         kTypeDataResponse,
957         kTypeDiscoveryRequest,
958         kTypeDiscoveryResponse,
959         kTypeGenericDelayed,
960         kTypeGenericUdp,
961         kTypeParentRequestToRouters,
962         kTypeParentRequestToRoutersReeds,
963         kTypeParentResponse,
964 #if OPENTHREAD_FTD
965         kTypeAddressRelease,
966         kTypeAddressReleaseReply,
967         kTypeAddressReply,
968         kTypeAddressSolicit,
969         kTypeChildUpdateRequestOfChild,
970         kTypeChildUpdateResponseOfChild,
971         kTypeChildUpdateResponseOfUnknownChild,
972         kTypeLinkAccept,
973         kTypeLinkAcceptAndRequest,
974         kTypeLinkReject,
975         kTypeLinkRequest,
976         kTypeParentRequest,
977 #endif
978 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
979         kTypeLinkMetricsManagementRequest,
980         kTypeLinkMetricsManagementResponse,
981         kTypeLinkProbe,
982 #endif
983 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
984         kTypeTimeSync,
985 #endif
986     };
987 
988     //------------------------------------------------------------------------------------------------------------------
989     // Nested types
990 
991     static constexpr uint8_t kMaxTlvListSize = 32; // Maximum number of TLVs in a `TlvList`.
992 
993     class TlvList : public Array<uint8_t, kMaxTlvListSize>
994     {
995     public:
996         TlvList(void) = default;
997 
998         void Add(uint8_t aTlvType);
999         void AddElementsFrom(const TlvList &aTlvList);
1000     };
1001 
1002     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1003 
1004     class TxMessage : public Message
1005     {
1006     public:
1007         Error AppendSourceAddressTlv(void);
1008         Error AppendModeTlv(DeviceMode aMode);
1009         Error AppendTimeoutTlv(uint32_t aTimeout);
1010         Error AppendChallengeTlv(const TxChallenge &aChallenge);
1011         Error AppendResponseTlv(const RxChallenge &aResponse);
1012         Error AppendLinkFrameCounterTlv(void);
1013         Error AppendMleFrameCounterTlv(void);
1014         Error AppendAddress16Tlv(uint16_t aRloc16);
1015         Error AppendNetworkDataTlv(NetworkData::Type aType);
1016         Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength);
1017         Error AppendLeaderDataTlv(void);
1018         Error AppendScanMaskTlv(uint8_t aScanMask);
1019         Error AppendStatusTlv(StatusTlv::Status aStatus);
1020         Error AppendLinkMarginTlv(uint8_t aLinkMargin);
1021         Error AppendVersionTlv(void);
1022         Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses);
1023         Error AppendSupervisionIntervalTlv(uint16_t aInterval);
1024         Error AppendXtalAccuracyTlv(void);
1025         Error AppendActiveTimestampTlv(void);
1026         Error AppendPendingTimestampTlv(void);
1027         Error AppendActiveAndPendingTimestampTlvs(void);
1028 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1029         Error AppendTimeRequestTlv(void);
1030         Error AppendTimeParameterTlv(void);
1031 #endif
1032 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1033         Error AppendCslChannelTlv(void);
1034         Error AppendCslTimeoutTlv(void);
1035 #endif
1036 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1037         Error AppendCslClockAccuracyTlv(void);
1038 #endif
1039 #if OPENTHREAD_FTD
1040         Error AppendRouteTlv(Neighbor *aNeighbor = nullptr);
1041         Error AppendActiveDatasetTlv(void);
1042         Error AppendPendingDatasetTlv(void);
1043         Error AppendConnectivityTlv(void);
1044         Error AppendSteeringDataTlv(void);
1045         Error AppendAddressRegistrationTlv(Child &aChild);
1046 #endif
AppendTlvRequestTlv(const uint8_t (& aTlvArray)[kArrayLength])1047         template <uint8_t kArrayLength> Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength])
1048         {
1049             return AppendTlvRequestTlv(aTlvArray, kArrayLength);
1050         }
1051 
1052         Error SendTo(const Ip6::Address &aDestination);
1053         Error SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
1054 
1055     private:
1056         Error AppendCompressedAddressEntry(uint8_t aContextId, const Ip6::Address &aAddress);
1057         Error AppendAddressEntry(const Ip6::Address &aAddress);
1058         Error AppendDatasetTlv(MeshCoP::Dataset::Type mDatasetType);
1059     };
1060 
1061     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1062 
1063     class RxMessage : public Message
1064     {
1065     public:
1066         bool  ContainsTlv(Tlv::Type aTlvType) const;
1067         Error ReadModeTlv(DeviceMode &aMode) const;
1068         Error ReadVersionTlv(uint16_t &aVersion) const;
1069         Error ReadChallengeTlv(RxChallenge &aChallenge) const;
1070         Error ReadResponseTlv(RxChallenge &aResponse) const;
1071         Error ReadAndMatchResponseTlvWith(const TxChallenge &aChallenge) const;
1072         Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
1073         Error ReadTlvRequestTlv(TlvList &aTlvList) const;
1074         Error ReadLeaderDataTlv(LeaderData &aLeaderData) const;
1075 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1076         Error ReadCslClockAccuracyTlv(Mac::CslAccuracy &aCslAccuracy) const;
1077 #endif
1078 #if OPENTHREAD_FTD
1079         Error ReadRouteTlv(RouteTlv &aRouteTlv) const;
1080 #endif
1081 
1082     private:
1083         Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const;
1084     };
1085 
1086     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1087 
1088     struct RxInfo
1089     {
1090         enum Class : uint8_t
1091         {
1092             kUnknown,              // Unknown (default value, also indicates MLE message parse error).
1093             kAuthoritativeMessage, // Authoritative message (larger received key seq MUST be adopted).
1094             kPeerMessage,          // Peer message (adopt only if from a known neighbor and is greater by one).
1095         };
1096 
RxInfoot::Mle::Mle::RxInfo1097         RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
1098             : mMessage(static_cast<RxMessage &>(aMessage))
1099             , mMessageInfo(aMessageInfo)
1100             , mFrameCounter(0)
1101             , mKeySequence(0)
1102             , mNeighbor(nullptr)
1103             , mClass(kUnknown)
1104         {
1105         }
1106 
IsNeighborStateValidot::Mle::Mle::RxInfo1107         bool IsNeighborStateValid(void) const { return (mNeighbor != nullptr) && mNeighbor->IsStateValid(); }
1108 
1109         RxMessage              &mMessage;      // The MLE message.
1110         const Ip6::MessageInfo &mMessageInfo;  // The `MessageInfo` associated with the message.
1111         uint32_t                mFrameCounter; // The frame counter from aux security header.
1112         uint32_t                mKeySequence;  // The key sequence from aux security header.
1113         Neighbor               *mNeighbor;     // Neighbor from which message was received (can be `nullptr`).
1114         Class                   mClass;        // The message class (authoritative, peer, or unknown).
1115     };
1116 
1117     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1118 
1119     struct DelayedResponseMetadata
1120     {
AppendToot::Mle::Mle::DelayedResponseMetadata1121         Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
1122         void  ReadFrom(const Message &aMessage);
1123         void  RemoveFrom(Message &aMessage) const;
1124 
1125         Ip6::Address mDestination; // IPv6 address of the message destination.
1126         TimeMilli    mSendTime;    // Time when the message shall be sent.
1127     };
1128 
1129     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1130 
1131     OT_TOOL_PACKED_BEGIN
1132     class SecurityHeader
1133     {
1134     public:
InitSecurityControl(void)1135         void InitSecurityControl(void) { mSecurityControl = kKeyIdMode2Mic32; }
IsSecurityControlValid(void) const1136         bool IsSecurityControlValid(void) const { return (mSecurityControl == kKeyIdMode2Mic32); }
1137 
GetFrameCounter(void) const1138         uint32_t GetFrameCounter(void) const { return LittleEndian::HostSwap32(mFrameCounter); }
SetFrameCounter(uint32_t aCounter)1139         void     SetFrameCounter(uint32_t aCounter) { mFrameCounter = LittleEndian::HostSwap32(aCounter); }
1140 
GetKeyId(void) const1141         uint32_t GetKeyId(void) const { return BigEndian::HostSwap32(mKeySource); }
SetKeyId(uint32_t aKeySequence)1142         void     SetKeyId(uint32_t aKeySequence)
1143         {
1144             mKeySource = BigEndian::HostSwap32(aKeySequence);
1145             mKeyIndex  = (aKeySequence & 0x7f) + 1;
1146         }
1147 
1148     private:
1149         static constexpr uint8_t kKeyIdMode2Mic32 =
1150             static_cast<uint8_t>(Mac::Frame::kKeyIdMode2) | static_cast<uint8_t>(Mac::Frame::kSecurityEncMic32);
1151 
1152         uint8_t  mSecurityControl;
1153         uint32_t mFrameCounter;
1154         uint32_t mKeySource;
1155         uint8_t  mKeyIndex;
1156     } OT_TOOL_PACKED_END;
1157 
1158     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1159 
1160     class ParentCandidate : public Parent
1161     {
1162     public:
Init(Instance & aInstance)1163         void Init(Instance &aInstance) { Parent::Init(aInstance); }
1164         void Clear(void);
1165         void CopyTo(Parent &aParent) const;
1166 
1167         RxChallenge mRxChallenge;
1168         int8_t      mPriority;
1169         uint8_t     mLinkQuality3;
1170         uint8_t     mLinkQuality2;
1171         uint8_t     mLinkQuality1;
1172         uint16_t    mSedBufferSize;
1173         uint8_t     mSedDatagramCount;
1174         uint8_t     mLinkMargin;
1175         LeaderData  mLeaderData;
1176         bool        mIsSingleton;
1177     };
1178 
1179     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1180 
1181 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1182     class ServiceAloc : public Ip6::Netif::UnicastAddress
1183     {
1184     public:
1185         static constexpr uint16_t kNotInUse = Mac::kShortAddrInvalid;
1186 
1187         ServiceAloc(void);
1188 
IsInUse(void) const1189         bool     IsInUse(void) const { return GetAloc16() != kNotInUse; }
MarkAsNotInUse(void)1190         void     MarkAsNotInUse(void) { SetAloc16(kNotInUse); }
GetAloc16(void) const1191         uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); }
SetAloc16(uint16_t aAloc16)1192         void     SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); }
1193     };
1194 #endif
1195 
1196     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1197 
1198 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
HandleParentSearchTimer(void)1199     void HandleParentSearchTimer(void) { mParentSearch.HandleTimer(); }
1200 
1201     class ParentSearch : public InstanceLocator
1202     {
1203     public:
ParentSearch(Instance & aInstance)1204         explicit ParentSearch(Instance &aInstance)
1205             : InstanceLocator(aInstance)
1206             , mIsInBackoff(false)
1207             , mBackoffWasCanceled(false)
1208             , mRecentlyDetached(false)
1209             , mBackoffCancelTime(0)
1210             , mTimer(aInstance)
1211         {
1212         }
1213 
1214         void StartTimer(void);
1215         void UpdateState(void);
SetRecentlyDetached(void)1216         void SetRecentlyDetached(void) { mRecentlyDetached = true; }
1217         void HandleTimer(void);
1218 
1219     private:
1220         // All timer intervals are converted to milliseconds.
1221         static constexpr uint32_t kCheckInterval   = (OPENTHREAD_CONFIG_PARENT_SEARCH_CHECK_INTERVAL * 1000u);
1222         static constexpr uint32_t kBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u);
1223         static constexpr uint32_t kJitterInterval  = (15 * 1000u);
1224         static constexpr int8_t   kRssThreshold    = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD;
1225 
1226         using SearchTimer = TimerMilliIn<Mle, &Mle::HandleParentSearchTimer>;
1227 
1228         bool        mIsInBackoff : 1;
1229         bool        mBackoffWasCanceled : 1;
1230         bool        mRecentlyDetached : 1;
1231         TimeMilli   mBackoffCancelTime;
1232         SearchTimer mTimer;
1233     };
1234 #endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
1235 
1236     //------------------------------------------------------------------------------------------------------------------
1237     // Methods
1238 
1239     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
1240     static void HandleDetachGracefullyTimer(Timer &aTimer);
1241 
1242     Error      Start(StartMode aMode);
1243     void       Stop(StopMode aMode);
1244     TxMessage *NewMleMessage(Command aCommand);
1245     void       SetRole(DeviceRole aRole);
1246     void       Attach(AttachMode aMode);
1247     void       SetAttachState(AttachState aState);
1248     void       InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo);
ClearParentCandidate(void)1249     void       ClearParentCandidate(void) { mParentCandidate.Clear(); }
1250     Error      SendDataRequest(const Ip6::Address &aDestination);
1251     void       HandleNotifierEvents(Events aEvents);
1252     void       SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata);
1253     void       HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
1254     void       ReestablishLinkWithNeighbor(Neighbor &aNeighbor);
1255     void       HandleDetachGracefullyTimer(void);
IsDetachingGracefully(void)1256     bool       IsDetachingGracefully(void) { return mDetachGracefullyTimer.IsRunning(); }
1257     Error      SendChildUpdateRequest(ChildUpdateRequestMode aMode);
1258     Error      SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
1259     Error      SendChildUpdateRequest(void);
1260     Error      SendChildUpdateResponse(const TlvList      &aTlvList,
1261                                        const RxChallenge  &aChallenge,
1262                                        const Ip6::Address &aDestination);
1263     void       SetRloc16(uint16_t aRloc16);
1264     void       SetStateDetached(void);
1265     void       SetStateChild(uint16_t aRloc16);
1266     void       SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId);
1267     void       SetLeaderData(const LeaderData &aLeaderData);
1268     void       InformPreviousChannel(void);
IsAnnounceAttach(void) const1269     bool       IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; }
1270     void       ScheduleMessageTransmissionTimer(void);
1271     void       HandleAttachTimer(void);
1272     void       HandleDelayedResponseTimer(void);
1273     void       HandleMessageTransmissionTimer(void);
1274     void       ProcessKeySequence(RxInfo &aRxInfo);
1275     void       HandleAdvertisement(RxInfo &aRxInfo);
1276     void       HandleChildIdResponse(RxInfo &aRxInfo);
1277     void       HandleChildUpdateRequest(RxInfo &aRxInfo);
1278     void       HandleChildUpdateResponse(RxInfo &aRxInfo);
1279     void       HandleDataResponse(RxInfo &aRxInfo);
1280     void       HandleParentResponse(RxInfo &aRxInfo);
1281     void       HandleAnnounce(RxInfo &aRxInfo);
1282     Error      HandleLeaderData(RxInfo &aRxInfo);
1283     void       ProcessAnnounce(void);
1284     bool       HasUnregisteredAddress(void);
1285     uint32_t   GetAttachStartDelay(void) const;
1286     void       SendParentRequest(ParentRequestType aType);
1287     Error      SendChildIdRequest(void);
1288     Error      GetNextAnnounceChannel(uint8_t &aChannel) const;
1289     bool       HasMoreChannelsToAnnounce(void) const;
1290     bool       PrepareAnnounceState(void);
1291     void       SendAnnounce(uint8_t aChannel, AnnounceMode aMode);
1292     void       SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce);
1293     uint32_t   Reattach(void);
1294     bool       HasAcceptableParentCandidate(void) const;
1295     Error      DetermineParentRequestType(ParentRequestType &aType) const;
1296     bool       IsBetterParent(uint16_t                aRloc16,
1297                               uint8_t                 aTwoWayLinkMargin,
1298                               const ConnectivityTlv  &aConnectivityTlv,
1299                               uint16_t                aVersion,
1300                               const Mac::CslAccuracy &aCslAccuracy);
1301     bool       IsNetworkDataNewer(const LeaderData &aLeaderData);
1302     Error      ProcessMessageSecurity(Crypto::AesCcm::Mode    aMode,
1303                                       Message                &aMessage,
1304                                       const Ip6::MessageInfo &aMessageInfo,
1305                                       uint16_t                aCmdOffset,
1306                                       const SecurityHeader   &aHeader);
1307     void RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination);
1308     void RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination);
1309 
1310 #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
1311     void InformPreviousParent(void);
1312 #endif
1313 
1314 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
1315     void UpdateRoleTimeCounters(DeviceRole aRole);
1316 #endif
1317 
1318 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1319     ServiceAloc *FindInServiceAlocs(uint16_t aAloc16);
1320     void         UpdateServiceAlocs(void);
1321 #endif
1322 
1323 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1324     void HandleTimeSync(RxInfo &aRxInfo);
1325 #endif
1326 
1327 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1328     void  HandleLinkMetricsManagementRequest(RxInfo &aRxInfo);
1329     void  HandleLinkProbe(RxInfo &aRxInfo);
1330     Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus);
1331 #endif
1332 
1333 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
1334     void  HandleLinkMetricsManagementResponse(RxInfo &aRxInfo);
1335     Error SendDataRequestForLinkMetricsReport(const Ip6::Address                      &aDestination,
1336                                               const LinkMetrics::Initiator::QueryInfo &aQueryInfo);
1337     Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv);
1338     Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength);
1339     Error SendDataRequest(const Ip6::Address                      &aDestination,
1340                           const uint8_t                           *aTlvs,
1341                           uint8_t                                  aTlvsLength,
1342                           uint16_t                                 aDelay,
1343                           const LinkMetrics::Initiator::QueryInfo *aQueryInfo = nullptr);
1344 #else
1345     Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay);
1346 #endif
1347 
1348 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
1349     static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress);
1350     static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc);
1351 #else
Log(MessageAction,MessageType,const Ip6::Address &)1352     static void Log(MessageAction, MessageType, const Ip6::Address &) {}
Log(MessageAction,MessageType,const Ip6::Address &,uint16_t)1353     static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {}
1354 #endif
1355 
1356 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
1357     static const char *AttachModeToString(AttachMode aMode);
1358     static const char *AttachStateToString(AttachState aState);
1359     static const char *ReattachStateToString(ReattachState aState);
1360 #endif
1361 
1362 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
1363     static void        LogError(MessageAction aAction, MessageType aType, Error aError);
1364     static const char *MessageActionToString(MessageAction aAction);
1365     static const char *MessageTypeToString(MessageType aType);
1366     static const char *MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction);
1367     static void        LogProcessError(MessageType aType, Error aError);
1368     static void        LogSendError(MessageType aType, Error aError);
1369 #else
LogProcessError(MessageType,Error)1370     static void LogProcessError(MessageType, Error) {}
LogSendError(MessageType,Error)1371     static void LogSendError(MessageType, Error) {}
1372 #endif
1373 
1374     //------------------------------------------------------------------------------------------------------------------
1375     // Variables
1376 
1377     using DetachGracefullyTimer = TimerMilliIn<Mle, &Mle::HandleDetachGracefullyTimer>;
1378     using AttachTimer           = TimerMilliIn<Mle, &Mle::HandleAttachTimer>;
1379     using DelayTimer            = TimerMilliIn<Mle, &Mle::HandleDelayedResponseTimer>;
1380     using MsgTxTimer            = TimerMilliIn<Mle, &Mle::HandleMessageTransmissionTimer>;
1381 
1382     static const otMeshLocalPrefix kMeshLocalPrefixInit;
1383 
1384     bool mRetrieveNewNetworkData : 1;
1385     bool mRequestRouteTlv : 1;
1386     bool mHasRestored : 1;
1387     bool mReceivedResponseFromParent : 1;
1388     bool mInitiallyAttachedAsSleepy : 1;
1389 #if OPENTHREAD_FTD
1390     bool mWasLeader : 1;
1391 #endif
1392 
1393     DeviceRole              mRole;
1394     DeviceMode              mDeviceMode;
1395     AttachState             mAttachState;
1396     ReattachState           mReattachState;
1397     AttachMode              mAttachMode;
1398     DataRequestState        mDataRequestState;
1399     AddressRegistrationMode mAddressRegistrationMode;
1400     ChildUpdateRequestState mChildUpdateRequestState;
1401 
1402     uint8_t mParentRequestCounter;
1403     uint8_t mChildUpdateAttempts;
1404     uint8_t mDataRequestAttempts;
1405     uint8_t mAnnounceChannel;
1406     uint8_t mAlternateChannel;
1407 #if OPENTHREAD_FTD
1408     uint8_t mLinkRequestAttempts;
1409 #endif
1410     uint16_t mRloc16;
1411     uint16_t mPreviousParentRloc;
1412     uint16_t mAttachCounter;
1413     uint16_t mAnnounceDelay;
1414     uint16_t mAlternatePanId;
1415     uint32_t mTimeout;
1416 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1417     uint32_t mCslTimeout;
1418 #endif
1419     uint64_t mAlternateTimestamp;
1420 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
1421     uint64_t mLastUpdatedTimestamp;
1422 #endif
1423 
1424     LeaderData       mLeaderData;
1425     Parent           mParent;
1426     NeighborTable    mNeighborTable;
1427     MessageQueue     mDelayedResponses;
1428     TxChallenge      mParentRequestChallenge;
1429     ParentCandidate  mParentCandidate;
1430     Ip6::Udp::Socket mSocket;
1431     Counters         mCounters;
1432 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
1433     ParentSearch mParentSearch;
1434 #endif
1435 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1436     ServiceAloc mServiceAlocs[kMaxServiceAlocs];
1437 #endif
1438     Callback<otDetachGracefullyCallback> mDetachGracefullyCallback;
1439 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
1440     Callback<otThreadParentResponseCallback> mParentResponseCallback;
1441 #endif
1442     AttachTimer                  mAttachTimer;
1443     DelayTimer                   mDelayedResponseTimer;
1444     MsgTxTimer                   mMessageTransmissionTimer;
1445     DetachGracefullyTimer        mDetachGracefullyTimer;
1446     Ip6::NetworkPrefix           mMeshLocalPrefix;
1447     Ip6::Netif::UnicastAddress   mLinkLocal64;
1448     Ip6::Netif::UnicastAddress   mMeshLocal64;
1449     Ip6::Netif::UnicastAddress   mMeshLocal16;
1450     Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes;
1451     Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes;
1452 };
1453 
1454 } // namespace Mle
1455 
1456 /**
1457  * @}
1458  *
1459  */
1460 
1461 } // namespace ot
1462 
1463 #endif // MLE_HPP_
1464