[ip6] define NetworkPrefix type (#5213)

This commit adds `Ip6::NetworkPrefix` mirroring `otIp6NetworkPrefix`
which represents the Network Prefix (most significant 64 bits) of an
IPv6 address. Methods in `Ip6::Address` are updated to use the new
type. The `otMeshLocalPrefix` and `Mle::MeshLocalPrefix` are also
updated use the `NetworkPrefix` type.
diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h
index 9296c39..344b7e7 100644
--- a/include/openthread/dataset.h
+++ b/include/openthread/dataset.h
@@ -99,23 +99,13 @@
  */
 typedef struct otExtendedPanId otExtendedPanId;
 
-#define OT_MESH_LOCAL_PREFIX_SIZE 8 ///< Size of the Mesh Local Prefix (bytes)
+#define OT_MESH_LOCAL_PREFIX_SIZE OT_IP6_PREFIX_SIZE ///< Size of the Mesh Local Prefix (bytes)
 
 /**
  * This structure represents a Mesh Local Prefix.
  *
  */
-OT_TOOL_PACKED_BEGIN
-struct otMeshLocalPrefix
-{
-    uint8_t m8[OT_MESH_LOCAL_PREFIX_SIZE]; ///< Byte values
-} OT_TOOL_PACKED_END;
-
-/**
- * This structure represents a Mesh Local Prefix.
- *
- */
-typedef struct otMeshLocalPrefix otMeshLocalPrefix;
+typedef otIp6NetworkPrefix otMeshLocalPrefix;
 
 #define OT_PSKC_MAX_SIZE 16 ///< Maximum size of the PSKc (bytes)
 
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index 3b9fb46..e144eed 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@
  * @note This number versions both OpenThread platform and user APIs.
  *
  */
-#define OPENTHREAD_API_VERSION (16)
+#define OPENTHREAD_API_VERSION (17)
 
 /**
  * @addtogroup api-instance
diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp
index bafce01..fd67a92 100644
--- a/src/core/meshcop/dataset_manager_ftd.cpp
+++ b/src/core/meshcop/dataset_manager_ftd.cpp
@@ -322,8 +322,7 @@
     SuccessOrExit(error = static_cast<Pskc &>(aDataset.mPskc).GenerateRandom());
     SuccessOrExit(error = Random::Crypto::FillBuffer(aDataset.mExtendedPanId.m8, sizeof(aDataset.mExtendedPanId)));
 
-    aDataset.mMeshLocalPrefix.m8[0] = 0xfd;
-    SuccessOrExit(error = Random::Crypto::FillBuffer(&aDataset.mMeshLocalPrefix.m8[1], OT_MESH_LOCAL_PREFIX_SIZE - 1));
+    SuccessOrExit(error = static_cast<Ip6::NetworkPrefix &>(aDataset.mMeshLocalPrefix).GenerateRandomUla());
 
     aDataset.mSecurityPolicy.mFlags = Get<KeyManager>().GetSecurityPolicyFlags();
 
diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp
index c6ceea3..413d528 100644
--- a/src/core/net/ip6_address.cpp
+++ b/src/core/net/ip6_address.cpp
@@ -47,6 +47,16 @@
 namespace Ip6 {
 
 //---------------------------------------------------------------------------------------------------------------------
+// NetworkPrefix methods
+
+otError NetworkPrefix::GenerateRandomUla(void)
+{
+    m8[0] = 0xfd;
+
+    return Random::Crypto::FillBuffer(&m8[1], kSize - 1);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
 // InterfaceIdentifier methods
 
 bool InterfaceIdentifier::IsUnspecified(void) const
@@ -252,6 +262,11 @@
     *this = GetRealmLocalAllMplForwarders();
 }
 
+void Address::SetPrefix(const NetworkPrefix &aNetworkPrefix)
+{
+    mFields.mComponents.mNetworkPrefix = aNetworkPrefix;
+}
+
 void Address::SetPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
 {
     SetPrefix(0, aPrefix, aPrefixLength);
@@ -286,9 +301,9 @@
     mFields.m8[kMulticastNetworkPrefixLengthOffset] = aPrefixLength;
 }
 
-void Address::SetToLocator(const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint16_t aLocator)
+void Address::SetToLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aLocator)
 {
-    SetPrefix(aMeshLocalPrefix);
+    SetPrefix(aNetworkPrefix);
     GetIid().SetToLocator(aLocator);
 }
 
diff --git a/src/core/net/ip6_address.hpp b/src/core/net/ip6_address.hpp
index 30f5d3c..7c23019 100644
--- a/src/core/net/ip6_address.hpp
+++ b/src/core/net/ip6_address.hpp
@@ -43,7 +43,6 @@
 #include "common/equatable.hpp"
 #include "common/string.hpp"
 #include "mac/mac_types.hpp"
-#include "thread/mle_types.hpp"
 
 using ot::Encoding::BigEndian::HostSwap16;
 
@@ -58,6 +57,32 @@
  */
 
 /**
+ * This class represents the Network Prefix of an IPv6 address (most significant 64 bits of the address).
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class NetworkPrefix : public otIp6NetworkPrefix, public Equatable<NetworkPrefix>, public Clearable<NetworkPrefix>
+{
+public:
+    enum
+    {
+        kSize   = OT_IP6_PREFIX_SIZE,            ///< Size in bytes.
+        kLength = OT_IP6_PREFIX_SIZE * CHAR_BIT, ///< Length of Network Prefix in bits.
+    };
+
+    /**
+     * This method generates and sets the Network Prefix to a crypto-secure random Unique Local Address (ULA) based
+     * on the pattern `fdxx:xxxx:xxxx:` (RFC 4193).
+     *
+     * @retval OT_ERROR_NONE     Successfully generated a random ULA Network Prefix
+     * @retval OT_ERROR_FAILED   Failed to generate random ULA Network Prefix.
+     *
+     */
+    otError GenerateRandomUla(void);
+
+} OT_TOOL_PACKED_END;
+
+/**
  * This class represents the Interface Identifier of an IPv6 address.
  *
  */
