/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements MLE functionality required for the Thread Child, Router and Leader roles.
 */

#include "mle.hpp"

#include <openthread/platform/radio.h>
#include <openthread/platform/time.h>

#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/random.hpp"
#include "common/serial_number.hpp"
#include "common/settings.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "net/netif.hpp"
#include "net/udp6.hpp"
#include "thread/address_resolver.hpp"
#include "thread/key_manager.hpp"
#include "thread/link_metrics.hpp"
#include "thread/mle_router.hpp"
#include "thread/thread_netif.hpp"
#include "thread/time_sync_service.hpp"

using ot::Encoding::BigEndian::HostSwap16;

namespace ot {
namespace Mle {

RegisterLogModule("Mle");

Mle::Mle(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mRetrieveNewNetworkData(false)
    , mRole(kRoleDisabled)
    , mNeighborTable(aInstance)
    , mDeviceMode(DeviceMode::kModeRxOnWhenIdle)
    , mAttachState(kAttachStateIdle)
    , mReattachState(kReattachStop)
    , mAttachCounter(0)
    , mAnnounceDelay(kAnnounceTimeout)
    , mAttachTimer(aInstance, Mle::HandleAttachTimer)
    , mDelayedResponseTimer(aInstance, Mle::HandleDelayedResponseTimer)
    , mMessageTransmissionTimer(aInstance, Mle::HandleMessageTransmissionTimer)
    , mParentLeaderCost(0)
    , mAttachMode(kAnyPartition)
    , mParentPriority(0)
    , mParentLinkQuality3(0)
    , mParentLinkQuality2(0)
    , mParentLinkQuality1(0)
    , mParentSedBufferSize(0)
    , mParentSedDatagramCount(0)
    , mChildUpdateAttempts(0)
    , mChildUpdateRequestState(kChildUpdateRequestNone)
    , mDataRequestAttempts(0)
    , mDataRequestState(kDataRequestNone)
    , mAddressRegistrationMode(kAppendAllAddresses)
    , mHasRestored(false)
    , mParentLinkMargin(0)
    , mParentIsSingleton(false)
    , mReceivedResponseFromParent(false)
    , mSocket(aInstance)
    , mTimeout(kMleEndDeviceTimeout)
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    , mCslTimeout(OPENTHREAD_CONFIG_CSL_TIMEOUT)
#endif
    , mPreviousParentRloc(Mac::kShortAddrInvalid)
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
    , mParentSearchIsInBackoff(false)
    , mParentSearchBackoffWasCanceled(false)
    , mParentSearchRecentlyDetached(false)
    , mParentSearchBackoffCancelTime(0)
    , mParentSearchTimer(aInstance, Mle::HandleParentSearchTimer)
#endif
    , mAnnounceChannel(0)
    , mAlternateChannel(0)
    , mAlternatePanId(Mac::kPanIdBroadcast)
    , mAlternateTimestamp(0)
    , mParentResponseCb(nullptr)
    , mParentResponseCbContext(nullptr)
{
    MeshLocalPrefix meshLocalPrefix;

    mParent.Init(aInstance);
    mParentCandidate.Init(aInstance);

    mLeaderData.Clear();
    mParentLeaderData.Clear();
    mParent.Clear();
    mParentCandidate.Clear();
    ResetCounters();

    mLinkLocal64.InitAsThreadOrigin(/* aPreferred */ true);
    mLinkLocal64.GetAddress().SetToLinkLocalAddress(Get<Mac::Mac>().GetExtAddress());

    mLeaderAloc.InitAsThreadOriginRealmLocalScope();

    meshLocalPrefix.SetFromExtendedPanId(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId());

    mMeshLocal64.InitAsThreadOriginRealmLocalScope();
    mMeshLocal64.GetAddress().GetIid().GenerateRandom();

    mMeshLocal16.InitAsThreadOriginRealmLocalScope();
    mMeshLocal16.GetAddress().GetIid().SetToLocator(0);
    mMeshLocal16.mRloc = true;

    // Store RLOC address reference in MPL module.
    Get<Ip6::Mpl>().SetMatchingAddress(mMeshLocal16.GetAddress());

    mLinkLocalAllThreadNodes.Clear();
    mLinkLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff32);
    mLinkLocalAllThreadNodes.GetAddress().mFields.m16[7] = HostSwap16(0x0001);

    mRealmLocalAllThreadNodes.Clear();
    mRealmLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff33);
    mRealmLocalAllThreadNodes.GetAddress().mFields.m16[7] = HostSwap16(0x0001);

    SetMeshLocalPrefix(meshLocalPrefix);

    // `SetMeshLocalPrefix()` also adds the Mesh-Local EID and subscribes
    // to the Link- and Realm-Local All Thread Nodes multicast addresses.
}

Error Mle::Enable(void)
{
    Error error = kErrorNone;

    UpdateLinkLocalAddress();
    SuccessOrExit(error = mSocket.Open(&Mle::HandleUdpReceive, this));
    SuccessOrExit(error = mSocket.Bind(kUdpPort));

#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
    StartParentSearchTimer();
#endif
exit:
    return error;
}

void Mle::ScheduleChildUpdateRequest(void)
{
    mChildUpdateRequestState = kChildUpdateRequestPending;
    ScheduleMessageTransmissionTimer();
}

Error Mle::Disable(void)
{
    Error error = kErrorNone;

    Stop(kKeepNetworkDatasets);
    SuccessOrExit(error = mSocket.Close());
    Get<ThreadNetif>().RemoveUnicastAddress(mLinkLocal64);

exit:
    return error;
}

Error Mle::Start(StartMode aMode)
{
    Error error = kErrorNone;

    // cannot bring up the interface if IEEE 802.15.4 promiscuous mode is enabled
    VerifyOrExit(!Get<Radio>().GetPromiscuous(), error = kErrorInvalidState);
    VerifyOrExit(Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);

    if (Get<Mac::Mac>().GetPanId() == Mac::kPanIdBroadcast)
    {
        Get<Mac::Mac>().SetPanId(Mac::GenerateRandomPanId());
    }

    SetStateDetached();

    ApplyMeshLocalPrefix();
    SetRloc16(GetRloc16());

    mAttachCounter = 0;

    Get<KeyManager>().Start();

    if (aMode == kNormalAttach)
    {
        mReattachState = kReattachStart;
    }

    if ((aMode == kAnnounceAttach) || (GetRloc16() == Mac::kShortAddrInvalid))
    {
        Attach(kAnyPartition);
    }
#if OPENTHREAD_FTD
    else if (IsActiveRouter(GetRloc16()))
    {
        if (Get<MleRouter>().BecomeRouter(ThreadStatusTlv::kTooFewRouters) != kErrorNone)
        {
            Attach(kAnyPartition);
        }
    }
#endif
    else
    {
        mChildUpdateAttempts = 0;
        IgnoreError(SendChildUpdateRequest());
    }

exit:
    return error;
}

void Mle::Stop(StopMode aMode)
{
    if (aMode == kUpdateNetworkDatasets)
    {
        Get<MeshCoP::ActiveDatasetManager>().HandleDetach();
        Get<MeshCoP::PendingDatasetManager>().HandleDetach();
    }

    VerifyOrExit(!IsDisabled());

    Get<KeyManager>().Stop();
    SetStateDetached();
    Get<ThreadNetif>().UnsubscribeMulticast(mRealmLocalAllThreadNodes);
    Get<ThreadNetif>().UnsubscribeMulticast(mLinkLocalAllThreadNodes);
    Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal16);
    Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal64);

    SetRole(kRoleDisabled);

exit:
    return;
}

void Mle::SetRole(DeviceRole aRole)
{
    DeviceRole oldRole = mRole;

    SuccessOrExit(Get<Notifier>().Update(mRole, aRole, kEventThreadRoleChanged));

    LogNote("Role %s -> %s", RoleToString(oldRole), RoleToString(mRole));

    switch (mRole)
    {
    case kRoleDisabled:
        mCounters.mDisabledRole++;
        break;
    case kRoleDetached:
        mCounters.mDetachedRole++;
        break;
    case kRoleChild:
        mCounters.mChildRole++;
        break;
    case kRoleRouter:
        mCounters.mRouterRole++;
        break;
    case kRoleLeader:
        mCounters.mLeaderRole++;
        break;
    }

    // If the previous state is disabled, the parent can be in kStateRestored.
    if (!IsChild() && oldRole != kRoleDisabled)
    {
        mParent.SetState(Neighbor::kStateInvalid);
    }

exit:
    return;
}

void Mle::SetAttachState(AttachState aState)
{
    VerifyOrExit(aState != mAttachState);
    LogInfo("AttachState %s -> %s", AttachStateToString(mAttachState), AttachStateToString(aState));
    mAttachState = aState;

exit:
    return;
}

void Mle::Restore(void)
{
    Settings::NetworkInfo networkInfo;
    Settings::ParentInfo  parentInfo;

    IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
    IgnoreError(Get<MeshCoP::PendingDatasetManager>().Restore());

#if OPENTHREAD_CONFIG_DUA_ENABLE
    Get<DuaManager>().Restore();
#endif

    SuccessOrExit(Get<Settings>().Read(networkInfo));

    Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence());
    Get<KeyManager>().SetMleFrameCounter(networkInfo.GetMleFrameCounter());
    Get<KeyManager>().SetAllMacFrameCounters(networkInfo.GetMacFrameCounter());

#if OPENTHREAD_MTD
    mDeviceMode.Set(networkInfo.GetDeviceMode() & ~DeviceMode::kModeFullThreadDevice);
#else
    mDeviceMode.Set(networkInfo.GetDeviceMode());
#endif

    // force re-attach when version mismatch.
    VerifyOrExit(networkInfo.GetVersion() == kThreadVersion);

    switch (networkInfo.GetRole())
    {
    case kRoleChild:
    case kRoleRouter:
    case kRoleLeader:
        break;

    default:
        ExitNow();
    }

#if OPENTHREAD_MTD
    if (!IsActiveRouter(networkInfo.GetRloc16()))
#endif
    {
        Get<Mac::Mac>().SetShortAddress(networkInfo.GetRloc16());
    }
    Get<Mac::Mac>().SetExtAddress(networkInfo.GetExtAddress());

    mMeshLocal64.GetAddress().SetIid(networkInfo.GetMeshLocalIid());

    if (networkInfo.GetRloc16() == Mac::kShortAddrInvalid)
    {
        ExitNow();
    }

    if (!IsActiveRouter(networkInfo.GetRloc16()))
    {
        if (Get<Settings>().Read(parentInfo) != kErrorNone)
        {
            // If the restored RLOC16 corresponds to an end-device, it
            // is expected that the `ParentInfo` settings to be valid
            // as well. The device can still recover from such an invalid
            // setting by skipping the re-attach ("Child Update Request"
            // exchange) and going through the full attach process.

            LogWarn("Invalid settings - no saved parent info with valid end-device RLOC16 0x%04x",
                    networkInfo.GetRloc16());
            ExitNow();
        }

        mParent.Clear();
        mParent.SetExtAddress(parentInfo.GetExtAddress());
        mParent.SetVersion(static_cast<uint8_t>(parentInfo.GetVersion()));
        mParent.SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
                                         DeviceMode::kModeFullNetworkData));
        mParent.SetRloc16(Rloc16FromRouterId(RouterIdFromRloc16(networkInfo.GetRloc16())));
        mParent.SetState(Neighbor::kStateRestored);

        mPreviousParentRloc = mParent.GetRloc16();
    }
#if OPENTHREAD_FTD
    else
    {
        Get<MleRouter>().SetRouterId(RouterIdFromRloc16(GetRloc16()));
        Get<MleRouter>().SetPreviousPartitionId(networkInfo.GetPreviousPartitionId());
        Get<ChildTable>().Restore();
    }
#endif

    // Successfully restored the network information from non-volatile settings after boot.
    mHasRestored = true;

exit:
    return;
}

Error Mle::Store(void)
{
    Error                 error = kErrorNone;
    Settings::NetworkInfo networkInfo;

    networkInfo.Init();

    if (IsAttached())
    {
        // Only update network information while we are attached to
        // avoid losing/overwriting previous information when a reboot
        // occurs after a message is sent but before attaching.

        networkInfo.SetRole(mRole);
        networkInfo.SetRloc16(GetRloc16());
        networkInfo.SetPreviousPartitionId(mLeaderData.GetPartitionId());
        networkInfo.SetExtAddress(Get<Mac::Mac>().GetExtAddress());
        networkInfo.SetMeshLocalIid(mMeshLocal64.GetAddress().GetIid());
        networkInfo.SetVersion(kThreadVersion);

        if (IsChild())
        {
            Settings::ParentInfo parentInfo;

            parentInfo.Init();
            parentInfo.SetExtAddress(mParent.GetExtAddress());
            parentInfo.SetVersion(mParent.GetVersion());

            SuccessOrExit(error = Get<Settings>().Save(parentInfo));
        }
    }
    else
    {
        // When not attached, read out any previous saved `NetworkInfo`.
        // If there is none, it indicates that device was never attached
        // before. In that case, no need to save any info (note that on
        // a device reset the MLE/MAC frame counters would reset but
        // device also starts with a new randomly generated extended
        // address. If there is a previously saved `NetworkInfo`, we
        // just update the key sequence and MAC and MLE frame counters.

        SuccessOrExit(Get<Settings>().Read(networkInfo));
    }

    networkInfo.SetKeySequence(Get<KeyManager>().GetCurrentKeySequence());
    networkInfo.SetMleFrameCounter(Get<KeyManager>().GetMleFrameCounter() +
                                   OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD);
    networkInfo.SetMacFrameCounter(Get<KeyManager>().GetMaximumMacFrameCounter() +
                                   OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD);
    networkInfo.SetDeviceMode(mDeviceMode.Get());

    SuccessOrExit(error = Get<Settings>().Save(networkInfo));

    Get<KeyManager>().SetStoredMleFrameCounter(networkInfo.GetMleFrameCounter());
    Get<KeyManager>().SetStoredMacFrameCounter(networkInfo.GetMacFrameCounter());

    LogDebg("Store Network Information");

exit:
    return error;
}

Error Mle::BecomeDetached(void)
{
    Error error = kErrorNone;

    VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);

    // In case role is already detached and attach state is `kAttachStateStart`
    // (i.e., waiting to start an attach attempt), there is no need to make any
    // changes.

    VerifyOrExit(!IsDetached() || mAttachState != kAttachStateStart);

    // not in reattach stage after reset
    if (mReattachState == kReattachStop)
    {
        Get<MeshCoP::PendingDatasetManager>().HandleDetach();
    }

#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
    mParentSearchRecentlyDetached = true;
#endif

    SetStateDetached();
    mParent.SetState(Neighbor::kStateInvalid);
    SetRloc16(Mac::kShortAddrInvalid);
    Attach(kAnyPartition);

exit:
    return error;
}

Error Mle::BecomeChild(void)
{
    Error error = kErrorNone;

    VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
    VerifyOrExit(!IsAttaching(), error = kErrorBusy);

    Attach(kAnyPartition);

exit:
    return error;
}

void Mle::Attach(AttachMode aMode)
{
    VerifyOrExit(!IsDisabled() && !IsAttaching());

    if (!IsDetached())
    {
        mAttachCounter = 0;
    }

    if (mReattachState == kReattachStart)
    {
        if (Get<MeshCoP::ActiveDatasetManager>().Restore() == kErrorNone)
        {
            mReattachState = kReattachActive;
        }
        else
        {
            mReattachState = kReattachStop;
        }
    }

    mParentCandidate.Clear();
    SetAttachState(kAttachStateStart);
    mAttachMode = aMode;

    if (aMode != kBetterPartition)
    {
#if OPENTHREAD_FTD
        if (IsFullThreadDevice())
        {
            Get<MleRouter>().StopAdvertiseTrickleTimer();
        }
#endif
    }
    else
    {
        mCounters.mBetterPartitionAttachAttempts++;
    }

    mAttachTimer.Start(GetAttachStartDelay());

    if (IsDetached())
    {
        mAttachCounter++;

        if (mAttachCounter == 0)
        {
            mAttachCounter--;
        }

        mCounters.mAttachAttempts++;

        if (!IsRxOnWhenIdle())
        {
            Get<Mac::Mac>().SetRxOnWhenIdle(false);
        }
    }

exit:
    return;
}

uint32_t Mle::GetAttachStartDelay(void) const
{
    uint32_t delay = 1;
    uint32_t jitter;

    VerifyOrExit(IsDetached());

    if (mAttachCounter == 0)
    {
        delay = 1 + Random::NonCrypto::GetUint32InRange(0, kParentRequestRouterTimeout);
        ExitNow();
    }
#if OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_ENABLE
    else
    {
        uint16_t       counter = mAttachCounter - 1;
        const uint32_t ratio   = kAttachBackoffMaxInterval / kAttachBackoffMinInterval;

        if ((counter < sizeof(ratio) * CHAR_BIT) && ((1UL << counter) <= ratio))
        {
            delay = kAttachBackoffMinInterval;
            delay <<= counter;
        }
        else
        {
            delay = Random::NonCrypto::AddJitter(kAttachBackoffMaxInterval, kAttachBackoffJitter);
        }
    }
#endif // OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_ENABLE

    jitter = Random::NonCrypto::GetUint32InRange(0, kAttachStartJitter);

    if (jitter + delay > delay) // check for overflow
    {
        delay += jitter;
    }

    LogNote("Attach attempt %d unsuccessful, will try again in %u.%03u seconds", mAttachCounter, delay / 1000,
            delay % 1000);

exit:
    return delay;
}

bool Mle::IsAttached(void) const
{
    return (IsChild() || IsRouter() || IsLeader());
}

bool Mle::IsRouterOrLeader(void) const
{
    return (IsRouter() || IsLeader());
}

void Mle::SetStateDetached(void)
{
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    if (Get<Mac::Mac>().IsCslEnabled())
    {
        IgnoreError(Get<Radio>().EnableCsl(0, GetParent().GetRloc16(), &GetParent().GetExtAddress()));
    }
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
    Get<BackboneRouter::Local>().Reset();
#endif
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
    Get<BackboneRouter::Leader>().Reset();
#endif

    if (IsLeader())
    {
        Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);
    }

    SetRole(kRoleDetached);
    SetAttachState(kAttachStateIdle);
    mAttachTimer.Stop();
    mMessageTransmissionTimer.Stop();
    mChildUpdateRequestState = kChildUpdateRequestNone;
    mChildUpdateAttempts     = 0;
    mDataRequestState        = kDataRequestNone;
    mDataRequestAttempts     = 0;
    Get<MeshForwarder>().SetRxOnWhenIdle(true);
    Get<Mac::Mac>().SetBeaconEnabled(false);
