[ip6] add otIp6Init() to configure external address pools (#12603)

This commit introduces the `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE`
configuration and the `otIp6Init()` API. When enabled, this feature
allows the OpenThread stack to use externally provided memory buffers for
its external unicast and multicast address pools.

By decoupling the pool sizes from build-time configurations
(`OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS` and
`OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS`), the OpenThread stack can be
compiled as a generic library without hardcoding the address pool sizes.
It delegates the memory allocation and configuration to the application
layer at run-time.

When the feature is enabled, `otIp6Init()` must be invoked to initialize
the `Netif` address pools before calling `otIp6SetEnabled()`.
This commit is contained in:
Abtin Keshavarzian
2026-03-17 19:24:47 -05:00
committed by GitHub
parent b28b4a6a5d
commit a0c332b2a2
12 changed files with 237 additions and 9 deletions
+1
View File
@@ -218,6 +218,7 @@ ot_option(OT_EXTERNAL_HEAP OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE "external heap
ot_option(OT_FIREWALL OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE "firewall")
ot_option(OT_HISTORY_TRACKER OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE "history tracker")
ot_option(OT_IP6_FRAGM OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE "ipv6 fragmentation")
ot_option(OT_IP6_INIT_ADDR_POOL OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE "IPv6 init address pool")
ot_option(OT_JAM_DETECTION OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE "jam detection")
ot_option(OT_JOINER OPENTHREAD_CONFIG_JOINER_ENABLE "joiner")
ot_option(OT_LINK_METRICS_INITIATOR OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE "link metrics initiator")
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (581)
#define OPENTHREAD_API_VERSION (582)
/**
* @addtogroup api-instance
+48 -3
View File
@@ -264,17 +264,59 @@ enum
OT_IP6_PROTO_DST_OPTS = 60, ///< Destination Options for IPv6
};
/**
* Initializes the IPv6 interface and its external address pools.
*
* Requires `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE`.
*
* It provides the memory buffers for the external unicast and multicast address pools and must be called before
* enabling the IPv6 interface.
*
* The provided memory buffers MUST persist and remain valid as long as the OpenThread instance is initialized.
* OpenThread will use these provided buffers to manage the pools of externally added unicast and multicast
* addresses (i.e., those added via `otIp6AddUnicastAddress()` and `otIp6SubscribeMulticastAddress()`).
*
* This function can only be called once. Subsequent calls will return `OT_ERROR_ALREADY`.
*
* The `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE` feature and this function allow the external unicast/multicast
* address pools to be configured at run-time after OpenThread instance initialization, rather than build-time.
* When this feature is disabled, the build-time configs `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS` and
* `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS` specify the pool sizes used by the OpenThread stack.
*
* This feature allows the OpenThread stack to be compiled as a library without specifying the address pool sizes.
* It delegates the configuration of the pools to the next layer, allowing the OpenThread stack to be integrated into
* various projects without requiring a new OpenThread stack configuration to be built.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aUnicastAddrPool A pointer to an array of `otNetifAddress`.
* @param[in] aUnicastAddrPoolSize The number of entries in @p aUnicastAddrPool.
* @param[in] aMulticastAddrPool A pointer to an array of `otNetifMulticastAddress`.
* @param[in] aMulticastAddrPoolSize The number of entries in @p aMulticastAddrPool.
*
* @retval OT_ERROR_NONE Successfully initialized the IPv6 interface.
* @retval OT_ERROR_ALREADY The IPv6 interface is already initialized.
*/
otError otIp6Init(otInstance *aInstance,
otNetifAddress *aUnicastAddrPool,
uint16_t aUnicastAddrPoolSize,
otNetifMulticastAddress *aMulticastAddrPool,
uint16_t aMulticastAddrPoolSize);
/**
* Brings the IPv6 interface up or down.
*
* Call this to enable or disable IPv6 communication.
*
* When `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE` is enabled, `otIp6Init()` MUST be called prior to calling
* this function. If it is not, this function will return `OT_ERROR_INVALID_STATE`.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnabled TRUE to enable IPv6, FALSE otherwise.
*
* @retval OT_ERROR_NONE Successfully brought the IPv6 interface up/down.
* @retval OT_ERROR_INVALID_STATE IPv6 interface is not available since device is operating in raw-link mode
* (applicable only when `OPENTHREAD_CONFIG_LINK_RAW_ENABLE` feature is enabled).
* (applicable only when `OPENTHREAD_CONFIG_LINK_RAW_ENABLE` feature is enabled),
* or not initialized under `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE`.
*/
otError otIp6SetEnabled(otInstance *aInstance, bool aEnabled);
@@ -292,7 +334,8 @@ bool otIp6IsEnabled(otInstance *aInstance);
* Adds a Network Interface Address to the Thread interface.
*
* The passed-in instance @p aAddress is copied by the Thread interface. The Thread interface only
* supports a fixed number of externally added unicast addresses. See `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS`.
* supports a fixed number of externally added unicast addresses. See `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS`
* and `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE`.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aAddress A pointer to a Network Interface Address.
@@ -339,7 +382,9 @@ bool otIp6HasUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress)
* Subscribes the Thread interface to a Network Interface Multicast Address.
*
* The passed in instance @p aAddress will be copied by the Thread interface. The Thread interface only
* supports a fixed number of externally added multicast addresses. See `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS`.
* supports a fixed number of externally added multicast addresses. See `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS`
* and `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE`.
*
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aAddress A pointer to an IP Address.
+61
View File
@@ -49,6 +49,7 @@
#include <openthread/dataset_ftd.h>
#include <openthread/diag.h>
#include <openthread/dns.h>
#include <openthread/heap.h>
#include <openthread/icmp6.h>
#include <openthread/nat64.h>
#include <openthread/ncp.h>
@@ -3316,6 +3317,12 @@ template <> otError Interpreter::Process<Cmd("ifconfig")>(Arg aArgs[])
{
SuccessOrExit(error = otIp6SetEnabled(GetInstancePtr(), false));
}
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE && OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE
else if (aArgs[0] == "init")
{
error = ProcessIfconfigInit(aArgs + 1);
}
#endif
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
@@ -3325,6 +3332,60 @@ exit:
return error;
}
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE && OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE
otError Interpreter::ProcessIfconfigInit(Arg aArgs[])
{
/**
* @cli ifconfig init
* @code
* ifconfig init 5 6
* Done
* @endcode
* @cparam ifconfig @ca{unicast-addr-pool-size} @ca{multicast-addr-pool-size}
* @par
* This command is intended for testing purposes only and requires `OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE`
* and `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE`.
* @par api_copy
* #otIp6Init
*/
otError error;
uint16_t unicastPoolSize;
uint16_t multicastPoolSize;
otNetifAddress *unicastPool = nullptr;
otNetifMulticastAddress *multicastPool = nullptr;
SuccessOrExit(error = aArgs[0].ParseAsUint16(unicastPoolSize));
SuccessOrExit(error = aArgs[1].ParseAsUint16(multicastPoolSize));
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
if (unicastPoolSize > 0)
{
unicastPool = static_cast<otNetifAddress *>(otHeapCAlloc(unicastPoolSize, sizeof(otNetifAddress)));
VerifyOrExit(unicastPool != nullptr, error = OT_ERROR_NO_BUFS);
}
if (multicastPoolSize > 0)
{
multicastPool =
static_cast<otNetifMulticastAddress *>(otHeapCAlloc(multicastPoolSize, sizeof(otNetifMulticastAddress)));
VerifyOrExit(multicastPool != nullptr, error = OT_ERROR_NO_BUFS);
}
SuccessOrExit(error = otIp6Init(GetInstancePtr(), unicastPool, unicastPoolSize, multicastPool, multicastPoolSize));
unicastPool = nullptr;
multicastPool = nullptr;
exit:
otHeapFree(unicastPool);
otHeapFree(multicastPool);
return error;
}
#endif // OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE && OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE
template <> otError Interpreter::Process<Cmd("instanceid")>(Arg aArgs[])
{
/**
+5
View File
@@ -228,6 +228,11 @@ private:
#if OPENTHREAD_FTD
void OutputEidCacheEntry(const otCacheEntryInfo &aEntry);
#endif
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE && OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE
otError ProcessIfconfigInit(Arg aArgs[]);
#endif
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
static void HandleLocateResult(void *aContext,
otError aError,
+13
View File
@@ -69,6 +69,19 @@
#define OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE 1
#endif
/**
* @def OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE
*
* Indicates whether or not the CLI `ifconfig init` command to be supported.
*
* This is applicable when `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE` is used.
*
* The `ifconfig init` is intended for testing purposes only.
*/
#ifndef OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE
#define OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_CLI_TCP_ENABLE
*
+18 -2
View File
@@ -37,11 +37,27 @@
using namespace ot;
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
otError otIp6Init(otInstance *aInstance,
otNetifAddress *aUnicastAddrPool,
uint16_t aUnicastAddrPoolSize,
otNetifMulticastAddress *aMulticastAddrPool,
uint16_t aMulticastAddrPoolSize)
{
return AsCoreType(aInstance).Get<ThreadNetif>().Init(AsCoreTypePtr(aUnicastAddrPool), aUnicastAddrPoolSize,
AsCoreTypePtr(aMulticastAddrPool), aMulticastAddrPoolSize);
}
#endif
otError otIp6SetEnabled(otInstance *aInstance, bool aEnabled)
{
Error error = kErrorNone;
Instance &instance = AsCoreType(aInstance);
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
VerifyOrExit(instance.Get<ThreadNetif>().IsInitialized(), error = kErrorInvalidState);
#endif
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
VerifyOrExit(!instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
#endif
@@ -55,9 +71,9 @@ otError otIp6SetEnabled(otInstance *aInstance, bool aEnabled)
instance.Get<ThreadNetif>().Down();
}
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
ExitNow();
exit:
#endif
return error;
}
+22
View File
@@ -46,10 +46,30 @@
#include "config/border_routing.h"
#include "config/misc.h"
/**
* @def OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
*
* Define as 1 to enable feature to require Thread Network interface initialization which allows configuring
* the external unicast/multicast address pool used by the OpenThread stack.
*
* This feature allows the OpenThread stack to be compiled as a library without specifying the address pool sizes.
* It delegates the configuration of the pools to the next layer, making it run-time configurable after OpenThread
* instance initialization. This allows the OpenThread stack to be integrated into various projects without requiring a
* new OpenThread stack configuration to be built.
*
* When this feature is enabled, the configs `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS` and
* `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS` are no longer applicable or used.
*/
#ifndef OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
#define OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS
*
* The maximum number of supported IPv6 addresses allows to be externally added.
*
* If `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE` is enabled, this config is not used.
*/
#ifndef OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS
#define OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS 4
@@ -59,6 +79,8 @@
* @def OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS
*
* The maximum number of supported IPv6 multicast addresses allows to be externally added.
*
* If `OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE` is enabled, this config is not used.
*/
#ifndef OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+23
View File
@@ -89,9 +89,32 @@ const otNetifMulticastAddress Netif::kLinkLocalAllRoutersMulticastAddress = {
Netif::Netif(Instance &aInstance)
: InstanceLocator(aInstance)
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
, mInitialized(false)
#endif
{
}
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
Error Netif::Init(UnicastAddress *aUnicastAddrPool,
uint16_t aUnicastAddrPoolSize,
MulticastAddress *aMulticastAddrPool,
uint16_t aMulticastAddrPoolSize)
{
Error error = kErrorNone;
VerifyOrExit(!mInitialized, error = kErrorAlready);
mInitialized = true;
SuccessOrExit(error = mExtUnicastAddressPool.Init(aUnicastAddrPool, aUnicastAddrPoolSize));
SuccessOrExit(error = mExtMulticastAddressPool.Init(aMulticastAddrPool, aMulticastAddrPoolSize));
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
bool Netif::IsMulticastSubscribed(const Address &aAddress) const
{
return mMulticastAddresses.ContainsMatching(aAddress);
+39 -3
View File
@@ -326,6 +326,37 @@ public:
*/
explicit Netif(Instance &aInstance);
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
/**
* Initializes the network interface with external address pools.
*
* It provides the memory buffers to be used for the external unicast and multicast address pools. The provided
* pool memory buffers MUST persist and remain valid as long as the OpenThread instance is initialized.
*
* @param[in] aUnicastAddrPool A pointer to an array of `UnicastAddress` entries.
* @param[in] aUnicastAddrPoolSize The number of entries in @p aUnicastAddrPool.
* @param[in] aMulticastAddrPool A pointer to an array of `MulticastAddress` entries.
* @param[in] aMulticastAddrPoolSize The number of entries in @p aMulticastAddrPool.
*
* @retval kErrorNone Successfully initialized the network interface.
* @retval kErrorAlready The network interface is already initialized.
*/
Error Init(UnicastAddress *aUnicastAddrPool,
uint16_t aUnicastAddrPoolSize,
MulticastAddress *aMulticastAddrPool,
uint16_t aMulticastAddrPoolSize);
/**
* Indicates whether or not the network interface is initialized.
*
* @retval TRUE If the network interface is initialized.
* @retval FALSE If the network interface is not initialized.
*/
bool IsInitialized(void) const { return mInitialized; }
#endif // OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
/**
* Registers a callback to notify internal IPv6 address changes.
*
@@ -582,13 +613,18 @@ private:
const MulticastAddress *aStart,
const MulticastAddress *aEnd);
LinkedList<UnicastAddress> mUnicastAddresses;
LinkedList<MulticastAddress> mMulticastAddresses;
LinkedList<UnicastAddress> mUnicastAddresses;
LinkedList<MulticastAddress> mMulticastAddresses;
Callback<otIp6AddressCallback> mAddressCallback;
#if OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE
ConfigPool<UnicastAddress> mExtUnicastAddressPool;
ConfigPool<MulticastAddress> mExtMulticastAddressPool;
bool mInitialized;
#else
Pool<UnicastAddress, kMaxExtUnicastAddrs> mExtUnicastAddressPool;
Pool<MulticastAddress, kMaxExtMulticastAddrs> mExtMulticastAddressPool;
#endif
static const otNetifMulticastAddress kRealmLocalAllMplForwardersMulticastAddress;
static const otNetifMulticastAddress kLinkLocalAllNodesMulticastAddress;
@@ -38,6 +38,10 @@
#define OPENTHREAD_CONFIG_PLATFORM_INFO "POSIX-toranj"
#define OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE 1
#define OPENTHREAD_CONFIG_CLI_IFCONFIG_INIT_ENABLE 1
#define OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE 1
#define OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE 1
@@ -43,6 +43,8 @@
#define OPENTHREAD_CONFIG_PLATFORM_INFO "SIMULATION-toranj"
#endif
#define OPENTHREAD_CONFIG_IP6_INIT_EXT_ADDR_POOL_ENABLE 0
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_SERVER_ENABLE 1
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE 1