[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:
whd
2023-10-25 01:33:52 -07:00
committed by GitHub
parent 52e0c8bdd9
commit 9106817c62
6 changed files with 88 additions and 29 deletions
-1
View File
@@ -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;
+6
View File
@@ -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
+31 -23
View File
@@ -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)
+21 -2
View File
@@ -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
+18 -3
View File
@@ -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;
}