#if OPENTHREAD_FTD
    Get<MleRouter>().HandleDetachStart();
#endif
    Get<Ip6::Ip6>().SetForwardingEnabled(false);
#if OPENTHREAD_FTD
    Get<Ip6::Mpl>().SetTimerExpirations(0);
#endif
}

void Mle::SetStateChild(uint16_t aRloc16)
{
    if (IsLeader())
    {
        Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);
    }

    SetRloc16(aRloc16);
    SetRole(kRoleChild);
    SetAttachState(kAttachStateIdle);
    mAttachTimer.Start(kAttachBackoffDelayToResetCounter);
    mReattachState       = kReattachStop;
    mChildUpdateAttempts = 0;
    mDataRequestAttempts = 0;
    Get<Mac::Mac>().SetBeaconEnabled(false);
    ScheduleMessageTransmissionTimer();

#if OPENTHREAD_FTD
    if (IsFullThreadDevice())
    {
        Get<MleRouter>().HandleChildStart(mAttachMode);
    }
#endif

    Get<Ip6::Ip6>().SetForwardingEnabled(false);
#if OPENTHREAD_FTD
    Get<Ip6::Mpl>().SetTimerExpirations(kMplChildDataMessageTimerExpirations);
#endif

    // send announce after attached if needed
    InformPreviousChannel();

#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
    UpdateParentSearchState();
#endif

    if ((mPreviousParentRloc != Mac::kShortAddrInvalid) && (mPreviousParentRloc != mParent.GetRloc16()))
    {
        mCounters.mParentChanges++;

#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
        InformPreviousParent();
#endif
    }

    mPreviousParentRloc = mParent.GetRloc16();

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    if (Get<Mac::Mac>().IsCslCapable())
    {
        uint32_t period = IsRxOnWhenIdle() ? 0 : Get<Mac::Mac>().GetCslPeriod();
        IgnoreError(Get<Radio>().EnableCsl(period, GetParent().GetRloc16(), &GetParent().GetExtAddress()));
        ScheduleChildUpdateRequest();
    }
#endif
}

void Mle::InformPreviousChannel(void)
{
    VerifyOrExit(mAlternatePanId != Mac::kPanIdBroadcast);
    VerifyOrExit(IsChild() || IsRouter());

#if OPENTHREAD_FTD
    VerifyOrExit(!IsFullThreadDevice() || IsRouter() || Get<MleRouter>().GetRouterSelectionJitterTimeout() == 0);
#endif

    mAlternatePanId = Mac::kPanIdBroadcast;
    Get<AnnounceBeginServer>().SendAnnounce(1 << mAlternateChannel);

exit:
    return;
}

void Mle::SetTimeout(uint32_t aTimeout)
{
    VerifyOrExit(mTimeout != aTimeout);

    if (aTimeout < kMinTimeout)
    {
        aTimeout = kMinTimeout;
    }

    mTimeout = aTimeout;

    Get<DataPollSender>().RecalculatePollPeriod();

    if (IsChild())
    {
        IgnoreError(SendChildUpdateRequest());
    }

exit:
    return;
}

Error Mle::SetDeviceMode(DeviceMode aDeviceMode)
{
    Error      error   = kErrorNone;
    DeviceMode oldMode = mDeviceMode;

#if OPENTHREAD_MTD
    VerifyOrExit(!aDeviceMode.IsFullThreadDevice(), error = kErrorInvalidArgs);
#endif

    VerifyOrExit(aDeviceMode.IsValid(), error = kErrorInvalidArgs);
    VerifyOrExit(mDeviceMode != aDeviceMode);
    mDeviceMode = aDeviceMode;

#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
    Get<Utils::HistoryTracker>().RecordNetworkInfo();
#endif

#if OPENTHREAD_CONFIG_OTNS_ENABLE
    Get<Utils::Otns>().EmitDeviceMode(mDeviceMode);
#endif

    LogNote("Mode 0x%02x -> 0x%02x [%s]", oldMode.Get(), mDeviceMode.Get(), mDeviceMode.ToString().AsCString());

    IgnoreError(Store());

    switch (mRole)
    {
    case kRoleDisabled:
        break;

    case kRoleDetached:
        mAttachCounter = 0;
        SetStateDetached();
        Attach(kAnyPartition);
        break;

    case kRoleChild:
        SetStateChild(GetRloc16());
        IgnoreError(SendChildUpdateRequest());
        break;

    case kRoleRouter:
    case kRoleLeader:
        if (oldMode.IsFullThreadDevice() && !mDeviceMode.IsFullThreadDevice())
        {
            IgnoreError(BecomeDetached());
        }

        break;
    }

exit:
    return error;
}

void Mle::UpdateLinkLocalAddress(void)
{
    Get<ThreadNetif>().RemoveUnicastAddress(mLinkLocal64);
    mLinkLocal64.GetAddress().GetIid().SetFromExtAddress(Get<Mac::Mac>().GetExtAddress());
    Get<ThreadNetif>().AddUnicastAddress(mLinkLocal64);

    Get<Notifier>().Signal(kEventThreadLinkLocalAddrChanged);
}

void Mle::SetMeshLocalPrefix(const MeshLocalPrefix &aMeshLocalPrefix)
{
    VerifyOrExit(GetMeshLocalPrefix() != aMeshLocalPrefix,
                 Get<Notifier>().SignalIfFirst(kEventThreadMeshLocalAddrChanged));

    if (Get<ThreadNetif>().IsUp())
    {
        Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);

        // We must remove the old addresses before adding the new ones.
        Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal64);
        Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal16);
        Get<ThreadNetif>().UnsubscribeMulticast(mLinkLocalAllThreadNodes);
        Get<ThreadNetif>().UnsubscribeMulticast(mRealmLocalAllThreadNodes);
    }

    mMeshLocal64.GetAddress().SetPrefix(aMeshLocalPrefix);
    mMeshLocal16.GetAddress().SetPrefix(aMeshLocalPrefix);
    mLeaderAloc.GetAddress().SetPrefix(aMeshLocalPrefix);

    // Just keep mesh local prefix if network interface is down
    VerifyOrExit(Get<ThreadNetif>().IsUp());

    ApplyMeshLocalPrefix();

exit:
    return;
}

#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
Error Mle::SetMeshLocalIid(const Ip6::InterfaceIdentifier &aMlIid)
{
    Error error = kErrorNone;

    VerifyOrExit(!Get<ThreadNetif>().HasUnicastAddress(mMeshLocal64), error = kErrorInvalidState);

    mMeshLocal64.GetAddress().SetIid(aMlIid);
exit:
    return error;
}
#endif

void Mle::ApplyMeshLocalPrefix(void)
{
    mLinkLocalAllThreadNodes.GetAddress().SetMulticastNetworkPrefix(GetMeshLocalPrefix());
    mRealmLocalAllThreadNodes.GetAddress().SetMulticastNetworkPrefix(GetMeshLocalPrefix());

    VerifyOrExit(!IsDisabled());

    // Add the addresses back into the table.
    Get<ThreadNetif>().AddUnicastAddress(mMeshLocal64);
    Get<ThreadNetif>().SubscribeMulticast(mLinkLocalAllThreadNodes);
    Get<ThreadNetif>().SubscribeMulticast(mRealmLocalAllThreadNodes);

    if (IsAttached())
    {
        Get<ThreadNetif>().AddUnicastAddress(mMeshLocal16);
    }

    // update Leader ALOC
    if (IsLeader())
    {
        Get<ThreadNetif>().AddUnicastAddress(mLeaderAloc);
    }

#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
    Get<MeshCoP::Commissioner>().ApplyMeshLocalPrefix();
#endif

#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
    Get<MeshCoP::BorderAgent>().ApplyMeshLocalPrefix();
#endif

#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
    Get<Dhcp6::Server>().ApplyMeshLocalPrefix();
#endif

#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
    Get<NeighborDiscovery::Agent>().ApplyMeshLocalPrefix();
#endif

#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
    for (ServiceAloc &serviceAloc : mServiceAlocs)
    {
        if (serviceAloc.IsInUse())
        {
            Get<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
        }

        serviceAloc.ApplyMeshLocalPrefix(GetMeshLocalPrefix());

        if (serviceAloc.IsInUse())
        {
            Get<ThreadNetif>().AddUnicastAddress(serviceAloc);
        }
    }
#endif

#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
    Get<BackboneRouter::Local>().ApplyMeshLocalPrefix();
#endif

exit:
    // Changing the prefix also causes the mesh local address to be different.
    Get<Notifier>().Signal(kEventThreadMeshLocalAddrChanged);
}

uint16_t Mle::GetRloc16(void) const
{
    return Get<Mac::Mac>().GetShortAddress();
}

void Mle::SetRloc16(uint16_t aRloc16)
{
    uint16_t oldRloc16 = GetRloc16();

    if (aRloc16 != oldRloc16)
    {
        LogNote("RLOC16 %04x -> %04x", oldRloc16, aRloc16);
    }

    if (Get<ThreadNetif>().HasUnicastAddress(mMeshLocal16) &&
        (mMeshLocal16.GetAddress().GetIid().GetLocator() != aRloc16))
    {
        Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal16);
        Get<Tmf::Agent>().ClearRequests(mMeshLocal16.GetAddress());
    }

    Get<Mac::Mac>().SetShortAddress(aRloc16);
    Get<Ip6::Mpl>().SetSeedId(aRloc16);

    if (aRloc16 != Mac::kShortAddrInvalid)
    {
        // We can always call `AddUnicastAddress(mMeshLocat16)` and if
        // the address is already added, it will perform no action.

        mMeshLocal16.GetAddress().GetIid().SetLocator(aRloc16);
        Get<ThreadNetif>().AddUnicastAddress(mMeshLocal16);
#if OPENTHREAD_FTD
        Get<AddressResolver>().RestartAddressQueries();
#endif
    }
}

void Mle::SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId)
{
    if (mLeaderData.GetPartitionId() != aPartitionId)
    {
#if OPENTHREAD_FTD
        Get<MleRouter>().HandlePartitionChange();
#endif
        Get<Notifier>().Signal(kEventThreadPartitionIdChanged);
        mCounters.mPartitionIdChanges++;
    }
    else
    {
        Get<Notifier>().SignalIfFirst(kEventThreadPartitionIdChanged);
    }

    mLeaderData.SetPartitionId(aPartitionId);
    mLeaderData.SetWeighting(aWeighting);
    mLeaderData.SetLeaderRouterId(aLeaderRouterId);
}

Error Mle::GetLeaderAddress(Ip6::Address &aAddress) const
{
    Error error = kErrorNone;

    VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);

    aAddress.SetToRoutingLocator(GetMeshLocalPrefix(), Rloc16FromRouterId(mLeaderData.GetLeaderRouterId()));

exit:
    return error;
}

Error Mle::GetLocatorAddress(Ip6::Address &aAddress, uint16_t aLocator) const
{
    Error error = kErrorNone;

    VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);

    memcpy(&aAddress, &mMeshLocal16.GetAddress(), 14);
    aAddress.GetIid().SetLocator(aLocator);

exit:
    return error;
}

Error Mle::GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const
{
    Error error = kErrorNone;

    VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);
    aAddress.SetToAnycastLocator(GetMeshLocalPrefix(), ServiceAlocFromId(aServiceId));

exit:
    return error;
}

const LeaderData &Mle::GetLeaderData(void)
{
    mLeaderData.SetDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet));
    mLeaderData.SetStableDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kStableSubset));

    return mLeaderData;
}

Message *Mle::NewMleMessage(Command aCommand)
{
    Error             error = kErrorNone;
    Message *         message;
    Message::Settings settings(Message::kNoLinkSecurity, Message::kPriorityNet);
    Message::SubType  subType;
    uint8_t           securitySuite;

    message = mSocket.NewMessage(0, settings);
    VerifyOrExit(message != nullptr, error = kErrorNoBufs);

    securitySuite = k154Security;
    subType       = Message::kSubTypeMleGeneral;

    switch (aCommand)
    {
    case kCommandAnnounce:
        subType = Message::kSubTypeMleAnnounce;
        break;

    case kCommandDiscoveryRequest:
        subType       = Message::kSubTypeMleDiscoverRequest;
        securitySuite = kNoSecurity;
        break;

    case kCommandDiscoveryResponse:
        subType       = Message::kSubTypeMleDiscoverResponse;
        securitySuite = kNoSecurity;
        break;

    case kCommandChildUpdateRequest:
        subType = Message::kSubTypeMleChildUpdateRequest;
        break;

    case kCommandDataResponse:
        subType = Message::kSubTypeMleDataResponse;
        break;

    case kCommandChildIdRequest:
        subType = Message::kSubTypeMleChildIdRequest;
        break;

    case kCommandDataRequest:
        subType = Message::kSubTypeMleDataRequest;
        break;

    default:
        break;
    }

    message->SetSubType(subType);

    SuccessOrExit(error = message->Append(securitySuite));

    if (securitySuite == k154Security)
    {
        SecurityHeader securityHeader;

        // The other fields in security header are updated in the
        // message in `SendMessage()` before message is sent.

        securityHeader.InitSecurityControl();
        SuccessOrExit(error = message->Append(securityHeader));
    }

    error = message->Append<uint8_t>(aCommand);

exit:
    FreeAndNullMessageOnError(message, error);
    return message;
}

Error Mle::AppendSourceAddress(Message &aMessage) const
{
    return Tlv::Append<SourceAddressTlv>(aMessage, GetRloc16());
}

Error Mle::AppendStatus(Message &aMessage, StatusTlv::Status aStatus)
{
    return Tlv::Append<StatusTlv>(aMessage, aStatus);
}

Error Mle::AppendMode(Message &aMessage, DeviceMode aMode)
{
    return Tlv::Append<ModeTlv>(aMessage, aMode.Get());
}

Error Mle::AppendTimeout(Message &aMessage, uint32_t aTimeout)
{
    return Tlv::Append<TimeoutTlv>(aMessage, aTimeout);
}

Error Mle::AppendChallenge(Message &aMessage, const Challenge &aChallenge)
{
    return Tlv::Append<ChallengeTlv>(aMessage, aChallenge.mBuffer, aChallenge.mLength);
}

Error Mle::AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength)
{
    return Tlv::Append<ChallengeTlv>(aMessage, aChallenge, aChallengeLength);
}

Error Mle::AppendResponse(Message &aMessage, const Challenge &aResponse)
{
    return Tlv::Append<ResponseTlv>(aMessage, aResponse.mBuffer, aResponse.mLength);
}

Error Mle::ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer)
{
    Error    error;
    uint16_t offset;
    uint16_t length;

    SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, aTlvType, offset, length));
    VerifyOrExit(length >= kMinChallengeSize, error = kErrorParse);

    if (length > kMaxChallengeSize)
    {
        length = kMaxChallengeSize;
    }

    aMessage.ReadBytes(offset, aBuffer.mBuffer, length);
    aBuffer.mLength = static_cast<uint8_t>(length);

exit:
    return error;
}

Error Mle::ReadChallenge(const Message &aMessage, Challenge &aChallenge)
{
    return ReadChallengeOrResponse(aMessage, Tlv::kChallenge, aChallenge);
}

Error Mle::ReadResponse(const Message &aMessage, Challenge &aResponse)
{
    return ReadChallengeOrResponse(aMessage, Tlv::kResponse, aResponse);
}

Error Mle::AppendLinkFrameCounter(Message &aMessage)
{
    uint32_t counter;

    // When including Link-layer Frame Counter TLV in an MLE message
    // the value is set to the maximum MAC frame counter on all
    // supported radio links. All radio links must also start using
    // the same counter value as the value included in the TLV.

    counter = Get<KeyManager>().GetMaximumMacFrameCounter();

#if OPENTHREAD_CONFIG_MULTI_RADIO
    Get<KeyManager>().SetAllMacFrameCounters(counter);
#endif

    return Tlv::Append<LinkFrameCounterTlv>(aMessage, counter);
}

Error Mle::AppendMleFrameCounter(Message &aMessage)
{
    return Tlv::Append<MleFrameCounterTlv>(aMessage, Get<KeyManager>().GetMleFrameCounter());
}

Error Mle::ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const
{
    Error error;

    SuccessOrExit(error = Tlv::Find<LinkFrameCounterTlv>(aMessage, aLinkFrameCounter));

    switch (Tlv::Find<MleFrameCounterTlv>(aMessage, aMleFrameCounter))
    {
    case kErrorNone:
        break;
    case kErrorNotFound:
        aMleFrameCounter = aLinkFrameCounter;
        break;
    default:
        error = kErrorParse;
        break;
    }

exit:
    return error;
}

Error Mle::AppendAddress16(Message &aMessage, uint16_t aRloc16)
{
    return Tlv::Append<Address16Tlv>(aMessage, aRloc16);
}

Error Mle::AppendLeaderData(Message &aMessage)
{
    LeaderDataTlv leaderDataTlv;

    mLeaderData.SetDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet));
    mLeaderData.SetStableDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kStableSubset));

    leaderDataTlv.Init();
    leaderDataTlv.Set(mLeaderData);

    return leaderDataTlv.AppendTo(aMessage);
}

Error Mle::ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData)
{
    Error         error;
    LeaderDataTlv leaderDataTlv;

    SuccessOrExit(error = Tlv::FindTlv(aMessage, leaderDataTlv));
    VerifyOrExit(leaderDataTlv.IsValid(), error = kErrorParse);
    leaderDataTlv.Get(aLeaderData);

exit:
    return error;
}

Error Mle::AppendNetworkData(Message &aMessage, NetworkData::Type aType)
{
    Error   error = kErrorNone;
    uint8_t networkData[NetworkData::NetworkData::kMaxSize];
    uint8_t length;

    VerifyOrExit(!mRetrieveNewNetworkData, error = kErrorInvalidState);

    length = sizeof(networkData);
    IgnoreError(Get<NetworkData::Leader>().CopyNetworkData(aType, networkData, length));

    error = Tlv::Append<NetworkDataTlv>(aMessage, networkData, length);

exit:
    return error;
}

Error Mle::AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength)
{
    return Tlv::Append<TlvRequestTlv>(aMessage, aTlvs, aTlvsLength);
}

Error Mle::FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs)
{
    Error    error;
    uint16_t offset;
    uint16_t length;

    SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kTlvRequest, offset, length));

    if (length > sizeof(aRequestedTlvs.mTlvs))
    {
        length = sizeof(aRequestedTlvs.mTlvs);
    }

    aMessage.ReadBytes(offset, aRequestedTlvs.mTlvs, length);
    aRequestedTlvs.mNumTlvs = static_cast<uint8_t>(length);

exit:
    return error;
}

Error Mle::AppendScanMask(Message &aMessage, uint8_t aScanMask)
{
    return Tlv::Append<ScanMaskTlv>(aMessage, aScanMask);
}

