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 "mac/wakeup_tx_scheduler.hpp" 49 #include "meshcop/dataset.hpp" 50 #include "meshcop/joiner_router.hpp" 51 #include "meshcop/meshcop.hpp" 52 #include "net/udp6.hpp" 53 #include "thread/child.hpp" 54 #include "thread/link_metrics.hpp" 55 #include "thread/link_metrics_tlvs.hpp" 56 #include "thread/mle_tlvs.hpp" 57 #include "thread/mle_types.hpp" 58 #include "thread/neighbor_table.hpp" 59 #include "thread/network_data_types.hpp" 60 #include "thread/router.hpp" 61 62 namespace ot { 63 64 /** 65 * @addtogroup core-mle MLE 66 * 67 * @brief 68 * This module includes definitions for the MLE protocol. 69 * 70 * @{ 71 * 72 * @defgroup core-mle-core Core 73 * @defgroup core-mle-router Router 74 * @defgroup core-mle-tlvs TLVs 75 * 76 * @} 77 */ 78 79 class SupervisionListener; 80 class UnitTester; 81 82 /** 83 * @namespace ot::Mle 84 * 85 * @brief 86 * This namespace includes definitions for the MLE protocol. 87 */ 88 89 namespace Mle { 90 91 /** 92 * @addtogroup core-mle-core 93 * 94 * @brief 95 * This module includes definitions for MLE functionality required by the Thread Child, Router, and Leader roles. 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 class Mle : public InstanceLocator, private NonCopyable 108 { 109 #if OPENTHREAD_FTD 110 friend class MleRouter; 111 #endif 112 friend class DiscoverScanner; 113 friend class ot::Instance; 114 friend class ot::Notifier; 115 friend class ot::SupervisionListener; 116 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 117 friend class ot::LinkMetrics::Initiator; 118 #endif 119 friend class ot::UnitTester; 120 121 public: 122 typedef otDetachGracefullyCallback DetachCallback; ///< Callback to signal end of graceful detach. 123 124 typedef otWakeupCallback WakeupCallback; ///< Callback to communicate the result of waking a Wake-up End Device 125 126 /** 127 * Initializes the MLE object. 128 * 129 * @param[in] aInstance A reference to the OpenThread instance. 130 */ 131 explicit Mle(Instance &aInstance); 132 133 /** 134 * Enables MLE. 135 * 136 * @retval kErrorNone Successfully enabled MLE. 137 * @retval kErrorAlready MLE was already enabled. 138 */ 139 Error Enable(void); 140 141 /** 142 * Disables MLE. 143 * 144 * @retval kErrorNone Successfully disabled MLE. 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 */ Start(void)154 Error Start(void) { return Start(kNormalAttach); } 155 156 /** 157 * Stops the MLE protocol operation. 158 */ Stop(void)159 void Stop(void) { Stop(kUpdateNetworkDatasets); } 160 161 /** 162 * Restores network information from non-volatile memory (if any). 163 */ 164 void Restore(void); 165 166 /** 167 * Stores network information into non-volatile memory. 168 * 169 * @retval kErrorNone Successfully store the network information. 170 * @retval kErrorNoBufs Could not store the network information due to insufficient memory space. 171 */ 172 Error Store(void); 173 174 /** 175 * Generates an MLE Announce message. 176 * 177 * @param[in] aChannel The channel to use when transmitting. 178 */ SendAnnounce(uint8_t aChannel)179 void SendAnnounce(uint8_t aChannel) { SendAnnounce(aChannel, kNormalAnnounce); } 180 181 /** 182 * Causes the Thread interface to detach from the Thread network. 183 * 184 * @retval kErrorNone Successfully detached from the Thread network. 185 * @retval kErrorInvalidState MLE is Disabled. 186 */ 187 Error BecomeDetached(void); 188 189 /** 190 * Causes the Thread interface to attempt an MLE attach. 191 * 192 * @retval kErrorNone Successfully began the attach process. 193 * @retval kErrorInvalidState MLE is Disabled. 194 * @retval kErrorBusy An attach process is in progress. 195 */ 196 Error BecomeChild(void); 197 198 /** 199 * Notifies other nodes in the network (if any) and then stops Thread protocol operation. 200 * 201 * It sends an Address Release if it's a router, or sets its child timeout to 0 if it's a child. 202 * 203 * @param[in] aCallback A pointer to a function that is called upon finishing detaching. 204 * @param[in] aContext A pointer to callback application-specific context. 205 * 206 * @retval kErrorNone Successfully started detaching. 207 * @retval kErrorBusy Detaching is already in progress. 208 */ 209 Error DetachGracefully(DetachCallback aCallback, void *aContext); 210 211 /** 212 * Indicates whether or not the Thread device is attached to a Thread network. 213 * 214 * @retval TRUE Attached to a Thread network. 215 * @retval FALSE Not attached to a Thread network. 216 */ 217 bool IsAttached(void) const; 218 219 /** 220 * Indicates whether device is currently attaching or not. 221 * 222 * Note that an already attached device may also be in attaching state. Examples of this include a leader/router 223 * trying to attach to a better partition, or a child trying to find a better parent (when feature 224 * `OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE` is enabled). 225 * 226 * @retval TRUE Device is currently trying to attach. 227 * @retval FALSE Device is not in middle of attach process. 228 */ IsAttaching(void) const229 bool IsAttaching(void) const { return (mAttachState != kAttachStateIdle); } 230 231 /** 232 * Returns the current Thread device role. 233 * 234 * @returns The current Thread device role. 235 */ GetRole(void) const236 DeviceRole GetRole(void) const { return mRole; } 237 238 /** 239 * Indicates whether device role is disabled. 240 * 241 * @retval TRUE Device role is disabled. 242 * @retval FALSE Device role is not disabled. 243 */ IsDisabled(void) const244 bool IsDisabled(void) const { return (mRole == kRoleDisabled); } 245 246 /** 247 * Indicates whether device role is detached. 248 * 249 * @retval TRUE Device role is detached. 250 * @retval FALSE Device role is not detached. 251 */ IsDetached(void) const252 bool IsDetached(void) const { return (mRole == kRoleDetached); } 253 254 /** 255 * Indicates whether device role is child. 256 * 257 * @retval TRUE Device role is child. 258 * @retval FALSE Device role is not child. 259 */ IsChild(void) const260 bool IsChild(void) const { return (mRole == kRoleChild); } 261 262 /** 263 * Indicates whether device role is router. 264 * 265 * @retval TRUE Device role is router. 266 * @retval FALSE Device role is not router. 267 */ IsRouter(void) const268 bool IsRouter(void) const { return (mRole == kRoleRouter); } 269 270 /** 271 * Indicates whether device role is leader. 272 * 273 * @retval TRUE Device role is leader. 274 * @retval FALSE Device role is not leader. 275 */ IsLeader(void) const276 bool IsLeader(void) const { return (mRole == kRoleLeader); } 277 278 /** 279 * Indicates whether device role is either router or leader. 280 * 281 * @retval TRUE Device role is either router or leader. 282 * @retval FALSE Device role is neither router nor leader. 283 */ 284 bool IsRouterOrLeader(void) const; 285 286 /** 287 * Returns the Device Mode as reported in the Mode TLV. 288 * 289 * @returns The Device Mode as reported in the Mode TLV. 290 */ GetDeviceMode(void) const291 DeviceMode GetDeviceMode(void) const { return mDeviceMode; } 292 293 /** 294 * Sets the Device Mode as reported in the Mode TLV. 295 * 296 * @param[in] aDeviceMode The device mode to set. 297 * 298 * @retval kErrorNone Successfully set the Mode TLV. 299 * @retval kErrorInvalidArgs The mode combination specified in @p aMode is invalid. 300 */ 301 Error SetDeviceMode(DeviceMode aDeviceMode); 302 303 /** 304 * Indicates whether or not the device is rx-on-when-idle. 305 * 306 * @returns TRUE if rx-on-when-idle, FALSE otherwise. 307 */ IsRxOnWhenIdle(void) const308 bool IsRxOnWhenIdle(void) const { return mDeviceMode.IsRxOnWhenIdle(); } 309 310 /** 311 * Indicates whether or not the device is a Full Thread Device. 312 * 313 * @returns TRUE if a Full Thread Device, FALSE otherwise. 314 */ IsFullThreadDevice(void) const315 bool IsFullThreadDevice(void) const { return mDeviceMode.IsFullThreadDevice(); } 316 317 /** 318 * Indicates whether or not the device is a Minimal End Device. 319 * 320 * @returns TRUE if the device is a Minimal End Device, FALSE otherwise. 321 */ IsMinimalEndDevice(void) const322 bool IsMinimalEndDevice(void) const { return mDeviceMode.IsMinimalEndDevice(); } 323 324 /** 325 * Gets the Network Data type (full set or stable subset) that this device requests. 326 * 327 * @returns The Network Data type requested by this device. 328 */ GetNetworkDataType(void) const329 NetworkData::Type GetNetworkDataType(void) const { return mDeviceMode.GetNetworkDataType(); } 330 331 /** 332 * Returns a pointer to the Mesh Local Prefix. 333 * 334 * @returns A reference to the Mesh Local Prefix. 335 */ GetMeshLocalPrefix(void) const336 const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; } 337 338 /** 339 * Sets the Mesh Local Prefix. 340 * 341 * @param[in] aMeshLocalPrefix A reference to the Mesh Local Prefix. 342 */ 343 void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix); 344 345 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 346 /** 347 * Sets the Mesh Local IID. 348 * 349 * Available only when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled. 350 * 351 * @param[in] aMlIid The Mesh Local IID. 352 * 353 * @retval kErrorNone Successfully configured Mesh Local IID. 354 * @retval kErrorInvalidState If the Thread stack is already enabled. 355 */ 356 Error SetMeshLocalIid(const Ip6::InterfaceIdentifier &aMlIid); 357 #endif 358 359 /** 360 * Returns a reference to the Thread link-local address. 361 * 362 * The Thread link local address is derived using IEEE802.15.4 Extended Address as Interface Identifier. 363 * 364 * @returns A reference to the Thread link local address. 365 */ GetLinkLocalAddress(void) const366 const Ip6::Address &GetLinkLocalAddress(void) const { return mLinkLocalAddress.GetAddress(); } 367 368 /** 369 * Updates the link local address. 370 * 371 * Call this method when the IEEE 802.15.4 Extended Address has changed. 372 */ 373 void UpdateLinkLocalAddress(void); 374 375 /** 376 * Returns a reference to the link-local all Thread nodes multicast address. 377 * 378 * @returns A reference to the link-local all Thread nodes multicast address. 379 */ GetLinkLocalAllThreadNodesAddress(void) const380 const Ip6::Address &GetLinkLocalAllThreadNodesAddress(void) const { return mLinkLocalAllThreadNodes.GetAddress(); } 381 382 /** 383 * Returns a reference to the realm-local all Thread nodes multicast address. 384 * 385 * @returns A reference to the realm-local all Thread nodes multicast address. 386 */ GetRealmLocalAllThreadNodesAddress(void) const387 const Ip6::Address &GetRealmLocalAllThreadNodesAddress(void) const 388 { 389 return mRealmLocalAllThreadNodes.GetAddress(); 390 } 391 392 /** 393 * Gets the parent's RLOC16. 394 * 395 * @returns The parent's RLOC16, or `kInvalidRloc16` if parent's state is not valid. 396 */ 397 uint16_t GetParentRloc16(void) const; 398 399 /** 400 * Gets the parent when operating in End Device mode. 401 * 402 * @returns A reference to the parent. 403 */ GetParent(void)404 Parent &GetParent(void) { return mParent; } 405 406 /** 407 * Gets the parent when operating in End Device mode. 408 * 409 * @returns A reference to the parent. 410 */ GetParent(void) const411 const Parent &GetParent(void) const { return mParent; } 412 413 /** 414 * The method retrieves information about the parent. 415 * 416 * @param[out] aParentInfo Reference to a parent information structure. 417 * 418 * @retval kErrorNone Successfully retrieved the parent info and updated @p aParentInfo. 419 * @retval kErrorInvalidState Device role is not child. 420 */ 421 Error GetParentInfo(Router::Info &aParentInfo) const; 422 423 /** 424 * Get the parent candidate. 425 * 426 * The parent candidate is valid when attempting to attach to a new parent. 427 */ GetParentCandidate(void)428 Parent &GetParentCandidate(void) { return mParentCandidate; } 429 430 /** 431 * Starts the process for child to search for a better parent while staying attached to its current 432 * parent 433 * 434 * @retval kErrorNone Successfully started the process to search for a better parent. 435 * @retval kErrorInvalidState Device role is not child. 436 */ 437 Error SearchForBetterParent(void); 438 439 /** 440 * Indicates whether or not an IPv6 address is an RLOC. 441 * 442 * @retval TRUE If @p aAddress is an RLOC. 443 * @retval FALSE If @p aAddress is not an RLOC. 444 */ 445 bool IsRoutingLocator(const Ip6::Address &aAddress) const; 446 447 /** 448 * Indicates whether or not an IPv6 address is an ALOC. 449 * 450 * @retval TRUE If @p aAddress is an ALOC. 451 * @retval FALSE If @p aAddress is not an ALOC. 452 */ 453 bool IsAnycastLocator(const Ip6::Address &aAddress) const; 454 455 /** 456 * Indicates whether or not an IPv6 address is a Mesh Local Address. 457 * 458 * @retval TRUE If @p aAddress is a Mesh Local Address. 459 * @retval FALSE If @p aAddress is not a Mesh Local Address. 460 */ 461 bool IsMeshLocalAddress(const Ip6::Address &aAddress) const; 462 463 /** 464 * Returns the MLE Timeout value. 465 * 466 * @returns The MLE Timeout value in seconds. 467 */ GetTimeout(void) const468 uint32_t GetTimeout(void) const { return mTimeout; } 469 470 /** 471 * Sets the MLE Timeout value. 472 * 473 * @param[in] aTimeout The Timeout value in seconds. 474 */ SetTimeout(uint32_t aTimeout)475 void SetTimeout(uint32_t aTimeout) { SetTimeout(aTimeout, kSendChildUpdateToParent); } 476 477 /** 478 * Returns the RLOC16 assigned to the Thread interface. 479 * 480 * @returns The RLOC16 assigned to the Thread interface. 481 */ GetRloc16(void) const482 uint16_t GetRloc16(void) const { return mRloc16; } 483 484 /** 485 * Indicates whether or not this device is using a given RLOC16. 486 * 487 * @param[in] aRloc16 The RLOC16 to check. 488 * 489 * @retval TRUE This device is using @p aRloc16. 490 * @retval FALSE This device is not using @p aRloc16. 491 */ HasRloc16(uint16_t aRloc16) const492 bool HasRloc16(uint16_t aRloc16) const { return mRloc16 == aRloc16; } 493 494 /** 495 * Indicates whether or not this device RLOC16 matches a given Router ID. 496 * 497 * @param[in] aRouterId The Router ID to check. 498 * 499 * @retval TRUE This device's RLOC16 matches the @p aRouterId. 500 * @retval FALSE This device's RLOC16 does not match the @p aRouterId. 501 */ MatchesRouterId(uint8_t aRouterId) const502 bool MatchesRouterId(uint8_t aRouterId) const { return RouterIdFromRloc16(mRloc16) == aRouterId; } 503 504 /** 505 * Indicates whether or not this device's RLOC16 shares the same Router ID with a given RLOC16. 506 * 507 * A shared Router ID implies that this device and the @ aRloc16 are either directly related as parent and child, 508 * or are children of the same parent within the Thread network. 509 * 510 * @param[in] aRloc16 The RLOC16 to check. 511 * 512 * @retval TRUE This device and @p aRloc16 have a matching router ID. 513 * @retval FALSE This device and @p aRloc16 do not have a matching router ID. 514 */ HasMatchingRouterIdWith(uint16_t aRloc16) const515 bool HasMatchingRouterIdWith(uint16_t aRloc16) const { return RouterIdMatch(mRloc16, aRloc16); } 516 517 /** 518 * Returns the mesh local RLOC IPv6 address assigned to the Thread interface. 519 * 520 * @returns The mesh local RLOC IPv6 address. 521 */ GetMeshLocalRloc(void) const522 const Ip6::Address &GetMeshLocalRloc(void) const { return mMeshLocalRloc.GetAddress(); } 523 524 /** 525 * Returns the mesh local endpoint identifier (ML-EID) IPv6 address assigned to the Thread interface. 526 * 527 * @returns The ML-EID address. 528 */ GetMeshLocalEid(void) const529 const Ip6::Address &GetMeshLocalEid(void) const { return mMeshLocalEid.GetAddress(); } 530 531 /** 532 * Returns a reference to the ML-EID as a `Netif::UnicastAddress`. 533 * 534 * @returns A reference to the ML-EID. 535 */ GetMeshLocalEidUnicastAddress(void)536 Ip6::Netif::UnicastAddress &GetMeshLocalEidUnicastAddress(void) { return mMeshLocalEid; } 537 538 /** 539 * Returns the Router ID of the Leader. 540 * 541 * @returns The Router ID of the Leader. 542 */ GetLeaderId(void) const543 uint8_t GetLeaderId(void) const { return mLeaderData.GetLeaderRouterId(); } 544 545 /** 546 * Returns the RLOC16 of the Leader. 547 * 548 * @returns The RLOC16 of the Leader. 549 */ GetLeaderRloc16(void) const550 uint16_t GetLeaderRloc16(void) const { return Rloc16FromRouterId(GetLeaderId()); } 551 552 /** 553 * Retrieves the Leader's RLOC. 554 * 555 * @param[out] aAddress A reference to an address to return the Leader's RLOC. 556 */ 557 void GetLeaderRloc(Ip6::Address &aAddress) const; 558 559 /** 560 * Retrieves the Leader's ALOC. 561 * 562 * @param[out] aAddress A reference to an address to return the Leader's ALOC. 563 */ 564 void GetLeaderAloc(Ip6::Address &aAddress) const; 565 566 /** 567 * Retrieves the Commissioner's ALOC for a given session ID. 568 * 569 * @param[in] aSessionId Commissioner session id. 570 * @param[out] aAddress A reference to an address to return the Commissioner's ALOC. 571 */ 572 void GetCommissionerAloc(uint16_t aSessionId, Ip6::Address &aAddress) const; 573 574 /** 575 * Retrieves the Service ALOC for given Service ID. 576 * 577 * @param[in] aServiceId Service ID to get ALOC for. 578 * @param[out] aAddress A reference to an address to return the Service ALOC. 579 */ 580 void GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const; 581 582 /** 583 * Returns the most recently received Leader Data. 584 * 585 * @returns A reference to the most recently received Leader Data. 586 */ 587 const LeaderData &GetLeaderData(void); 588 589 /** 590 * Returns a reference to the send queue. 591 * 592 * @returns A reference to the send queue. 593 */ GetMessageQueue(void) const594 const MessageQueue &GetMessageQueue(void) const { return mDelayedSender.GetQueue(); } 595 596 /** 597 * Gets the MLE counters. 598 * 599 * @returns A reference to the MLE counters. 600 */ 601 const Counters &GetCounters(void); 602 603 /** 604 * Resets the MLE counters. 605 */ 606 void ResetCounters(void); 607 608 #if OPENTHREAD_CONFIG_UPTIME_ENABLE 609 /** 610 * Determines the current attach duration (number of seconds since the device last attached). 611 * 612 * @returns Current attach duration in seconds. 613 */ 614 uint32_t GetCurrentAttachDuration(void) const; 615 #endif 616 617 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE 618 /** 619 * Registers the client callback that is called when processing an MLE Parent Response message. 620 * 621 * @param[in] aCallback A pointer to a function that is called to deliver MLE Parent Response data. 622 * @param[in] aContext A pointer to application-specific context. 623 */ RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback,void * aContext)624 void RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext) 625 { 626 mParentResponseCallback.Set(aCallback, aContext); 627 } 628 #endif 629 /** 630 * Notifies MLE whether the Child ID Request message was transmitted successfully. 631 * 632 * @param[in] aMessage The transmitted message. 633 */ 634 void HandleChildIdRequestTxDone(Message &aMessage); 635 636 /** 637 * Requests MLE layer to prepare and send a shorter version of Child ID Request message by only 638 * including the mesh-local IPv6 address in the Address Registration TLV. 639 * 640 * Should be called when a previous MLE Child ID Request message would require fragmentation at 6LoWPAN 641 * layer. 642 */ 643 void RequestShorterChildIdRequest(void); 644 645 /** 646 * Schedules a Child Update Request. 647 */ 648 void ScheduleChildUpdateRequest(void); 649 650 /** 651 * Sends a Child Update Request to the parent. 652 * 653 * @retval kErrorNone Successfully prepared and sent an MLE Child Update Request message. 654 * @retval kErrorNoBufs Insufficient buffers to construct the MLE Child Update Request message. 655 */ 656 Error SendChildUpdateRequestToParent(void); 657 658 /* 659 * Indicates whether or not the device has restored the network information from 660 * non-volatile settings after boot. 661 * 662 * @retval true Successfully restored the network information. 663 * @retval false No valid network information was found. 664 */ HasRestored(void) const665 bool HasRestored(void) const { return mHasRestored; } 666 667 /** 668 * Indicates whether or not a given netif multicast address instance is a prefix-based address added by MLE and 669 * uses the mesh local prefix. 670 * 671 * @param[in] aAddress A `Netif::MulticastAddress` address instance. 672 * 673 * @retval TRUE If @p aAddress is a prefix-based address which uses the mesh local prefix. 674 * @retval FALSE If @p aAddress is not a prefix-based address which uses the mesh local prefix. 675 */ IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress & aAddress) const676 bool IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress &aAddress) const 677 { 678 return (&aAddress == &mLinkLocalAllThreadNodes) || (&aAddress == &mRealmLocalAllThreadNodes); 679 } 680 681 /** 682 * Schedules a "Child Update Request" transmission if the device is an MTD child. 683 * 684 * For example, the `Slaac` class, which manages SLAAC addresses, calls this method to notify `Mle` that an 685 * existing SLAAC address's Context ID has changed. This can occur due to Network Data updates where the same 686 * on-mesh prefix receives a new Context ID. 687 */ 688 void ScheduleChildUpdateRequestIfMtdChild(void); 689 690 #if OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE 691 /** 692 * Sets the store frame counter ahead. 693 * 694 * @param[in] aStoreFrameCounterAhead The store frame counter ahead to set. 695 */ SetStoreFrameCounterAhead(uint32_t aStoreFrameCounterAhead)696 void SetStoreFrameCounterAhead(uint32_t aStoreFrameCounterAhead) 697 { 698 mStoreFrameCounterAhead = aStoreFrameCounterAhead; 699 } 700 701 /** 702 * Gets the current store frame counter ahead. 703 * 704 * @returns The current store frame counter ahead. 705 */ GetStoreFrameCounterAhead(void)706 uint32_t GetStoreFrameCounterAhead(void) { return mStoreFrameCounterAhead; } 707 #endif // OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE 708 709 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 710 /** 711 * Gets the CSL timeout. 712 * 713 * @returns CSL timeout 714 */ GetCslTimeout(void) const715 uint32_t GetCslTimeout(void) const { return mCslTimeout; } 716 717 /** 718 * Sets the CSL timeout. 719 * 720 * @param[in] aTimeout The CSL timeout in seconds. 721 */ 722 void SetCslTimeout(uint32_t aTimeout); 723 724 /** 725 * Calculates CSL metric of parent. 726 * 727 * @param[in] aCslAccuracy The CSL accuracy. 728 * 729 * @returns CSL metric. 730 */ 731 uint64_t CalcParentCslMetric(const Mac::CslAccuracy &aCslAccuracy) const; 732 733 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 734 735 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 736 /** 737 * Attempts to wake a Wake-up End Device. 738 * 739 * @param[in] aWedAddress The extended address of the Wake-up End Device. 740 * @param[in] aIntervalUs An interval between consecutive wake-up frames (in microseconds). 741 * @param[in] aDurationMs Duration of the wake-up sequence (in milliseconds). 742 * @param[in] aCallback A pointer to function that is called when the wake-up succeeds or fails. 743 * @param[in] aContext A pointer to callback application-specific context. 744 * 745 * @retval kErrorNone Successfully started the wake-up. 746 * @retval kErrorInvalidState Another wake-up request is still in progress. 747 * @retval kErrorInvalidArgs The wake-up interval or duration are invalid. 748 */ 749 Error Wakeup(const Mac::ExtAddress &aWedAddress, 750 uint16_t aIntervalUs, 751 uint16_t aDurationMs, 752 WakeupCallback aCallback, 753 void *aCallbackContext); 754 #endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 755 756 private: 757 //------------------------------------------------------------------------------------------------------------------ 758 // Constants 759 760 // All time intervals are in milliseconds 761 static constexpr uint32_t kParentRequestRouterTimeout = 750; // Wait time after tx of Parent Req to routers 762 static constexpr uint32_t kParentRequestReedTimeout = 1250; // Wait timer after tx of Parent Req to REEDs 763 static constexpr uint32_t kParentRequestDuplicateMargin = 50; // Margin to detect duplicate received Parent Req 764 static constexpr uint32_t kChildIdResponseTimeout = 1250; // Wait time to receive Child ID Response 765 static constexpr uint32_t kAttachStartJitter = 50; // Max jitter time added to start of attach 766 static constexpr uint32_t kAnnounceProcessTimeout = 250; // Delay after Announce rx before processing 767 static constexpr uint32_t kAnnounceTimeout = 1400; // Total timeout for sending Announce messages 768 static constexpr uint16_t kMinAnnounceDelay = 80; // Min delay between Announcement messages 769 static constexpr uint32_t kParentResponseMaxDelayRouters = 500; // Max response delay for Parent Req to routers 770 static constexpr uint32_t kParentResponseMaxDelayAll = 1000; // Max response delay for Parent Req to all 771 static constexpr uint32_t kChildUpdateRequestDelay = 100; // Delay for aggregating Child Update Req 772 static constexpr uint32_t kMaxLinkRequestDelayOnRouter = 1000; // Max delay to tx Link Request on Adv rx 773 static constexpr uint32_t kMinLinkRequestDelayOnChild = 1500; // Min delay to tx Link Request on Adv rx (child) 774 static constexpr uint32_t kMaxLinkRequestDelayOnChild = 3000; // Max delay to tx Link Request on Adv rx (child) 775 static constexpr uint32_t kMaxLinkAcceptDelay = 1000; // Max delay to tx Link Accept for multicast Req 776 static constexpr uint32_t kChildIdRequestTimeout = 5000; // Max delay to rx a Child ID Req after Parent Res 777 static constexpr uint32_t kLinkRequestTimeout = 2000; // Max delay to rx a Link Accept 778 static constexpr uint32_t kDetachGracefullyTimeout = 1000; // Timeout for graceful detach 779 static constexpr uint32_t kUnicastRetxDelay = 1000; // Base delay for MLE unicast retx 780 static constexpr uint32_t kMulticastRetxDelay = 5000; // Base delay for MLE multicast retx 781 static constexpr uint32_t kMulticastRetxDelayMin = kMulticastRetxDelay * 9 / 10; // 0.9 * base delay 782 static constexpr uint32_t kMulticastRetxDelayMax = kMulticastRetxDelay * 11 / 10; // 1.1 * base delay 783 static constexpr uint32_t kAnnounceBackoffForPendingDataset = 60000; // Max delay left to block Announce processing. 784 785 static constexpr uint8_t kMaxTxCount = 3; // Max tx count for MLE message 786 static constexpr uint8_t kMaxCriticalTxCount = 6; // Max tx count for critical MLE message 787 static constexpr uint8_t kMaxChildKeepAliveAttempts = 4; // Max keep alive attempts before reattach 788 789 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 790 // Attach backoff feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds. 791 792 static constexpr uint32_t kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL; 793 static constexpr uint32_t kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL; 794 static constexpr uint32_t kAttachBackoffJitter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL; 795 static constexpr uint32_t kAttachBackoffDelayToResetCounter = 796 OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL; 797 798 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 799 // Number of Parent Requests in first and next attach cycles 800 801 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3 802 // First attach cycle includes two Parent Requests to routers, followed by four to routers and REEDs. 803 static constexpr uint8_t kFirstAttachCycleTotalParentRequests = 6; 804 static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 2; 805 #else 806 // First attach cycle in Thread 1.1/1.2 includes a Parent Requests to routers, followed by one to routers and REEDs. 807 static constexpr uint8_t kFirstAttachCycleTotalParentRequests = 2; 808 static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 1; 809 #endif 810 811 // Next attach cycles includes one Parent Request to routers, followed by one to routers and REEDs. 812 static constexpr uint8_t kNextAttachCycleTotalParentRequests = 2; 813 static constexpr uint8_t kNextAttachCycleNumParentRequestToRouters = 1; 814 815 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 816 817 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 818 static constexpr uint8_t kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS + 1; 819 #else 820 static constexpr uint8_t kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS; 821 #endif 822 823 static constexpr uint8_t kMleHopLimit = 255; 824 static constexpr uint8_t kMleSecurityTagSize = 4; 825 static constexpr uint32_t kDefaultStoreFrameCounterAhead = OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD; 826 static constexpr uint8_t kMaxIpAddressesToRegister = OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER; 827 static constexpr uint32_t kDefaultChildTimeout = OPENTHREAD_CONFIG_MLE_CHILD_TIMEOUT_DEFAULT; 828 static constexpr uint32_t kDefaultCslTimeout = OPENTHREAD_CONFIG_CSL_TIMEOUT; 829 830 //------------------------------------------------------------------------------------------------------------------ 831 // Enumerations 832 833 enum AttachMode : uint8_t 834 { 835 kAnyPartition, // Attach to any Thread partition. 836 kSamePartition, // Attach to the same Thread partition (when losing connectivity). 837 kBetterPartition, // Attach to a better (i.e. higher weight/partition id) Thread partition. 838 kDowngradeToReed, // Attach to the same Thread partition during downgrade process. 839 kBetterParent, // Attach to a better parent. 840 kSelectedParent, // Attach to a selected parent. 841 }; 842 843 enum AttachState : uint8_t 844 { 845 kAttachStateIdle, // Not currently searching for a parent. 846 kAttachStateProcessAnnounce, // Waiting to process a received Announce (to switch channel/pan-id). 847 kAttachStateStart, // Starting to look for a parent. 848 kAttachStateParentRequest, // Send Parent Request (current number tracked by `mParentRequestCounter`). 849 kAttachStateAnnounce, // Send Announce messages 850 kAttachStateChildIdRequest, // Sending a Child ID Request message. 851 }; 852 853 enum ReattachState : uint8_t 854 { 855 kReattachStop, // Reattach process is disabled or finished 856 kReattachStart, // Start reattach process 857 kReattachActive, // Reattach using stored Active Dataset 858 kReattachPending, // Reattach using stored Pending Dataset 859 }; 860 861 static constexpr uint16_t kMleMaxResponseDelay = 1000u; // Max delay before responding to a multicast request. 862 863 enum AddressRegistrationMode : uint8_t // Used by `AppendAddressRegistrationTlv()` 864 { 865 kAppendAllAddresses, // Append all addresses (unicast/multicast) in Address Registration TLV. 866 kAppendMeshLocalOnly, // Only append the Mesh Local (ML-EID) address in Address Registration TLV. 867 }; 868 869 enum StartMode : uint8_t // Used in `Start()`. 870 { 871 kNormalAttach, 872 kAnnounceAttach, // Try to attach on the announced thread network with newer active timestamp. 873 }; 874 875 enum StopMode : uint8_t // Used in `Stop()`. 876 { 877 kKeepNetworkDatasets, 878 kUpdateNetworkDatasets, 879 }; 880 881 enum AnnounceMode : uint8_t // Used in `SendAnnounce()` 882 { 883 kNormalAnnounce, 884 kOrphanAnnounce, 885 }; 886 887 enum ParentRequestType : uint8_t 888 { 889 kToRouters, // Parent Request to routers only. 890 kToRoutersAndReeds, // Parent Request to all routers and REEDs. 891 kToSelectedRouter, // Parent Request to a selected router (e.g., by `ParentSearch` module). 892 }; 893 894 enum ChildUpdateRequestMode : uint8_t // Used in `SendChildUpdateRequest()` 895 { 896 kNormalChildUpdateRequest, // Normal Child Update Request. 897 kAppendChallengeTlv, // Append Challenge TLV to Child Update Request even if currently attached. 898 kAppendZeroTimeout, // Use zero timeout when appending Timeout TLV (used for graceful detach). 899 }; 900 901 enum SecuritySuite : uint8_t 902 { 903 k154Security = 0, // Security suite value indicating that MLE message is not secured. 904 kNoSecurity = 255, // Security suite value indicating that MLE message is secured. 905 }; 906 907 enum TimeoutAction : uint8_t // Used as input in `SetTimeout()` to determine whether or not to update the parent. 908 { 909 kSendChildUpdateToParent, 910 kDoNotSendChildUpdateToParent, 911 }; 912 913 enum MessageAction : uint8_t 914 { 915 kMessageSend, 916 kMessageReceive, 917 kMessageDelay, 918 kMessageRemoveDelayed, 919 }; 920 921 enum MessageType : uint8_t 922 { 923 kTypeAdvertisement, 924 kTypeAnnounce, 925 kTypeChildIdRequest, 926 kTypeChildIdRequestShort, 927 kTypeChildIdResponse, 928 kTypeChildUpdateRequestAsChild, 929 kTypeChildUpdateResponseAsChild, 930 kTypeDataRequest, 931 kTypeDataResponse, 932 kTypeDiscoveryRequest, 933 kTypeDiscoveryResponse, 934 kTypeGenericDelayed, 935 kTypeGenericUdp, 936 kTypeParentRequestToRouters, 937 kTypeParentRequestToRoutersReeds, 938 kTypeParentResponse, 939 #if OPENTHREAD_FTD 940 kTypeAddressRelease, 941 kTypeAddressReleaseReply, 942 kTypeAddressReply, 943 kTypeAddressSolicit, 944 kTypeChildUpdateRequestOfChild, 945 kTypeChildUpdateResponseOfChild, 946 kTypeChildUpdateResponseOfUnknownChild, 947 kTypeLinkAccept, 948 kTypeLinkAcceptAndRequest, 949 kTypeLinkReject, 950 kTypeLinkRequest, 951 kTypeParentRequest, 952 #endif 953 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 954 kTypeLinkMetricsManagementRequest, 955 kTypeLinkMetricsManagementResponse, 956 kTypeLinkProbe, 957 #endif 958 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 959 kTypeTimeSync, 960 #endif 961 }; 962 963 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 964 enum WedAttachState : uint8_t{ 965 kWedDetached, 966 kWedAttaching, 967 kWedAttached, 968 kWedDetaching, 969 }; 970 #endif 971 972 //------------------------------------------------------------------------------------------------------------------ 973 // Nested types 974 975 static constexpr uint8_t kMaxTlvListSize = 32; // Maximum number of TLVs in a `TlvList`. 976 977 class TlvList : public Array<uint8_t, kMaxTlvListSize> 978 { 979 public: 980 TlvList(void) = default; 981 982 void Add(uint8_t aTlvType); 983 void AddElementsFrom(const TlvList &aTlvList); 984 }; 985 986 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 987 988 class TxMessage : public Message 989 { 990 public: 991 Error AppendSourceAddressTlv(void); 992 Error AppendModeTlv(DeviceMode aMode); 993 Error AppendTimeoutTlv(uint32_t aTimeout); 994 Error AppendChallengeTlv(const TxChallenge &aChallenge); 995 Error AppendResponseTlv(const RxChallenge &aResponse); 996 Error AppendLinkFrameCounterTlv(void); 997 Error AppendMleFrameCounterTlv(void); 998 Error AppendLinkAndMleFrameCounterTlvs(void); 999 Error AppendAddress16Tlv(uint16_t aRloc16); 1000 Error AppendNetworkDataTlv(NetworkData::Type aType); 1001 Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength); 1002 Error AppendLeaderDataTlv(void); 1003 Error AppendScanMaskTlv(uint8_t aScanMask); 1004 Error AppendStatusTlv(StatusTlv::Status aStatus); 1005 Error AppendLinkMarginTlv(uint8_t aLinkMargin); 1006 Error AppendVersionTlv(void); 1007 Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses); 1008 Error AppendSupervisionIntervalTlvIfSleepyChild(void); 1009 Error AppendSupervisionIntervalTlv(uint16_t aInterval); 1010 Error AppendXtalAccuracyTlv(void); 1011 Error AppendActiveTimestampTlv(void); 1012 Error AppendPendingTimestampTlv(void); 1013 Error AppendActiveAndPendingTimestampTlvs(void); 1014 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1015 Error AppendTimeRequestTlv(void); 1016 Error AppendTimeParameterTlv(void); 1017 #endif 1018 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1019 Error AppendCslChannelTlv(void); 1020 Error AppendCslTimeoutTlv(void); 1021 #endif 1022 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 1023 Error AppendCslClockAccuracyTlv(void); 1024 #endif 1025 #if OPENTHREAD_FTD 1026 Error AppendRouteTlv(Neighbor *aNeighbor = nullptr); 1027 Error AppendActiveDatasetTlv(void); 1028 Error AppendPendingDatasetTlv(void); 1029 Error AppendConnectivityTlv(void); 1030 Error AppendSteeringDataTlv(void); 1031 Error AppendAddressRegistrationTlv(Child &aChild); 1032 #endif AppendTlvRequestTlv(const uint8_t (& aTlvArray)[kArrayLength])1033 template <uint8_t kArrayLength> Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength]) 1034 { 1035 return AppendTlvRequestTlv(aTlvArray, kArrayLength); 1036 } 1037 1038 Error SendTo(const Ip6::Address &aDestination); 1039 1040 private: 1041 Error AppendAddressRegistrationEntry(const Ip6::Address &aAddress); 1042 Error AppendDatasetTlv(MeshCoP::Dataset::Type aDatasetType); 1043 }; 1044 1045 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1046 1047 class RxMessage : public Message 1048 { 1049 public: 1050 bool ContainsTlv(Tlv::Type aTlvType) const; 1051 Error ReadModeTlv(DeviceMode &aMode) const; 1052 Error ReadVersionTlv(uint16_t &aVersion) const; 1053 Error ReadChallengeTlv(RxChallenge &aChallenge) const; 1054 Error ReadResponseTlv(RxChallenge &aResponse) const; 1055 Error ReadAndMatchResponseTlvWith(const TxChallenge &aChallenge) const; 1056 Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const; 1057 Error ReadTlvRequestTlv(TlvList &aTlvList) const; 1058 Error ReadLeaderDataTlv(LeaderData &aLeaderData) const; 1059 Error ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const; 1060 Error ReadAndSaveActiveDataset(const MeshCoP::Timestamp &aActiveTimestamp) const; 1061 Error ReadAndSavePendingDataset(const MeshCoP::Timestamp &aPendingTimestamp) const; 1062 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1063 Error ReadCslClockAccuracyTlv(Mac::CslAccuracy &aCslAccuracy) const; 1064 #endif 1065 #if OPENTHREAD_FTD 1066 Error ReadRouteTlv(RouteTlv &aRouteTlv) const; 1067 #endif 1068 1069 private: 1070 Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const; 1071 Error ReadAndSaveDataset(MeshCoP::Dataset::Type aDatasetType, const MeshCoP::Timestamp &aTimestamp) const; 1072 }; 1073 1074 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1075 1076 struct RxInfo 1077 { 1078 enum Class : uint8_t 1079 { 1080 kUnknown, // Unknown (default value, also indicates MLE message parse error). 1081 kAuthoritativeMessage, // Authoritative message (larger received key seq MUST be adopted). 1082 kPeerMessage, // Peer message (adopt only if from a known neighbor and is greater by one). 1083 }; 1084 RxInfoot::Mle::Mle::RxInfo1085 RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) 1086 : mMessage(static_cast<RxMessage &>(aMessage)) 1087 , mMessageInfo(aMessageInfo) 1088 , mFrameCounter(0) 1089 , mKeySequence(0) 1090 , mNeighbor(nullptr) 1091 , mClass(kUnknown) 1092 { 1093 } 1094 IsNeighborStateValidot::Mle::Mle::RxInfo1095 bool IsNeighborStateValid(void) const { return (mNeighbor != nullptr) && mNeighbor->IsStateValid(); } 1096 1097 RxMessage &mMessage; // The MLE message. 1098 const Ip6::MessageInfo &mMessageInfo; // The `MessageInfo` associated with the message. 1099 uint32_t mFrameCounter; // The frame counter from aux security header. 1100 uint32_t mKeySequence; // The key sequence from aux security header. 1101 Neighbor *mNeighbor; // Neighbor from which message was received (can be `nullptr`). 1102 Class mClass; // The message class (authoritative, peer, or unknown). 1103 }; 1104 1105 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1106 1107 #if OPENTHREAD_FTD 1108 struct ParentResponseInfo 1109 { 1110 Mac::ExtAddress mChildExtAddress; // The child extended address. 1111 RxChallenge mRxChallenge; // The challenge from the Parent Request. 1112 }; 1113 1114 struct LinkAcceptInfo 1115 { 1116 Mac::ExtAddress mExtAddress; // The neighbor/router extended address. 1117 TlvList mRequestedTlvList; // The requested TLVs in Link Request. 1118 RxChallenge mRxChallenge; // The challenge in Link Request. 1119 uint8_t mLinkMargin; // Link margin of the received Link Request. 1120 }; 1121 1122 struct DiscoveryResponseInfo 1123 { 1124 Mac::PanId mPanId; 1125 #if OPENTHREAD_CONFIG_MULTI_RADIO 1126 Mac::RadioType mRadioType; 1127 #endif 1128 }; 1129 1130 #endif // OPENTHREAD_FTD 1131 1132 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1133 HandleDelayedSenderTimer(void)1134 void HandleDelayedSenderTimer(void) { mDelayedSender.HandleTimer(); } 1135 1136 class DelayedSender : public InstanceLocator 1137 { 1138 public: 1139 explicit DelayedSender(Instance &aInstance); 1140 1141 void Stop(void); 1142 1143 void ScheduleDataRequest(const Ip6::Address &aDestination, uint16_t aDelay); 1144 void ScheduleChildUpdateRequestToParent(uint16_t aDelay); 1145 #if OPENTHREAD_FTD 1146 void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay); 1147 void ScheduleAdvertisement(const Ip6::Address &aDestination, uint16_t aDelay); 1148 void ScheduleMulticastDataResponse(uint16_t aDelay); 1149 void ScheduleLinkRequest(const Router &aRouter, uint16_t aDelay); 1150 void RemoveScheduledLinkRequest(const Router &aRouter); 1151 bool HasAnyScheduledLinkRequest(const Router &aRouter) const; 1152 void ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay); 1153 void ScheduleDiscoveryResponse(const Ip6::Address &aDestination, 1154 const DiscoveryResponseInfo &aInfo, 1155 uint16_t aDelay); 1156 #endif 1157 void RemoveScheduledChildUpdateRequestToParent(void); 1158 1159 void HandleTimer(void); GetQueue(void) const1160 const MessageQueue &GetQueue(void) const { return mSchedules; } 1161 1162 private: 1163 typedef Message Schedule; 1164 1165 struct Header 1166 { ReadFromot::Mle::Mle::DelayedSender::Header1167 void ReadFrom(const Schedule &aSchedule) { IgnoreError(aSchedule.Read(/* aOffset */ 0, *this)); } 1168 1169 TimeMilli mSendTime; 1170 Ip6::Address mDestination; 1171 MessageType mMessageType; 1172 }; 1173 1174 void AddSchedule(MessageType aMessageType, 1175 const Ip6::Address &aDestination, 1176 uint16_t aDelay, 1177 const void *aInfo, 1178 uint16_t aInfoSize); 1179 void Execute(const Schedule &aSchedule); 1180 bool HasMatchingSchedule(MessageType aMessageType, const Ip6::Address &aDestination) const; 1181 void RemoveMatchingSchedules(MessageType aMessageType, const Ip6::Address &aDestination); 1182 1183 static bool Match(const Schedule &aSchedule, MessageType aMessageType, const Ip6::Address &aDestination); 1184 1185 using DelayTimer = TimerMilliIn<Mle, &Mle::HandleDelayedSenderTimer>; 1186 1187 MessageQueue mSchedules; 1188 DelayTimer mTimer; 1189 }; 1190 1191 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1192 1193 OT_TOOL_PACKED_BEGIN 1194 class SecurityHeader 1195 { 1196 public: InitSecurityControl(void)1197 void InitSecurityControl(void) { mSecurityControl = kKeyIdMode2Mic32; } IsSecurityControlValid(void) const1198 bool IsSecurityControlValid(void) const { return (mSecurityControl == kKeyIdMode2Mic32); } 1199 GetFrameCounter(void) const1200 uint32_t GetFrameCounter(void) const { return LittleEndian::HostSwap32(mFrameCounter); } SetFrameCounter(uint32_t aCounter)1201 void SetFrameCounter(uint32_t aCounter) { mFrameCounter = LittleEndian::HostSwap32(aCounter); } 1202 GetKeyId(void) const1203 uint32_t GetKeyId(void) const { return BigEndian::HostSwap32(mKeySource); } SetKeyId(uint32_t aKeySequence)1204 void SetKeyId(uint32_t aKeySequence) 1205 { 1206 mKeySource = BigEndian::HostSwap32(aKeySequence); 1207 mKeyIndex = (aKeySequence & 0x7f) + 1; 1208 } 1209 1210 private: 1211 static constexpr uint8_t kKeyIdMode2Mic32 = 1212 static_cast<uint8_t>(Mac::Frame::kKeyIdMode2) | static_cast<uint8_t>(Mac::Frame::kSecurityEncMic32); 1213 1214 uint8_t mSecurityControl; 1215 uint32_t mFrameCounter; 1216 uint32_t mKeySource; 1217 uint8_t mKeyIndex; 1218 } OT_TOOL_PACKED_END; 1219 1220 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1221 1222 class ParentCandidate : public Parent 1223 { 1224 public: Init(Instance & aInstance)1225 void Init(Instance &aInstance) { Parent::Init(aInstance); } 1226 void Clear(void); 1227 void CopyTo(Parent &aParent) const; 1228 1229 RxChallenge mRxChallenge; 1230 int8_t mPriority; 1231 uint8_t mLinkQuality3; 1232 uint8_t mLinkQuality2; 1233 uint8_t mLinkQuality1; 1234 uint16_t mSedBufferSize; 1235 uint8_t mSedDatagramCount; 1236 uint8_t mLinkMargin; 1237 LeaderData mLeaderData; 1238 bool mIsSingleton; 1239 }; 1240 1241 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1242 1243 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1244 class ServiceAloc : public Ip6::Netif::UnicastAddress 1245 { 1246 public: 1247 static constexpr uint16_t kNotInUse = kInvalidRloc16; 1248 1249 ServiceAloc(void); 1250 IsInUse(void) const1251 bool IsInUse(void) const { return GetAloc16() != kNotInUse; } MarkAsNotInUse(void)1252 void MarkAsNotInUse(void) { SetAloc16(kNotInUse); } GetAloc16(void) const1253 uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); } SetAloc16(uint16_t aAloc16)1254 void SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); } 1255 }; 1256 #endif 1257 1258 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1259 1260 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE HandleParentSearchTimer(void)1261 void HandleParentSearchTimer(void) { mParentSearch.HandleTimer(); } 1262 1263 class ParentSearch : public InstanceLocator 1264 { 1265 public: ParentSearch(Instance & aInstance)1266 explicit ParentSearch(Instance &aInstance) 1267 : InstanceLocator(aInstance) 1268 , mEnabled(false) 1269 , mIsInBackoff(false) 1270 , mBackoffWasCanceled(false) 1271 , mRecentlyDetached(false) 1272 , mBackoffCancelTime(0) 1273 , mTimer(aInstance) 1274 { 1275 } 1276 1277 void SetEnabled(bool aEnabled); IsEnabled(void) const1278 bool IsEnabled(void) const { return mEnabled; } 1279 void UpdateState(void); SetRecentlyDetached(void)1280 void SetRecentlyDetached(void) { mRecentlyDetached = true; } 1281 void HandleTimer(void); 1282 #if OPENTHREAD_FTD GetSelectedParent(void) const1283 const Neighbor &GetSelectedParent(void) const { return *mSelectedParent; } 1284 #endif 1285 1286 private: 1287 // All timer intervals are converted to milliseconds. 1288 static constexpr uint32_t kCheckInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_CHECK_INTERVAL * 1000u); 1289 static constexpr uint32_t kBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u); 1290 static constexpr uint32_t kJitterInterval = (15 * 1000u); 1291 static constexpr int8_t kRssThreshold = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD; 1292 1293 #if OPENTHREAD_FTD 1294 static constexpr int8_t kRssMarginOverParent = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_MARGIN; 1295 1296 Error SelectBetterParent(void); 1297 void CompareAndUpdateSelectedParent(Router &aRouter); 1298 #endif 1299 void StartTimer(void); 1300 1301 using SearchTimer = TimerMilliIn<Mle, &Mle::HandleParentSearchTimer>; 1302 1303 bool mEnabled : 1; 1304 bool mIsInBackoff : 1; 1305 bool mBackoffWasCanceled : 1; 1306 bool mRecentlyDetached : 1; 1307 TimeMilli mBackoffCancelTime; 1308 SearchTimer mTimer; 1309 #if OPENTHREAD_FTD 1310 Router *mSelectedParent; 1311 #endif 1312 }; 1313 #endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1314 1315 //------------------------------------------------------------------------------------------------------------------ 1316 // Methods 1317 1318 Error Start(StartMode aMode); 1319 void Stop(StopMode aMode); 1320 TxMessage *NewMleMessage(Command aCommand); 1321 void SetRole(DeviceRole aRole); 1322 void Attach(AttachMode aMode); 1323 void SetAttachState(AttachState aState); 1324 void InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo); ClearParentCandidate(void)1325 void ClearParentCandidate(void) { mParentCandidate.Clear(); } 1326 Error SendDataRequest(const Ip6::Address &aDestination); 1327 void HandleNotifierEvents(Events aEvents); 1328 void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 1329 void ReestablishLinkWithNeighbor(Neighbor &aNeighbor); 1330 Error SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode); 1331 Error SendChildUpdateResponse(const TlvList &aTlvList, 1332 const RxChallenge &aChallenge, 1333 const Ip6::Address &aDestination); 1334 void SetRloc16(uint16_t aRloc16); 1335 void SetStateDetached(void); 1336 void SetStateChild(uint16_t aRloc16); 1337 void SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId); 1338 void SetLeaderData(const LeaderData &aLeaderData); 1339 void SetTimeout(uint32_t aTimeout, TimeoutAction aAction); 1340 void InformPreviousChannel(void); IsAnnounceAttach(void) const1341 bool IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; } 1342 void ScheduleMessageTransmissionTimer(void); 1343 void HandleAttachTimer(void); 1344 void HandleMessageTransmissionTimer(void); 1345 void ProcessKeySequence(RxInfo &aRxInfo); 1346 void HandleAdvertisement(RxInfo &aRxInfo); 1347 void HandleChildIdResponse(RxInfo &aRxInfo); 1348 void HandleChildUpdateRequest(RxInfo &aRxInfo); 1349 void HandleChildUpdateRequestOnChild(RxInfo &aRxInfo); 1350 void HandleChildUpdateResponse(RxInfo &aRxInfo); 1351 void HandleChildUpdateResponseOnChild(RxInfo &aRxInfo); 1352 void HandleDataResponse(RxInfo &aRxInfo); 1353 void HandleParentResponse(RxInfo &aRxInfo); 1354 void HandleAnnounce(RxInfo &aRxInfo); 1355 Error HandleLeaderData(RxInfo &aRxInfo); 1356 void ProcessAnnounce(void); 1357 bool HasUnregisteredAddress(void); 1358 uint32_t GetAttachStartDelay(void) const; 1359 void SendParentRequest(ParentRequestType aType); 1360 Error SendChildIdRequest(void); 1361 Error GetNextAnnounceChannel(uint8_t &aChannel) const; 1362 bool HasMoreChannelsToAnnounce(void) const; 1363 bool PrepareAnnounceState(void); 1364 void SendAnnounce(uint8_t aChannel, AnnounceMode aMode); 1365 void SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce); 1366 uint32_t Reattach(void); 1367 bool HasAcceptableParentCandidate(void) const; 1368 Error DetermineParentRequestType(ParentRequestType &aType) const; 1369 bool IsBetterParent(uint16_t aRloc16, 1370 uint8_t aTwoWayLinkMargin, 1371 const ConnectivityTlv &aConnectivityTlv, 1372 uint16_t aVersion, 1373 const Mac::CslAccuracy &aCslAccuracy); 1374 bool IsNetworkDataNewer(const LeaderData &aLeaderData); 1375 Error ProcessMessageSecurity(Crypto::AesCcm::Mode aMode, 1376 Message &aMessage, 1377 const Ip6::MessageInfo &aMessageInfo, 1378 uint16_t aCmdOffset, 1379 const SecurityHeader &aHeader); 1380 1381 #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH 1382 void InformPreviousParent(void); 1383 #endif 1384 1385 #if OPENTHREAD_CONFIG_UPTIME_ENABLE 1386 void UpdateRoleTimeCounters(DeviceRole aRole); 1387 #endif 1388 1389 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1390 ServiceAloc *FindInServiceAlocs(uint16_t aAloc16); 1391 void UpdateServiceAlocs(void); 1392 #endif 1393 1394 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 1395 void CheckTrelPeerAddrOnSecureMleRx(const Message &aMessage); 1396 #endif 1397 1398 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1399 void HandleTimeSync(RxInfo &aRxInfo); 1400 #endif 1401 1402 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 1403 void HandleLinkMetricsManagementRequest(RxInfo &aRxInfo); 1404 void HandleLinkProbe(RxInfo &aRxInfo); 1405 Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus); 1406 #endif 1407 1408 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 1409 void HandleLinkMetricsManagementResponse(RxInfo &aRxInfo); 1410 Error SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, 1411 const LinkMetrics::Initiator::QueryInfo &aQueryInfo); 1412 Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv); 1413 Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength); 1414 Error SendDataRequest(const Ip6::Address &aDestination, 1415 const uint8_t *aTlvs, 1416 uint8_t aTlvsLength, 1417 const LinkMetrics::Initiator::QueryInfo *aQueryInfo = nullptr); 1418 #else 1419 Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength); 1420 #endif 1421 1422 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) 1423 static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress); 1424 static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc); 1425 #else Log(MessageAction,MessageType,const Ip6::Address &)1426 static void Log(MessageAction, MessageType, const Ip6::Address &) {} Log(MessageAction,MessageType,const Ip6::Address &,uint16_t)1427 static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {} 1428 #endif 1429 1430 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 1431 void HandleWedAttachTimer(void); 1432 #endif 1433 1434 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 1435 static const char *AttachModeToString(AttachMode aMode); 1436 static const char *AttachStateToString(AttachState aState); 1437 static const char *ReattachStateToString(ReattachState aState); 1438 #endif 1439 1440 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) 1441 static void LogError(MessageAction aAction, MessageType aType, Error aError); 1442 static const char *MessageActionToString(MessageAction aAction); 1443 static const char *MessageTypeToString(MessageType aType); 1444 static const char *MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction); 1445 static void LogProcessError(MessageType aType, Error aError); 1446 static void LogSendError(MessageType aType, Error aError); 1447 #else LogProcessError(MessageType,Error)1448 static void LogProcessError(MessageType, Error) {} LogSendError(MessageType,Error)1449 static void LogSendError(MessageType, Error) {} 1450 #endif 1451 1452 //------------------------------------------------------------------------------------------------------------------ 1453 // Variables 1454 1455 using AttachTimer = TimerMilliIn<Mle, &Mle::HandleAttachTimer>; 1456 using MsgTxTimer = TimerMilliIn<Mle, &Mle::HandleMessageTransmissionTimer>; 1457 using MleSocket = Ip6::Udp::SocketIn<Mle, &Mle::HandleUdpReceive>; 1458 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 1459 using WedAttachTimer = TimerMicroIn<Mle, &Mle::HandleWedAttachTimer>; 1460 #endif 1461 1462 static const otMeshLocalPrefix kMeshLocalPrefixInit; 1463 1464 bool mRetrieveNewNetworkData : 1; 1465 bool mRequestRouteTlv : 1; 1466 bool mHasRestored : 1; 1467 bool mReceivedResponseFromParent : 1; 1468 bool mDetachingGracefully : 1; 1469 bool mInitiallyAttachedAsSleepy : 1; 1470 bool mWaitingForChildUpdateResponse : 1; 1471 bool mWaitingForDataResponse : 1; 1472 1473 DeviceRole mRole; 1474 DeviceRole mLastSavedRole; 1475 DeviceMode mDeviceMode; 1476 AttachState mAttachState; 1477 ReattachState mReattachState; 1478 AttachMode mAttachMode; 1479 AddressRegistrationMode mAddressRegistrationMode; 1480 1481 uint8_t mParentRequestCounter; 1482 uint8_t mChildUpdateAttempts; 1483 uint8_t mDataRequestAttempts; 1484 uint8_t mAnnounceChannel; 1485 uint8_t mAlternateChannel; 1486 uint16_t mRloc16; 1487 uint16_t mPreviousParentRloc; 1488 uint16_t mAttachCounter; 1489 uint16_t mAnnounceDelay; 1490 uint16_t mAlternatePanId; 1491 uint32_t mStoreFrameCounterAhead; 1492 uint32_t mTimeout; 1493 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1494 uint32_t mCslTimeout; 1495 #endif 1496 #if OPENTHREAD_CONFIG_UPTIME_ENABLE 1497 uint32_t mLastAttachTime; 1498 uint64_t mLastUpdatedTimestamp; 1499 #endif 1500 uint64_t mAlternateTimestamp; 1501 1502 LeaderData mLeaderData; 1503 Parent mParent; 1504 NeighborTable mNeighborTable; 1505 DelayedSender mDelayedSender; 1506 TxChallenge mParentRequestChallenge; 1507 ParentCandidate mParentCandidate; 1508 MleSocket mSocket; 1509 Counters mCounters; 1510 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1511 ParentSearch mParentSearch; 1512 #endif 1513 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1514 ServiceAloc mServiceAlocs[kMaxServiceAlocs]; 1515 #endif 1516 Callback<DetachCallback> mDetachGracefullyCallback; 1517 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE 1518 Callback<otThreadParentResponseCallback> mParentResponseCallback; 1519 #endif 1520 AttachTimer mAttachTimer; 1521 MsgTxTimer mMessageTransmissionTimer; 1522 Ip6::NetworkPrefix mMeshLocalPrefix; 1523 Ip6::Netif::UnicastAddress mLinkLocalAddress; 1524 Ip6::Netif::UnicastAddress mMeshLocalEid; 1525 Ip6::Netif::UnicastAddress mMeshLocalRloc; 1526 Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes; 1527 Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes; 1528 1529 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 1530 WakeupTxScheduler mWakeupTxScheduler; 1531 WedAttachState mWedAttachState; 1532 WedAttachTimer mWedAttachTimer; 1533 Callback<WakeupCallback> mWakeupCallback; 1534 #endif 1535 }; 1536 1537 } // namespace Mle 1538 1539 /** 1540 * @} 1541 */ 1542 1543 } // namespace ot 1544 1545 #endif // MLE_HPP_ 1546