/*
 *  Copyright (c) 2016-2019, 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 includes definitions for MAC types.
 */

#ifndef MAC_TYPES_HPP_
#define MAC_TYPES_HPP_

#include "openthread-core-config.h"

#include <stdint.h>
#include <string.h>

#include <openthread/link.h>
#include <openthread/thread.h>

#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/data.hpp"
#include "common/equatable.hpp"
#include "common/string.hpp"
#include "crypto/storage.hpp"

namespace ot {
namespace Mac {

/**
 * @addtogroup core-mac
 *
 * @{
 *
 */

/**
 * This type represents the IEEE 802.15.4 PAN ID.
 *
 */
typedef otPanId PanId;

constexpr PanId kPanIdBroadcast = 0xffff; ///< Broadcast PAN ID.

/**
 * This type represents the IEEE 802.15.4 Short Address.
 *
 */
typedef otShortAddress ShortAddress;

constexpr ShortAddress kShortAddrBroadcast = 0xffff; ///< Broadcast Short Address.
constexpr ShortAddress kShortAddrInvalid   = 0xfffe; ///< Invalid Short Address.

/**
 * This function generates a random IEEE 802.15.4 PAN ID.
 *
 * @returns A randomly generated IEEE 802.15.4 PAN ID (excluding `kPanIdBroadcast`).
 *
 */
PanId GenerateRandomPanId(void);

/**
 * This structure represents an IEEE 802.15.4 Extended Address.
 *
 */
OT_TOOL_PACKED_BEGIN
class ExtAddress : public otExtAddress, public Equatable<ExtAddress>, public Clearable<ExtAddress>
{
public:
    static constexpr uint16_t kInfoStringSize = 17; ///< Max chars for the info string (`ToString()`).

    /**
     * This type defines the fixed-length `String` object returned from `ToString()`.
     *
     */
    typedef String<kInfoStringSize> InfoString;

    /**
     * This enumeration type specifies the copy byte order when Extended Address is being copied to/from a buffer.
     *
     */
    enum CopyByteOrder : uint8_t
    {
        kNormalByteOrder,  ///< Copy address bytes in normal order (as provided in array buffer).
        kReverseByteOrder, ///< Copy address bytes in reverse byte order.
    };

    /**
     * This method fills all bytes of address with a given byte value.
     *
     * @param[in] aByte A byte value to fill address with.
     *
     */
    void Fill(uint8_t aByte) { memset(this, aByte, sizeof(*this)); }

    /**
     * This method generates a random IEEE 802.15.4 Extended Address.
     *
     */
    void GenerateRandom(void);

    /**
     * This method sets the Extended Address from a given byte array.
     *
     * @param[in] aBuffer    Pointer to an array containing the Extended Address. `OT_EXT_ADDRESS_SIZE` bytes from
     *                       buffer are copied to form the Extended Address.
     * @param[in] aByteOrder The byte order to use when copying the address.
     *
     */
    void Set(const uint8_t *aBuffer, CopyByteOrder aByteOrder = kNormalByteOrder)
    {
        CopyAddress(m8, aBuffer, aByteOrder);
    }

    /**
     * This method indicates whether or not the Group bit is set.
     *
     * @retval TRUE   If the group bit is set.
     * @retval FALSE  If the group bit is not set.
     *
     */
    bool IsGroup(void) const { return (m8[0] & kGroupFlag) != 0; }

    /**
     * This method sets the Group bit.
     *
     * @param[in]  aGroup  TRUE if group address, FALSE otherwise.
     *
     */
    void SetGroup(bool aGroup)
    {
        if (aGroup)
        {
            m8[0] |= kGroupFlag;
        }
        else
        {
            m8[0] &= ~kGroupFlag;
        }
    }

    /**
     * This method toggles the Group bit.
     *
     */
    void ToggleGroup(void) { m8[0] ^= kGroupFlag; }

    /**
     * This method indicates whether or not the Local bit is set.
     *
     * @retval TRUE   If the local bit is set.
     * @retval FALSE  If the local bit is not set.
     *
     */
    bool IsLocal(void) const { return (m8[0] & kLocalFlag) != 0; }

    /**
     * This method sets the Local bit.
     *
     * @param[in]  aLocal  TRUE if locally administered, FALSE otherwise.
     *
     */
    void SetLocal(bool aLocal)
    {
        if (aLocal)
        {
            m8[0] |= kLocalFlag;
        }
        else
        {
            m8[0] &= ~kLocalFlag;
        }
    }

    /**
     * This method toggles the Local bit.
     *
     */
    void ToggleLocal(void) { m8[0] ^= kLocalFlag; }

    /**
     * This method copies the Extended Address into a given buffer.
     *
     * @param[out] aBuffer     A pointer to a buffer to copy the Extended Address into.
     * @param[in]  aByteOrder  The byte order to copy the address.
     *
     */
    void CopyTo(uint8_t *aBuffer, CopyByteOrder aByteOrder = kNormalByteOrder) const
    {
        CopyAddress(aBuffer, m8, aByteOrder);
    }

    /**
     * This method converts an address to a string.
     *
     * @returns An `InfoString` containing the string representation of the Extended Address.
     *
     */
    InfoString ToString(void) const;

private:
    static constexpr uint8_t kGroupFlag = (1 << 0);
    static constexpr uint8_t kLocalFlag = (1 << 1);

    static void CopyAddress(uint8_t *aDst, const uint8_t *aSrc, CopyByteOrder aByteOrder);
} OT_TOOL_PACKED_END;

/**
 * This class represents an IEEE 802.15.4 Short or Extended Address.
 *
 */
class Address
{
public:
    /**
     * This type defines the fixed-length `String` object returned from `ToString()`.
     *
     */
    typedef ExtAddress::InfoString InfoString;

    /**
     * This enumeration specifies the IEEE 802.15.4 Address type.
     *
     */
    enum Type : uint8_t
    {
        kTypeNone,     ///< No address.
        kTypeShort,    ///< IEEE 802.15.4 Short Address.
        kTypeExtended, ///< IEEE 802.15.4 Extended Address.
    };

    /**
     * This constructor initializes an Address.
     *
     */
    Address(void)
        : mType(kTypeNone)
    {
    }

    /**
     * This method gets the address type (Short Address, Extended Address, or none).
     *
     * @returns The address type.
     *
     */
    Type GetType(void) const { return mType; }

    /**
     * This method indicates whether or not there is an address.
     *
     * @returns TRUE if there is no address (i.e. address type is `kTypeNone`), FALSE otherwise.
     *
     */
    bool IsNone(void) const { return (mType == kTypeNone); }

    /**
     * This method indicates whether or not the Address is a Short Address.
     *
     * @returns TRUE if it is a Short Address, FALSE otherwise.
     *
     */
    bool IsShort(void) const { return (mType == kTypeShort); }

    /**
     * This method indicates whether or not the Address is an Extended Address.
     *
     * @returns TRUE if it is an Extended Address, FALSE otherwise.
     *
     */
    bool IsExtended(void) const { return (mType == kTypeExtended); }

    /**
     * This method gets the address as a Short Address.
     *
     * This method MUST be used only if the address type is Short Address.
     *
     * @returns The Short Address.
     *
     */
    ShortAddress GetShort(void) const { return mShared.mShortAddress; }

    /**
     * This method gets the address as an Extended Address.
     *
     * This method MUST be used only if the address type is Extended Address.
     *
     * @returns A constant reference to the Extended Address.
     *
     */
    const ExtAddress &GetExtended(void) const { return mShared.mExtAddress; }

    /**
     * This method gets the address as an Extended Address.
     *
     * This method MUST be used only if the address type is Extended Address.
     *
     * @returns A reference to the Extended Address.
     *
     */
    ExtAddress &GetExtended(void) { return mShared.mExtAddress; }

    /**
     * This method sets the address to none (i.e., clears the address).
     *
     * Address type will be updated to `kTypeNone`.
     *
     */
    void SetNone(void) { mType = kTypeNone; }

    /**
     * This method sets the address with a Short Address.
     *
     * The type is also updated to indicate that address is Short.
     *
     * @param[in]  aShortAddress  A Short Address
     *
     */
    void SetShort(ShortAddress aShortAddress)
    {
        mShared.mShortAddress = aShortAddress;
        mType                 = kTypeShort;
    }

    /**
     * This method sets the address with an Extended Address.
     *
     * The type is also updated to indicate that the address is Extended.
     *
     * @param[in]  aExtAddress  An Extended Address
     *
     */
    void SetExtended(const ExtAddress &aExtAddress)
    {
        mShared.mExtAddress = aExtAddress;
        mType               = kTypeExtended;
    }

    /**
     * This method sets the address with an Extended Address given as a byte array.
     *
     * The type is also updated to indicate that the address is Extended.
     *
     * @param[in] aBuffer    Pointer to an array containing the Extended Address. `OT_EXT_ADDRESS_SIZE` bytes from
     *                       buffer are copied to form the Extended Address.
     * @param[in] aByteOrder The byte order to copy the address from @p aBuffer.
     *
     */
    void SetExtended(const uint8_t *aBuffer, ExtAddress::CopyByteOrder aByteOrder = ExtAddress::kNormalByteOrder)
    {
        mShared.mExtAddress.Set(aBuffer, aByteOrder);
        mType = kTypeExtended;
    }

    /**
     * This method indicates whether or not the address is a Short Broadcast Address.
     *
     * @returns TRUE if address is Short Broadcast Address, FALSE otherwise.
     *
     */
    bool IsBroadcast(void) const { return ((mType == kTypeShort) && (GetShort() == kShortAddrBroadcast)); }

    /**
     * This method indicates whether or not the address is a Short Invalid Address.
     *
     * @returns TRUE if address is Short Invalid Address, FALSE otherwise.
     *
     */
    bool IsShortAddrInvalid(void) const { return ((mType == kTypeShort) && (GetShort() == kShortAddrInvalid)); }

    /**
     * This method converts an address to a null-terminated string
     *
     * @returns A `String` representing the address.
     *
     */
    InfoString ToString(void) const;

private:
    union
    {
        ShortAddress mShortAddress; ///< The IEEE 802.15.4 Short Address.
        ExtAddress   mExtAddress;   ///< The IEEE 802.15.4 Extended Address.
    } mShared;

    Type mType; ///< The address type (Short, Extended, or none).
};

/**
 * This class represents a MAC key.
 *
 */
OT_TOOL_PACKED_BEGIN
class Key : public otMacKey, public Equatable<Key>, public Clearable<Key>
{
public:
    static constexpr uint16_t kSize = OT_MAC_KEY_SIZE; ///< Key size in bytes.

    /**
     * This method gets a pointer to the bytes array containing the key
     *
     * @returns A pointer to the byte array containing the key.
     *
     */
    const uint8_t *GetBytes(void) const { return m8; }

} OT_TOOL_PACKED_END;

/**
 * This type represents a MAC Key Ref used by PSA.
 *
 */
typedef otMacKeyRef KeyRef;

/**
 * This class represents a MAC Key Material.
 *
 */
class KeyMaterial : public otMacKeyMaterial, public Unequatable<KeyMaterial>
{
public:
    /**
     * This constructor initializes a `KeyMaterial`.
     *
     */
    KeyMaterial(void)
    {
        GetKey().Clear();
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
        SetKeyRef(kInvalidKeyRef);
#endif
    }

#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
    /**
     * This method overload `=` operator to assign the `KeyMaterial` from another one.
     *
     * If the `KeyMaterial` currently stores a valid and different `KeyRef`, the assignment of new value will ensure to
     * delete the previous one before using the new `KeyRef` from @p aOther.
     *
     * @param[in] aOther  aOther  The other `KeyMaterial` instance to assign from.
     *
     * @returns A reference to the current `KeyMaterial`
     *
     */
    KeyMaterial &operator=(const KeyMaterial &aOther);

    KeyMaterial(const KeyMaterial &) = delete;
#endif

    /**
     *  This method clears the `KeyMaterial`.
     *
     * Under `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE`, if the `KeyMaterial` currently stores a valid previous
     * `KeyRef`, the `Clear()` call will ensure to delete the previous `KeyRef` and set it to `kInvalidKeyRef`.
     *
     */
    void Clear(void);

#if !OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
    /**
     * This method gets the literal `Key`.
     *
     * @returns The literal `Key`
     *
     */
    const Key &GetKey(void) const { return static_cast<const Key &>(mKeyMaterial.mKey); }

#else
    /**
     * This method gets the stored `KeyRef`
     *
     * @returns The `KeyRef`
     *
     */
    KeyRef GetKeyRef(void) const { return mKeyMaterial.mKeyRef; }
#endif

    /**
     * This method sets the `KeyMaterial` from a given Key.
     *
     * If the `KeyMaterial` currently stores a valid `KeyRef`, the `SetFrom()` call will ensure to delete the previous
     * one before creating and using a new `KeyRef` associated with the new `Key`.
     *
     * @param[in] aKey           A reference to the new key.
     * @param[in] aIsExportable  Boolean indicating if the key is exportable (this is only applicable under
     *                           `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` config).
     *
     */
    void SetFrom(const Key &aKey, bool aIsExportable = false);