Error Mle::AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin)
{
    return Tlv::Append<LinkMarginTlv>(aMessage, aLinkMargin);
}

Error Mle::AppendVersion(Message &aMessage)
{
    return Tlv::Append<VersionTlv>(aMessage, kThreadVersion);
}

bool Mle::HasUnregisteredAddress(void)
{
    bool retval = false;

    // Checks whether there are any addresses in addition to the mesh-local
    // address that need to be registered.

    for (const Ip6::Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
    {
        if (!addr.GetAddress().IsLinkLocal() && !IsRoutingLocator(addr.GetAddress()) &&
            !IsAnycastLocator(addr.GetAddress()) && addr.GetAddress() != GetMeshLocal64())
        {
            ExitNow(retval = true);
        }
    }

    if (!IsRxOnWhenIdle())
    {
        // For sleepy end-device, we register any external multicast
        // addresses.

        retval = Get<ThreadNetif>().HasAnyExternalMulticastAddress();
    }

exit:
    return retval;
}

Error Mle::AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode)
{
    Error                    error = kErrorNone;
    Tlv                      tlv;
    AddressRegistrationEntry entry;
    Lowpan::Context          context;
    uint8_t                  length      = 0;
    uint8_t                  counter     = 0;
    uint16_t                 startOffset = aMessage.GetLength();
#if OPENTHREAD_CONFIG_DUA_ENABLE
    Ip6::Address domainUnicastAddress;
#endif

    tlv.SetType(Tlv::kAddressRegistration);
    SuccessOrExit(error = aMessage.Append(tlv));

    // Prioritize ML-EID
    entry.SetContextId(kMeshLocalPrefixContextId);
    entry.SetIid(GetMeshLocal64().GetIid());
    SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
    length += entry.GetLength();

    // Continue to append the other addresses if not `kAppendMeshLocalOnly` mode
    VerifyOrExit(aMode != kAppendMeshLocalOnly);
    counter++;

#if OPENTHREAD_CONFIG_DUA_ENABLE
    // Cache Domain Unicast Address.
    domainUnicastAddress = Get<DuaManager>().GetDomainUnicastAddress();

    if (Get<ThreadNetif>().HasUnicastAddress(domainUnicastAddress))
    {
        SuccessOrAssert(Get<NetworkData::Leader>().GetContext(domainUnicastAddress, context));

        // Prioritize DUA, compressed entry
        entry.SetContextId(context.mContextId);
        entry.SetIid(domainUnicastAddress.GetIid());
        SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
        length += entry.GetLength();
        counter++;
    }
#endif // OPENTHREAD_CONFIG_DUA_ENABLE

    for (const Ip6::Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
    {
        if (addr.GetAddress().IsLinkLocal() || IsRoutingLocator(addr.GetAddress()) ||
            IsAnycastLocator(addr.GetAddress()) || addr.GetAddress() == GetMeshLocal64())
        {
            continue;
        }

#if OPENTHREAD_CONFIG_DUA_ENABLE
        // Skip DUA that was already appended above.
        if (addr.GetAddress() == domainUnicastAddress)
        {
            continue;
        }
#endif

        if (Get<NetworkData::Leader>().GetContext(addr.GetAddress(), context) == kErrorNone)
        {
            // compressed entry
            entry.SetContextId(context.mContextId);
            entry.SetIid(addr.GetAddress().GetIid());
        }
        else
        {
            // uncompressed entry
            entry.SetUncompressed();
            entry.SetIp6Address(addr.GetAddress());
        }

        SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
        length += entry.GetLength();
        counter++;
        // only continue to append if there is available entry.
        VerifyOrExit(counter < OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER);
    }

    // Append external multicast addresses.  For sleepy end device,
    // register all external multicast addresses with the parent for
    // indirect transmission. Since Thread 1.2, non-sleepy MED should
    // also register external multicast addresses of scope larger than
    // realm with a 1.2 or higher parent.
    if (!IsRxOnWhenIdle()
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
        || !GetParent().IsThreadVersion1p1()
#endif
    )
    {
        for (const Ip6::Netif::MulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses())
        {
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
            // For Thread 1.2 MED, skip multicast address with scope not
            // larger than realm local when registering.
            if (IsRxOnWhenIdle() && !addr.GetAddress().IsMulticastLargerThanRealmLocal())
            {
                continue;
            }
#endif

            entry.SetUncompressed();
            entry.SetIp6Address(addr.GetAddress());
            SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
            length += entry.GetLength();

            counter++;
            // only continue to append if there is available entry.
            VerifyOrExit(counter < OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER);
        }
    }

exit:

    if (error == kErrorNone && length > 0)
    {
        tlv.SetLength(length);
        aMessage.Write(startOffset, tlv);
    }

    return error;
}

#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Error Mle::AppendTimeRequest(Message &aMessage)
{
    // `TimeRequestTlv` has no value.
    return Tlv::Append<TimeRequestTlv>(aMessage, nullptr, 0);
}

Error Mle::AppendTimeParameter(Message &aMessage)
{
    TimeParameterTlv tlv;

    tlv.Init();
    tlv.SetTimeSyncPeriod(Get<TimeSync>().GetTimeSyncPeriod());
    tlv.SetXtalThreshold(Get<TimeSync>().GetXtalThreshold());

    return tlv.AppendTo(aMessage);
}

Error Mle::AppendXtalAccuracy(Message &aMessage)
{
    return Tlv::Append<XtalAccuracyTlv>(aMessage, otPlatTimeGetXtalAccuracy());
}
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE

Error Mle::AppendActiveTimestamp(Message &aMessage)
{
    Error                     error     = kErrorNone;
    const MeshCoP::Timestamp *timestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();

    VerifyOrExit(timestamp != nullptr);
    error = Tlv::Append<ActiveTimestampTlv>(aMessage, *timestamp);

exit:
    return error;
}

Error Mle::AppendPendingTimestamp(Message &aMessage)
{
    Error                     error     = kErrorNone;
    const MeshCoP::Timestamp *timestamp = Get<MeshCoP::PendingDatasetManager>().GetTimestamp();

    VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0);
    error = Tlv::Append<PendingTimestampTlv>(aMessage, *timestamp);

exit:
    return error;
}

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
Error Mle::AppendCslChannel(Message &aMessage)
{
    Error         error = kErrorNone;
    CslChannelTlv cslChannel;

    // In current implementation, it's allowed to set CSL Channel unspecified. As `0` is not valid for Channel value
    // in CSL Channel TLV, if CSL channel is not specified, we don't append CSL Channel TLV.
    // And on transmitter side, it would also set CSL Channel for the child to `0` if it doesn't find a CSL Channel
    // TLV.
    VerifyOrExit(Get<Mac::Mac>().IsCslChannelSpecified());

    cslChannel.Init();
    cslChannel.SetChannelPage(0);
    cslChannel.SetChannel(Get<Mac::Mac>().GetCslChannel());

    SuccessOrExit(error = aMessage.Append(cslChannel));

exit:
    return error;
}

Error Mle::AppendCslTimeout(Message &aMessage)
{
    OT_ASSERT(Get<Mac::Mac>().IsCslEnabled());
    return Tlv::Append<CslTimeoutTlv>(aMessage, mCslTimeout == 0 ? mTimeout : mCslTimeout);
}

void Mle::SetCslTimeout(uint32_t aTimeout)
{
    VerifyOrExit(mCslTimeout != aTimeout);

    mCslTimeout = aTimeout;

    Get<DataPollSender>().RecalculatePollPeriod();

    if (Get<Mac::Mac>().IsCslEnabled())
    {
        ScheduleChildUpdateRequest();
    }

exit:
    return;
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE

#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
Error Mle::AppendCslClockAccuracy(Message &aMessage)
{
    Error               error = kErrorNone;
    CslClockAccuracyTlv cslClockAccuracy;

    cslClockAccuracy.Init();

    cslClockAccuracy.SetCslClockAccuracy(Get<Radio>().GetCslAccuracy());
    cslClockAccuracy.SetCslUncertainty(Get<Radio>().GetCslClockUncertainty());

    SuccessOrExit(error = aMessage.Append(cslClockAccuracy));

exit:
    return error;
}
#endif

void Mle::HandleNotifierEvents(Events aEvents)
{
    VerifyOrExit(!IsDisabled());

    if (aEvents.Contains(kEventThreadRoleChanged))
    {
        if (IsChild() && !IsFullThreadDevice() && mAddressRegistrationMode == kAppendMeshLocalOnly)
        {
            // If only mesh-local address was registered in the "Child
            // ID Request" message, after device is attached, trigger a
            // "Child Update Request" to register the remaining
            // addresses.

            mAddressRegistrationMode = kAppendAllAddresses;
            mChildUpdateRequestState = kChildUpdateRequestPending;
            ScheduleMessageTransmissionTimer();
        }
    }

    if (aEvents.ContainsAny(kEventIp6AddressAdded | kEventIp6AddressRemoved))
    {
        if (!Get<ThreadNetif>().HasUnicastAddress(mMeshLocal64.GetAddress()))
        {
            // Mesh Local EID was removed, choose a new one and add it back
            mMeshLocal64.GetAddress().GetIid().GenerateRandom();

            Get<ThreadNetif>().AddUnicastAddress(mMeshLocal64);
            Get<Notifier>().Signal(kEventThreadMeshLocalAddrChanged);
        }

        if (IsChild() && !IsFullThreadDevice())
        {
            mChildUpdateRequestState = kChildUpdateRequestPending;
            ScheduleMessageTransmissionTimer();
        }
    }

    if (aEvents.ContainsAny(kEventIp6MulticastSubscribed | kEventIp6MulticastUnsubscribed))
    {
        // When multicast subscription changes, SED always notifies its parent as it depends on its
        // parent for indirect transmission. Since Thread 1.2, MED MAY also notify its parent of 1.2
        // or higher version as it could depend on its parent to perform Multicast Listener Report.
        if (IsChild() && !IsFullThreadDevice() &&
            (!IsRxOnWhenIdle()
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
             || !GetParent().IsThreadVersion1p1()
#endif
                 ))

        {
            mChildUpdateRequestState = kChildUpdateRequestPending;
            ScheduleMessageTransmissionTimer();
        }
    }

    if (aEvents.Contains(kEventThreadNetdataChanged))
    {
#if OPENTHREAD_FTD
        if (IsFullThreadDevice())
        {
            Get<MleRouter>().HandleNetworkDataUpdateRouter();
        }
        else
#endif
        {
            if (!aEvents.Contains(kEventThreadRoleChanged))
            {
                mChildUpdateRequestState = kChildUpdateRequestPending;
                ScheduleMessageTransmissionTimer();
            }
        }

#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
        Get<BackboneRouter::Leader>().Update();
#endif
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
        UpdateServiceAlocs();
#endif

#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
        IgnoreError(Get<Dhcp6::Server>().UpdateService());
#endif

#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
        Get<NeighborDiscovery::Agent>().UpdateService();
#endif

#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
        Get<Dhcp6::Client>().UpdateAddresses();
#endif
    }

    if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadKeySeqCounterChanged))
    {
        // Store the settings on a key seq change, or when role changes and device
        // is attached (i.e., skip `Store()` on role change to detached).

        if (aEvents.Contains(kEventThreadKeySeqCounterChanged) || IsAttached())
        {
            IgnoreError(Store());
        }
    }

exit:
    return;
}

#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE

Mle::ServiceAloc::ServiceAloc(void)
{
    InitAsThreadOriginRealmLocalScope();
    GetAddress().GetIid().SetToLocator(kNotInUse);
}

Mle::ServiceAloc *Mle::FindInServiceAlocs(uint16_t aAloc16)
{
    // Search in `mServiceAlocs` for an entry matching `aAloc16`.
    // Can be used with `aAloc16 = ServerAloc::kNotInUse` to find
    // an unused entry in the array.

    ServiceAloc *match = nullptr;

    for (ServiceAloc &serviceAloc : mServiceAlocs)
    {
        if (serviceAloc.GetAloc16() == aAloc16)
        {
            match = &serviceAloc;
            break;
        }
    }

    return match;
}

void Mle::UpdateServiceAlocs(void)
{
    NetworkData::Iterator      iterator;
    NetworkData::ServiceConfig service;

    VerifyOrExit(!IsDisabled());

    // First remove all ALOCs which are no longer in the Network
    // Data to free up space in `mServiceAlocs` array.

    for (ServiceAloc &serviceAloc : mServiceAlocs)
    {
        bool found = false;

        if (!serviceAloc.IsInUse())
        {
            continue;
        }

        iterator = NetworkData::kIteratorInit;

        while (Get<NetworkData::Leader>().GetNextService(iterator, GetRloc16(), service) == kErrorNone)
        {
            if (service.mServiceId == ServiceIdFromAloc(serviceAloc.GetAloc16()))
            {
                found = true;
                break;
            }
        }

        if (!found)
        {
            Get<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
            serviceAloc.MarkAsNotInUse();
        }
    }

    // Now add any new ALOCs if there is space in `mServiceAlocs`.

    iterator = NetworkData::kIteratorInit;

    while (Get<NetworkData::Leader>().GetNextService(iterator, GetRloc16(), service) == kErrorNone)
    {
        uint16_t aloc16 = ServiceAlocFromId(service.mServiceId);

        if (FindInServiceAlocs(aloc16) == nullptr)
        {
            // No matching ALOC in `mServiceAlocs`, so we try to add it.
            ServiceAloc *newServiceAloc = FindInServiceAlocs(ServiceAloc::kNotInUse);

            VerifyOrExit(newServiceAloc != nullptr);
            newServiceAloc->SetAloc16(aloc16);
            Get<ThreadNetif>().AddUnicastAddress(*newServiceAloc);
        }
    }

exit:
    return;
}

#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE

void Mle::HandleAttachTimer(Timer &aTimer)
{
    aTimer.Get<Mle>().HandleAttachTimer();
}

bool Mle::HasAcceptableParentCandidate(void) const
{
    bool    hasAcceptableParent = false;
    uint8_t linkQuality;

    VerifyOrExit(mParentCandidate.IsStateParentResponse());

    switch (mAttachState)
    {
    case kAttachStateAnnounce:
        VerifyOrExit(!HasMoreChannelsToAnnouce());
        break;

    case kAttachStateParentRequestRouter:
        // If we cannot find a parent with best link quality (3) when
        // in `kAttachStateParentRequestRouter` state we will keep the
        // candidate and forward to REED stage to potentially find a
        // better parent.
        linkQuality = OT_MIN(mParentCandidate.GetLinkInfo().GetLinkQuality(), mParentCandidate.GetLinkQualityOut());
        VerifyOrExit(linkQuality == 3);
        break;

    case kAttachStateParentRequestReed:
        break;

    default:
        ExitNow();
    }

    if (IsChild())
    {
        // If already attached, accept the parent candidate if
        // we are trying to attach to a better partition or if a
        // Parent Response was also received from the current parent
        // to which the device is attached. This ensures that the
        // new parent candidate is compared with the current parent
        // and that it is indeed preferred over the current one.

        VerifyOrExit(mReceivedResponseFromParent || (mAttachMode == kBetterPartition));
    }

    hasAcceptableParent = true;

exit:
    return hasAcceptableParent;
}

void Mle::HandleAttachTimer(void)
{
    uint32_t delay          = 0;
    bool     shouldAnnounce = true;

    // First, check if we are waiting to receive parent responses and
    // found an acceptable parent candidate.

    if (HasAcceptableParentCandidate() && (SendChildIdRequest() == kErrorNone))
    {
        SetAttachState(kAttachStateChildIdRequest);
        delay = kParentRequestReedTimeout;
        ExitNow();
    }

    switch (mAttachState)
    {
    case kAttachStateIdle:
        mAttachCounter = 0;
        break;

    case kAttachStateProcessAnnounce:
        ProcessAnnounce();
        break;

    case kAttachStateStart:
        if (mAttachCounter > 0)
        {
            LogNote("Attempt to attach - attempt %d, %s %s", mAttachCounter, AttachModeToString(mAttachMode),
                    ReattachStateToString(mReattachState));
        }
        else
        {
            LogNote("Attempt to attach - %s %s", AttachModeToString(mAttachMode),
                    ReattachStateToString(mReattachState));
        }

        SetAttachState(kAttachStateParentRequestRouter);
        mParentCandidate.SetState(Neighbor::kStateInvalid);
        mReceivedResponseFromParent = false;
        Get<MeshForwarder>().SetRxOnWhenIdle(true);

        // initial MLE Parent Request has both E and R flags set in Scan Mask TLV
        // during reattach when losing connectivity.
        if (mAttachMode == kSamePartition || mAttachMode == kSamePartitionRetry)
        {
            SendParentRequest(kToRoutersAndReeds);
            delay = kParentRequestReedTimeout;
        }
        // initial MLE Parent Request has only R flag set in Scan Mask TLV for
        // during initial attach or downgrade process
        else
        {
            SendParentRequest(kToRouters);
            delay = kParentRequestRouterTimeout;
        }

        break;

    case kAttachStateParentRequestRouter:
        SetAttachState(kAttachStateParentRequestReed);
        SendParentRequest(kToRoutersAndReeds);
        delay = kParentRequestReedTimeout;
        break;

    case kAttachStateParentRequestReed:
        shouldAnnounce = PrepareAnnounceState();

        if (shouldAnnounce)
        {
            // We send an extra "Parent Request" as we switch to
            // `kAttachStateAnnounce` and start sending Announce on
            // all channels. This gives an additional chance to find
            // a parent during this phase. Note that we can stay in
            // `kAttachStateAnnounce` for multiple iterations, each
            // time sending an Announce on a different channel
            // (with `mAnnounceDelay` wait between them).

            SetAttachState(kAttachStateAnnounce);
            SendParentRequest(kToRoutersAndReeds);
            mAnnounceChannel = Mac::ChannelMask::kChannelIteratorFirst;
            delay            = mAnnounceDelay;
            break;
        }

        OT_FALL_THROUGH;

    case kAttachStateAnnounce:
        if (shouldAnnounce && (GetNextAnnouceChannel(mAnnounceChannel) == kErrorNone))
        {
            SendAnnounce(mAnnounceChannel, kOrphanAnnounce);
            delay = mAnnounceDelay;
            break;
        }

        OT_FALL_THROUGH;

    case kAttachStateChildIdRequest:
        SetAttachState(kAttachStateIdle);
        mParentCandidate.Clear();
        delay = Reattach();
        break;
    }

exit:

    if (delay != 0)
    {
        mAttachTimer.Start(delay);
    }
}

