mirror of
https://github.com/espressif/openthread.git
synced 2026-08-30 22:09:54 +00:00
[posix] add otSysSetInfraNetif API (#9528)
This commit adds a new API `otSysSetInfraNetif` to support specifying the infrastructure network interface for the platform. This can be useful in following cases: - The infra link cannot be determined at the start up of `otbr-agent`. We can call this API to specify the infra link without specifying it in the command line arguments. - Let Thread Border Router switch to another infra link without restarting the whole OpenThread stack.
This commit is contained in:
@@ -60,7 +60,6 @@ Error InfraIf::Init(uint32_t aIfIndex)
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(!mInitialized, error = kErrorInvalidState);
|
||||
VerifyOrExit(aIfIndex > 0, error = kErrorInvalidArgs);
|
||||
|
||||
mIfIndex = aIfIndex;
|
||||
mInitialized = true;
|
||||
|
||||
@@ -82,6 +82,12 @@ enum
|
||||
* No response from radio spinel.
|
||||
*/
|
||||
OT_EXIT_RADIO_SPINEL_NO_RESPONSE = 6,
|
||||
|
||||
/**
|
||||
* Invalid state.
|
||||
*/
|
||||
OT_EXIT_INVALID_STATE = 7,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -226,6 +226,18 @@ typedef struct otSysInfraNetIfAddressCounters
|
||||
*/
|
||||
void otSysCountInfraNetifAddresses(otSysInfraNetIfAddressCounters *aAddressCounters);
|
||||
|
||||
/**
|
||||
* Sets the infrastructure network interface and the ICMPv6 socket.
|
||||
*
|
||||
* This function specifies the network interface name and the ICMPv6 socket on that interface. After calling this
|
||||
* function, the caller can call otBorderRoutingInit() to let Border Routing work on that interface.
|
||||
*
|
||||
* @param[in] aInfraNetifName The name of the infrastructure network interface.
|
||||
* @param[in] aIcmp6Socket A SOCK_RAW socket running on the infrastructure network interface.
|
||||
*
|
||||
*/
|
||||
void otSysSetInfraNetif(const char *aInfraNetifName, int aIcmp6Socket);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
@@ -123,9 +123,8 @@ void otSysCountInfraNetifAddresses(otSysInfraNetIfAddressCounters *aAddressCount
|
||||
|
||||
namespace ot {
|
||||
namespace Posix {
|
||||
namespace {
|
||||
|
||||
int CreateIcmp6Socket(void)
|
||||
int InfraNetif::CreateIcmp6Socket(const char *aInfraIfName)
|
||||
{
|
||||
int sock;
|
||||
int rval;
|
||||
@@ -168,6 +167,13 @@ int CreateIcmp6Socket(void)
|
||||
rval = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kHopLimit, sizeof(kHopLimit));
|
||||
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
#ifdef __linux__
|
||||
rval = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, aInfraIfName, strlen(aInfraIfName));
|
||||
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
|
||||
rval = setsockopt(mInfraIfIcmp6Socket, IPPROTO_IPV6, IPV6_BOUND_IF, &mInfraIfIndex, sizeof(mInfraIfIndex));
|
||||
#endif // __linux__
|
||||
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
@@ -200,8 +206,6 @@ int CreateNetLinkSocket(void)
|
||||
return sock;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
otError InfraNetif::SendIcmp6Nd(uint32_t aInfraIfIndex,
|
||||
const otIp6Address &aDestAddress,
|
||||
const uint8_t *aBuffer,
|
||||
@@ -276,7 +280,10 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool InfraNetif::IsRunning(void) const { return (GetFlags() & IFF_RUNNING) && HasLinkLocalAddress(); }
|
||||
bool InfraNetif::IsRunning(void) const
|
||||
{
|
||||
return mInfraIfIndex ? ((GetFlags() & IFF_RUNNING) && HasLinkLocalAddress()) : false;
|
||||
}
|
||||
|
||||
uint32_t InfraNetif::GetFlags(void) const
|
||||
{
|
||||
@@ -368,10 +375,18 @@ bool InfraNetif::HasLinkLocalAddress(void) const
|
||||
return hasLla;
|
||||
}
|
||||
|
||||
void InfraNetif::Init(const char *aIfName)
|
||||
void InfraNetif::Init(void) { mNetLinkSocket = CreateNetLinkSocket(); }
|
||||
|
||||
void InfraNetif::SetInfraNetif(const char *aIfName, int aIcmp6Socket)
|
||||
{
|
||||
ssize_t rval;
|
||||
uint32_t ifIndex = 0;
|
||||
uint32_t ifIndex = 0;
|
||||
otBorderRoutingState state = otBorderRoutingGetState(gInstance);
|
||||
|
||||
OT_ASSERT(gInstance != nullptr);
|
||||
|
||||
VerifyOrDie(mNetLinkSocket != -1, OT_EXIT_INVALID_STATE);
|
||||
VerifyOrDie(state == OT_BORDER_ROUTING_STATE_UNINITIALIZED || state == OT_BORDER_ROUTING_STATE_DISABLED,
|
||||
OT_EXIT_INVALID_STATE);
|
||||
|
||||
if (aIfName == nullptr || aIfName[0] == '\0')
|
||||
{
|
||||
@@ -389,17 +404,14 @@ void InfraNetif::Init(const char *aIfName)
|
||||
otLogCritPlat("Failed to get the index for infra interface %s", aIfName);
|
||||
DieNow(OT_EXIT_INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
mInfraIfIndex = ifIndex;
|
||||
|
||||
mInfraIfIcmp6Socket = CreateIcmp6Socket();
|
||||
#ifdef __linux__
|
||||
rval = setsockopt(mInfraIfIcmp6Socket, SOL_SOCKET, SO_BINDTODEVICE, mInfraIfName, strlen(mInfraIfName));
|
||||
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
|
||||
rval = setsockopt(mInfraIfIcmp6Socket, IPPROTO_IPV6, IPV6_BOUND_IF, &mInfraIfIndex, sizeof(mInfraIfIndex));
|
||||
#endif // __linux__
|
||||
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
mNetLinkSocket = CreateNetLinkSocket();
|
||||
if (mInfraIfIcmp6Socket != -1)
|
||||
{
|
||||
close(mInfraIfIcmp6Socket);
|
||||
}
|
||||
mInfraIfIcmp6Socket = aIcmp6Socket;
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -408,7 +420,7 @@ exit:
|
||||
void InfraNetif::SetUp(void)
|
||||
{
|
||||
OT_ASSERT(gInstance != nullptr);
|
||||
VerifyOrExit(mInfraIfIndex != 0);
|
||||
VerifyOrExit(mNetLinkSocket != -1);
|
||||
|
||||
SuccessOrDie(otBorderRoutingInit(gInstance, mInfraIfIndex, platformInfraIfIsRunning()));
|
||||
SuccessOrDie(otBorderRoutingSetEnabled(gInstance, /* aEnabled */ true));
|
||||
@@ -419,12 +431,8 @@ exit:
|
||||
|
||||
void InfraNetif::TearDown(void)
|
||||
{
|
||||
VerifyOrExit(mInfraIfIndex != 0);
|
||||
|
||||
IgnoreError(otBorderRoutingSetEnabled(gInstance, false));
|
||||
Mainloop::Manager::Get().Remove(*this);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void InfraNetif::Deinit(void)
|
||||
|
||||
@@ -71,12 +71,21 @@ public:
|
||||
/**
|
||||
* Initializes the infrastructure network interface.
|
||||
*
|
||||
* To specify the infrastructure network interface, you need to call SetInfraNetif() after Init().
|
||||
*
|
||||
* @note This method is called before OpenThread instance is created.
|
||||
*
|
||||
* @param[in] aIfName A pointer to infrastructure network interface name.
|
||||
*/
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* Sets the infrastructure network interface.
|
||||
*
|
||||
* @param[in] aIfName A pointer to infrastructure network interface name.
|
||||
* @param[in] aIcmp6Socket A SOCK_RAW socket for sending/receiving ICMPv6 messages.
|
||||
*
|
||||
*/
|
||||
void Init(const char *aIfName);
|
||||
void SetInfraNetif(const char *aIfName, int aIcmp6Socket);
|
||||
|
||||
/**
|
||||
* Sets up the infrastructure network interface.
|
||||
@@ -175,6 +184,16 @@ public:
|
||||
*/
|
||||
static InfraNetif &Get(void);
|
||||
|
||||
/**
|
||||
* Creates a socket for sending/receiving ICMPv6 messages.
|
||||
*
|
||||
* @param[in] aInfraIfName The infrastructure network interface name.
|
||||
*
|
||||
* @returns The file descriptor of the socket.
|
||||
*
|
||||
*/
|
||||
static int CreateIcmp6Socket(const char *aInfraIfName);
|
||||
|
||||
private:
|
||||
static const char kWellKnownIpv4OnlyName[]; // "ipv4only.arpa"
|
||||
static const otIp4Address kWellKnownIpv4OnlyAddress1; // 192.0.0.170
|
||||
|
||||
@@ -121,6 +121,13 @@ static const char *getTrelRadioUrl(otPlatformConfig *aPlatformConfig)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
|
||||
void otSysSetInfraNetif(const char *aInfraNetifName, int aIcmp6Socket)
|
||||
{
|
||||
ot::Posix::InfraNetif::Get().SetInfraNetif(aInfraNetifName, aIcmp6Socket);
|
||||
}
|
||||
#endif
|
||||
|
||||
void platformInit(otPlatformConfig *aPlatformConfig)
|
||||
{
|
||||
#if OPENTHREAD_POSIX_CONFIG_BACKTRACE_ENABLE
|
||||
@@ -143,7 +150,8 @@ void platformInit(otPlatformConfig *aPlatformConfig)
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
|
||||
ot::Posix::InfraNetif::Get().Init(aPlatformConfig->mBackboneInterfaceName);
|
||||
ot::Posix::InfraNetif::Get().Init();
|
||||
|
||||
#endif
|
||||
|
||||
gNetifName[0] = '\0';
|
||||
@@ -164,8 +172,10 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void platformSetUp(void)
|
||||
void platformSetUp(otPlatformConfig *aPlatformConfig)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aPlatformConfig);
|
||||
|
||||
VerifyOrExit(!gDryRun);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
@@ -173,6 +183,11 @@ void platformSetUp(void)
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
|
||||
if (aPlatformConfig->mBackboneInterfaceName != nullptr && strlen(aPlatformConfig->mBackboneInterfaceName) > 0)
|
||||
{
|
||||
otSysSetInfraNetif(aPlatformConfig->mBackboneInterfaceName,
|
||||
ot::Posix::InfraNetif::CreateIcmp6Socket(aPlatformConfig->mBackboneInterfaceName));
|
||||
}
|
||||
ot::Posix::InfraNetif::Get().SetUp();
|
||||
#endif
|
||||
|
||||
@@ -206,7 +221,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
|
||||
gInstance = otInstanceInitSingle();
|
||||
OT_ASSERT(gInstance != nullptr);
|
||||
|
||||
platformSetUp();
|
||||
platformSetUp(aPlatformConfig);
|
||||
|
||||
return gInstance;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user