Skip to content

Commit

Permalink
[udp] add kNetifThreadInternal which disallows platform UDP use (op…
Browse files Browse the repository at this point in the history
…enthread#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.
  • Loading branch information
abtink authored Nov 28, 2024
1 parent ae5b750 commit 473af53
Show file tree
Hide file tree
Showing 16 changed files with 113 additions and 78 deletions.
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion include/openthread/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/cli/cli_udp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/api/udp_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/core/meshcop/joiner_router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion src/core/net/dhcp6_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/core/net/dhcp6_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/core/net/dnssd_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/core/net/srp_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/core/net/srp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
117 changes: 62 additions & 55 deletions src/core/net/udp6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -136,14 +136,65 @@ 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:
return error;
}
#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

Expand Down Expand Up @@ -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);

Expand All @@ -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()),
Expand All @@ -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

Expand All @@ -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:
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
33 changes: 26 additions & 7 deletions src/core/net/udp6.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
};

/**
Expand Down Expand Up @@ -142,6 +143,14 @@ class Udp : public InstanceLocator, private NonCopyable
*/
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.
Expand Down Expand Up @@ -649,14 +658,24 @@ class Udp : public InstanceLocator, private NonCopyable
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;
Expand Down
2 changes: 1 addition & 1 deletion src/core/thread/mle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/core/thread/tmf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Loading

0 comments on commit 473af53

Please sign in to comment.