bool Mle::PrepareAnnounceState(void)
{
    bool             shouldAnnounce = false;
    Mac::ChannelMask channelMask;

    VerifyOrExit(!IsChild() && (mReattachState == kReattachStop) &&
                 (Get<MeshCoP::ActiveDatasetManager>().IsPartiallyComplete() || !IsFullThreadDevice()));

    if (Get<MeshCoP::ActiveDatasetManager>().GetChannelMask(channelMask) != kErrorNone)
    {
        channelMask = Get<Mac::Mac>().GetSupportedChannelMask();
    }

    mAnnounceDelay = kAnnounceTimeout / (channelMask.GetNumberOfChannels() + 1);

    if (mAnnounceDelay < kMinAnnounceDelay)
    {
        mAnnounceDelay = kMinAnnounceDelay;
    }

    shouldAnnounce = true;

exit:
    return shouldAnnounce;
}

uint32_t Mle::Reattach(void)
{
    uint32_t delay = 0;

    if (mReattachState == kReattachActive)
    {
        if (Get<MeshCoP::PendingDatasetManager>().Restore() == kErrorNone)
        {
            IgnoreError(Get<MeshCoP::PendingDatasetManager>().ApplyConfiguration());
            mReattachState = kReattachPending;
            SetAttachState(kAttachStateStart);
            delay = 1 + Random::NonCrypto::GetUint32InRange(0, kAttachStartJitter);
        }
        else
        {
            mReattachState = kReattachStop;
        }
    }
    else if (mReattachState == kReattachPending)
    {
        mReattachState = kReattachStop;
        IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
    }

    VerifyOrExit(mReattachState == kReattachStop);

    switch (mAttachMode)
    {
    case kAnyPartition:
    case kBetterParent:
        if (!IsChild())
        {
            if (mAlternatePanId != Mac::kPanIdBroadcast)
            {
                IgnoreError(Get<Mac::Mac>().SetPanChannel(mAlternateChannel));
                Get<Mac::Mac>().SetPanId(mAlternatePanId);
                mAlternatePanId = Mac::kPanIdBroadcast;
                IgnoreError(BecomeDetached());
            }
#if OPENTHREAD_FTD
            else if (IsFullThreadDevice() && Get<MleRouter>().BecomeLeader() == kErrorNone)
            {
                // do nothing
            }
#endif
            else
            {
                IgnoreError(BecomeDetached());
            }
        }
        else if (!IsRxOnWhenIdle())
        {
            // return to sleepy operation
            Get<DataPollSender>().SetAttachMode(false);
            Get<MeshForwarder>().SetRxOnWhenIdle(false);
        }

        break;

    case kSamePartition:
        Attach(kSamePartitionRetry);
        break;

    case kSamePartitionRetry:
    case kDowngradeToReed:
        Attach(kAnyPartition);
        break;

    case kBetterPartition:
        break;
    }

exit:
    return delay;
}

void Mle::HandleDelayedResponseTimer(Timer &aTimer)
{
    aTimer.Get<Mle>().HandleDelayedResponseTimer();
}

void Mle::HandleDelayedResponseTimer(void)
{
    TimeMilli now          = TimerMilli::GetNow();
    TimeMilli nextSendTime = now.GetDistantFuture();

    for (Message &message : mDelayedResponses)
    {
        DelayedResponseMetadata metadata;

        metadata.ReadFrom(message);

        if (now < metadata.mSendTime)
        {
            if (nextSendTime > metadata.mSendTime)
            {
                nextSendTime = metadata.mSendTime;
            }
        }
        else
        {
            mDelayedResponses.Dequeue(message);
            SendDelayedResponse(message, metadata);
        }
    }

    if (nextSendTime < now.GetDistantFuture())
    {
        mDelayedResponseTimer.FireAt(nextSendTime);
    }
}

void Mle::SendDelayedResponse(Message &aMessage, const DelayedResponseMetadata &aMetadata)
{
    Error error = kErrorNone;

    aMetadata.RemoveFrom(aMessage);

    if (aMessage.GetSubType() == Message::kSubTypeMleDataRequest)
    {
        SuccessOrExit(error = AppendActiveTimestamp(aMessage));
        SuccessOrExit(error = AppendPendingTimestamp(aMessage));
    }

    SuccessOrExit(error = SendMessage(aMessage, aMetadata.mDestination));

    Log(kMessageSend, kTypeGenericDelayed, aMetadata.mDestination);

    if (!IsRxOnWhenIdle())
    {
        // Start fast poll mode, assuming enqueued msg is MLE Data Request.
        // Note: Finer-grade check may be required when deciding whether or
        // not to enter fast poll mode for other type of delayed message.

        Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
    }

exit:
    FreeMessageOnError(&aMessage, error);
}

void Mle::RemoveDelayedDataResponseMessage(void)
{
    RemoveDelayedMessage(Message::kSubTypeMleDataResponse, kTypeDataResponse, nullptr);
}

void Mle::RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination)
{
    RemoveDelayedMessage(Message::kSubTypeMleDataRequest, kTypeDataRequest, &aDestination);
}

void Mle::RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination)
{
    for (Message &message : mDelayedResponses)
    {
        DelayedResponseMetadata metadata;

        metadata.ReadFrom(message);

        if ((message.GetSubType() == aSubType) &&
            ((aDestination == nullptr) || (metadata.mDestination == *aDestination)))
        {
            mDelayedResponses.DequeueAndFree(message);
            Log(kMessageRemoveDelayed, aMessageType, metadata.mDestination);
        }
    }
}

void Mle::SendParentRequest(ParentRequestType aType)
{
    Error        error = kErrorNone;
    Message *    message;
    uint8_t      scanMask = 0;
    Ip6::Address destination;

    mParentRequestChallenge.GenerateRandom();

    switch (aType)
    {
    case kToRouters:
        scanMask = ScanMaskTlv::kRouterFlag;
        break;

    case kToRoutersAndReeds:
        scanMask = ScanMaskTlv::kRouterFlag | ScanMaskTlv::kEndDeviceFlag;
        break;
    }

    VerifyOrExit((message = NewMleMessage(kCommandParentRequest)) != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = AppendMode(*message, mDeviceMode));
    SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
    SuccessOrExit(error = AppendScanMask(*message, scanMask));
    SuccessOrExit(error = AppendVersion(*message));
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
    SuccessOrExit(error = AppendTimeRequest(*message));
#endif

    destination.SetToLinkLocalAllRoutersMulticast();
    SuccessOrExit(error = SendMessage(*message, destination));

    switch (aType)
    {
    case kToRouters:
        Log(kMessageSend, kTypeParentRequestToRouters, destination);
        break;

    case kToRoutersAndReeds:
        Log(kMessageSend, kTypeParentRequestToRoutersReeds, destination);
        break;
    }

exit:
    FreeMessageOnError(message, error);
}

void Mle::RequestShorterChildIdRequest(void)
{
    if (mAttachState == kAttachStateChildIdRequest)
    {
        mAddressRegistrationMode = kAppendMeshLocalOnly;
        IgnoreError(SendChildIdRequest());
    }
}

Error Mle::SendChildIdRequest(void)
{
    Error        error   = kErrorNone;
    uint8_t      tlvs[]  = {Tlv::kAddress16, Tlv::kNetworkData, Tlv::kRoute};
    uint8_t      tlvsLen = sizeof(tlvs);
    Message *    message = nullptr;
    Ip6::Address destination;

    if (mParent.GetExtAddress() == mParentCandidate.GetExtAddress())
    {
        if (IsChild())
        {
            LogInfo("Already attached to candidate parent");
            ExitNow(error = kErrorAlready);
        }
        else
        {
            // Invalidate stale parent state.
            //
            // Parent state is not normally invalidated after becoming a Router/Leader (see #1875).  When trying to
            // attach to a better partition, invalidating old parent state (especially when in kStateRestored) ensures
            // that FindNeighbor() returns mParentCandidate when processing the Child ID Response.
            mParent.SetState(Neighbor::kStateInvalid);
        }
    }

    VerifyOrExit((message = NewMleMessage(kCommandChildIdRequest)) != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = AppendResponse(*message, mParentCandidateChallenge));
    SuccessOrExit(error = AppendLinkFrameCounter(*message));
    SuccessOrExit(error = AppendMleFrameCounter(*message));
    SuccessOrExit(error = AppendMode(*message, mDeviceMode));
    SuccessOrExit(error = AppendTimeout(*message, mTimeout));
    SuccessOrExit(error = AppendVersion(*message));

    if (!IsFullThreadDevice())
    {
        SuccessOrExit(error = AppendAddressRegistration(*message, mAddressRegistrationMode));

        // no need to request the last Route64 TLV for MTD
        tlvsLen -= 1;
    }

    SuccessOrExit(error = AppendTlvRequest(*message, tlvs, tlvsLen));
    SuccessOrExit(error = AppendActiveTimestamp(*message));
    SuccessOrExit(error = AppendPendingTimestamp(*message));

    mParentCandidate.SetState(Neighbor::kStateValid);

    destination.SetToLinkLocalAddress(mParentCandidate.GetExtAddress());
    SuccessOrExit(error = SendMessage(*message, destination));

    Log(kMessageSend,
        (mAddressRegistrationMode == kAppendMeshLocalOnly) ? kTypeChildIdRequestShort : kTypeChildIdRequest,
        destination);

    if (!IsRxOnWhenIdle())
    {
        Get<DataPollSender>().SetAttachMode(true);
        Get<MeshForwarder>().SetRxOnWhenIdle(false);
    }

exit:
    FreeMessageOnError(message, error);
    return error;
}

Error Mle::SendDataRequest(const Ip6::Address &aDestination,
                           const uint8_t *     aTlvs,
                           uint8_t             aTlvsLength,
                           uint16_t            aDelay,
                           const uint8_t *     aExtraTlvs,
                           uint8_t             aExtraTlvsLength)
{
    Error    error = kErrorNone;
    Message *message;

    RemoveDelayedDataRequestMessage(aDestination);

    VerifyOrExit((message = NewMleMessage(kCommandDataRequest)) != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = AppendTlvRequest(*message, aTlvs, aTlvsLength));

    if (aExtraTlvs != nullptr && aExtraTlvsLength > 0)
    {
        SuccessOrExit(error = message->AppendBytes(aExtraTlvs, aExtraTlvsLength));
    }

    if (aDelay)
    {
        SuccessOrExit(error = AddDelayedResponse(*message, aDestination, aDelay));
        Log(kMessageDelay, kTypeDataRequest, aDestination);
    }
    else
    {
        SuccessOrExit(error = AppendActiveTimestamp(*message));
        SuccessOrExit(error = AppendPendingTimestamp(*message));

        SuccessOrExit(error = SendMessage(*message, aDestination));
        Log(kMessageSend, kTypeDataRequest, aDestination);

        if (!IsRxOnWhenIdle())
        {
            Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
        }
    }

exit:
    FreeMessageOnError(message, error);

    if (IsChild() && !IsRxOnWhenIdle())
    {
        mDataRequestState = kDataRequestActive;

        if (mChildUpdateRequestState == kChildUpdateRequestNone)
        {
            ScheduleMessageTransmissionTimer();
        }
    }

    return error;
}

void Mle::ScheduleMessageTransmissionTimer(void)
{
    uint32_t interval = 0;

    switch (mChildUpdateRequestState)
    {
    case kChildUpdateRequestNone:
        break;

    case kChildUpdateRequestPending:
        ExitNow(interval = kChildUpdateRequestPendingDelay);

    case kChildUpdateRequestActive:
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        // CSL transmitter may respond in next CSL cycle.
        // This condition IsCslCapable() && !IsRxOnWhenIdle() is used instead of
        // IsCslEnabled because during transitions SSED -> MED and MED -> SSED
        // there is a delay in synchronisation of IsRxOnWhenIdle residing in MAC
        // and in MLE, which causes below datapoll interval to be calculated incorrectly.
        if (Get<Mac::Mac>().IsCslCapable() && !IsRxOnWhenIdle())
        {
            ExitNow(interval = Get<Mac::Mac>().GetCslPeriod() * kUsPerTenSymbols / 1000 +
                               static_cast<uint32_t>(kUnicastRetransmissionDelay));
        }
        else
#endif
        {
            ExitNow(interval = kUnicastRetransmissionDelay);
        }
    }

    switch (mDataRequestState)
    {
    case kDataRequestNone:
        break;

    case kDataRequestActive:
        ExitNow(interval = kUnicastRetransmissionDelay);
    }

    if (IsChild() && IsRxOnWhenIdle())
    {
        interval =
            Time::SecToMsec(mTimeout) - static_cast<uint32_t>(kUnicastRetransmissionDelay) * kMaxChildKeepAliveAttempts;
    }

exit:
    if (interval != 0)
    {
        mMessageTransmissionTimer.Start(interval);
    }
    else
    {
        mMessageTransmissionTimer.Stop();
    }
}

void Mle::HandleMessageTransmissionTimer(Timer &aTimer)
{
    aTimer.Get<Mle>().HandleMessageTransmissionTimer();
}

void Mle::HandleMessageTransmissionTimer(void)
{
    // The `mMessageTransmissionTimer` is used for:
    //
    //  - Delaying kEvent notification triggered "Child Update Request" transmission (to allow aggregation),
    //  - Retransmission of "Child Update Request",
    //  - Retransmission of "Data Request" on a child,
    //  - Sending periodic keep-alive "Child Update Request" messages on a non-sleepy (rx-on) child.

    switch (mChildUpdateRequestState)
    {
    case kChildUpdateRequestNone:
        if (mDataRequestState == kDataRequestActive)
        {
            static const uint8_t tlvs[] = {Tlv::kNetworkData};
            Ip6::Address         destination;

            VerifyOrExit(mDataRequestAttempts < kMaxChildKeepAliveAttempts, IgnoreError(BecomeDetached()));

            destination.SetToLinkLocalAddress(mParent.GetExtAddress());

            if (SendDataRequest(destination, tlvs, sizeof(tlvs), 0) == kErrorNone)
            {
                mDataRequestAttempts++;
            }

            ExitNow();
        }

        // Keep-alive "Child Update Request" only on a non-sleepy child
        VerifyOrExit(IsChild() && IsRxOnWhenIdle());
        break;

    case kChildUpdateRequestPending:
        if (Get<Notifier>().IsPending())
        {
            // Here intentionally delay another kChildUpdateRequestPendingDelay
            // cycle to ensure we only send a Child Update Request after we
            // know there are no more pending changes.
            ScheduleMessageTransmissionTimer();
            ExitNow();
        }

        mChildUpdateAttempts = 0;
        break;

    case kChildUpdateRequestActive:
        break;
    }

    VerifyOrExit(mChildUpdateAttempts < kMaxChildKeepAliveAttempts, IgnoreError(BecomeDetached()));

    if (SendChildUpdateRequest() == kErrorNone)
    {
        mChildUpdateAttempts++;
    }

exit:
    return;
}

Error Mle::SendChildUpdateRequest(void)
{
    Error                   error = kErrorNone;
    Ip6::Address            destination;
    Message *               message = nullptr;
    AddressRegistrationMode mode    = kAppendAllAddresses;

    if (!mParent.IsStateValidOrRestoring())
    {
        LogWarn("No valid parent when sending Child Update Request");
        IgnoreError(BecomeDetached());
        ExitNow();
    }

    mChildUpdateRequestState = kChildUpdateRequestActive;
    ScheduleMessageTransmissionTimer();

    VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = AppendMode(*message, mDeviceMode));

    switch (mRole)
    {
    case kRoleDetached:
        mParentRequestChallenge.GenerateRandom();
        SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
        mode = kAppendMeshLocalOnly;
        break;

    case kRoleChild:
        SuccessOrExit(error = AppendSourceAddress(*message));
        SuccessOrExit(error = AppendLeaderData(*message));
        SuccessOrExit(error = AppendTimeout(*message, mTimeout));
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        if (Get<Mac::Mac>().IsCslEnabled())
        {
            SuccessOrExit(error = AppendCslChannel(*message));
            SuccessOrExit(error = AppendCslTimeout(*message));
        }
#endif
        break;

    case kRoleDisabled:
    case kRoleRouter:
    case kRoleLeader:
        OT_ASSERT(false);
        OT_UNREACHABLE_CODE(break);
    }

    if (!IsFullThreadDevice())
    {
        SuccessOrExit(error = AppendAddressRegistration(*message, mode));
    }

    destination.SetToLinkLocalAddress(mParent.GetExtAddress());
    SuccessOrExit(error = SendMessage(*message, destination));

    Log(kMessageSend, kTypeChildUpdateRequestOfParent, destination);

    if (!IsRxOnWhenIdle())
    {
        Get<MeshForwarder>().SetRxOnWhenIdle(false);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        Get<DataPollSender>().SetAttachMode(!Get<Mac::Mac>().IsCslEnabled());
#else
        Get<DataPollSender>().SetAttachMode(true);
#endif
    }
    else
    {
        Get<MeshForwarder>().SetRxOnWhenIdle(true);
    }

exit:
    FreeMessageOnError(message, error);
    return error;
}

Error Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge)
{
    Error        error = kErrorNone;
    Ip6::Address destination;
    Message *    message;
    bool         checkAddress = false;

    VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = AppendSourceAddress(*message));
    SuccessOrExit(error = AppendLeaderData(*message));

    for (int i = 0; i < aNumTlvs; i++)
    {
        switch (aTlvs[i])
        {
        case Tlv::kTimeout:
            SuccessOrExit(error = AppendTimeout(*message, mTimeout));
            break;

        case Tlv::kStatus:
            SuccessOrExit(error = AppendStatus(*message, StatusTlv::kError));
            break;

        case Tlv::kAddressRegistration:
            if (!IsFullThreadDevice())
            {
                // We only register the mesh-local address in the "Child
                // Update Response" message and if there are additional
                // addresses to register we follow up with a "Child Update
                // Request".

                SuccessOrExit(error = AppendAddressRegistration(*message, kAppendMeshLocalOnly));
                checkAddress = true;
            }

            break;

        case Tlv::kResponse:
            SuccessOrExit(error = AppendResponse(*message, aChallenge));
            break;

        case Tlv::kLinkFrameCounter:
            SuccessOrExit(error = AppendLinkFrameCounter(*message));
            break;

        case Tlv::kMleFrameCounter:
            SuccessOrExit(error = AppendMleFrameCounter(*message));
            break;

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        case Tlv::kCslTimeout:
            if (Get<Mac::Mac>().IsCslEnabled())
            {
                SuccessOrExit(error = AppendCslTimeout(*message));
            }
            break;
#endif
        }
    }

    destination.SetToLinkLocalAddress(mParent.GetExtAddress());
    SuccessOrExit(error = SendMessage(*message, destination));

    Log(kMessageSend, kTypeChildUpdateResponseOfParent, destination);

    if (checkAddress && HasUnregisteredAddress())
    {
        IgnoreError(SendChildUpdateRequest());
    }