    /**
     * This method extracts the literal key from `KeyMaterial`
     *
     * @param[out] aKey  A reference to the output the key.
     *
     */
    void ExtractKey(Key &aKey);

    /**
     * This method converts `KeyMaterial` to a `Crypto::Key`.
     *
     * @param[out]  aCryptoKey  A reference to a `Crypto::Key` to populate.
     *
     */
    void ConvertToCryptoKey(Crypto::Key &aCryptoKey) const;

    /**
     * This method overloads operator `==` to evaluate whether or not two `KeyMaterial` instances are equal.
     *
     * @param[in]  aOther  The other `KeyMaterial` instance to compare with.
     *
     * @retval TRUE   If the two `KeyMaterial` instances are equal.
     * @retval FALSE  If the two `KeyMaterial` instances are not equal.
     *
     */
    bool operator==(const KeyMaterial &aOther) const;

private:
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
    static constexpr KeyRef kInvalidKeyRef = Crypto::Storage::kInvalidKeyRef;

    void DestroyKey(void);
    void SetKeyRef(KeyRef aKeyRef) { mKeyMaterial.mKeyRef = aKeyRef; }
#endif
    Key &GetKey(void) { return static_cast<Key &>(mKeyMaterial.mKey); }
    void SetKey(const Key &aKey) { mKeyMaterial.mKey = aKey; }
};

#if OPENTHREAD_CONFIG_MULTI_RADIO

/**
 * This enumeration defines the radio link types.
 *
 */
enum RadioType : uint8_t
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    kRadioTypeIeee802154, ///< IEEE 802.15.4 (2.4GHz) link type.
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    kRadioTypeTrel, ///< Thread Radio Encapsulation link type.
#endif
};

/**
 * This constant specifies the number of supported radio link types.
 *
 */
constexpr uint8_t kNumRadioTypes = (((OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE) ? 1 : 0) +
                                    ((OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE) ? 1 : 0));

/**
 * This class represents a set of radio links.
 *
 */
class RadioTypes
{
public:
    static constexpr uint16_t kInfoStringSize = 32; ///< Max chars for the info string (`ToString()`).

    /**
     * This type defines the fixed-length `String` object returned from `ToString()`.
     *
     */
    typedef String<kInfoStringSize> InfoString;

    /**
     * This static class variable defines an array containing all supported radio link types.
     *
     */
    static const RadioType kAllRadioTypes[kNumRadioTypes];

    /**
     * This constructor initializes a `RadioTypes` object as empty set
     *
     */
    RadioTypes(void)
        : mBitMask(0)
    {
    }

    /**
     * This constructor initializes a `RadioTypes` object with a given bit-mask.
     *
     * @param[in] aMask   A bit-mask representing the radio types (the first bit corresponds to radio type 0, and so on)
     *
     */
    explicit RadioTypes(uint8_t aMask)
        : mBitMask(aMask)
    {
    }

    /**
     * This method clears the set.
     *
     */
    void Clear(void) { mBitMask = 0; }

    /**
     * This method indicates whether the set is empty or not
     *
     * @returns TRUE if the set is empty, FALSE otherwise.
     *
     */
    bool IsEmpty(void) const { return (mBitMask == 0); }

    /**
     *  This method indicates whether the set contains only a single radio type.
     *
     * @returns TRUE if the set contains a single radio type, FALSE otherwise.
     *
     */
    bool ContainsSingleRadio(void) const { return !IsEmpty() && ((mBitMask & (mBitMask - 1)) == 0); }

    /**
     * This method indicates whether or not the set contains a given radio type.
     *
     * @param[in] aType  A radio link type.
     *
     * @returns TRUE if the set contains @p aType, FALSE otherwise.
     *
     */
    bool Contains(RadioType aType) const { return ((mBitMask & BitFlag(aType)) != 0); }

    /**
     * This method adds a radio type to the set.
     *
     * @param[in] aType  A radio link type.
     *
     */
    void Add(RadioType aType) { mBitMask |= BitFlag(aType); }

    /**
     * This method adds another radio types set to the current one.
     *
     * @param[in] aTypes   A radio link type set to add.
     *
     */
    void Add(RadioTypes aTypes) { mBitMask |= aTypes.mBitMask; }

    /**
     * This method adds all radio types supported by device to the set.
     *
     */
    void AddAll(void);