@@ -461,29 +486,40 @@
     bool IsMulticastLargerThanRealmLocal(void) const;
 
     /**
-     * This method sets the IPv6 address to a Routing Locator (RLOC) IPv6 address with a given Mesh-local prefix and
+     * This method sets the IPv6 address to a Routing Locator (RLOC) IPv6 address with a given Network Prefix and
      * RLOC16 value.
      *
-     * @param[in]  aMeshLocalPrefix  A Mesh Local Prefix.
+     * @param[in]  aNetworkPrefix    A Network Prefix.
      * @param[in]  aRloc16           A RLOC16 value.
      *
      */
-    void SetToRoutingLocator(const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint16_t aRloc16)
+    void SetToRoutingLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aRloc16)
     {
-        SetToLocator(aMeshLocalPrefix, aRloc16);
+        SetToLocator(aNetworkPrefix, aRloc16);
     }
 
     /**
-     * This method sets the IPv6 address to a Anycast Locator (ALOC) IPv6 address with a given Mesh-local prefix and
+     * This method sets the IPv6 address to a Anycast Locator (ALOC) IPv6 address with a given Network Prefix and
      * ALOC16 value.
      *
-     * @param[in]  aMeshLocalPrefix  A Mesh Local Prefix.
+     * @param[in]  aNetworkPrefix    A Network Prefix.
      * @param[in]  aAloc16           A ALOC16 value.
      *
      */
-    void SetToAnycastLocator(const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint16_t aAloc16)
+    void SetToAnycastLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aAloc16)
     {
-        SetToLocator(aMeshLocalPrefix, aAloc16);
+        SetToLocator(aNetworkPrefix, aAloc16);
+    }
+
+    /**
+     * This method returns the Network Prefix of the IPv6 address (most significant 64 bits of the address).
+     *
+     * @returns A reference to the Network Prefix.
+     *
+     */
+    const NetworkPrefix &GetPrefix(void) const
+    {
+        return static_cast<const NetworkPrefix &>(mFields.mComponents.mNetworkPrefix);
     }
 
     /**
@@ -499,15 +535,12 @@
     void SetPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength);
 
     /**
-     * This method sets the IPv6 address prefix to the given Mesh Local Prefix.
+     * This method sets the IPv6 address prefix to the given Network Prefix.
      *
-     * @param[in]  aMeshLocalPrefix   A Mesh Local Prefix.
+     * @param[in]  aNetworkPrefix   A Network Prefix.
      *
      */