exit:
    FreeMessageOnError(message, error);
    return error;
}

void Mle::SendAnnounce(uint8_t aChannel, AnnounceMode aMode)
{
    Ip6::Address destination;

    destination.SetToLinkLocalAllNodesMulticast();

    SendAnnounce(aChannel, destination, aMode);
}

void Mle::SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode)
{
    Error              error = kErrorNone;
    ChannelTlv         channel;
    MeshCoP::Timestamp activeTimestamp;
    Message *          message = nullptr;

    VerifyOrExit(Get<Mac::Mac>().GetSupportedChannelMask().ContainsChannel(aChannel), error = kErrorInvalidArgs);
    VerifyOrExit((message = NewMleMessage(kCommandAnnounce)) != nullptr, error = kErrorNoBufs);
    message->SetLinkSecurityEnabled(true);
    message->SetChannel(aChannel);

    channel.Init();
    channel.SetChannelPage(0);
    channel.SetChannel(Get<Mac::Mac>().GetPanChannel());
    SuccessOrExit(error = channel.AppendTo(*message));

    switch (aMode)
    {
    case kOrphanAnnounce:
        activeTimestamp.Clear();
        activeTimestamp.SetAuthoritative(true);
        SuccessOrExit(error = Tlv::Append<ActiveTimestampTlv>(*message, activeTimestamp));
        break;

    case kNormalAnnounce:
        SuccessOrExit(error = AppendActiveTimestamp(*message));
        break;
    }

    SuccessOrExit(error = Tlv::Append<PanIdTlv>(*message, Get<Mac::Mac>().GetPanId()));

    SuccessOrExit(error = SendMessage(*message, aDestination));

    LogInfo("Send Announce on channel %d", aChannel);

exit:
    FreeMessageOnError(message, error);
}

Error Mle::GetNextAnnouceChannel(uint8_t &aChannel) const
{
    // This method gets the next channel to send announce on after
    // `aChannel`. Returns `kErrorNotFound` if no more channel in the
    // channel mask after `aChannel`.

    Mac::ChannelMask channelMask;

    if (Get<MeshCoP::ActiveDatasetManager>().GetChannelMask(channelMask) != kErrorNone)
    {
        channelMask = Get<Mac::Mac>().GetSupportedChannelMask();
    }

    return channelMask.GetNextChannel(aChannel);
}

bool Mle::HasMoreChannelsToAnnouce(void) const
{
    uint8_t channel = mAnnounceChannel;

    return GetNextAnnouceChannel(channel) == kErrorNone;
}

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
Error Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus)
{
    Error    error = kErrorNone;
    Message *message;
    Tlv      tlv;
    ot::Tlv  statusSubTlv;

    VerifyOrExit((message = NewMleMessage(kCommandLinkMetricsManagementResponse)) != nullptr, error = kErrorNoBufs);

    tlv.SetType(Tlv::kLinkMetricsManagement);
    statusSubTlv.SetType(LinkMetrics::SubTlv::kStatus);
    statusSubTlv.SetLength(sizeof(aStatus));
    tlv.SetLength(statusSubTlv.GetSize());

    SuccessOrExit(error = message->Append(tlv));
    SuccessOrExit(error = message->Append(statusSubTlv));
    SuccessOrExit(error = message->Append(aStatus));

    SuccessOrExit(error = SendMessage(*message, aDestination));

exit:
    FreeMessageOnError(message, error);
    return error;
}
#endif

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
Error Mle::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength)
{
    Error    error = kErrorNone;
    Message *message;
    Tlv      tlv;

    VerifyOrExit((message = NewMleMessage(kCommandLinkProbe)) != nullptr, error = kErrorNoBufs);

    tlv.SetType(Tlv::kLinkProbe);
    tlv.SetLength(sizeof(aSeriesId) + aLength);

    SuccessOrExit(error = message->Append(tlv));
    SuccessOrExit(error = message->Append(aSeriesId));
    SuccessOrExit(error = message->AppendBytes(aBuf, aLength));

    SuccessOrExit(error = SendMessage(*message, aDestination));

exit:
    FreeMessageOnError(message, error);
    return error;
}
#endif

Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode    aMode,
                                  Message &               aMessage,
                                  const Ip6::MessageInfo &aMessageInfo,
                                  uint16_t                aCmdOffset,
                                  const SecurityHeader &  aHeader)
{
    // This method performs MLE message security. Based on `aMode` it
    // can be used to encrypt and append tag to `aMessage` or to
    // decrypt and validate the tag in a received `aMessage` (which is
    // then removed from `aMessage`).
    //
    // `aCmdOffset` in both cases specifies the offset in `aMessage`
    // to the start of MLE payload (i.e., the command field).
    //
    // When decrypting, possible errors are:
    // `kErrorNone` decrypted and verified tag, tag is also removed.
    // `kErrorParse` message does not contain the tag
    // `kErrorSecurity` message tag is invalid.
    //
    // When encrypting, possible errors are:
    // `kErrorNone` message encrypted and tag appended to message.
    // `kErrorNoBufs` could not grow the message to append the tag.

    Error               error = kErrorNone;
    Crypto::AesCcm      aesCcm;
    uint8_t             nonce[Crypto::AesCcm::kNonceSize];
    uint8_t             tag[kMleSecurityTagSize];
    Mac::ExtAddress     extAddress;
    uint32_t            keySequence;
    uint16_t            payloadLength   = aMessage.GetLength() - aCmdOffset;
    const Ip6::Address *senderAddress   = &aMessageInfo.GetSockAddr();
    const Ip6::Address *receiverAddress = &aMessageInfo.GetPeerAddr();

    switch (aMode)
    {
    case Crypto::AesCcm::kEncrypt:
        // Use the initialized values for `senderAddress`,
        // `receiverAddress` and `payloadLength`
        break;

    case Crypto::AesCcm::kDecrypt:
        senderAddress   = &aMessageInfo.GetPeerAddr();
        receiverAddress = &aMessageInfo.GetSockAddr();
        // Ensure message contains command field (uint8_t) and
        // tag. Then exclude the tag from payload to decrypt.
        VerifyOrExit(aCmdOffset + sizeof(uint8_t) + kMleSecurityTagSize <= aMessage.GetLength(), error = kErrorParse);
        payloadLength -= kMleSecurityTagSize;
        break;
    }

    senderAddress->GetIid().ConvertToExtAddress(extAddress);
    Crypto::AesCcm::GenerateNonce(extAddress, aHeader.GetFrameCounter(), Mac::Frame::kSecEncMic32, nonce);

    keySequence = aHeader.GetKeyId();

    aesCcm.SetKey(keySequence == Get<KeyManager>().GetCurrentKeySequence()
                      ? Get<KeyManager>().GetCurrentMleKey()
                      : Get<KeyManager>().GetTemporaryMleKey(keySequence));

    aesCcm.Init(sizeof(Ip6::Address) + sizeof(Ip6::Address) + sizeof(SecurityHeader), payloadLength,
                kMleSecurityTagSize, nonce, sizeof(nonce));

    aesCcm.Header(*senderAddress);
    aesCcm.Header(*receiverAddress);
    aesCcm.Header(aHeader);

#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    if (aMode == Crypto::AesCcm::kDecrypt)
    {
        // Skip decrypting the message under fuzz build mode
        IgnoreError(aMessage.SetLength(aMessage.GetLength() - kMleSecurityTagSize));
        ExitNow();
    }
#endif

    aesCcm.Payload(aMessage, aCmdOffset, payloadLength, aMode);
    aesCcm.Finalize(tag);

    if (aMode == Crypto::AesCcm::kEncrypt)
    {
        SuccessOrExit(error = aMessage.Append(tag));
    }
    else
    {
        VerifyOrExit(aMessage.Compare(aMessage.GetLength() - kMleSecurityTagSize, tag), error = kErrorSecurity);
        IgnoreError(aMessage.SetLength(aMessage.GetLength() - kMleSecurityTagSize));
    }

exit:
    return error;
}

Error Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination)
{
    Error            error  = kErrorNone;
    uint16_t         offset = 0;
    uint8_t          securitySuite;
    Ip6::MessageInfo messageInfo;

    messageInfo.SetPeerAddr(aDestination);
    messageInfo.SetSockAddr(mLinkLocal64.GetAddress());
    messageInfo.SetPeerPort(kUdpPort);
    messageInfo.SetHopLimit(kMleHopLimit);

    IgnoreError(aMessage.Read(offset, securitySuite));
    offset += sizeof(securitySuite);

    if (securitySuite == k154Security)
    {
        SecurityHeader header;

        // Update the fields in the security header

        IgnoreError(aMessage.Read(offset, header));
        header.SetFrameCounter(Get<KeyManager>().GetMleFrameCounter());
        header.SetKeyId(Get<KeyManager>().GetCurrentKeySequence());
        aMessage.Write(offset, header);
        offset += sizeof(SecurityHeader);

        SuccessOrExit(error = ProcessMessageSecurity(Crypto::AesCcm::kEncrypt, aMessage, messageInfo, offset, header));

        Get<KeyManager>().IncrementMleFrameCounter();
    }

    SuccessOrExit(error = mSocket.SendTo(aMessage, messageInfo));

exit:
    return error;
}

Error Mle::AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
{
    Error                   error = kErrorNone;
    DelayedResponseMetadata metadata;

    metadata.mSendTime    = TimerMilli::GetNow() + aDelay;
    metadata.mDestination = aDestination;

    SuccessOrExit(error = metadata.AppendTo(aMessage));
    mDelayedResponses.Enqueue(aMessage);

    mDelayedResponseTimer.FireAtIfEarlier(metadata.mSendTime);

exit:
    return error;
}

void Mle::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    static_cast<Mle *>(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
}

void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    Error           error = kErrorNone;
    RxInfo          rxInfo(aMessage, aMessageInfo);
    uint8_t         securitySuite;
    SecurityHeader  header;
    uint32_t        keySequence;
    uint32_t        frameCounter;
    Mac::ExtAddress extAddr;
    uint8_t         command;
    Neighbor *      neighbor;

    LogDebg("Receive MLE message");

    VerifyOrExit(aMessageInfo.GetLinkInfo() != nullptr);
    VerifyOrExit(aMessageInfo.GetHopLimit() == kMleHopLimit, error = kErrorParse);

    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), securitySuite));
    aMessage.MoveOffset(sizeof(securitySuite));

    if (securitySuite == kNoSecurity)
    {
        SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), command));
        aMessage.MoveOffset(sizeof(command));

        switch (command)
        {
#if OPENTHREAD_FTD
        case kCommandDiscoveryRequest:
            Get<MleRouter>().HandleDiscoveryRequest(rxInfo);
            break;
#endif
        case kCommandDiscoveryResponse:
            Get<DiscoverScanner>().HandleDiscoveryResponse(rxInfo);
            break;

        default:
            break;
        }

        ExitNow();
    }

    VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
    VerifyOrExit(securitySuite == k154Security, error = kErrorParse);

    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), header));
    aMessage.MoveOffset(sizeof(header));

    VerifyOrExit(header.IsSecurityControlValid(), error = kErrorParse);

    keySequence  = header.GetKeyId();
    frameCounter = header.GetFrameCounter();

    SuccessOrExit(
        error = ProcessMessageSecurity(Crypto::AesCcm::kDecrypt, aMessage, aMessageInfo, aMessage.GetOffset(), header));

    if (keySequence > Get<KeyManager>().GetCurrentKeySequence())
    {
        Get<KeyManager>().SetCurrentKeySequence(keySequence);
    }

    IgnoreError(aMessage.Read(aMessage.GetOffset(), command));
    aMessage.MoveOffset(sizeof(command));

    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
    neighbor = (command == kCommandChildIdResponse) ? mNeighborTable.FindParent(extAddr)
                                                    : mNeighborTable.FindNeighbor(extAddr);

    if (neighbor != nullptr && neighbor->IsStateValid())
    {
        if (keySequence == neighbor->GetKeySequence())
        {
#if OPENTHREAD_CONFIG_MULTI_RADIO
            // Only when counter is exactly one off, we allow it to be
            // used for updating radio link info (by `RadioSelector`)
            // before message is dropped as a duplicate. This handles
            // the common case where a broadcast MLE message (such as
            // Link Advertisement) is received over multiple radio
            // links.

            if ((frameCounter + 1) == neighbor->GetMleFrameCounter())
            {
                OT_ASSERT(aMessage.IsRadioTypeSet());
                Get<RadioSelector>().UpdateOnReceive(*neighbor, aMessage.GetRadioType(), /* IsDuplicate */ true);

                // We intentionally exit without setting the error to
                // skip logging "Failed to process UDP" at the exit
                // label. Note that in multi-radio mode, receiving
                // duplicate MLE message (with one-off counter) would
                // be common and ok for broadcast MLE messages (e.g.
                // MLE Link Advertisements).
                ExitNow();
            }
#endif
            VerifyOrExit(frameCounter >= neighbor->GetMleFrameCounter(), error = kErrorDuplicated);
        }
        else
        {
            VerifyOrExit(keySequence > neighbor->GetKeySequence(), error = kErrorDuplicated);
            neighbor->SetKeySequence(keySequence);
            neighbor->GetLinkFrameCounters().Reset();
            neighbor->SetLinkAckFrameCounter(0);
        }

        neighbor->SetMleFrameCounter(frameCounter + 1);
    }

#if OPENTHREAD_CONFIG_MULTI_RADIO
    if (neighbor != nullptr)
    {
        OT_ASSERT(aMessage.IsRadioTypeSet());
        Get<RadioSelector>().UpdateOnReceive(*neighbor, aMessage.GetRadioType(), /* IsDuplicate */ false);
    }
#endif

    rxInfo.mKeySequence  = keySequence;
    rxInfo.mFrameCounter = frameCounter;
    rxInfo.mNeighbor     = neighbor;

    switch (command)
    {
    case kCommandAdvertisement:
        HandleAdvertisement(rxInfo);
        break;

    case kCommandDataResponse:
        HandleDataResponse(rxInfo);
        break;

    case kCommandParentResponse:
        HandleParentResponse(rxInfo);
        break;

    case kCommandChildIdResponse:
        HandleChildIdResponse(rxInfo);
        break;

    case kCommandAnnounce:
        HandleAnnounce(rxInfo);
        break;

    case kCommandChildUpdateRequest:
#if OPENTHREAD_FTD
        if (IsRouterOrLeader())
        {
            Get<MleRouter>().HandleChildUpdateRequest(rxInfo);
        }
        else
#endif
        {
            HandleChildUpdateRequest(rxInfo);
        }

        break;

    case kCommandChildUpdateResponse:
#if OPENTHREAD_FTD
        if (IsRouterOrLeader())
        {
            Get<MleRouter>().HandleChildUpdateResponse(rxInfo);
        }
        else
#endif
        {
            HandleChildUpdateResponse(rxInfo);
        }

        break;

#if OPENTHREAD_FTD
    case kCommandLinkRequest:
        Get<MleRouter>().HandleLinkRequest(rxInfo);
        break;

    case kCommandLinkAccept:
        Get<MleRouter>().HandleLinkAccept(rxInfo);
        break;

    case kCommandLinkAcceptAndRequest:
        Get<MleRouter>().HandleLinkAcceptAndRequest(rxInfo);
        break;

    case kCommandDataRequest:
        Get<MleRouter>().HandleDataRequest(rxInfo);
        break;

    case kCommandParentRequest:
        Get<MleRouter>().HandleParentRequest(rxInfo);
        break;

    case kCommandChildIdRequest:
        Get<MleRouter>().HandleChildIdRequest(rxInfo);
        break;

#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
    case kCommandTimeSync:
        Get<MleRouter>().HandleTimeSync(rxInfo);
        break;
#endif
#endif // OPENTHREAD_FTD

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
    case kCommandLinkMetricsManagementRequest:
        HandleLinkMetricsManagementRequest(rxInfo);
        break;
#endif

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
    case kCommandLinkMetricsManagementResponse:
        HandleLinkMetricsManagementResponse(rxInfo);
        break;
#endif

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
    case kCommandLinkProbe:
        HandleLinkProbe(rxInfo);
        break;
#endif

    default:
        ExitNow(error = kErrorDrop);
    }

#if OPENTHREAD_CONFIG_MULTI_RADIO
    // If we could not find a neighbor matching the MAC address of the
    // received MLE messages, or if the neighbor is now invalid, we
    // check again after the message is handled with a relaxed neighbor
    // state filer. The processing of the received MLE message may
    // create a new neighbor or change the neighbor table (e.g.,
    // receiving a "Parent Request" from a new child, or processing a
    // "Link Request" from a previous child which is being promoted to a
    // router).

    if ((neighbor == nullptr) || neighbor->IsStateInvalid())
    {
        neighbor = Get<NeighborTable>().FindNeighbor(extAddr, Neighbor::kInStateAnyExceptInvalid);

        if (neighbor != nullptr)
        {
            Get<RadioSelector>().UpdateOnReceive(*neighbor, aMessage.GetRadioType(), /* aIsDuplicate */ false);
        }
    }
#endif

exit:
    // We skip logging failures for broadcast MLE messages since it
    // can be common to receive such messages from adjacent Thread
    // networks.
    if (!aMessageInfo.GetSockAddr().IsMulticast() || !aMessageInfo.GetThreadLinkInfo()->IsDstPanIdBroadcast())
    {
        LogProcessError(kTypeGenericUdp, error);
    }
}

void Mle::HandleAdvertisement(RxInfo &aRxInfo)
{
    Error      error = kErrorNone;
    uint16_t   sourceAddress;
    LeaderData leaderData;
    uint8_t    tlvs[] = {Tlv::kNetworkData};
    uint16_t   delay;

    // Source Address
    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));

    Log(kMessageReceive, kTypeAdvertisement, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);

    // Leader Data
    SuccessOrExit(error = ReadLeaderData(aRxInfo.mMessage, leaderData));

    if (!IsDetached())
    {
#if OPENTHREAD_FTD
        if (IsFullThreadDevice())
        {
            SuccessOrExit(error = Get<MleRouter>().HandleAdvertisement(aRxInfo));
        }
        else
#endif
        {
            if ((aRxInfo.mNeighbor == &mParent) && (mParent.GetRloc16() != sourceAddress))
            {
                // Remove stale parent.
                IgnoreError(BecomeDetached());
            }
        }
    }

    switch (mRole)
    {
    case kRoleDisabled:
    case kRoleDetached:
        ExitNow();

    case kRoleChild:
        VerifyOrExit(aRxInfo.mNeighbor == &mParent);

        if ((mParent.GetRloc16() == sourceAddress) && (leaderData.GetPartitionId() != mLeaderData.GetPartitionId() ||
                                                       leaderData.GetLeaderRouterId() != GetLeaderId()))
        {
            SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());

#if OPENTHREAD_FTD
            if (IsFullThreadDevice())
            {
                RouteTlv route;

                if ((Tlv::FindTlv(aRxInfo.mMessage, route) == kErrorNone) && route.IsValid())
                {
                    // Overwrite Route Data
                    IgnoreError(Get<MleRouter>().ProcessRouteTlv(route));
                }
            }
#endif

            mRetrieveNewNetworkData = true;
        }

        mParent.SetLastHeard(TimerMilli::GetNow());
        break;

    case kRoleRouter:
    case kRoleLeader:
        VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid());
        break;
    }

    if (mRetrieveNewNetworkData || IsNetworkDataNewer(leaderData))
    {
        delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
        IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
    }

