diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 5771186b5..34eb419bd 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -66,7 +66,7 @@ namespace Mle { RegisterLogModule("Mle"); -const otMeshLocalPrefix Mle::sMeshLocalPrefixInit = { +const otMeshLocalPrefix Mle::kMeshLocalPrefixInit = { {0xfd, 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0x00}, }; @@ -140,7 +140,7 @@ Mle::Mle(Instance &aInstance) mRealmLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff33); mRealmLocalAllThreadNodes.GetAddress().mFields.m16[7] = HostSwap16(0x0001); - SetMeshLocalPrefix(AsCoreType(&sMeshLocalPrefixInit)); + SetMeshLocalPrefix(AsCoreType(&kMeshLocalPrefixInit)); // `SetMeshLocalPrefix()` also adds the Mesh-Local EID and subscribes // to the Link- and Realm-Local All Thread Nodes multicast addresses. diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 29a69b911..94d7b3892 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -94,13 +94,17 @@ namespace Mle { * */ +class MleRouter; + /** * Implements MLE functionality required by the Thread EndDevices, Router, and Leader roles. * */ class Mle : public InstanceLocator, private NonCopyable { + friend class MleRouter; friend class DiscoverScanner; + friend class ot::Instance; friend class ot::Notifier; friend class ot::SupervisionListener; #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE @@ -705,1024 +709,10 @@ public: #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -protected: - /** - * MLE Command Types. - * - */ - enum Command : uint8_t - { - kCommandLinkRequest = 0, ///< Link Request - kCommandLinkAccept = 1, ///< Link Accept - kCommandLinkAcceptAndRequest = 2, ///< Link Accept and Reject - kCommandLinkReject = 3, ///< Link Reject - kCommandAdvertisement = 4, ///< Advertisement - kCommandUpdate = 5, ///< Update - kCommandUpdateRequest = 6, ///< Update Request - kCommandDataRequest = 7, ///< Data Request - kCommandDataResponse = 8, ///< Data Response - kCommandParentRequest = 9, ///< Parent Request - kCommandParentResponse = 10, ///< Parent Response - kCommandChildIdRequest = 11, ///< Child ID Request - kCommandChildIdResponse = 12, ///< Child ID Response - kCommandChildUpdateRequest = 13, ///< Child Update Request - kCommandChildUpdateResponse = 14, ///< Child Update Response - kCommandAnnounce = 15, ///< Announce - kCommandDiscoveryRequest = 16, ///< Discovery Request - kCommandDiscoveryResponse = 17, ///< Discovery Response - kCommandLinkMetricsManagementRequest = 18, ///< Link Metrics Management Request - kCommandLinkMetricsManagementResponse = 19, ///< Link Metrics Management Response - kCommandLinkProbe = 20, ///< Link Probe - kCommandTimeSync = 99, ///< Time Sync (when OPENTHREAD_CONFIG_TIME_SYNC_ENABLE enabled) - }; - - /** - * Attach mode. - * - */ - enum AttachMode : uint8_t - { - kAnyPartition, ///< Attach to any Thread partition. - kSamePartition, ///< Attach to the same Thread partition (attempt 1 when losing connectivity). - kSamePartitionRetry, ///< Attach to the same Thread partition (attempt 2 when losing connectivity). - kBetterPartition, ///< Attach to a better (i.e. higher weight/partition id) Thread partition. - kDowngradeToReed, ///< Attach to the same Thread partition during downgrade process. - kBetterParent, ///< Attach to a better parent. - }; - - /** - * States during attach (when searching for a parent). - * - */ - enum AttachState : uint8_t - { - kAttachStateIdle, ///< Not currently searching for a parent. - kAttachStateProcessAnnounce, ///< Waiting to process a received Announce (to switch channel/pan-id). - kAttachStateStart, ///< Starting to look for a parent. - kAttachStateParentRequest, ///< Send Parent Request (current number tracked by `mParentRequestCounter`). - kAttachStateAnnounce, ///< Send Announce messages - kAttachStateChildIdRequest, ///< Sending a Child ID Request message. - }; - - /** - * States when reattaching network using stored dataset - * - */ - enum ReattachState : uint8_t - { - kReattachStop, ///< Reattach process is disabled or finished - kReattachStart, ///< Start reattach process - kReattachActive, ///< Reattach using stored Active Dataset - kReattachPending, ///< Reattach using stored Pending Dataset - }; - - static constexpr uint16_t kMleMaxResponseDelay = 1000u; ///< Max delay before responding to a multicast request. - - /** - * Type is used in `AppendAddressRegistrationTlv()` to determine which addresses to include in the - * appended Address Registration TLV. - * - */ - enum AddressRegistrationMode : uint8_t - { - kAppendAllAddresses, ///< Append all addresses (unicast/multicast) in Address Registration TLV. - kAppendMeshLocalOnly, ///< Only append the Mesh Local (ML-EID) address in Address Registration TLV. - }; - - /** - * Represents the message actions used in `Log()` methods. - * - */ - enum MessageAction : uint8_t - { - kMessageSend, - kMessageReceive, - kMessageDelay, - kMessageRemoveDelayed, - }; - - /** - * Represents message types used in `Log()` methods. - * - */ - enum MessageType : uint8_t - { - kTypeAdvertisement, - kTypeAnnounce, - kTypeChildIdRequest, - kTypeChildIdRequestShort, - kTypeChildIdResponse, - kTypeChildUpdateRequestOfParent, - kTypeChildUpdateResponseOfParent, - kTypeDataRequest, - kTypeDataResponse, - kTypeDiscoveryRequest, - kTypeDiscoveryResponse, - kTypeGenericDelayed, - kTypeGenericUdp, - kTypeParentRequestToRouters, - kTypeParentRequestToRoutersReeds, - kTypeParentResponse, -#if OPENTHREAD_FTD - kTypeAddressRelease, - kTypeAddressReleaseReply, - kTypeAddressReply, - kTypeAddressSolicit, - kTypeChildUpdateRequestOfChild, - kTypeChildUpdateResponseOfChild, - kTypeChildUpdateResponseOfUnknownChild, - kTypeLinkAccept, - kTypeLinkAcceptAndRequest, - kTypeLinkReject, - kTypeLinkRequest, - kTypeParentRequest, -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - kTypeTimeSync, -#endif -#endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - kTypeLinkMetricsManagementRequest, - kTypeLinkMetricsManagementResponse, - kTypeLinkProbe, -#endif - }; - - static constexpr uint8_t kMaxTlvListSize = 32; ///< Maximum number of TLVs in a `TlvList`. - - /** - * Represents a list of TLVs (array of TLV types). - * - */ - class TlvList : public Array - { - public: - /** - * Initializes the `TlvList` as empty. - * - */ - TlvList(void) = default; - - /** - * Checks if a given TLV type is not already present in the list and adds it in the list. - * - * If the list is full, this method logs it as a warning. - * - * @param[in] aTlvType The TLV type to add to the list. - * - */ - void Add(uint8_t aTlvType); - - /** - * Adds elements from a given list to this TLV list (if not already present in the list). - * - * @param[in] aTlvList The TLV list to add elements from. - * - */ - void AddElementsFrom(const TlvList &aTlvList); - }; - - /** - * Represents an MLE Tx message. - * - */ - class TxMessage : public Message - { - public: - /** - * Appends a Source Address TLV to the message. - * - * @retval kErrorNone Successfully appended the Source Address TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Source Address TLV. - * - */ - Error AppendSourceAddressTlv(void); - - /** - * Appends a Mode TLV to the message. - * - * @param[in] aMode The Device Mode. - * - * @retval kErrorNone Successfully appended the Mode TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Mode TLV. - * - */ - Error AppendModeTlv(DeviceMode aMode); - - /** - * Appends a Timeout TLV to the message. - * - * @param[in] aTimeout The Timeout value. - * - * @retval kErrorNone Successfully appended the Timeout TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Timeout TLV. - * - */ - Error AppendTimeoutTlv(uint32_t aTimeout); - - /** - * Appends a Challenge TLV to the message. - * - * @param[in] aChallenge A reference to the Challenge data. - * - * @retval kErrorNone Successfully appended the Challenge TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Challenge TLV. - * - */ - Error AppendChallengeTlv(const TxChallenge &aChallenge); - - /** - * Appends a Response TLV to the message. - * - * @param[in] aResponse The Response data. - * - * @retval kErrorNone Successfully appended the Response TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Response TLV. - * - */ - Error AppendResponseTlv(const RxChallenge &aResponse); - - /** - * Appends a Link Frame Counter TLV to the message. - * - * @retval kErrorNone Successfully appended the Link Frame Counter TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Link Frame Counter TLV. - * - */ - Error AppendLinkFrameCounterTlv(void); - - /** - * Appends an MLE Frame Counter TLV to the message. - * - * @retval kErrorNone Successfully appended the Frame Counter TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the MLE Frame Counter TLV. - * - */ - Error AppendMleFrameCounterTlv(void); - - /** - * Appends an Address16 TLV to the message. - * - * @param[in] aRloc16 The RLOC16 value. - * - * @retval kErrorNone Successfully appended the Address16 TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Address16 TLV. - * - */ - Error AppendAddress16Tlv(uint16_t aRloc16); - - /** - * Appends a Network Data TLV to the message. - * - * @param[in] aType The Network Data type to append, full set or stable subset. - * - * @retval kErrorNone Successfully appended the Network Data TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Network Data TLV. - * - */ - Error AppendNetworkDataTlv(NetworkData::Type aType); - - /** - * Appends a TLV Request TLV to the message. - * - * @param[in] aTlvs A pointer to the list of TLV types. - * @param[in] aTlvsLength The number of TLV types in @p aTlvs - * - * @retval kErrorNone Successfully appended the TLV Request TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the TLV Request TLV. - * - */ - Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength); - - /** - * Appends a TLV Request TLV to the message. - * - * @tparam kArrayLength The TLV array length. - * - * @param[in] aTlvArray A reference to an array of TLV types of @p kArrayLength length. - * - * @retval kErrorNone Successfully appended the TLV Request TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the TLV Request TLV. - * - */ - template Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength]) - { - return AppendTlvRequestTlv(aTlvArray, kArrayLength); - } - - /** - * Appends a Leader Data TLV to the message. - * - * @retval kErrorNone Successfully appended the Leader Data TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Leader Data TLV. - * - */ - Error AppendLeaderDataTlv(void); - - /** - * Appends a Scan Mask TLV to th message. - * - * @param[in] aScanMask The Scan Mask value. - * - * @retval kErrorNone Successfully appended the Scan Mask TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Scan Mask TLV. - * - */ - Error AppendScanMaskTlv(uint8_t aScanMask); - - /** - * Appends a Status TLV to the message. - * - * @param[in] aStatus The Status value. - * - * @retval kErrorNone Successfully appended the Status TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Status TLV. - * - */ - Error AppendStatusTlv(StatusTlv::Status aStatus); - - /** - * Appends a Link Margin TLV to the message. - * - * @param[in] aLinkMargin The Link Margin value. - * - * @retval kErrorNone Successfully appended the Link Margin TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Link Margin TLV. - * - */ - Error AppendLinkMarginTlv(uint8_t aLinkMargin); - - /** - * Appends a Version TLV to the message. - * - * @retval kErrorNone Successfully appended the Version TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Version TLV. - * - */ - Error AppendVersionTlv(void); - - /** - * Appends an Address Registration TLV to the message. - * - * @param[in] aMode Determines which addresses to include in the TLV (see `AddressRegistrationMode`). - * - * @retval kErrorNone Successfully appended the Address Registration TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Address Registration TLV. - * - */ - Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses); - - /** - * Appends a Supervision Interval TLV to the message. - * - * @param[in] aInterval The interval value. - * - * @retval kErrorNone Successfully appended the Supervision Interval TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Supervision Interval TLV. - * - */ - Error AppendSupervisionIntervalTlv(uint16_t aInterval); - -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - /** - * Appends a Time Request TLV to the message. - * - * @retval kErrorNone Successfully appended the Time Request TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Time Request TLV. - * - */ - Error AppendTimeRequestTlv(void); - - /** - * Appends a Time Parameter TLV to the message. - * - * @retval kErrorNone Successfully appended the Time Parameter TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Time Parameter TLV. - * - */ - Error AppendTimeParameterTlv(void); -#endif - /** - * Appends a XTAL Accuracy TLV to the message. - * - * @retval kErrorNone Successfully appended the XTAL Accuracy TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the XTAl Accuracy TLV. - * - */ - Error AppendXtalAccuracyTlv(void); - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - /** - * Appends a CSL Channel TLV to the message. - * - * @retval kErrorNone Successfully appended the CSL Channel TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the CSL Channel TLV. - * - */ - Error AppendCslChannelTlv(void); - - /** - * Appends a CSL Sync Timeout TLV to the message. - * - * @retval kErrorNone Successfully appended the CSL Timeout TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the CSL Timeout TLV. - * - */ - Error AppendCslTimeoutTlv(void); -#endif - -#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - /** - * Appends a CSL Clock Accuracy TLV to the message. - * - * @retval kErrorNone Successfully appended the CSL Accuracy TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the CSL Accuracy TLV. - * - */ - Error AppendCslClockAccuracyTlv(void); -#endif - - /** - * Appends a Active Timestamp TLV to the message. - * - * @retval kErrorNone Successfully appended the Active Timestamp TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Active Timestamp TLV. - * - */ - Error AppendActiveTimestampTlv(void); - - /** - * Appends a Pending Timestamp TLV to the message. - * - * @retval kErrorNone Successfully appended the Pending Timestamp TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Pending Timestamp TLV. - * - */ - Error AppendPendingTimestampTlv(void); - -#if OPENTHREAD_FTD - /** - * Appends a Route TLV to the message. - * - * @param[in] aNeighbor A pointer to the intended destination (can be `nullptr`). - * - * @retval kErrorNone Successfully appended the Route TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Route TLV. - * - */ - Error AppendRouteTlv(Neighbor *aNeighbor = nullptr); - - /** - * Appends a Active Dataset TLV to the message. - * - * @retval kErrorNone Successfully appended the Active Dataset TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Active Dataset TLV. - * - */ - Error AppendActiveDatasetTlv(void); - - /** - * Appends a Pending Dataset TLV to the message. - * - * @retval kErrorNone Successfully appended the Pending Dataset TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Pending Dataset TLV. - * - */ - Error AppendPendingDatasetTlv(void); - - /** - * Appends a Connectivity TLV to the message. - * - * @retval kErrorNone Successfully appended the Connectivity TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Connectivity TLV. - * - */ - Error AppendConnectivityTlv(void); - - /** - * Appends a Address Registration TLV to the message with addresses from a given child. - * - * @param[in] aChild The child to include its list of addresses in the Address Registration TLV. - * - * @retval kErrorNone Successfully appended the Connectivity TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Connectivity TLV. - * - */ - Error AppendAddressRegistrationTlv(Child &aChild); -#endif // OPENTHREAD_FTD - - /** - * Submits the MLE message to the UDP socket to be sent. - * - * @param[in] aDestination A reference to the IPv6 address of the destination. - * - * @retval kErrorNone Successfully submitted the MLE message. - * @retval kErrorNoBufs Insufficient buffers to form the rest of the MLE message. - * - */ - Error SendTo(const Ip6::Address &aDestination); - - /** - * Enqueues the message to be sent after a given delay. - * - * @param[in] aDestination The IPv6 address of the recipient of the message. - * @param[in] aDelay The delay in milliseconds before transmission of the message. - * - * @retval kErrorNone Successfully queued the message to transmit after the delay. - * @retval kErrorNoBufs Insufficient buffers to queue the message. - * - */ - Error SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay); - - private: - Error AppendCompressedAddressEntry(uint8_t aContextId, const Ip6::Address &aAddress); - Error AppendAddressEntry(const Ip6::Address &aAddress); - }; - - /** - * Represents an MLE Rx message. - * - */ - class RxMessage : public Message - { - public: - /** - * Reads Challenge TLV from the message. - * - * @param[out] aChallenge A `RxChallenge` to output the read challenge data. - * - * @retval kErrorNone Successfully read the Challenge TLV. - * @retval kErrorNotFound Challenge TLV was not found in the message. - * @retval kErrorParse Challenge TLV was found but could not be parsed. - * - */ - Error ReadChallengeTlv(RxChallenge &aChallenge) const; - - /** - * Reads Response TLV from the message. - * - * @param[out] aResponse A `RxChallenge` to output the read challenge data. - * - * @retval kErrorNone Successfully read the Response TLV. - * @retval kErrorNotFound Response TLV was not found in the message. - * @retval kErrorParse Response TLV was found but could not be parsed. - * - */ - Error ReadResponseTlv(RxChallenge &aResponse) const; - - /** - * Reads Link and MLE Frame Counters from the message. - * - * Link Frame Counter TLV must be present in the message and its value is read into @p aLinkFrameCounter. If MLE - * Frame Counter TLV is present in the message, its value is read into @p aMleFrameCounter. If the MLE Frame - * Counter TLV is not present in the message, then @p aMleFrameCounter is set to the same value as - * @p aLinkFrameCounter. - * - * @param[out] aLinkFrameCounter A reference to an `uint32_t` to output the Link Frame Counter. - * @param[out] aMleFrameCounter A reference to an `uint32_t` to output the MLE Frame Counter. - * - * @retval kErrorNone Successfully read the counters. - * @retval kErrorNotFound Link Frame Counter TLV was not found in the message. - * @retval kErrorParse TLVs are not well-formed. - * - */ - Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const; - - /** - * Reads TLV Request TLV from the message. - * - * @param[out] aTlvList A reference to output the read list of requested TLVs. - * - * @retval kErrorNone Successfully read the TLV. - * @retval kErrorNotFound TLV was not found in the message. - * @retval kErrorParse TLV was found but could not be parsed. - * - */ - Error ReadTlvRequestTlv(TlvList &aTlvList) const; - - /** - * Reads Leader Data TLV from a message. - * - * @param[out] aLeaderData A reference to output the Leader Data. - * - * @retval kErrorNone Successfully read the TLV. - * @retval kErrorNotFound TLV was not found in the message. - * @retval kErrorParse TLV was found but could not be parsed. - * - */ - Error ReadLeaderDataTlv(LeaderData &aLeaderData) const; - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - /** - * Reads CSL Clock Accuracy TLV from a message. - * - * @param[out] aCslAccuracy A reference to output the CSL accuracy. - * - * @retval kErrorNone Successfully read the TLV. - * @retval kErrorNotFound TLV was not found in the message. - * @retval kErrorParse TLV was found but could not be parsed. - * - */ - Error ReadCslClockAccuracyTlv(Mac::CslAccuracy &aCslAccuracy) const; -#endif - -#if OPENTHREAD_FTD - /** - * Reads and validates Route TLV from a message. - * - * @param[out] aRouteTlv A reference to output the read Route TLV. - * - * @retval kErrorNone Successfully read and validated the Route TLV. - * @retval kErrorNotFound TLV was not found in the message. - * @retval kErrorParse TLV was found but could not be parsed or is not valid. - * - */ - Error ReadRouteTlv(RouteTlv &aRouteTlv) const; -#endif - - private: - Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const; - }; - - /** - * Represents a received MLE message containing additional information about the message (e.g. - * key sequence, neighbor from which it was received). - * - */ - struct RxInfo - { - /** - * Represents a received MLE message class. - * - */ - enum Class : uint8_t - { - kUnknown, ///< Unknown (default value, also indicates MLE message parse error). - kAuthoritativeMessage, ///< Authoritative message (larger received key seq MUST be adopted). - kPeerMessage, ///< Peer message (adopt only if from a known neighbor and is greater by one). - }; - - /** - * Initializes the `RxInfo`. - * - * @param[in] aMessage The received MLE message. - * @param[in] aMessageInfo The `Ip6::MessageInfo` associated with message. - * - */ - RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) - : mMessage(static_cast(aMessage)) - , mMessageInfo(aMessageInfo) - , mFrameCounter(0) - , mKeySequence(0) - , mNeighbor(nullptr) - , mClass(kUnknown) - { - } - - /** - * Indicates whether the `mNeighbor` (neighbor from which message was received) is non-null and - * in valid state. - * - * @retval TRUE If `mNeighbor` is non-null and in valid state. - * @retval FALSE If `mNeighbor` is `nullptr` or not in valid state. - * - */ - bool IsNeighborStateValid(void) const { return (mNeighbor != nullptr) && mNeighbor->IsStateValid(); } - - RxMessage &mMessage; ///< The MLE message. - const Ip6::MessageInfo &mMessageInfo; ///< The `MessageInfo` associated with the message. - uint32_t mFrameCounter; ///< The frame counter from aux security header. - uint32_t mKeySequence; ///< The key sequence from aux security header. - Neighbor *mNeighbor; ///< Neighbor from which message was received (can be `nullptr`). - Class mClass; ///< The message class (authoritative, peer, or unknown). - }; - - /** - * Allocates and initializes new MLE message for a given command. - * - * @param[in] aCommand The MLE command. - * - * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. - * - */ - TxMessage *NewMleMessage(Command aCommand); - - /** - * Sets the device role. - * - * @param[in] aRole A device role. - * - */ - void SetRole(DeviceRole aRole); - - /** - * Causes the Thread interface to attempt an MLE attach. - * - * @param[in] aMode Indicates what partitions to attach to. - * - */ - void Attach(AttachMode aMode); - - /** - * Sets the attach state - * - * @param[in] aState An attach state - * - */ - void SetAttachState(AttachState aState); - - /** - * Initializes a given @p aNeighbor with information from @p aRxInfo. - * - * Updates the following properties on @p aNeighbor from @p aRxInfo: - * - * - Sets the Extended MAC address from `MessageInfo` peer IPv6 address IID. - * - Clears the `GetLinkInfo()` and adds RSS from the `GetThreadLinkInfo()`. - * - Resets the link failure counter (`ResetLinkFailures()`). - * - Sets the "last heard" time to now (`SetLastHeard()`). - * - * @param[in,out] aNeighbor The `Neighbor` to initialize. - * @param[in] aRxInfo The `RxtInfo` to use for initialization. - * - */ - void InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo); - - /** - * Clears the parent candidate. - * - */ - void ClearParentCandidate(void) { mParentCandidate.Clear(); } - - /** - * Checks if the destination is reachable. - * - * @param[in] aMeshDest The RLOC16 of the destination. - * @param[in] aIp6Header The IPv6 header of the message. - * - * @retval kErrorNone The destination is reachable. - * @retval kErrorNoRoute The destination is not reachable and the message should be dropped. - * - */ - Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header); - - /** - * Returns the next hop towards an RLOC16 destination. - * - * @param[in] aDestination The RLOC16 of the destination. - * - * @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise. - * - */ - Mac::ShortAddress GetNextHop(uint16_t aDestination) const; - - /** - * Generates an MLE Data Request message. - * - * @param[in] aDestination The IPv6 destination address. - * - * @retval kErrorNone Successfully generated an MLE Data Request message. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message. - * - */ - Error SendDataRequest(const Ip6::Address &aDestination); - -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE - /** - * Generates an MLE Data Request message which request Link Metrics Report TLV. - * - * @param[in] aDestination A reference to the IPv6 address of the destination. - * @param[in] aQueryInfo A Link Metrics query info. - * - * @retval kErrorNone Successfully generated an MLE Data Request message. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message. - * - */ - Error SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, - const LinkMetrics::Initiator::QueryInfo &aQueryInfo); -#endif - - /** - * Generates an MLE Child Update Request message. - * - * @retval kErrorNone Successfully generated an MLE Child Update Request message. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Request message. - * - */ - Error SendChildUpdateRequest(void); - - /** - * Generates an MLE Child Update Response message. - * - * @param[in] aTlvList A list of requested TLV types. - * @param[in] aChallenge The challenge data to include in response. - * - * @retval kErrorNone Successfully generated an MLE Child Update Response message. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Response message. - * - */ - Error SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge); - - /** - * Sets the RLOC16 assigned to the Thread interface. - * - * @param[in] aRloc16 The RLOC16 to set. - * - */ - void SetRloc16(uint16_t aRloc16); - - /** - * Sets the Device State to Detached. - * - */ - void SetStateDetached(void); - - /** - * Sets the Device State to Child. - * - */ - void SetStateChild(uint16_t aRloc16); - - /** - * Sets the Leader's Partition ID, Weighting, and Router ID values. - * - * @param[in] aPartitionId The Leader's Partition ID value. - * @param[in] aWeighting The Leader's Weighting value. - * @param[in] aLeaderRouterId The Leader's Router ID value. - * - */ - void SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId); - -#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) - /** - * Emits a log message with an IPv6 address. - * - * @param[in] aAction The message action (send/receive/delay, etc). - * @param[in] aType The message type. - * @param[in] aAddress The IPv6 address of the peer. - * - */ - static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress); - - /** - * Emits a log message with an IPv6 address and RLOC16. - * - * @param[in] aAction The message action (send/receive/delay, etc). - * @param[in] aType The message type. - * @param[in] aAddress The IPv6 address of the peer. - * @param[in] aRloc The RLOC16. - * - */ - static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc); -#else - static void Log(MessageAction, MessageType, const Ip6::Address &) {} - static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {} -#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_INFO) - -#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) - /** - * Emits a log message indicating an error in processing of a message. - * - * Note that log message is emitted only if there is an error, i.e., @p aError is not `kErrorNone`. The log - * message will have the format "Failed to process {aMessageString} : {ErrorString}". - * - * @param[in] aType The message type. - * @param[in] aError The error in processing of the message. - * - */ - static void LogProcessError(MessageType aType, Error aError); - - /** - * Emits a log message indicating an error when sending a message. - * - * Note that log message is emitted only if there is an error, i.e. @p aError is not `kErrorNone`. The log - * message will have the format "Failed to send {Message Type} : {ErrorString}". - * - * @param[in] aType The message type. - * @param[in] aError The error in sending the message. - * - */ - static void LogSendError(MessageType aType, Error aError); -#else - static void LogProcessError(MessageType, Error) {} - static void LogSendError(MessageType, Error) {} -#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_WARN) - - /** - * Triggers MLE Announce on previous channel after the Thread device successfully - * attaches and receives the new Active Commissioning Dataset if needed. - * - * MTD would send Announce immediately after attached. - * FTD would delay to send Announce after tried to become Router or decided to stay in REED role. - * - */ - void InformPreviousChannel(void); - - /** - * Indicates whether or not in announce attach process. - * - * @retval true if attaching/attached on the announced parameters, false otherwise. - * - */ - bool IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; } - -#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) - /** - * Converts an `AttachMode` enumeration value into a human-readable string. - * - * @param[in] aMode An attach mode - * - * @returns A human-readable string corresponding to the attach mode. - * - */ - static const char *AttachModeToString(AttachMode aMode); - - /** - * Converts an `AttachState` enumeration value into a human-readable string. - * - * @param[in] aState An attach state - * - * @returns A human-readable string corresponding to the attach state. - * - */ - static const char *AttachStateToString(AttachState aState); - - /** - * Converts a `ReattachState` enumeration value into a human-readable string. - * - * @param[in] aState A reattach state - * - * @returns A human-readable string corresponding to the reattach state. - * - */ - static const char *ReattachStateToString(ReattachState aState); -#endif - -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE - /** - * Sends a Link Metrics Management Request message. - * - * @param[in] aDestination A reference to the IPv6 address of the destination. - * @param[in] aSubTlv A reference to the sub-TLV to include. - * - * @retval kErrorNone Successfully sent a Link Metrics Management Request. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message. - * - */ - Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv); - - /** - * Sends an MLE Link Probe message. - * - * @param[in] aDestination A reference to the IPv6 address of the destination. - * @param[in] aSeriesId The Series ID [1, 254] which the Probe message targets at. - * @param[in] aBuf A pointer to the data payload. - * @param[in] aLength The length of the data payload in Link Probe TLV, [0, 64]. - * - * @retval kErrorNone Successfully sent a Link Metrics Management Request. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message. - * @retval kErrorInvalidArgs Series ID is not a valid value, not within range [1, 254]. - * - */ - Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength); - -#endif - - void ScheduleMessageTransmissionTimer(void); - void ProcessKeySequence(RxInfo &aRxInfo); - private: - // Declare early so we can use in as `TimerMilli` callbacks. - void HandleAttachTimer(void); - void HandleDelayedResponseTimer(void); - void HandleMessageTransmissionTimer(void); + //------------------------------------------------------------------------------------------------------------------ + // Constants -protected: - using AttachTimer = TimerMilliIn; - using DelayTimer = TimerMilliIn; - using MsgTxTimer = TimerMilliIn; - - Ip6::Netif::UnicastAddress mLeaderAloc; ///< Leader anycast locator - - LeaderData mLeaderData; ///< Last received Leader Data TLV. - bool mRetrieveNewNetworkData : 1; ///< Indicating new Network Data is needed if set. - bool mRequestRouteTlv : 1; ///< Request Route TLV when sending Data Request. - DeviceRole mRole; ///< Current Thread role. - Parent mParent; ///< Parent information. - NeighborTable mNeighborTable; ///< The neighbor table. - DeviceMode mDeviceMode; ///< Device mode setting. - AttachState mAttachState; ///< The attach state. - uint8_t mParentRequestCounter; ///< Number of parent requests while in `kAttachStateParentRequest`. - ReattachState mReattachState; ///< Reattach state - uint16_t mAttachCounter; ///< Attach attempt counter. - uint16_t mAnnounceDelay; ///< Delay in between sending Announce messages during attach. - AttachTimer mAttachTimer; ///< The timer for driving the attach process. - DelayTimer mDelayedResponseTimer; ///< The timer to delay MLE responses. - MsgTxTimer mMessageTransmissionTimer; ///< The timer for (re-)sending of MLE messages (e.g. Child Update). -#if OPENTHREAD_FTD - uint8_t mLinkRequestAttempts; ///< Number of remaining link requests to send after reset. - bool mWasLeader; ///< Indicating if device was leader before reset. -#endif - -private: static constexpr uint8_t kMleHopLimit = 255; static constexpr uint8_t kMleSecurityTagSize = 4; // Security tag size in bytes. @@ -1753,6 +743,71 @@ private: static constexpr uint8_t kMaxIpAddressesToRegister = OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER; static constexpr uint32_t kDefaultCslTimeout = OPENTHREAD_CONFIG_CSL_TIMEOUT; + //------------------------------------------------------------------------------------------------------------------ + // Enumerations + + enum Command : uint8_t + { + kCommandLinkRequest = 0, + kCommandLinkAccept = 1, + kCommandLinkAcceptAndRequest = 2, + kCommandLinkReject = 3, + kCommandAdvertisement = 4, + kCommandUpdate = 5, + kCommandUpdateRequest = 6, + kCommandDataRequest = 7, + kCommandDataResponse = 8, + kCommandParentRequest = 9, + kCommandParentResponse = 10, + kCommandChildIdRequest = 11, + kCommandChildIdResponse = 12, + kCommandChildUpdateRequest = 13, + kCommandChildUpdateResponse = 14, + kCommandAnnounce = 15, + kCommandDiscoveryRequest = 16, + kCommandDiscoveryResponse = 17, + kCommandLinkMetricsManagementRequest = 18, + kCommandLinkMetricsManagementResponse = 19, + kCommandLinkProbe = 20, + kCommandTimeSync = 99, + }; + + enum AttachMode : uint8_t + { + kAnyPartition, // Attach to any Thread partition. + kSamePartition, // Attach to the same Thread partition (attempt 1 when losing connectivity). + kSamePartitionRetry, // Attach to the same Thread partition (attempt 2 when losing connectivity). + kBetterPartition, // Attach to a better (i.e. higher weight/partition id) Thread partition. + kDowngradeToReed, // Attach to the same Thread partition during downgrade process. + kBetterParent, // Attach to a better parent. + }; + + enum AttachState : uint8_t + { + kAttachStateIdle, // Not currently searching for a parent. + kAttachStateProcessAnnounce, // Waiting to process a received Announce (to switch channel/pan-id). + kAttachStateStart, // Starting to look for a parent. + kAttachStateParentRequest, // Send Parent Request (current number tracked by `mParentRequestCounter`). + kAttachStateAnnounce, // Send Announce messages + kAttachStateChildIdRequest, // Sending a Child ID Request message. + }; + + enum ReattachState : uint8_t + { + kReattachStop, // Reattach process is disabled or finished + kReattachStart, // Start reattach process + kReattachActive, // Reattach using stored Active Dataset + kReattachPending, // Reattach using stored Pending Dataset + }; + + static constexpr uint16_t kMleMaxResponseDelay = 1000u; // Max delay before responding to a multicast request. + + enum AddressRegistrationMode : uint8_t // Used by `AppendAddressRegistrationTlv()` + { + kAppendAllAddresses, // Append all addresses (unicast/multicast) in Address Registration TLV. + kAppendMeshLocalOnly, // Only append the Mesh Local (ML-EID) address in Address Registration TLV. + }; + enum StartMode : uint8_t // Used in `Start()`. { kNormalAttach, @@ -1803,6 +858,180 @@ private: kNoSecurity = 255, // Security suite value indicating that MLE message is secured. }; + enum MessageAction : uint8_t + { + kMessageSend, + kMessageReceive, + kMessageDelay, + kMessageRemoveDelayed, + }; + + enum MessageType : uint8_t + { + kTypeAdvertisement, + kTypeAnnounce, + kTypeChildIdRequest, + kTypeChildIdRequestShort, + kTypeChildIdResponse, + kTypeChildUpdateRequestOfParent, + kTypeChildUpdateResponseOfParent, + kTypeDataRequest, + kTypeDataResponse, + kTypeDiscoveryRequest, + kTypeDiscoveryResponse, + kTypeGenericDelayed, + kTypeGenericUdp, + kTypeParentRequestToRouters, + kTypeParentRequestToRoutersReeds, + kTypeParentResponse, +#if OPENTHREAD_FTD + kTypeAddressRelease, + kTypeAddressReleaseReply, + kTypeAddressReply, + kTypeAddressSolicit, + kTypeChildUpdateRequestOfChild, + kTypeChildUpdateResponseOfChild, + kTypeChildUpdateResponseOfUnknownChild, + kTypeLinkAccept, + kTypeLinkAcceptAndRequest, + kTypeLinkReject, + kTypeLinkRequest, + kTypeParentRequest, +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + kTypeTimeSync, +#endif +#endif +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + kTypeLinkMetricsManagementRequest, + kTypeLinkMetricsManagementResponse, + kTypeLinkProbe, +#endif + }; + + //------------------------------------------------------------------------------------------------------------------ + // Nested types + + static constexpr uint8_t kMaxTlvListSize = 32; // Maximum number of TLVs in a `TlvList`. + + class TlvList : public Array + { + public: + TlvList(void) = default; + + void Add(uint8_t aTlvType); + void AddElementsFrom(const TlvList &aTlvList); + }; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + class TxMessage : public Message + { + public: + Error AppendSourceAddressTlv(void); + Error AppendModeTlv(DeviceMode aMode); + Error AppendTimeoutTlv(uint32_t aTimeout); + Error AppendChallengeTlv(const TxChallenge &aChallenge); + Error AppendResponseTlv(const RxChallenge &aResponse); + Error AppendLinkFrameCounterTlv(void); + Error AppendMleFrameCounterTlv(void); + Error AppendAddress16Tlv(uint16_t aRloc16); + Error AppendNetworkDataTlv(NetworkData::Type aType); + Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength); + Error AppendLeaderDataTlv(void); + Error AppendScanMaskTlv(uint8_t aScanMask); + Error AppendStatusTlv(StatusTlv::Status aStatus); + Error AppendLinkMarginTlv(uint8_t aLinkMargin); + Error AppendVersionTlv(void); + Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses); + Error AppendSupervisionIntervalTlv(uint16_t aInterval); + Error AppendXtalAccuracyTlv(void); + Error AppendActiveTimestampTlv(void); + Error AppendPendingTimestampTlv(void); +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + Error AppendTimeRequestTlv(void); + Error AppendTimeParameterTlv(void); +#endif +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + Error AppendCslChannelTlv(void); + Error AppendCslTimeoutTlv(void); +#endif +#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE + Error AppendCslClockAccuracyTlv(void); +#endif +#if OPENTHREAD_FTD + Error AppendRouteTlv(Neighbor *aNeighbor = nullptr); + Error AppendActiveDatasetTlv(void); + Error AppendPendingDatasetTlv(void); + Error AppendConnectivityTlv(void); + Error AppendAddressRegistrationTlv(Child &aChild); +#endif + template Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength]) + { + return AppendTlvRequestTlv(aTlvArray, kArrayLength); + } + + Error SendTo(const Ip6::Address &aDestination); + Error SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay); + + private: + Error AppendCompressedAddressEntry(uint8_t aContextId, const Ip6::Address &aAddress); + Error AppendAddressEntry(const Ip6::Address &aAddress); + }; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + class RxMessage : public Message + { + public: + Error ReadChallengeTlv(RxChallenge &aChallenge) const; + Error ReadResponseTlv(RxChallenge &aResponse) const; + Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const; + Error ReadTlvRequestTlv(TlvList &aTlvList) const; + Error ReadLeaderDataTlv(LeaderData &aLeaderData) const; +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + Error ReadCslClockAccuracyTlv(Mac::CslAccuracy &aCslAccuracy) const; +#endif +#if OPENTHREAD_FTD + Error ReadRouteTlv(RouteTlv &aRouteTlv) const; +#endif + + private: + Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const; + }; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + struct RxInfo + { + enum Class : uint8_t + { + kUnknown, // Unknown (default value, also indicates MLE message parse error). + kAuthoritativeMessage, // Authoritative message (larger received key seq MUST be adopted). + kPeerMessage, // Peer message (adopt only if from a known neighbor and is greater by one). + }; + + RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) + : mMessage(static_cast(aMessage)) + , mMessageInfo(aMessageInfo) + , mFrameCounter(0) + , mKeySequence(0) + , mNeighbor(nullptr) + , mClass(kUnknown) + { + } + + bool IsNeighborStateValid(void) const { return (mNeighbor != nullptr) && mNeighbor->IsStateValid(); } + + RxMessage &mMessage; // The MLE message. + const Ip6::MessageInfo &mMessageInfo; // The `MessageInfo` associated with the message. + uint32_t mFrameCounter; // The frame counter from aux security header. + uint32_t mKeySequence; // The key sequence from aux security header. + Neighbor *mNeighbor; // Neighbor from which message was received (can be `nullptr`). + Class mClass; // The message class (authoritative, peer, or unknown). + }; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + struct DelayedResponseMetadata { Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } @@ -1813,6 +1042,8 @@ private: TimeMilli mSendTime; // Time when the message shall be sent. }; + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + OT_TOOL_PACKED_BEGIN class SecurityHeader { @@ -1840,6 +1071,8 @@ private: uint8_t mKeyIndex; } OT_TOOL_PACKED_END; + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class ParentCandidate : public Parent { public: @@ -1859,6 +1092,8 @@ private: bool mIsSingleton; }; + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE class ServiceAloc : public Ip6::Netif::UnicastAddress { @@ -1875,6 +1110,8 @@ private: }; #endif + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE void HandleParentSearchTimer(void) { mParentSearch.HandleTimer(); } @@ -1913,20 +1150,105 @@ private: }; #endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE - Error Start(StartMode aMode); - void Stop(StopMode aMode); - void HandleNotifierEvents(Events aEvents); - void SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata); + //------------------------------------------------------------------------------------------------------------------ + // Methods + static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); - void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - void ReestablishLinkWithNeighbor(Neighbor &aNeighbor); static void HandleDetachGracefullyTimer(Timer &aTimer); - void HandleDetachGracefullyTimer(void); - bool IsDetachingGracefully(void) { return mDetachGracefullyTimer.IsRunning(); } - Error SendChildUpdateRequest(ChildUpdateRequestMode aMode); - Error SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay); + + Error Start(StartMode aMode); + void Stop(StopMode aMode); + TxMessage *NewMleMessage(Command aCommand); + void SetRole(DeviceRole aRole); + void Attach(AttachMode aMode); + void SetAttachState(AttachState aState); + void InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo); + void ClearParentCandidate(void) { mParentCandidate.Clear(); } + Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header); + uint16_t GetNextHop(uint16_t aDestination) const; + Error SendDataRequest(const Ip6::Address &aDestination); + void HandleNotifierEvents(Events aEvents); + void SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata); + void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void ReestablishLinkWithNeighbor(Neighbor &aNeighbor); + void HandleDetachGracefullyTimer(void); + bool IsDetachingGracefully(void) { return mDetachGracefullyTimer.IsRunning(); } + Error SendChildUpdateRequest(ChildUpdateRequestMode aMode); + Error SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay); + Error SendChildUpdateRequest(void); + Error SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge); + void SetRloc16(uint16_t aRloc16); + void SetStateDetached(void); + void SetStateChild(uint16_t aRloc16); + void SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId); + void InformPreviousChannel(void); + bool IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; } + void ScheduleMessageTransmissionTimer(void); + void HandleAttachTimer(void); + void HandleDelayedResponseTimer(void); + void HandleMessageTransmissionTimer(void); + void ProcessKeySequence(RxInfo &aRxInfo); + void HandleAdvertisement(RxInfo &aRxInfo); + void HandleChildIdResponse(RxInfo &aRxInfo); + void HandleChildUpdateRequest(RxInfo &aRxInfo); + void HandleChildUpdateResponse(RxInfo &aRxInfo); + void HandleDataResponse(RxInfo &aRxInfo); + void HandleParentResponse(RxInfo &aRxInfo); + void HandleAnnounce(RxInfo &aRxInfo); + Error HandleLeaderData(RxInfo &aRxInfo); + void ProcessAnnounce(void); + bool HasUnregisteredAddress(void); + uint32_t GetAttachStartDelay(void) const; + void SendParentRequest(ParentRequestType aType); + Error SendChildIdRequest(void); + Error GetNextAnnounceChannel(uint8_t &aChannel) const; + bool HasMoreChannelsToAnnounce(void) const; + bool PrepareAnnounceState(void); + void SendAnnounce(uint8_t aChannel, AnnounceMode aMode); + void SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce); + uint32_t Reattach(void); + bool HasAcceptableParentCandidate(void) const; + Error DetermineParentRequestType(ParentRequestType &aType) const; + bool IsBetterParent(uint16_t aRloc16, + LinkQuality aLinkQuality, + uint8_t aLinkMargin, + const ConnectivityTlv &aConnectivityTlv, + uint16_t aVersion, + const Mac::CslAccuracy &aCslAccuracy); + bool IsNetworkDataNewer(const LeaderData &aLeaderData); + Error ProcessMessageSecurity(Crypto::AesCcm::Mode aMode, + Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + uint16_t aCmdOffset, + const SecurityHeader &aHeader); + void RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination); + void RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination); + +#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH + void InformPreviousParent(void); +#endif + +#if OPENTHREAD_CONFIG_UPTIME_ENABLE + void UpdateRoleTimeCounters(DeviceRole aRole); +#endif + +#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + ServiceAloc *FindInServiceAlocs(uint16_t aAloc16); + void UpdateServiceAlocs(void); +#endif + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + void HandleLinkMetricsManagementRequest(RxInfo &aRxInfo); + void HandleLinkProbe(RxInfo &aRxInfo); + Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus); +#endif #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + void HandleLinkMetricsManagementResponse(RxInfo &aRxInfo); + Error SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, + const LinkMetrics::Initiator::QueryInfo &aQueryInfo); + Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv); + Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength); Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, @@ -1936,70 +1258,18 @@ private: Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay); #endif -#if OPENTHREAD_FTD - static void HandleDetachGracefullyAddressReleaseResponse(void *aContext, - otMessage *aMessage, - const otMessageInfo *aMessageInfo, - Error aResult); - void HandleDetachGracefullyAddressReleaseResponse(void); +#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) + static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress); + static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc); +#else + static void Log(MessageAction, MessageType, const Ip6::Address &) {} + static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {} #endif - void HandleAdvertisement(RxInfo &aRxInfo); - void HandleChildIdResponse(RxInfo &aRxInfo); - void HandleChildUpdateRequest(RxInfo &aRxInfo); - void HandleChildUpdateResponse(RxInfo &aRxInfo); - void HandleDataResponse(RxInfo &aRxInfo); - void HandleParentResponse(RxInfo &aRxInfo); - void HandleAnnounce(RxInfo &aRxInfo); -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - void HandleLinkMetricsManagementRequest(RxInfo &aRxInfo); - void HandleLinkProbe(RxInfo &aRxInfo); -#endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE - void HandleLinkMetricsManagementResponse(RxInfo &aRxInfo); -#endif - Error HandleLeaderData(RxInfo &aRxInfo); - void ProcessAnnounce(void); - bool HasUnregisteredAddress(void); - - uint32_t GetAttachStartDelay(void) const; - void SendParentRequest(ParentRequestType aType); - Error SendChildIdRequest(void); - Error GetNextAnnounceChannel(uint8_t &aChannel) const; - bool HasMoreChannelsToAnnounce(void) const; - bool PrepareAnnounceState(void); - void SendAnnounce(uint8_t aChannel, AnnounceMode aMode); - void SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce); - void RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination); - void RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination); -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus); -#endif - uint32_t Reattach(void); - bool HasAcceptableParentCandidate(void) const; - Error DetermineParentRequestType(ParentRequestType &aType) const; - - bool IsBetterParent(uint16_t aRloc16, - LinkQuality aLinkQuality, - uint8_t aLinkMargin, - const ConnectivityTlv &aConnectivityTlv, - uint16_t aVersion, - const Mac::CslAccuracy &aCslAccuracy); - bool IsNetworkDataNewer(const LeaderData &aLeaderData); - - Error ProcessMessageSecurity(Crypto::AesCcm::Mode aMode, - Message &aMessage, - const Ip6::MessageInfo &aMessageInfo, - uint16_t aCmdOffset, - const SecurityHeader &aHeader); - -#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - ServiceAloc *FindInServiceAlocs(uint16_t aAloc16); - void UpdateServiceAlocs(void); -#endif - -#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH - void InformPreviousParent(void); +#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) + static const char *AttachModeToString(AttachMode aMode); + static const char *AttachStateToString(AttachState aState); + static const char *ReattachStateToString(ReattachState aState); #endif #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) @@ -2007,70 +1277,83 @@ private: static const char *MessageActionToString(MessageAction aAction); static const char *MessageTypeToString(MessageType aType); static const char *MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction); + static void LogProcessError(MessageType aType, Error aError); + static void LogSendError(MessageType aType, Error aError); +#else + static void LogProcessError(MessageType, Error) {} + static void LogSendError(MessageType, Error) {} #endif -#if OPENTHREAD_CONFIG_UPTIME_ENABLE - void UpdateRoleTimeCounters(DeviceRole aRole); -#endif + //------------------------------------------------------------------------------------------------------------------ + // Variables using DetachGracefullyTimer = TimerMilliIn; + using AttachTimer = TimerMilliIn; + using DelayTimer = TimerMilliIn; + using MsgTxTimer = TimerMilliIn; - MessageQueue mDelayedResponses; - - TxChallenge mParentRequestChallenge; - - AttachMode mAttachMode; - ParentCandidate mParentCandidate; + static const otMeshLocalPrefix kMeshLocalPrefixInit; + Ip6::Netif::UnicastAddress mLeaderAloc; + LeaderData mLeaderData; + bool mRetrieveNewNetworkData : 1; + bool mRequestRouteTlv : 1; + DeviceRole mRole; + Parent mParent; + NeighborTable mNeighborTable; + DeviceMode mDeviceMode; + AttachState mAttachState; + uint8_t mParentRequestCounter; + ReattachState mReattachState; + uint16_t mAttachCounter; + uint16_t mAnnounceDelay; + AttachTimer mAttachTimer; + DelayTimer mDelayedResponseTimer; + MsgTxTimer mMessageTransmissionTimer; +#if OPENTHREAD_FTD + uint8_t mLinkRequestAttempts; + bool mWasLeader; +#endif + MessageQueue mDelayedResponses; + TxChallenge mParentRequestChallenge; + AttachMode mAttachMode; + ParentCandidate mParentCandidate; uint8_t mChildUpdateAttempts; ChildUpdateRequestState mChildUpdateRequestState; uint8_t mDataRequestAttempts; DataRequestState mDataRequestState; - AddressRegistrationMode mAddressRegistrationMode; - - bool mHasRestored; - bool mReceivedResponseFromParent; - bool mInitiallyAttachedAsSleepy; - - Ip6::Udp::Socket mSocket; - uint32_t mTimeout; + bool mHasRestored; + bool mReceivedResponseFromParent; + bool mInitiallyAttachedAsSleepy; + Ip6::Udp::Socket mSocket; + uint32_t mTimeout; #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE uint32_t mCslTimeout; #endif - uint16_t mRloc16; uint16_t mPreviousParentRloc; - #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE ParentSearch mParentSearch; #endif - uint8_t mAnnounceChannel; uint8_t mAlternateChannel; uint16_t mAlternatePanId; uint64_t mAlternateTimestamp; - #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE ServiceAloc mServiceAlocs[kMaxServiceAlocs]; #endif - Counters mCounters; #if OPENTHREAD_CONFIG_UPTIME_ENABLE uint64_t mLastUpdatedTimestamp; #endif - - static const otMeshLocalPrefix sMeshLocalPrefixInit; - - Ip6::Netif::UnicastAddress mLinkLocal64; - Ip6::Netif::UnicastAddress mMeshLocal64; - Ip6::Netif::UnicastAddress mMeshLocal16; - Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes; - Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes; - + Ip6::Netif::UnicastAddress mLinkLocal64; + Ip6::Netif::UnicastAddress mMeshLocal64; + Ip6::Netif::UnicastAddress mMeshLocal16; + Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes; + Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes; DetachGracefullyTimer mDetachGracefullyTimer; Callback mDetachGracefullyCallback; - #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE Callback mParentResponseCallback; #endif