Skip to content

Commit

Permalink
[posix] add otSysSetInfraNetif API (openthread#9528)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
superwhd committed Oct 25, 2023
1 parent 52e0c8b commit 9106817
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 29 deletions.
1 change: 0 additions & 1 deletion src/core/border_router/infra_if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions src/lib/platform/exit_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ enum
* No response from radio spinel.
*/
OT_EXIT_RADIO_SPINEL_NO_RESPONSE = 6,

/**
* Invalid state.
*/
OT_EXIT_INVALID_STATE = 7,

};

/**
Expand Down
12 changes: 12 additions & 0 deletions src/posix/platform/include/openthread/openthread-system.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 31 additions & 23 deletions src/posix/platform/infra_if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -200,8 +206,6 @@ int CreateNetLinkSocket(void)
return sock;
}

} // namespace

otError InfraNetif::SendIcmp6Nd(uint32_t aInfraIfIndex,
const otIp6Address &aDestAddress,
const uint8_t *aBuffer,
Expand Down Expand Up @@ -276,7 +280,10 @@ otError InfraNetif::SendIcmp6Nd(uint32_t aInfraIfIndex,
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
{
Expand Down Expand Up @@ -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')
{
Expand All @@ -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);
mInfraIfIndex = ifIndex;

mNetLinkSocket = CreateNetLinkSocket();
if (mInfraIfIcmp6Socket != -1)
{
close(mInfraIfIcmp6Socket);
}
mInfraIfIcmp6Socket = aIcmp6Socket;

exit:
return;
Expand All @@ -408,7 +420,7 @@ void InfraNetif::Init(const char *aIfName)
void InfraNetif::SetUp(void)
{
OT_ASSERT(gInstance != nullptr);
VerifyOrExit(mInfraIfIndex != 0);
VerifyOrExit(mNetLinkSocket != -1);

SuccessOrDie(otBorderRoutingInit(gInstance, mInfraIfIndex, platformInfraIfIsRunning()));
SuccessOrDie(otBorderRoutingSetEnabled(gInstance, /* aEnabled */ true));
Expand All @@ -419,12 +431,8 @@ void InfraNetif::SetUp(void)

void InfraNetif::TearDown(void)
{
VerifyOrExit(mInfraIfIndex != 0);

IgnoreError(otBorderRoutingSetEnabled(gInstance, false));
Mainloop::Manager::Get().Remove(*this);

exit:
return;
}

void InfraNetif::Deinit(void)
Expand Down
23 changes: 21 additions & 2 deletions src/posix/platform/infra_if.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,21 @@ class InfraNetif : public Mainloop::Source, private NonCopyable
/**
* 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.
Expand Down Expand Up @@ -175,6 +184,16 @@ class InfraNetif : public Mainloop::Source, private NonCopyable
*/
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
Expand Down
21 changes: 18 additions & 3 deletions src/posix/platform/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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';
Expand All @@ -164,15 +172,22 @@ void platformInit(otPlatformConfig *aPlatformConfig)
return;
}

void platformSetUp(void)
void platformSetUp(otPlatformConfig *aPlatformConfig)
{
OT_UNUSED_VARIABLE(aPlatformConfig);

VerifyOrExit(!gDryRun);

#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
platformBackboneSetUp();
#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

Expand Down Expand Up @@ -206,7 +221,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
gInstance = otInstanceInitSingle();
OT_ASSERT(gInstance != nullptr);

platformSetUp();
platformSetUp(aPlatformConfig);

return gInstance;
}
Expand Down

0 comments on commit 9106817

Please sign in to comment.