exit:
    LogProcessError(kTypeAdvertisement, error);
}

void Mle::HandleDataResponse(RxInfo &aRxInfo)
{
    Error error;
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
    uint16_t metricsReportValueOffset;
    uint16_t length;
#endif

    Log(kMessageReceive, kTypeDataResponse, aRxInfo.mMessageInfo.GetPeerAddr());

    VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid(), error = kErrorDrop);

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
    if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kLinkMetricsReport, metricsReportValueOffset, length) ==
        kErrorNone)
    {
        Get<LinkMetrics::LinkMetrics>().HandleReport(aRxInfo.mMessage, metricsReportValueOffset, length,
                                                     aRxInfo.mMessageInfo.GetPeerAddr());
    }
#endif

    error = HandleLeaderData(aRxInfo);

    if (mDataRequestState == kDataRequestNone && !IsRxOnWhenIdle())
    {
        // Here simply stops fast data poll request by Mle Data Request.
        // Note that in some cases fast data poll may continue after below stop operation until
        // running out the specified number. E.g. other component also trigger fast poll, and
        // is waiting for response; or the corner case where multiple Mle Data Request attempts
        // happened due to the retransmission mechanism.
        Get<DataPollSender>().StopFastPolls();
    }

exit:
    LogProcessError(kTypeDataResponse, error);
}

bool Mle::IsNetworkDataNewer(const LeaderData &aLeaderData)
{
    return SerialNumber::IsGreater(aLeaderData.GetDataVersion(GetNetworkDataType()),
                                   Get<NetworkData::Leader>().GetVersion(GetNetworkDataType()));
}

Error Mle::HandleLeaderData(RxInfo &aRxInfo)
{
    Error                     error = kErrorNone;
    LeaderData                leaderData;
    MeshCoP::Timestamp        activeTimestamp;
    MeshCoP::Timestamp        pendingTimestamp;
    const MeshCoP::Timestamp *timestamp;
    bool                      hasActiveTimestamp   = false;
    bool                      hasPendingTimestamp  = false;
    uint16_t                  networkDataOffset    = 0;
    uint16_t                  activeDatasetOffset  = 0;
    uint16_t                  pendingDatasetOffset = 0;
    bool                      dataRequest          = false;
    Tlv                       tlv;

    // Leader Data
    SuccessOrExit(error = ReadLeaderData(aRxInfo.mMessage, leaderData));

    if ((leaderData.GetPartitionId() != mLeaderData.GetPartitionId()) ||
        (leaderData.GetWeighting() != mLeaderData.GetWeighting()) || (leaderData.GetLeaderRouterId() != GetLeaderId()))
    {
        if (IsChild())
        {
            SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
            mRetrieveNewNetworkData = true;
        }
        else
        {
            ExitNow(error = kErrorDrop);
        }
    }
    else if (!mRetrieveNewNetworkData)
    {
        VerifyOrExit(IsNetworkDataNewer(leaderData));
    }

    // Active Timestamp
    switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, activeTimestamp))
    {
    case kErrorNone:
        hasActiveTimestamp = true;

        timestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();

        // if received timestamp does not match the local value and message does not contain the dataset,
        // send MLE Data Request
        if (!IsLeader() && (MeshCoP::Timestamp::Compare(&activeTimestamp, timestamp) != 0) &&
            (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kActiveDataset, activeDatasetOffset) != kErrorNone))
        {
            ExitNow(dataRequest = true);
        }

        break;

    case kErrorNotFound:
        break;

    default:
        ExitNow(error = kErrorParse);
    }

    // Pending Timestamp
    switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, pendingTimestamp))
    {
    case kErrorNone:
        hasPendingTimestamp = true;

        timestamp = Get<MeshCoP::PendingDatasetManager>().GetTimestamp();

        // if received timestamp does not match the local value and message does not contain the dataset,
        // send MLE Data Request
        if (!IsLeader() && (MeshCoP::Timestamp::Compare(&pendingTimestamp, timestamp) != 0) &&
            (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kPendingDataset, pendingDatasetOffset) != kErrorNone))
        {
            ExitNow(dataRequest = true);
        }

        break;

    case kErrorNotFound:
        break;

    default:
        ExitNow(error = kErrorParse);
    }

    if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kNetworkData, networkDataOffset) == kErrorNone)
    {
        error = Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(NetworkData::kFullSet),
                                                          leaderData.GetDataVersion(NetworkData::kStableSubset),
                                                          GetNetworkDataType(), aRxInfo.mMessage, networkDataOffset);
        SuccessOrExit(error);
    }
    else
    {
        ExitNow(dataRequest = true);
    }

#if OPENTHREAD_FTD
    if (IsLeader())
    {
        Get<NetworkData::Leader>().IncrementVersionAndStableVersion();
    }
    else
#endif
    {
        // Active Dataset
        if (hasActiveTimestamp)
        {
            if (activeDatasetOffset > 0)
            {
                IgnoreError(aRxInfo.mMessage.Read(activeDatasetOffset, tlv));
                IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Save(
                    activeTimestamp, aRxInfo.mMessage, activeDatasetOffset + sizeof(tlv), tlv.GetLength()));
            }
        }

        // Pending Dataset
        if (hasPendingTimestamp)
        {
            if (pendingDatasetOffset > 0)
            {
                IgnoreError(aRxInfo.mMessage.Read(pendingDatasetOffset, tlv));
                IgnoreError(Get<MeshCoP::PendingDatasetManager>().Save(
                    pendingTimestamp, aRxInfo.mMessage, pendingDatasetOffset + sizeof(tlv), tlv.GetLength()));
            }
        }
    }

    mRetrieveNewNetworkData = false;

exit:

    if (dataRequest)
    {
        static const uint8_t tlvs[] = {Tlv::kNetworkData};
        uint16_t             delay;

        if (aRxInfo.mMessageInfo.GetSockAddr().IsMulticast())
        {
            delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
        }
        else
        {
            // This method may have been called from an MLE request
            // handler.  We add a minimum delay here so that the MLE
            // response is enqueued before the MLE Data Request.
            delay = 10;
        }

        IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
    }
    else if (error == kErrorNone)
    {
        mDataRequestAttempts = 0;
        mDataRequestState    = kDataRequestNone;

        // Here the `mMessageTransmissionTimer` is intentionally not canceled
        // so that when it fires from its callback a "Child Update" is sent
        // if the device is a rx-on child. This way, even when the timer is
        // reused for retransmission of "Data Request" messages, it is ensured
        // that keep-alive "Child Update Request" messages are send within the
        // child's timeout.
    }

    return error;
}

bool Mle::IsBetterParent(uint16_t               aRloc16,
                         uint8_t                aLinkQuality,
                         uint8_t                aLinkMargin,
                         const ConnectivityTlv &aConnectivityTlv,
                         uint8_t                aVersion,
                         uint8_t                aCslClockAccuracy,
                         uint8_t                aCslUncertainty)
{
    bool rval = false;

    uint8_t candidateLinkQualityIn     = mParentCandidate.GetLinkInfo().GetLinkQuality();
    uint8_t candidateTwoWayLinkQuality = (candidateLinkQualityIn < mParentCandidate.GetLinkQualityOut())
                                             ? candidateLinkQualityIn
                                             : mParentCandidate.GetLinkQualityOut();
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    uint64_t candidateCslMetric = 0;
    uint64_t cslMetric          = 0;
#else
    OT_UNUSED_VARIABLE(aCslClockAccuracy);
    OT_UNUSED_VARIABLE(aCslUncertainty);
#endif

    // Mesh Impacting Criteria
    if (aLinkQuality != candidateTwoWayLinkQuality)
    {
        ExitNow(rval = (aLinkQuality > candidateTwoWayLinkQuality));
    }

    if (IsActiveRouter(aRloc16) != IsActiveRouter(mParentCandidate.GetRloc16()))
    {
        ExitNow(rval = IsActiveRouter(aRloc16));
    }

    if (aConnectivityTlv.GetParentPriority() != mParentPriority)
    {
        ExitNow(rval = (aConnectivityTlv.GetParentPriority() > mParentPriority));
    }

    // Prefer the parent with highest quality links (Link Quality 3 field in Connectivity TLV) to neighbors
    if (aConnectivityTlv.GetLinkQuality3() != mParentLinkQuality3)
    {
        ExitNow(rval = (aConnectivityTlv.GetLinkQuality3() > mParentLinkQuality3));
    }

    // Thread 1.2 Specification 4.5.2.1.2 Child Impacting Criteria
    if (aVersion != mParentCandidate.GetVersion())
    {
        ExitNow(rval = (aVersion > mParentCandidate.GetVersion()));
    }

    if (aConnectivityTlv.GetSedBufferSize() != mParentSedBufferSize)
    {
        ExitNow(rval = (aConnectivityTlv.GetSedBufferSize() > mParentSedBufferSize));
    }

    if (aConnectivityTlv.GetSedDatagramCount() != mParentSedDatagramCount)
    {
        ExitNow(rval = (aConnectivityTlv.GetSedDatagramCount() > mParentSedDatagramCount));
    }

    // Extra rules
    if (aConnectivityTlv.GetLinkQuality2() != mParentLinkQuality2)
    {
        ExitNow(rval = (aConnectivityTlv.GetLinkQuality2() > mParentLinkQuality2));
    }

    if (aConnectivityTlv.GetLinkQuality1() != mParentLinkQuality1)
    {
        ExitNow(rval = (aConnectivityTlv.GetLinkQuality1() > mParentLinkQuality1));
    }

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    // CSL metric
    if (!IsRxOnWhenIdle())
    {
        cslMetric = CalcParentCslMetric(aCslClockAccuracy, aCslUncertainty);
        candidateCslMetric =
            CalcParentCslMetric(mParentCandidate.GetCslClockAccuracy(), mParentCandidate.GetCslClockUncertainty());
        if (candidateCslMetric != cslMetric)
        {
            ExitNow(rval = (cslMetric < candidateCslMetric));
        }
    }
#endif

    rval = (aLinkMargin > mParentLinkMargin);

exit:
    return rval;
}

void Mle::HandleParentResponse(RxInfo &aRxInfo)
{
    Error                 error    = kErrorNone;
    const ThreadLinkInfo *linkInfo = aRxInfo.mMessageInfo.GetThreadLinkInfo();
    Challenge             response;
    uint16_t              version;
    uint16_t              sourceAddress;
    LeaderData            leaderData;
    uint8_t               linkMarginFromTlv;
    uint8_t               linkMargin;
    uint8_t               linkQuality;
    ConnectivityTlv       connectivity;
    uint32_t              linkFrameCounter;
    uint32_t              mleFrameCounter;
    Mac::ExtAddress       extAddress;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
    TimeParameterTlv timeParameter;
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    CslClockAccuracyTlv clockAccuracy;
#endif

    // Source Address
    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));

    Log(kMessageReceive, kTypeParentResponse, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);

    // Version
    SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
    VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);

    // Response
    SuccessOrExit(error = ReadResponse(aRxInfo.mMessage, response));
    VerifyOrExit(response == mParentRequestChallenge, error = kErrorParse);

    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddress);

    if (IsChild() && mParent.GetExtAddress() == extAddress)
    {
        mReceivedResponseFromParent = true;
    }

    // Leader Data
    SuccessOrExit(error = ReadLeaderData(aRxInfo.mMessage, leaderData));

    // Link Margin
    SuccessOrExit(error = Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMarginFromTlv));

    linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), linkInfo->GetRss());

    if (linkMargin > linkMarginFromTlv)
    {
        linkMargin = linkMarginFromTlv;
    }

    linkQuality = LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin);

    // Connectivity
    SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, connectivity));
    VerifyOrExit(connectivity.IsValid(), error = kErrorParse);

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    // CSL Accuracy
    if (Tlv::FindTlv(aRxInfo.mMessage, clockAccuracy) != kErrorNone)
    {
        clockAccuracy.SetCslClockAccuracy(kCslWorstCrystalPpm);
        clockAccuracy.SetCslUncertainty(kCslWorstUncertainty);
    }
#endif

    // Share data with application, if requested.
    if (mParentResponseCb)
    {
        otThreadParentResponseInfo parentinfo;

        parentinfo.mExtAddr      = extAddress;
        parentinfo.mRloc16       = sourceAddress;
        parentinfo.mRssi         = linkInfo->GetRss();
        parentinfo.mPriority     = connectivity.GetParentPriority();
        parentinfo.mLinkQuality3 = connectivity.GetLinkQuality3();
        parentinfo.mLinkQuality2 = connectivity.GetLinkQuality2();
        parentinfo.mLinkQuality1 = connectivity.GetLinkQuality1();
        parentinfo.mIsAttached   = IsAttached();

        mParentResponseCb(&parentinfo, mParentResponseCbContext);
    }

#if OPENTHREAD_FTD
    if (IsFullThreadDevice() && !IsDetached())
    {
        bool isPartitionIdSame = (leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
        bool isIdSequenceSame  = (connectivity.GetIdSequence() == Get<RouterTable>().GetRouterIdSequence());
        bool isIdSequenceGreater =
            SerialNumber::IsGreater(connectivity.GetIdSequence(), Get<RouterTable>().GetRouterIdSequence());

        switch (mAttachMode)
        {
        case kAnyPartition:
        case kBetterParent:
            VerifyOrExit(!isPartitionIdSame || isIdSequenceGreater);
            break;

        case kSamePartition:
        case kSamePartitionRetry:
            VerifyOrExit(isPartitionIdSame && isIdSequenceGreater);
            break;

        case kDowngradeToReed:
            VerifyOrExit(isPartitionIdSame && (isIdSequenceSame || isIdSequenceGreater));
            break;

        case kBetterPartition:
            VerifyOrExit(!isPartitionIdSame);

            VerifyOrExit(MleRouter::ComparePartitions(connectivity.GetActiveRouters() <= 1, leaderData,
                                                      Get<MleRouter>().IsSingleton(), mLeaderData) > 0);
            break;
        }
    }
#endif

    // Continue to process the "ParentResponse" if it is from current
    // parent candidate to update the challenge and frame counters.

    if (mParentCandidate.IsStateParentResponse() && (mParentCandidate.GetExtAddress() != extAddress))
    {
        // if already have a candidate parent, only seek a better parent

        int compare = 0;

#if OPENTHREAD_FTD
        if (IsFullThreadDevice())
        {
            compare = MleRouter::ComparePartitions(connectivity.GetActiveRouters() <= 1, leaderData, mParentIsSingleton,
                                                   mParentLeaderData);
        }

        // only consider partitions that are the same or better
        VerifyOrExit(compare >= 0);
#endif

        // only consider better parents if the partitions are the same
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        VerifyOrExit(compare != 0 ||
                     IsBetterParent(sourceAddress, linkQuality, linkMargin, connectivity, static_cast<uint8_t>(version),
                                    clockAccuracy.GetCslClockAccuracy(), clockAccuracy.GetCslUncertainty()));
#else
        VerifyOrExit(compare != 0 || IsBetterParent(sourceAddress, linkQuality, linkMargin, connectivity,
                                                    static_cast<uint8_t>(version), 0, 0));
#endif
    }

    // Link/MLE Frame Counters
    SuccessOrExit(error = ReadFrameCounters(aRxInfo.mMessage, linkFrameCounter, mleFrameCounter));

#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE

    // Time Parameter
    if (Tlv::FindTlv(aRxInfo.mMessage, timeParameter) == kErrorNone)
    {
        VerifyOrExit(timeParameter.IsValid());

        Get<TimeSync>().SetTimeSyncPeriod(timeParameter.GetTimeSyncPeriod());
        Get<TimeSync>().SetXtalThreshold(timeParameter.GetXtalThreshold());
    }

#if OPENTHREAD_CONFIG_TIME_SYNC_REQUIRED
    else
    {
        // If the time sync feature is required, don't choose the parent which doesn't support it.
        ExitNow();
    }

#endif // OPENTHREAD_CONFIG_TIME_SYNC_REQUIRED
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE

    // Challenge
    SuccessOrExit(error = ReadChallenge(aRxInfo.mMessage, mParentCandidateChallenge));

    mParentCandidate.SetExtAddress(extAddress);
    mParentCandidate.SetRloc16(sourceAddress);
    mParentCandidate.GetLinkFrameCounters().SetAll(linkFrameCounter);
    mParentCandidate.SetLinkAckFrameCounter(linkFrameCounter);
    mParentCandidate.SetMleFrameCounter(mleFrameCounter);
    mParentCandidate.SetVersion(static_cast<uint8_t>(version));
    mParentCandidate.SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
                                              DeviceMode::kModeFullNetworkData));
    mParentCandidate.GetLinkInfo().Clear();
    mParentCandidate.GetLinkInfo().AddRss(linkInfo->GetRss());
    mParentCandidate.ResetLinkFailures();
    mParentCandidate.SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMarginFromTlv));
    mParentCandidate.SetState(Neighbor::kStateParentResponse);
    mParentCandidate.SetKeySequence(aRxInfo.mKeySequence);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    mParentCandidate.SetCslClockAccuracy(clockAccuracy.GetCslClockAccuracy());
    mParentCandidate.SetCslClockUncertainty(clockAccuracy.GetCslUncertainty());
#endif

    mParentPriority         = connectivity.GetParentPriority();
    mParentLinkQuality3     = connectivity.GetLinkQuality3();
    mParentLinkQuality2     = connectivity.GetLinkQuality2();
    mParentLinkQuality1     = connectivity.GetLinkQuality1();
    mParentLeaderCost       = connectivity.GetLeaderCost();
    mParentSedBufferSize    = connectivity.GetSedBufferSize();
    mParentSedDatagramCount = connectivity.GetSedDatagramCount();
    mParentLeaderData       = leaderData;
    mParentIsSingleton      = connectivity.GetActiveRouters() <= 1;
    mParentLinkMargin       = linkMargin;

exit:
    LogProcessError(kTypeParentResponse, error);
}