    /**
     * This method removes a given radio type from the set.
     *
     * @param[in] aType  A radio link type.
     *
     */
    void Remove(RadioType aType) { mBitMask &= ~BitFlag(aType); }

    /**
     * This method gets the radio type set as a bitmask.
     *
     * The first bit in the mask corresponds to first radio type (radio type with value zero), and so on.
     *
     * @returns A bitmask representing the set of radio types.
     *
     */
    uint8_t GetAsBitMask(void) const { return mBitMask; }

    /**
     * This method overloads operator `-` to return a new set which is the set difference between current set and
     * a given set.
     *
     * @param[in] aOther  Another radio type set.
     *
     * @returns A new set which is set difference between current one and @p aOther.
     *
     */
    RadioTypes operator-(const RadioTypes &aOther) const { return RadioTypes(mBitMask & ~aOther.mBitMask); }

    /**
     * This method converts the radio set to human-readable string.
     *
     * @return A string representation of the set of radio types.
     *
     */
    InfoString ToString(void) const;

private:
    static uint8_t BitFlag(RadioType aType) { return static_cast<uint8_t>(1U << static_cast<uint8_t>(aType)); }

    uint8_t mBitMask;
};

/**
 * This function converts a link type to a string
 *
 * @param[in] aRadioType  A link type value.
 *
 * @returns A string representation of the link type.
 *
 */
const char *RadioTypeToString(RadioType aRadioType);

#endif // OPENTHREAD_CONFIG_MULTI_RADIO

/**
 * This class represents Link Frame Counters for all supported radio links.
 *
 */
class LinkFrameCounters
{
public:
    /**
     * This method resets all counters (set them all to zero).
     *
     */
    void Reset(void) { SetAll(0); }

#if OPENTHREAD_CONFIG_MULTI_RADIO

    /**
     * This method gets the link Frame Counter for a given radio link.
     *
     * @param[in] aRadioType  A radio link type.
     *
     * @returns The Link Frame Counter for radio link @p aRadioType.
     *
     */
    uint32_t Get(RadioType aRadioType) const;

    /**
     * This method sets the Link Frame Counter for a given radio link.
     *
     * @param[in] aRadioType  A radio link type.
     * @param[in] aCounter    The new counter value.
     *
     */
    void Set(RadioType aRadioType, uint32_t aCounter);

#else

    /**
     * This method gets the Link Frame Counter value.
     *
     * @return The Link Frame Counter value.
     *
     */
    uint32_t Get(void) const
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    {
        return m154Counter;
    }
#elif OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    {
        return mTrelCounter;
    }
#endif

    /**
     * This method sets the Link Frame Counter for a given radio link.
     *
     * @param[in] aCounter    The new counter value.
     *
     */
    void Set(uint32_t aCounter)
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    {
        m154Counter = aCounter;
    }
#elif OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    {
        mTrelCounter = aCounter;
    }
#endif

#endif // OPENTHREAD_CONFIG_MULTI_RADIO

#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    /**
     * This method gets the Link Frame Counter for 802.15.4 radio link.
     *
     * @returns The Link Frame Counter for 802.15.4 radio link.
     *
     */
    uint32_t Get154(void) const { return m154Counter; }

    /**
     * This method sets the Link Frame Counter for 802.15.4 radio link.
     *
     * @param[in] aCounter   The new counter value.
     *
     */
    void Set154(uint32_t aCounter) { m154Counter = aCounter; }
#endif

#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    /**
     * This method gets the Link Frame Counter for TREL radio link.
     *
     * @returns The Link Frame Counter for TREL radio link.
     *
     */
    uint32_t GetTrel(void) const { return mTrelCounter; }

    /**
     * This method increments the Link Frame Counter for TREL radio link.
     *
     */
    void IncrementTrel(void) { mTrelCounter++; }
#endif

    /**
     * This method gets the maximum Link Frame Counter among all supported radio links.
     *
     * @return The maximum Link frame Counter among all supported radio links.
     *
     */
    uint32_t GetMaximum(void) const;

    /**
     * This method sets the Link Frame Counter value for all radio links.
     *
     * @param[in]  aCounter  The Link Frame Counter value.
     *
     */
    void SetAll(uint32_t aCounter);

private:
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    uint32_t m154Counter;
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    uint32_t mTrelCounter;
#endif
};

/**
 * @}
 *
 */

} // namespace Mac

DefineCoreType(otExtAddress, Mac::ExtAddress);
DefineCoreType(otMacKey, Mac::Key);

} // namespace ot

#endif // MAC_TYPES_HPP_