-    void SetPrefix(const Mle::MeshLocalPrefix &aMeshLocalPrefix)
-    {
-        SetPrefix(aMeshLocalPrefix.m8, Mle::MeshLocalPrefix::kLength);
-    }
+    void SetPrefix(const NetworkPrefix &aNetworkPrefix);
 
     /**
      * This method sets the prefix content of the Prefix-Based Multicast Address.
@@ -519,14 +552,14 @@
     void SetMulticastNetworkPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength);
 
     /**
-     * This method sets the prefix content of Mesh Local Prefix-Based Multicast Address.
+     * This method sets the prefix content of Prefix-Based Multicast Address.
      *
-     * @param[in]  aMeshLocalPrefix   A reference to the Mesh Local Prefix.
+     * @param[in]  aNetworkPrefix   A reference to a Network Prefix.
      *
      */
-    void SetMulticastNetworkPrefix(const Mle::MeshLocalPrefix &aMeshLocalPrefix)
+    void SetMulticastNetworkPrefix(const NetworkPrefix &aNetworkPrefix)
     {
-        SetMulticastNetworkPrefix(aMeshLocalPrefix.m8, Mle::MeshLocalPrefix::kLength);
+        SetMulticastNetworkPrefix(aNetworkPrefix.m8, NetworkPrefix::kLength);
     }
 
     /**
@@ -618,7 +651,7 @@
 
 private:
     void SetPrefix(uint8_t aOffset, const uint8_t *aPrefix, uint8_t aPrefixLength);
-    void SetToLocator(const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint16_t aLocator);
+    void SetToLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aLocator);
 
     static const Address &GetLinkLocalAllNodesMulticast(void);
     static const Address &GetLinkLocalAllRoutersMulticast(void);
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index afc72e8..31ce1a2 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -3849,7 +3849,7 @@
 
 bool Mle::IsMeshLocalAddress(const Ip6::Address &aAddress) const
 {
-    return (memcmp(&GetMeshLocalPrefix(), &aAddress, MeshLocalPrefix::kSize) == 0);
+    return (aAddress.GetPrefix() == GetMeshLocalPrefix());
 }
 
 otError Mle::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp
index a90f8f0..efa4bb1 100644
--- a/src/core/thread/mle.hpp
+++ b/src/core/thread/mle.hpp
@@ -554,7 +554,7 @@
      */
     const MeshLocalPrefix &GetMeshLocalPrefix(void) const
     {
-        return reinterpret_cast<const MeshLocalPrefix &>(mMeshLocal16.GetAddress());
+        return static_cast<const MeshLocalPrefix &>(mMeshLocal16.GetAddress().GetPrefix());
     }
 
     /**
diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp
index c6ade33..ce865f8 100644
--- a/src/core/thread/mle_types.hpp
+++ b/src/core/thread/mle_types.hpp
@@ -47,6 +47,7 @@
 #include "common/equatable.hpp"
 #include "common/string.hpp"
 #include "mac/mac_types.hpp"
+#include "net/ip6_address.hpp"
 
 namespace ot {
 namespace Mle {
@@ -430,15 +431,9 @@
  *
  */
 OT_TOOL_PACKED_BEGIN
-class MeshLocalPrefix : public otMeshLocalPrefix, public Equatable<MeshLocalPrefix>
+class MeshLocalPrefix : public Ip6::NetworkPrefix
 {
 public:
-    enum
-    {
-        kSize   = OT_MESH_LOCAL_PREFIX_SIZE,            ///< Size in bytes.
-        kLength = OT_MESH_LOCAL_PREFIX_SIZE * CHAR_BIT, ///< Length of Mesh Local Prefix in bits.
-    };
-
     /**
      * This method derives and sets the Mesh Local Prefix from an Extended PAN ID.
      *