void Mle::HandleChildIdResponse(RxInfo &aRxInfo)
{
    Error              error = kErrorNone;
    LeaderData         leaderData;
    uint16_t           sourceAddress;
    uint16_t           shortAddress;
    MeshCoP::Timestamp timestamp;
    Tlv                tlv;
    uint16_t           networkDataOffset;
    uint16_t           offset;

    // Source Address
    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));

    Log(kMessageReceive, kTypeChildIdResponse, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);

    VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid(), error = kErrorSecurity);

    VerifyOrExit(mAttachState == kAttachStateChildIdRequest);

    // ShortAddress
    SuccessOrExit(error = Tlv::Find<Address16Tlv>(aRxInfo.mMessage, shortAddress));
    VerifyOrExit(RouterIdMatch(sourceAddress, shortAddress), error = kErrorRejected);

    // Leader Data
    SuccessOrExit(error = ReadLeaderData(aRxInfo.mMessage, leaderData));

    // Network Data
    error = Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kNetworkData, networkDataOffset);
    SuccessOrExit(error);

    // Active Timestamp
    switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
    {
    case kErrorNone:
        // Active Dataset
        if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kActiveDataset, offset) == kErrorNone)
        {
            IgnoreError(aRxInfo.mMessage.Read(offset, tlv));
            SuccessOrExit(error = Get<MeshCoP::ActiveDatasetManager>().Save(timestamp, aRxInfo.mMessage,
                                                                            offset + sizeof(tlv), tlv.GetLength()));
        }
        break;

    case kErrorNotFound:
        break;

    default:
        ExitNow(error = kErrorParse);
    }

    // clear Pending Dataset if device succeed to reattach using stored Pending Dataset
    if (mReattachState == kReattachPending)
    {
        Get<MeshCoP::PendingDatasetManager>().Clear();
    }

    // Pending Timestamp
    switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
    {
    case kErrorNone:
        // Pending Dataset
        if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kPendingDataset, offset) == kErrorNone)
        {
            IgnoreError(aRxInfo.mMessage.Read(offset, tlv));
            IgnoreError(Get<MeshCoP::PendingDatasetManager>().Save(timestamp, aRxInfo.mMessage, offset + sizeof(tlv),
                                                                   tlv.GetLength()));
        }
        break;

    case kErrorNotFound:
        Get<MeshCoP::PendingDatasetManager>().ClearNetwork();
        break;

    default:
        ExitNow(error = kErrorParse);
    }

#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
    // Sync to Thread network time
    if (aRxInfo.mMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ)
    {
        Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
    }
#endif

    // Parent Attach Success

    SetStateDetached();

    SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());

#if OPENTHREAD_FTD
    if (IsFullThreadDevice())
    {
        RouteTlv route;

        if (Tlv::FindTlv(aRxInfo.mMessage, route) == kErrorNone)
        {
            SuccessOrExit(error = Get<MleRouter>().ProcessRouteTlv(route));
        }
    }
#endif

    mParent = mParentCandidate;
    mParentCandidate.Clear();

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    Get<Mac::Mac>().SetCslParentUncertainty(mParent.GetCslClockUncertainty());
    Get<Mac::Mac>().SetCslParentClockAccuracy(mParent.GetCslClockAccuracy());
#endif

    mParent.SetRloc16(sourceAddress);

    IgnoreError(Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(NetworkData::kFullSet),
                                                          leaderData.GetDataVersion(NetworkData::kStableSubset),
                                                          GetNetworkDataType(), aRxInfo.mMessage, networkDataOffset));

    SetStateChild(shortAddress);

    if (!IsRxOnWhenIdle())
    {
        Get<DataPollSender>().SetAttachMode(false);
        Get<MeshForwarder>().SetRxOnWhenIdle(false);
    }
    else
    {
        Get<MeshForwarder>().SetRxOnWhenIdle(true);
    }

exit:
    LogProcessError(kTypeChildIdResponse, error);
}

void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
{
    static const uint8_t kMaxResponseTlvs = 6;

    Error         error = kErrorNone;
    uint16_t      sourceAddress;
    Challenge     challenge;
    RequestedTlvs requestedTlvs;
    uint8_t       tlvs[kMaxResponseTlvs] = {};
    uint8_t       numTlvs                = 0;

    // Source Address
    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));

    Log(kMessageReceive, kTypeChildUpdateRequestOfParent, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);

    // Challenge
    switch (ReadChallenge(aRxInfo.mMessage, challenge))
    {
    case kErrorNone:
        tlvs[numTlvs++] = Tlv::kResponse;
        tlvs[numTlvs++] = Tlv::kMleFrameCounter;
        tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
        break;
    case kErrorNotFound:
        challenge.mLength = 0;
        break;
    default:
        ExitNow(error = kErrorParse);
    }

    if (aRxInfo.mNeighbor == &mParent)
    {
        uint8_t status;

        switch (Tlv::Find<StatusTlv>(aRxInfo.mMessage, status))
        {
        case kErrorNone:
            VerifyOrExit(status != StatusTlv::kError, IgnoreError(BecomeDetached()));
            break;
        case kErrorNotFound:
            break;
        default:
            ExitNow(error = kErrorParse);
        }

        if (mParent.GetRloc16() != sourceAddress)
        {
            IgnoreError(BecomeDetached());
            ExitNow();
        }

        // Leader Data, Network Data, Active Timestamp, Pending Timestamp
        SuccessOrExit(error = HandleLeaderData(aRxInfo));

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        CslClockAccuracyTlv cslClockAccuracyTlv;
        if (Tlv::FindTlv(aRxInfo.mMessage, cslClockAccuracyTlv) == kErrorNone)
        {
            // MUST include CSL timeout TLV when request includes CSL accuracy
            tlvs[numTlvs++] = Tlv::kCslTimeout;
        }
#endif
    }
    else
    {
        // this device is not a child of the Child Update Request source
        tlvs[numTlvs++] = Tlv::kStatus;
    }

    // TLV Request
    switch (FindTlvRequest(aRxInfo.mMessage, requestedTlvs))
    {
    case kErrorNone:
        for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
        {
            if (numTlvs >= sizeof(tlvs))
            {
                LogWarn("Failed to respond with TLVs: %d of %d", i, requestedTlvs.mNumTlvs);
                break;
            }

            tlvs[numTlvs++] = requestedTlvs.mTlvs[i];
        }
        break;
    case kErrorNotFound:
        break;
    default:
        ExitNow(error = kErrorParse);
    }

#if OPENTHREAD_CONFIG_MULTI_RADIO
    if ((aRxInfo.mNeighbor != nullptr) && (challenge.mLength != 0))
    {
        aRxInfo.mNeighbor->ClearLastRxFragmentTag();
    }
#endif

    SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge));

exit:
    LogProcessError(kTypeChildUpdateRequestOfParent, error);
}

void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo)
{
    Error     error = kErrorNone;
    uint8_t   status;
    uint8_t   mode;
    Challenge response;
    uint32_t  linkFrameCounter;
    uint32_t  mleFrameCounter;
    uint16_t  sourceAddress;
    uint32_t  timeout;
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
    CslClockAccuracyTlv clockAccuracy;
#endif

    Log(kMessageReceive, kTypeChildUpdateResponseOfParent, aRxInfo.mMessageInfo.GetPeerAddr());

    switch (mRole)
    {
    case kRoleDetached:
        SuccessOrExit(error = ReadResponse(aRxInfo.mMessage, response));
        VerifyOrExit(response == mParentRequestChallenge, error = kErrorSecurity);
        break;

    case kRoleChild:
        VerifyOrExit((aRxInfo.mNeighbor == &mParent) && mParent.IsStateValid(), error = kErrorSecurity);
        break;

    default:
        OT_ASSERT(false);
        OT_UNREACHABLE_CODE(break);
    }

    // Status
    if (Tlv::Find<StatusTlv>(aRxInfo.mMessage, status) == kErrorNone)
    {
        IgnoreError(BecomeDetached());
        ExitNow();
    }

    // Mode
    SuccessOrExit(error = Tlv::Find<ModeTlv>(aRxInfo.mMessage, mode));
    VerifyOrExit(DeviceMode(mode) == mDeviceMode, error = kErrorDrop);

    switch (mRole)
    {
    case kRoleDetached:
        SuccessOrExit(error = ReadFrameCounters(aRxInfo.mMessage, linkFrameCounter, mleFrameCounter));

        mParent.GetLinkFrameCounters().SetAll(linkFrameCounter);
        mParent.SetLinkAckFrameCounter(linkFrameCounter);
        mParent.SetMleFrameCounter(mleFrameCounter);

        mParent.SetState(Neighbor::kStateValid);
        SetStateChild(GetRloc16());

        mRetrieveNewNetworkData = true;

        OT_FALL_THROUGH;

    case kRoleChild:
        // Source Address
        SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));

        if (RouterIdFromRloc16(sourceAddress) != RouterIdFromRloc16(GetRloc16()))
        {
            IgnoreError(BecomeDetached());
            ExitNow();
        }

        // Leader Data, Network Data, Active Timestamp, Pending Timestamp
        SuccessOrExit(error = HandleLeaderData(aRxInfo));

        // Timeout optional
        switch (Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout))
        {
        case kErrorNone:
            mTimeout = timeout;
            break;
        case kErrorNotFound:
            break;
        default:
            ExitNow(error = kErrorParse);
        }

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
        // CSL Accuracy
        if (Tlv::FindTlv(aRxInfo.mMessage, clockAccuracy) != kErrorNone)
        {
            Get<Mac::Mac>().SetCslParentClockAccuracy(clockAccuracy.GetCslClockAccuracy());
            Get<Mac::Mac>().SetCslParentUncertainty(clockAccuracy.GetCslUncertainty());
        }
#endif

        if (!IsRxOnWhenIdle())
        {
            Get<DataPollSender>().SetAttachMode(false);
            Get<MeshForwarder>().SetRxOnWhenIdle(false);
        }
        else
        {
            Get<MeshForwarder>().SetRxOnWhenIdle(true);
        }

        break;

    default:
        OT_ASSERT(false);
        OT_UNREACHABLE_CODE(break);
    }

exit:

    if (error == kErrorNone)
    {
        if (mChildUpdateRequestState == kChildUpdateRequestActive)
        {
            mChildUpdateAttempts     = 0;
            mChildUpdateRequestState = kChildUpdateRequestNone;
            ScheduleMessageTransmissionTimer();
        }
    }

    LogProcessError(kTypeChildUpdateResponseOfParent, error);
}

void Mle::HandleAnnounce(RxInfo &aRxInfo)
{
    Error                     error = kErrorNone;
    ChannelTlv                channelTlv;
    MeshCoP::Timestamp        timestamp;
    const MeshCoP::Timestamp *localTimestamp;
    uint8_t                   channel;
    uint16_t                  panId;

    Log(kMessageReceive, kTypeAnnounce, aRxInfo.mMessageInfo.GetPeerAddr());

    SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, channelTlv));
    VerifyOrExit(channelTlv.IsValid(), error = kErrorParse);

    channel = static_cast<uint8_t>(channelTlv.GetChannel());

    SuccessOrExit(error = Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp));
    SuccessOrExit(error = Tlv::Find<PanIdTlv>(aRxInfo.mMessage, panId));

    localTimestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();

    if (MeshCoP::Timestamp::Compare(&timestamp, localTimestamp) > 0)
    {
        // No action is required if device is detached, and current
        // channel and pan-id match the values from the received MLE
        // Announce message.

        VerifyOrExit(!IsDetached() || (Get<Mac::Mac>().GetPanChannel() != channel) ||
                     (Get<Mac::Mac>().GetPanId() != panId));

        if (mAttachState == kAttachStateProcessAnnounce)
        {
            VerifyOrExit(mAlternateTimestamp < timestamp.GetSeconds());
        }

        mAlternateTimestamp = timestamp.GetSeconds();
        mAlternateChannel   = channel;
        mAlternatePanId     = panId;
        SetAttachState(kAttachStateProcessAnnounce);
        mAttachTimer.Start(kAnnounceProcessTimeout);
        mAttachCounter = 0;

        LogNote("Delay processing Announce - channel %d, panid 0x%02x", channel, panId);
    }
    else if (MeshCoP::Timestamp::Compare(&timestamp, localTimestamp) < 0)
    {
        SendAnnounce(channel);

#if OPENTHREAD_CONFIG_MLE_SEND_UNICAST_ANNOUNCE_RESPONSE
        SendAnnounce(channel, aRxInfo.mMessageInfo.GetPeerAddr());
#endif
    }
    else
    {
        // Timestamps are equal.

#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
        // Notify `AnnounceSender` of the received Announce
        // message so it can update its state to determine
        // whether to send Announce or not.
        Get<AnnounceSender>().UpdateOnReceivedAnnounce();
#endif
    }

exit:
    LogProcessError(kTypeAnnounce, error);
}

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
void Mle::HandleLinkMetricsManagementRequest(RxInfo &aRxInfo)
{
    Error               error = kErrorNone;
    LinkMetrics::Status status;

    Log(kMessageReceive, kTypeLinkMetricsManagementRequest, aRxInfo.mMessageInfo.GetPeerAddr());

    VerifyOrExit(aRxInfo.mNeighbor != nullptr, error = kErrorInvalidState);

    SuccessOrExit(
        error = Get<LinkMetrics::LinkMetrics>().HandleManagementRequest(aRxInfo.mMessage, *aRxInfo.mNeighbor, status));
    error = SendLinkMetricsManagementResponse(aRxInfo.mMessageInfo.GetPeerAddr(), status);

exit:
    LogProcessError(kTypeLinkMetricsManagementRequest, error);
}

#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
void Mle::HandleLinkMetricsManagementResponse(RxInfo &aRxInfo)
{
    Error error = kErrorNone;

    Log(kMessageReceive, kTypeLinkMetricsManagementResponse, aRxInfo.mMessageInfo.GetPeerAddr());

    VerifyOrExit(aRxInfo.mNeighbor != nullptr, error = kErrorInvalidState);

    error =
        Get<LinkMetrics::LinkMetrics>().HandleManagementResponse(aRxInfo.mMessage, aRxInfo.mMessageInfo.GetPeerAddr());

exit:
    LogProcessError(kTypeLinkMetricsManagementResponse, error);
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
void Mle::HandleLinkProbe(RxInfo &aRxInfo)
{
    Error   error = kErrorNone;
    uint8_t seriesId;

    Log(kMessageReceive, kTypeLinkProbe, aRxInfo.mMessageInfo.GetPeerAddr());

    SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().HandleLinkProbe(aRxInfo.mMessage, seriesId));
    aRxInfo.mNeighbor->AggregateLinkMetrics(seriesId, LinkMetrics::SeriesInfo::kSeriesTypeLinkProbe,
                                            aRxInfo.mMessage.GetAverageLqi(), aRxInfo.mMessage.GetAverageRss());

exit:
    LogProcessError(kTypeLinkProbe, error);
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE

void Mle::ProcessAnnounce(void)
{
    uint8_t  newChannel = mAlternateChannel;
    uint16_t newPanId   = mAlternatePanId;

    OT_ASSERT(mAttachState == kAttachStateProcessAnnounce);

    LogNote("Processing Announce - channel %d, panid 0x%02x", newChannel, newPanId);

    Stop(kKeepNetworkDatasets);

    // Save the current/previous channel and pan-id
    mAlternateChannel   = Get<Mac::Mac>().GetPanChannel();
    mAlternatePanId     = Get<Mac::Mac>().GetPanId();
    mAlternateTimestamp = 0;

    IgnoreError(Get<Mac::Mac>().SetPanChannel(newChannel));
    Get<Mac::Mac>().SetPanId(newPanId);

    IgnoreError(Start(kAnnounceAttach));
}

uint16_t Mle::GetNextHop(uint16_t aDestination) const
{
    OT_UNUSED_VARIABLE(aDestination);
    return (mParent.IsStateValid()) ? mParent.GetRloc16() : static_cast<uint16_t>(Mac::kShortAddrInvalid);
}

bool Mle::IsRoutingLocator(const Ip6::Address &aAddress) const
{
    return IsMeshLocalAddress(aAddress) && aAddress.GetIid().IsRoutingLocator();
}

bool Mle::IsAnycastLocator(const Ip6::Address &aAddress) const
{
    return IsMeshLocalAddress(aAddress) && aAddress.GetIid().IsAnycastLocator();
}

bool Mle::IsMeshLocalAddress(const Ip6::Address &aAddress) const
{
    return (aAddress.GetPrefix() == GetMeshLocalPrefix());
}

Error Mle::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
{
    Error error;

    if ((aMeshDest != GetRloc16()) || Get<ThreadNetif>().HasUnicastAddress(aIp6Header.GetDestination()))
    {
        error = kErrorNone;
    }
    else
    {
        error = kErrorNoRoute;
    }

    return error;
}

#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
void Mle::InformPreviousParent(void)
{
    Error            error   = kErrorNone;
    Message *        message = nullptr;
    Ip6::MessageInfo messageInfo;

    VerifyOrExit((message = Get<Ip6::Ip6>().NewMessage(0)) != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = message->SetLength(0));

    messageInfo.SetSockAddr(GetMeshLocal64());
    messageInfo.SetPeerAddr(GetMeshLocal16());
    messageInfo.GetPeerAddr().GetIid().SetLocator(mPreviousParentRloc);

    SuccessOrExit(error = Get<Ip6::Ip6>().SendDatagram(*message, messageInfo, Ip6::kProtoNone));

    LogNote("Sending message to inform previous parent 0x%04x", mPreviousParentRloc);

exit:

    if (error != kErrorNone)
    {
        LogWarn("Failed to inform previous parent: %s", ErrorToString(error));

        FreeMessage(message);
    }
}
#endif // OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH

#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
void Mle::HandleParentSearchTimer(Timer &aTimer)
{
    aTimer.Get<Mle>().HandleParentSearchTimer();
}

void Mle::HandleParentSearchTimer(void)
{
    int8_t parentRss;

    LogInfo("PeriodicParentSearch: %s interval passed", mParentSearchIsInBackoff ? "Backoff" : "Check");

    if (mParentSearchBackoffWasCanceled)
    {
        // Backoff can be canceled if the device switches to a new parent.
        // from `UpdateParentSearchState()`. We want to limit this to happen
        // only once within a backoff interval.

        if (TimerMilli::GetNow() - mParentSearchBackoffCancelTime >= kParentSearchBackoffInterval)
        {
            mParentSearchBackoffWasCanceled = false;
            LogInfo("PeriodicParentSearch: Backoff cancellation is allowed on parent switch");
        }
    }

    mParentSearchIsInBackoff = false;

    VerifyOrExit(IsChild());

    parentRss = GetParent().GetLinkInfo().GetAverageRss();
    LogInfo("PeriodicParentSearch: Parent RSS %d", parentRss);
    VerifyOrExit(parentRss != OT_RADIO_RSSI_INVALID);

    if (parentRss < kParentSearchRssThreadhold)
    {
        LogInfo("PeriodicParentSearch: Parent RSS less than %d, searching for new parents", kParentSearchRssThreadhold);
        mParentSearchIsInBackoff = true;
        Attach(kBetterParent);
    }

exit:
    StartParentSearchTimer();
}

void Mle::StartParentSearchTimer(void)
{
    uint32_t interval;

    interval = Random::NonCrypto::GetUint32InRange(0, kParentSearchJitterInterval);

    if (mParentSearchIsInBackoff)
    {
        interval += kParentSearchBackoffInterval;
    }
    else
    {
        interval += kParentSearchCheckInterval;
    }

    mParentSearchTimer.Start(interval);

    LogInfo("PeriodicParentSearch: (Re)starting timer for %s interval", mParentSearchIsInBackoff ? "backoff" : "check");
}

void Mle::UpdateParentSearchState(void)
{
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH

    // If we are in middle of backoff and backoff was not canceled
    // recently and we recently detached from a previous parent,
    // then we check if the new parent is different from the previous
    // one, and if so, we cancel the backoff mode and also remember
    // the backoff cancel time. This way the canceling of backoff
    // is allowed only once within a backoff window.
    //
    // The reason behind the canceling of the backoff is to handle
    // the scenario where a previous parent is not available for a
    // short duration (e.g., it is going through a software update)
    // and the child switches to a less desirable parent. With this
    // model the child will check for other parents sooner and have
    // the chance to switch back to the original (and possibly
    // preferred) parent more quickly.

    if (mParentSearchIsInBackoff && !mParentSearchBackoffWasCanceled && mParentSearchRecentlyDetached)
    {
        if ((mPreviousParentRloc != Mac::kShortAddrInvalid) && (mPreviousParentRloc != mParent.GetRloc16()))
        {
            mParentSearchIsInBackoff        = false;
            mParentSearchBackoffWasCanceled = true;
            mParentSearchBackoffCancelTime  = TimerMilli::GetNow();
            LogInfo("PeriodicParentSearch: Canceling backoff on switching to a new parent");
        }
    }

#endif // OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH

    mParentSearchRecentlyDetached = false;

    if (!mParentSearchIsInBackoff)
    {
        StartParentSearchTimer();
    }
}
#endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
void Mle::Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress)
{
    Log(aAction, aType, aAddress, Mac::kShortAddrInvalid);
}

void Mle::Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc)
{
    enum : uint8_t
    {
        kRlocStringSize = 17,
    };

    String<kRlocStringSize> rlocString;

    if (aRloc != Mac::kShortAddrInvalid)
    {
        rlocString.Append(",0x%04x", aRloc);
    }

    LogInfo("%s %s%s (%s%s)", MessageActionToString(aAction), MessageTypeToString(aType),
            MessageTypeActionToSuffixString(aType, aAction), aAddress.ToString().AsCString(), rlocString.AsCString());
}
#endif

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
void Mle::LogProcessError(MessageType aType, Error aError)
{
    LogError(kMessageReceive, aType, aError);
}

void Mle::LogSendError(MessageType aType, Error aError)
{
    LogError(kMessageSend, aType, aError);
}

void Mle::LogError(MessageAction aAction, MessageType aType, Error aError)
{
    if (aError != kErrorNone)
    {
        if (aAction == kMessageReceive && (aError == kErrorDrop || aError == kErrorNoRoute))
        {
            LogInfo("Failed to %s %s%s: %s", "process", MessageTypeToString(aType),
                    MessageTypeActionToSuffixString(aType, aAction), ErrorToString(aError));
        }
        else
        {
            LogWarn("Failed to %s %s%s: %s", aAction == kMessageSend ? "send" : "process", MessageTypeToString(aType),
                    MessageTypeActionToSuffixString(aType, aAction), ErrorToString(aError));
        }
    }
}

const char *Mle::MessageActionToString(MessageAction aAction)
{
    static const char *const kMessageActionStrings[] = {
        "Send",           // (0) kMessageSend
        "Receive",        // (1) kMessageReceive
        "Delay",          // (2) kMessageDelay
        "Remove Delayed", // (3) kMessageRemoveDelayed
    };

    static_assert(kMessageSend == 0, "kMessageSend value is incorrect");
    static_assert(kMessageReceive == 1, "kMessageReceive value is incorrect");
    static_assert(kMessageDelay == 2, "kMessageDelay value is incorrect");
    static_assert(kMessageRemoveDelayed == 3, "kMessageRemoveDelayed value is incorrect");

    return kMessageActionStrings[aAction];
}

const char *Mle::MessageTypeToString(MessageType aType)
{
    static const char *const kMessageTypeStrings[] = {
        "Advertisement",         // (0)  kTypeAdvertisement
        "Announce",              // (1)  kTypeAnnounce
        "Child ID Request",      // (2)  kTypeChildIdRequest
        "Child ID Request",      // (3)  kTypeChildIdRequestShort
        "Child ID Response",     // (4)  kTypeChildIdResponse
        "Child Update Request",  // (5)  kTypeChildUpdateRequestOfParent
        "Child Update Response", // (6)  kTypeChildUpdateResponseOfParent
        "Data Request",          // (7)  kTypeDataRequest
        "Data Response",         // (8)  kTypeDataResponse
        "Discovery Request",     // (9)  kTypeDiscoveryRequest
        "Discovery Response",    // (10) kTypeDiscoveryResponse
        "delayed message",       // (11) kTypeGenericDelayed
        "UDP",                   // (12) kTypeGenericUdp
        "Parent Request",        // (13) kTypeParentRequestToRouters
        "Parent Request",        // (14) kTypeParentRequestToRoutersReeds
        "Parent Response",       // (15) kTypeParentResponse
#if OPENTHREAD_FTD
        "Address Release",         // (16) kTypeAddressRelease
        "Address Release Reply",   // (17) kTypeAddressReleaseReply
        "Address Reply",           // (18) kTypeAddressReply
        "Address Solicit",         // (19) kTypeAddressSolicit
        "Child Update Request",    // (20) kTypeChildUpdateRequestOfChild
        "Child Update Response",   // (21) kTypeChildUpdateResponseOfChild
        "Child Update Response",   // (22) kTypeChildUpdateResponseOfUnknownChild
        "Link Accept",             // (23) kTypeLinkAccept
        "Link Accept and Request", // (24) kTypeLinkAcceptAndRequest
        "Link Reject",             // (25) kTypeLinkReject
        "Link Request",            // (26) kTypeLinkRequest
        "Parent Request",          // (27) kTypeParentRequest
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
        "Time Sync", // (28) kTypeTimeSync
#endif
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
        "Link Metrics Management Request",  // (29) kTypeLinkMetricsManagementRequest
        "Link Metrics Management Response", // (30) kTypeLinkMetricsManagementResponse
        "Link Probe",                       // (31) kTypeLinkProbe
#endif
    };

    static_assert(kTypeAdvertisement == 0, "kTypeAdvertisement value is incorrect");
    static_assert(kTypeAnnounce == 1, "kTypeAnnounce value is incorrect");
    static_assert(kTypeChildIdRequest == 2, "kTypeChildIdRequest value is incorrect");
    static_assert(kTypeChildIdRequestShort == 3, "kTypeChildIdRequestShort value is incorrect");
    static_assert(kTypeChildIdResponse == 4, "kTypeChildIdResponse value is incorrect");
    static_assert(kTypeChildUpdateRequestOfParent == 5, "kTypeChildUpdateRequestOfParent value is incorrect");
    static_assert(kTypeChildUpdateResponseOfParent == 6, "kTypeChildUpdateResponseOfParent value is incorrect");
    static_assert(kTypeDataRequest == 7, "kTypeDataRequest value is incorrect");
    static_assert(kTypeDataResponse == 8, "kTypeDataResponse value is incorrect");
    static_assert(kTypeDiscoveryRequest == 9, "kTypeDiscoveryRequest value is incorrect");
    static_assert(kTypeDiscoveryResponse == 10, "kTypeDiscoveryResponse value is incorrect");
    static_assert(kTypeGenericDelayed == 11, "kTypeGenericDelayed value is incorrect");
    static_assert(kTypeGenericUdp == 12, "kTypeGenericUdp value is incorrect");
    static_assert(kTypeParentRequestToRouters == 13, "kTypeParentRequestToRouters value is incorrect");
    static_assert(kTypeParentRequestToRoutersReeds == 14, "kTypeParentRequestToRoutersReeds value is incorrect");
    static_assert(kTypeParentResponse == 15, "kTypeParentResponse value is incorrect");
#if OPENTHREAD_FTD
    static_assert(kTypeAddressRelease == 16, "kTypeAddressRelease value is incorrect");
    static_assert(kTypeAddressReleaseReply == 17, "kTypeAddressReleaseReply value is incorrect");
    static_assert(kTypeAddressReply == 18, "kTypeAddressReply value is incorrect");
    static_assert(kTypeAddressSolicit == 19, "kTypeAddressSolicit value is incorrect");
    static_assert(kTypeChildUpdateRequestOfChild == 20, "kTypeChildUpdateRequestOfChild value is incorrect");
    static_assert(kTypeChildUpdateResponseOfChild == 21, "kTypeChildUpdateResponseOfChild value is incorrect");
    static_assert(kTypeChildUpdateResponseOfUnknownChild == 22, "kTypeChildUpdateResponseOfUnknownChild is incorrect");
    static_assert(kTypeLinkAccept == 23, "kTypeLinkAccept value is incorrect");
    static_assert(kTypeLinkAcceptAndRequest == 24, "kTypeLinkAcceptAndRequest value is incorrect");
    static_assert(kTypeLinkReject == 25, "kTypeLinkReject value is incorrect");
    static_assert(kTypeLinkRequest == 26, "kTypeLinkRequest value is incorrect");
    static_assert(kTypeParentRequest == 27, "kTypeParentRequest value is incorrect");
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
    static_assert(kTypeTimeSync == 28, "kTypeTimeSync value is incorrect");
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
    static_assert(kTypeLinkMetricsManagementRequest == 29, "kTypeLinkMetricsManagementRequest value is incorrect)");
    static_assert(kTypeLinkMetricsManagementResponse == 30, "kTypeLinkMetricsManagementResponse value is incorrect)");
    static_assert(kTypeLinkProbe == 31, "kTypeLinkProbe value is incorrect)");
#endif
#else // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
    static_assert(kTypeLinkMetricsManagementRequest == 28, "kTypeLinkMetricsManagementRequest value is incorrect)");
    static_assert(kTypeLinkMetricsManagementResponse == 29, "kTypeLinkMetricsManagementResponse value is incorrect)");
    static_assert(kTypeLinkProbe == 30, "kTypeLinkProbe value is incorrect)");
#endif
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
#else  // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
    static_assert(kTypeLinkMetricsManagementRequest == 16, "kTypeLinkMetricsManagementRequest value is incorrect)");
    static_assert(kTypeLinkMetricsManagementResponse == 17, "kTypeLinkMetricsManagementResponse value is incorrect)");
    static_assert(kTypeLinkProbe == 18, "kTypeLinkProbe value is incorrect)");
#endif
#endif // OPENTHREAD_FTD

    return kMessageTypeStrings[aType];
}

const char *Mle::MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction)
{
    const char *str = "";

    switch (aType)
    {
    case kTypeChildIdRequestShort:
        str = " - short";
        break;
    case kTypeChildUpdateRequestOfParent:
    case kTypeChildUpdateResponseOfParent:
        str = (aAction == kMessageReceive) ? " from parent" : " to parent";
        break;
    case kTypeParentRequestToRouters:
        str = " to routers";
        break;
    case kTypeParentRequestToRoutersReeds:
        str = " to routers and REEDs";
        break;
#if OPENTHREAD_FTD
    case kTypeChildUpdateRequestOfChild:
    case kTypeChildUpdateResponseOfChild:
        str = (aAction == kMessageReceive) ? " from child" : " to child";
        break;
    case kTypeChildUpdateResponseOfUnknownChild:
        str = (aAction == kMessageReceive) ? " from unknown child" : " to child";
        break;
#endif // OPENTHREAD_FTD
    default:
        break;
    }

    return str;
}

#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_WARN)

const char *Mle::RoleToString(DeviceRole aRole)
{
    static const char *const kRoleStrings[] = {
        "disabled", // (0) kRoleDisabled
        "detached", // (1) kRoleDetached
        "child",    // (2) kRoleChild
        "router",   // (3) kRoleRouter
        "leader",   // (4) kRoleLeader
    };

    static_assert(kRoleDisabled == 0, "kRoleDisabled value is incorrect");
    static_assert(kRoleDetached == 1, "kRoleDetached value is incorrect");
    static_assert(kRoleChild == 2, "kRoleChild value is incorrect");
    static_assert(kRoleRouter == 3, "kRoleRouter value is incorrect");
    static_assert(kRoleLeader == 4, "kRoleLeader value is incorrect");

    return (aRole < GetArrayLength(kRoleStrings)) ? kRoleStrings[aRole] : "invalid";
}

// LCOV_EXCL_START

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)

const char *Mle::AttachModeToString(AttachMode aMode)
{
    static const char *const kAttachModeStrings[] = {
        "AnyPartition",       // (0) kAnyPartition
        "SamePartition",      // (1) kSamePartition
        "SamePartitionRetry", // (2) kSamePartitionRetry
        "BetterPartition",    // (3) kBetterPartition
        "DowngradeToReed",    // (4) kDowngradeToReed
        "BetterParent",       // (5) kBetterParent
    };

    static_assert(kAnyPartition == 0, "kAnyPartition value is incorrect");
    static_assert(kSamePartition == 1, "kSamePartition value is incorrect");
    static_assert(kSamePartitionRetry == 2, "kSamePartitionRetry value is incorrect");
    static_assert(kBetterPartition == 3, "kBetterPartition value is incorrect");
    static_assert(kDowngradeToReed == 4, "kDowngradeToReed value is incorrect");
    static_assert(kBetterParent == 5, "kBetterParent value is incorrect");

    return kAttachModeStrings[aMode];
}

const char *Mle::AttachStateToString(AttachState aState)
{
    static const char *const kAttachStateStrings[] = {
        "Idle",             // (0) kAttachStateIdle
        "ProcessAnnounce",  // (1) kAttachStateProcessAnnounce
        "Start",            // (2) kAttachStateStart
        "ParentReqRouters", // (3) kAttachStateParentRequestRouter
        "ParentReqReeds",   // (4) kAttachStateParentRequestReed
        "Announce",         // (5) kAttachStateAnnounce
        "ChildIdReq",       // (6) kAttachStateChildIdRequest
    };

    static_assert(kAttachStateIdle == 0, "kAttachStateIdle value is incorrect");
    static_assert(kAttachStateProcessAnnounce == 1, "kAttachStateProcessAnnounce value is incorrect");
    static_assert(kAttachStateStart == 2, "kAttachStateStart value is incorrect");
    static_assert(kAttachStateParentRequestRouter == 3, "kAttachStateParentRequestRouter value is incorrect");
    static_assert(kAttachStateParentRequestReed == 4, "kAttachStateParentRequestReed value is incorrect");
    static_assert(kAttachStateAnnounce == 5, "kAttachStateAnnounce value is incorrect");
    static_assert(kAttachStateChildIdRequest == 6, "kAttachStateChildIdRequest value is incorrect");

    return kAttachStateStrings[aState];
}

const char *Mle::ReattachStateToString(ReattachState aState)
{
    static const char *const kReattachStateStrings[] = {
        "",                                 // (0) kReattachStop
        "reattaching",                      // (1) kReattachStart
        "reattaching with Active Dataset",  // (2) kReattachActive
        "reattaching with Pending Dataset", // (3) kReattachPending
    };

    static_assert(kReattachStop == 0, "kReattachStop value is incorrect");
    static_assert(kReattachStart == 1, "kReattachStart value is incorrect");
    static_assert(kReattachActive == 2, "kReattachActive value is incorrect");
    static_assert(kReattachPending == 3, "kReattachPending value is incorrect");

    return kReattachStateStrings[aState];
}

#endif // OT_SHOULD_LOG_AT( OT_LOG_LEVEL_NOTE)

// LCOV_EXCL_STOP

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
Error Mle::SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const uint8_t *aSubTlvs, uint8_t aLength)
{
    Error    error = kErrorNone;
    Message *message;
    Tlv      tlv;

    VerifyOrExit((message = NewMleMessage(kCommandLinkMetricsManagementRequest)) != nullptr, error = kErrorNoBufs);

    // Link Metrics Management TLV
    tlv.SetType(Tlv::kLinkMetricsManagement);
    tlv.SetLength(aLength);

    SuccessOrExit(error = message->AppendBytes(&tlv, sizeof(tlv)));
    SuccessOrExit(error = message->AppendBytes(aSubTlvs, aLength));

    SuccessOrExit(error = SendMessage(*message, aDestination));

exit:
    FreeMessageOnError(message, error);
    return error;
}
#endif

void Mle::RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext)
{
    mParentResponseCb        = aCallback;
    mParentResponseCbContext = aContext;
}

#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
uint64_t Mle::CalcParentCslMetric(uint8_t aCslClockAccuracy, uint8_t aCslUncertainty)
{
    /*
     * This function calculates the overall time that device will operate on battery
     * by summming sequence of "ON quants" over a period of time.
     */
    const uint64_t usInSecond   = 1000000;
    uint64_t       cslPeriodUs  = kMinCslPeriod * kUsPerTenSymbols;
    uint64_t       cslTimeoutUs = GetCslTimeout() * usInSecond;
    uint64_t       k            = cslTimeoutUs / cslPeriodUs;

    return k * (k + 1) * cslPeriodUs / usInSecond * aCslClockAccuracy + aCslUncertainty * k * kUsPerUncertUnit;
}
#endif

void Mle::Challenge::GenerateRandom(void)
{
    mLength = kMaxChallengeSize;
    IgnoreError(Random::Crypto::FillBuffer(mBuffer, mLength));
}

bool Mle::Challenge::Matches(const uint8_t *aBuffer, uint8_t aLength) const
{
    return (mLength == aLength) && (memcmp(mBuffer, aBuffer, aLength) == 0);
}

void Mle::DelayedResponseMetadata::ReadFrom(const Message &aMessage)
{
    uint16_t length = aMessage.GetLength();

    OT_ASSERT(length >= sizeof(*this));
    IgnoreError(aMessage.Read(length - sizeof(*this), *this));
}

void Mle::DelayedResponseMetadata::RemoveFrom(Message &aMessage) const
{
    SuccessOrAssert(aMessage.SetLength(aMessage.GetLength() - sizeof(*this)));
}

} // namespace Mle
} // namespace ot
