[udp] add kNetifThreadInternal which disallows platform UDP use (#10965)

This commit introduces `kNetifThreadInternal` as a network interface
option for UDP sockets. Unlike other options, this disallows the use
of platform UDP for the socket, indicating that the socket should use
the OpenThread internal Thread network interface only.

This model replaces the previous approach where `ShouldUsePlatformUdp()`
would check the socket port against a set of port numbers used by
different modules (such as MLE, TMF, Joiner Router, etc) to determine
whether platform UDP APIs should be used. With the new model, each
module decides whether to associate its socket with the
`kNetifThreadInternal`.

This is a more flexible and extensible model, ensuring that sockets
that should not use the platform do not waste resources (they will
not be created or opened/closed on the platform). This also help
avoid edge cases where platform UDP operations may unintentionally
fail when the platform socket is not actually needed.
This commit is contained in:
Abtin Keshavarzian
2024-11-28 08:58:19 -08:00
committed by GitHub
parent ae5b750d30
commit 473af53155
16 changed files with 113 additions and 78 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (464)
#define OPENTHREAD_API_VERSION (465)
/**
* @addtogroup api-instance
+2 -1
View File
@@ -115,7 +115,8 @@ typedef void (*otUdpReceive)(void *aContext, otMessage *aMessage, const otMessag
typedef enum otNetifIdentifier
{
OT_NETIF_UNSPECIFIED = 0, ///< Unspecified network interface.
OT_NETIF_THREAD, ///< The Thread interface.
OT_NETIF_THREAD_HOST, ///< The host Thread interface - allow use of platform UDP.
OT_NETIF_THREAD_INTERNAL, ///< The internal Thread interface (within OpenThread) - do not use platform UDP.
OT_NETIF_BACKBONE, ///< The Backbone interface.
} otNetifIdentifier;
+1 -1
View File
@@ -83,7 +83,7 @@ template <> otError UdpExample::Process<Cmd("bind")>(Arg aArgs[])
{
otError error;
otSockAddr sockaddr;
otNetifIdentifier netif = OT_NETIF_THREAD;
otNetifIdentifier netif = OT_NETIF_THREAD_HOST;
if (aArgs[0] == "-u")
{
+1 -1
View File
@@ -44,7 +44,7 @@ otMessage *otUdpNewMessage(otInstance *aInstance, const otMessageSettings *aSett
otError otUdpOpen(otInstance *aInstance, otUdpSocket *aSocket, otUdpReceive aCallback, void *aContext)
{
return AsCoreType(aInstance).Get<Ip6::Udp>().Open(AsCoreType(aSocket), Ip6::kNetifThread, aCallback, aContext);
return AsCoreType(aInstance).Get<Ip6::Udp>().Open(AsCoreType(aSocket), Ip6::kNetifThreadHost, aCallback, aContext);
}
bool otUdpIsOpen(otInstance *aInstance, const otUdpSocket *aSocket)
+1 -1
View File
@@ -69,7 +69,7 @@ void JoinerRouter::Start(void)
VerifyOrExit(!mSocket.IsBound());
IgnoreError(mSocket.Open(Ip6::kNetifThread));
IgnoreError(mSocket.Open(Ip6::kNetifThreadInternal));
IgnoreError(mSocket.Bind(port));
IgnoreError(Get<Ip6::Filter>().AddUnsecurePort(port));
LogInfo("Joiner Router: start");
+1 -1
View File
@@ -162,7 +162,7 @@ void Client::Start(void)
{
VerifyOrExit(!mSocket.IsBound());
IgnoreError(mSocket.Open(Ip6::kNetifThread));
IgnoreError(mSocket.Open(Ip6::kNetifThreadInternal));
IgnoreError(mSocket.Bind(kDhcpClientPort));
ProcessNextIdentityAssociation();
+1 -1
View File
@@ -130,7 +130,7 @@ void Server::Start(void)
{
VerifyOrExit(!mSocket.IsOpen());
IgnoreError(mSocket.Open(Ip6::kNetifThread));
IgnoreError(mSocket.Open(Ip6::kNetifThreadInternal));
IgnoreError(mSocket.Bind(kDhcpServerPort));
exit:
+1 -1
View File
@@ -71,7 +71,7 @@ Error Server::Start(void)
VerifyOrExit(!IsRunning());
SuccessOrExit(error = mSocket.Open(kBindUnspecifiedNetif ? Ip6::kNetifUnspecified : Ip6::kNetifThread));
SuccessOrExit(error = mSocket.Open(kBindUnspecifiedNetif ? Ip6::kNetifUnspecified : Ip6::kNetifThreadInternal));
SuccessOrExit(error = mSocket.Bind(kPort));
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+1 -1
View File
@@ -400,7 +400,7 @@ Error Client::Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester)
VerifyOrExit(GetState() == kStateStopped,
error = (aServerSockAddr == GetServerAddress()) ? kErrorNone : kErrorBusy);
SuccessOrExit(error = mSocket.Open(Ip6::kNetifThread));
SuccessOrExit(error = mSocket.Open(Ip6::kNetifThreadInternal));
error = mSocket.Connect(aServerSockAddr);
+1 -1
View File
@@ -658,7 +658,7 @@ Error Server::PrepareSocket(void)
#endif
VerifyOrExit(!mSocket.IsOpen());
SuccessOrExit(error = mSocket.Open(Ip6::kNetifThread));
SuccessOrExit(error = mSocket.Open(Ip6::kNetifThreadHost));
error = mSocket.Bind(mPort);
exit:
+62 -55
View File
@@ -119,7 +119,7 @@ Error Udp::Socket::JoinNetifMulticastGroup(NetifIdentifier aNetifIdentifier, con
VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpJoinMulticastGroup(this, MapEnum(aNetifIdentifier), &aAddress);
error = Plat::JoinMulticastGroup(*this, aNetifIdentifier, aAddress);
#endif
exit:
@@ -136,7 +136,7 @@ Error Udp::Socket::LeaveNetifMulticastGroup(NetifIdentifier aNetifIdentifier, co
VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpLeaveMulticastGroup(this, MapEnum(aNetifIdentifier), &aAddress);
error = Plat::LeaveMulticastGroup(*this, aNetifIdentifier, aAddress);
#endif
exit:
@@ -144,6 +144,57 @@ exit:
}
#endif
//---------------------------------------------------------------------------------------------------------------------
// Udp::Plat
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
Error Udp::Plat::Open(SocketHandle &aSocket)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpSocket(&aSocket) : kErrorNone;
}
Error Udp::Plat::Close(SocketHandle &aSocket)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpClose(&aSocket) : kErrorNone;
}
Error Udp::Plat::Bind(SocketHandle &aSocket)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpBind(&aSocket) : kErrorNone;
}
Error Udp::Plat::BindToNetif(SocketHandle &aSocket)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpBindToNetif(&aSocket, MapEnum(aSocket.GetNetifId())) : kErrorNone;
}
Error Udp::Plat::Connect(SocketHandle &aSocket)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpConnect(&aSocket) : kErrorNone;
}
Error Udp::Plat::Send(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo)
{
OT_ASSERT(aSocket.ShouldUsePlatformUdp());
return otPlatUdpSend(&aSocket, &aMessage, &aMessageInfo);
}
Error Udp::Plat::JoinMulticastGroup(SocketHandle &aSocket, NetifIdentifier aNetifId, const Address &aAddress)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpJoinMulticastGroup(&aSocket, MapEnum(aNetifId), &aAddress)
: kErrorNone;
}
Error Udp::Plat::LeaveMulticastGroup(SocketHandle &aSocket, NetifIdentifier aNetifId, const Address &aAddress)
{
return aSocket.ShouldUsePlatformUdp() ? otPlatUdpLeaveMulticastGroup(&aSocket, MapEnum(aNetifId), &aAddress)
: kErrorNone;
}
#endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// Udp
@@ -178,7 +229,7 @@ Error Udp::Open(SocketHandle &aSocket, NetifIdentifier aNetifId, ReceiveHandler
aSocket.mContext = aContext;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpSocket(&aSocket);
error = Plat::Open(aSocket);
#endif
SuccessOrExit(error);
@@ -193,7 +244,7 @@ Error Udp::Bind(SocketHandle &aSocket, const SockAddr &aSockAddr)
Error error = kErrorNone;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
SuccessOrExit(error = otPlatUdpBindToNetif(&aSocket, MapEnum(aSocket.GetNetifId())));
SuccessOrExit(error = Plat::BindToNetif(aSocket));
#endif
VerifyOrExit(aSockAddr.GetAddress().IsUnspecified() || Get<ThreadNetif>().HasUnicastAddress(aSockAddr.GetAddress()),
@@ -207,14 +258,14 @@ Error Udp::Bind(SocketHandle &aSocket, const SockAddr &aSockAddr)
{
aSocket.mSockName.mPort = GetEphemeralPort();
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpBind(&aSocket);
error = Plat::Bind(aSocket);
#endif
} while (error != kErrorNone);
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
else if (ShouldUsePlatformUdp(aSocket))
else
{
error = otPlatUdpBind(&aSocket);
error = Plat::Bind(aSocket);
}
#endif
@@ -234,10 +285,7 @@ Error Udp::Connect(SocketHandle &aSocket, const SockAddr &aSockAddr)
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (ShouldUsePlatformUdp(aSocket))
{
error = otPlatUdpConnect(&aSocket);
}
error = Plat::Connect(aSocket);
#endif
exit:
@@ -251,9 +299,8 @@ Error Udp::Close(SocketHandle &aSocket)
VerifyOrExit(IsOpen(aSocket));
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpClose(&aSocket);
SuccessOrExit(error = Plat::Close(aSocket));
#endif
SuccessOrExit(error);
RemoveSocket(aSocket);
aSocket.GetSockName().Clear();
@@ -299,9 +346,9 @@ Error Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &a
messageInfoLocal.SetSockPort(aSocket.GetSockName().mPort);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (ShouldUsePlatformUdp(aSocket))
if (aSocket.ShouldUsePlatformUdp())
{
SuccessOrExit(error = otPlatUdpSend(&aSocket, &aMessage, &messageInfoLocal));
SuccessOrExit(error = Plat::Send(aSocket, aMessage, messageInfoLocal));
}
else
#endif
@@ -447,45 +494,5 @@ bool Udp::IsPortInUse(uint16_t aPort) const
return found;
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
bool Udp::ShouldUsePlatformUdp(uint16_t aPort) const
{
bool shouldUse = false;
VerifyOrExit(aPort != Mle::kUdpPort);
VerifyOrExit(aPort != Tmf::kUdpPort);
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE && !OPENTHREAD_CONFIG_DNSSD_SERVER_BIND_UNSPECIFIED_NETIF
VerifyOrExit(aPort != Dns::ServiceDiscovery::Server::kPort);
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
VerifyOrExit(aPort != Get<MeshCoP::BorderAgent>().GetUdpProxyPort());
#endif
#if OPENTHREAD_FTD
VerifyOrExit(aPort != Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort());
#endif
#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
VerifyOrExit(aPort != Dhcp6::kDhcpServerPort);
#endif
#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
VerifyOrExit(aPort != Dhcp6::kDhcpClientPort);
#endif
shouldUse = true;
exit:
return shouldUse;
}
bool Udp::ShouldUsePlatformUdp(const Udp::SocketHandle &aSocket) const
{
return (ShouldUsePlatformUdp(aSocket.mSockName.mPort)
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|| aSocket.IsBackbone()
#endif
);
}
#endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
} // namespace Ip6
} // namespace ot
+26 -7
View File
@@ -70,9 +70,10 @@ class Udp;
*/
enum NetifIdentifier : uint8_t
{
kNetifUnspecified = OT_NETIF_UNSPECIFIED, ///< Unspecified network interface.
kNetifThread = OT_NETIF_THREAD, ///< The Thread interface.
kNetifBackbone = OT_NETIF_BACKBONE, ///< The Backbone interface.
kNetifUnspecified = OT_NETIF_UNSPECIFIED, ///< Unspecified network interface.
kNetifThreadHost = OT_NETIF_THREAD_HOST, ///< The host Thread interface - allow use of platform UDP.
kNetifThreadInternal = OT_NETIF_THREAD_INTERNAL, ///< The internal Thread interface - do not use platform UDP.
kNetifBackbone = OT_NETIF_BACKBONE, ///< The Backbone interface.
};
/**
@@ -142,6 +143,14 @@ public:
*/
void SetNetifId(NetifIdentifier aNetifId) { mNetifId = static_cast<otNetifIdentifier>(aNetifId); }
/**
* Indicates whether or not the socket can use platform UDP.
*
* @retval TRUE This socket should use platform UDP.
* @retval FALSE This socket is associated with the internal Thread interface and should not use platform UDP.
*/
bool ShouldUsePlatformUdp(void) const { return GetNetifId() != kNetifThreadInternal; }
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
/**
* Indicate whether or not the socket is bound to the backbone network interface.
@@ -649,14 +658,24 @@ private:
static constexpr uint16_t kSrpServerPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN;
static constexpr uint16_t kSrpServerPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
struct Plat
{
static Error Open(SocketHandle &aSocket);
static Error Close(SocketHandle &aSocket);
static Error Bind(SocketHandle &aSocket);
static Error BindToNetif(SocketHandle &aSocket);
static Error Connect(SocketHandle &aSocket);
static Error Send(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo);
static Error JoinMulticastGroup(SocketHandle &aSocket, NetifIdentifier aNetifId, const Address &aAddress);
static Error LeaveMulticastGroup(SocketHandle &aSocket, NetifIdentifier aNetifId, const Address &aAddress);
};
#endif
static bool IsPortReserved(uint16_t aPort);
void AddSocket(SocketHandle &aSocket);
void RemoveSocket(SocketHandle &aSocket);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
bool ShouldUsePlatformUdp(uint16_t aPort) const;
bool ShouldUsePlatformUdp(const SocketHandle &aSocket) const;
#endif
uint16_t mEphemeralPort;
LinkedList<Receiver> mReceivers;
+1 -1
View File
@@ -127,7 +127,7 @@ Error Mle::Enable(void)
Error error = kErrorNone;
UpdateLinkLocalAddress();
SuccessOrExit(error = mSocket.Open(Ip6::kNetifThread));
SuccessOrExit(error = mSocket.Open(Ip6::kNetifThreadInternal));
SuccessOrExit(error = mSocket.Bind(kUdpPort));
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
+1 -1
View File
@@ -83,7 +83,7 @@ Agent::Agent(Instance &aInstance)
SetResourceHandler(&HandleResource);
}
Error Agent::Start(void) { return Coap::Start(kUdpPort, Ip6::kNetifThread); }
Error Agent::Start(void) { return Coap::Start(kUdpPort, Ip6::kNetifThreadInternal); }
template <> void Agent::HandleTmf<kUriRelayRx>(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
+11 -3
View File
@@ -305,7 +305,7 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
#endif // __linux__
break;
}
case OT_NETIF_THREAD:
case OT_NETIF_THREAD_HOST:
{
#ifdef __linux__
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &gNetifName, strlen(gNetifName)) == 0,
@@ -341,6 +341,9 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
break;
}
case OT_NETIF_THREAD_INTERNAL:
assert(false);
}
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) == 0, error = OT_ERROR_FAILED);
@@ -471,7 +474,7 @@ otError otPlatUdpJoinMulticastGroup(otUdpSocket *aUdpSocket,
{
case OT_NETIF_UNSPECIFIED:
break;
case OT_NETIF_THREAD:
case OT_NETIF_THREAD_HOST:
mreq.ipv6mr_interface = gNetifIndex;
break;
case OT_NETIF_BACKBONE:
@@ -481,6 +484,8 @@ otError otPlatUdpJoinMulticastGroup(otUdpSocket *aUdpSocket,
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
break;
case OT_NETIF_THREAD_INTERNAL:
assert(false);
}
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == 0 || errno == EADDRINUSE,
@@ -512,7 +517,7 @@ otError otPlatUdpLeaveMulticastGroup(otUdpSocket *aUdpSocket,
{
case OT_NETIF_UNSPECIFIED:
break;
case OT_NETIF_THREAD:
case OT_NETIF_THREAD_HOST:
mreq.ipv6mr_interface = gNetifIndex;
break;
case OT_NETIF_BACKBONE:
@@ -522,6 +527,9 @@ otError otPlatUdpLeaveMulticastGroup(otUdpSocket *aUdpSocket,
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
break;
case OT_NETIF_THREAD_INTERNAL:
assert(false);
}
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) == 0 || errno == EADDRINUSE,
+1 -1
View File
@@ -1076,7 +1076,7 @@ void TestSrpClientDelayedResponse(void)
sServerRxCount = 0;
SuccessOrQuit(udpSocket.Open(Ip6::kNetifThread));
SuccessOrQuit(udpSocket.Open(Ip6::kNetifThreadHost));
SuccessOrQuit(udpSocket.Bind(kServerPort));
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -