From 1fceb4c49075d689623cbedde5ea4cf20b7d5484 Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Tue, 8 Jun 2021 12:36:46 +0800 Subject: [PATCH] [posix] make platform udp as mainloop source (#6663) --- src/posix/platform/netif.cpp | 3 +- src/posix/platform/platform-posix.h | 26 ----------- src/posix/platform/system.cpp | 12 +++-- src/posix/platform/udp.cpp | 69 ++++++++++++++++++++--------- src/posix/platform/udp.hpp | 54 ++++++++++++++++++++++ 5 files changed, 109 insertions(+), 55 deletions(-) create mode 100644 src/posix/platform/udp.hpp diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp index b29930832..58f7513c7 100644 --- a/src/posix/platform/netif.cpp +++ b/src/posix/platform/netif.cpp @@ -146,6 +146,7 @@ extern int #include "common/code_utils.hpp" #include "common/logging.hpp" #include "net/ip6_address.hpp" +#include "posix/platform/udp.hpp" unsigned int gNetifIndex = 0; char gNetifName[IFNAMSIZ]; @@ -1475,7 +1476,7 @@ void platformNetifInit(otInstance *aInstance, const char *aInterfaceName) VerifyOrDie(gNetifIndex > 0, OT_EXIT_FAILURE); #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE - platformUdpInit(gNetifName); + ot::Posix::Udp::Get().Init(aInstance, gNetifName); #endif #if OPENTHREAD_POSIX_USE_MLD_MONITOR mldListenerInit(); diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h index 236f15648..dbd067f58 100644 --- a/src/posix/platform/platform-posix.h +++ b/src/posix/platform/platform-posix.h @@ -359,32 +359,6 @@ void virtualTimeSendSleepEvent(const struct timeval *aTimeout); */ void virtualTimeRadioSpinelProcess(otInstance *aInstance, const struct VirtualTimeEvent *aEvent); -/** - * This function initializes platform UDP driver. - * - * @param[in] aIfName The name of Thread's platform network interface. - * - */ -void platformUdpInit(const char *aIfName); - -/** - * This function performs platform UDP driver processing. - * - * @param[in] aInstance The OpenThread instance structure. - * @param[in] aReadFdSet A pointer to the read file descriptors. - * - */ -void platformUdpProcess(otInstance *aInstance, const fd_set *aReadSet); - -/** - * This function updates the file descriptor sets with file descriptors used by the platform UDP driver. - * - * @param[in] aInstance The OpenThread instance structure. - * @param[inout] aReadFdSet A pointer to the read file descriptors. - * @param[inout] aMaxFd A pointer to the max file descriptor. - */ -void platformUdpUpdateFdSet(otInstance *aInstance, fd_set *aReadFdSet, int *aMaxFd); - enum SocketBlockOption { kSocketBlock, diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp index eb65347fb..83d31463f 100644 --- a/src/posix/platform/system.cpp +++ b/src/posix/platform/system.cpp @@ -51,6 +51,7 @@ #include "posix/platform/infra_if.hpp" #include "posix/platform/mainloop.hpp" #include "posix/platform/radio_url.hpp" +#include "posix/platform/udp.hpp" #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE || OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE static void processStateChange(otChangedFlags aFlags, void *aContext) @@ -139,7 +140,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig) #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE platformNetifInit(instance, aPlatformConfig->mInterfaceName); #elif OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE - platformUdpInit(aPlatformConfig->mInterfaceName); + ot::Posix::Udp::Init(instance, aPlatformConfig->mInterfaceName); #else gNetifName[0] = '\0'; #endif @@ -163,6 +164,9 @@ void otSysDeinit(void) virtualTimeDeinit(); #endif platformRadioDeinit(); +#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE + ot::Posix::Udp::Get().Deinit(); +#endif #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE platformNetifDeinit(); #endif @@ -213,9 +217,6 @@ void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop) ot::Posix::Mainloop::Manager::Get().Update(*aMainloop); platformAlarmUpdateTimeout(&aMainloop->mTimeout); -#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE - platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd); -#endif #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE platformNetifUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd); @@ -296,9 +297,6 @@ void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMa #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet); #endif -#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE - platformUdpProcess(aInstance, &aMainloop->mReadFdSet); -#endif } #if OPENTHREAD_CONFIG_OTNS_ENABLE diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp index 80483b8ef..1ff976b86 100644 --- a/src/posix/platform/udp.cpp +++ b/src/posix/platform/udp.cpp @@ -56,32 +56,36 @@ #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE #include "posix/platform/ip6_utils.hpp" +#include "posix/platform/mainloop.hpp" +#include "posix/platform/udp.hpp" using namespace ot::Posix::Ip6Utils; -static const size_t kMaxUdpSize = 1280; +namespace { -static void *FdToHandle(int aFd) +constexpr size_t kMaxUdpSize = 1280; + +void *FdToHandle(int aFd) { return reinterpret_cast(aFd); } -static int FdFromHandle(void *aHandle) +int FdFromHandle(void *aHandle) { return static_cast(reinterpret_cast(aHandle)); } -static bool IsLinkLocal(const struct in6_addr &aAddress) +bool IsLinkLocal(const struct in6_addr &aAddress) { return aAddress.s6_addr[0] == 0xfe && aAddress.s6_addr[1] == 0x80; } -static bool IsMulticast(const otIp6Address &aAddress) +bool IsMulticast(const otIp6Address &aAddress) { return aAddress.mFields.m8[0] == 0xff; } -static otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMessageInfo &aMessageInfo) +otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMessageInfo &aMessageInfo) { #ifdef __APPLE__ // use fixed value for CMSG_SPACE is not a constant expression on macOS @@ -122,18 +126,16 @@ static otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, cons msg.msg_iovlen = 1; msg.msg_flags = 0; - cmsg = CMSG_FIRSTHDR(&msg); - { int hopLimit = (aMessageInfo.mHopLimit ? aMessageInfo.mHopLimit : OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT); + cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_HOPLIMIT; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); memcpy(CMSG_DATA(cmsg), &hopLimit, sizeof(int)); - cmsg = CMSG_NXTHDR(&msg, cmsg); controlLength += CMSG_SPACE(sizeof(int)); } @@ -142,6 +144,7 @@ static otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, cons { struct in6_pktinfo pktinfo; + cmsg = CMSG_NXTHDR(&msg, cmsg); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; cmsg->cmsg_len = CMSG_LEN(sizeof(pktinfo)); @@ -152,7 +155,6 @@ static otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, cons memcpy(CMSG_DATA(cmsg), &pktinfo, sizeof(pktinfo)); controlLength += CMSG_SPACE(sizeof(pktinfo)); - cmsg = CMSG_NXTHDR(&msg, cmsg); } #ifdef __APPLE__ @@ -175,7 +177,7 @@ exit: return error; } -static otError receivePacket(int aFd, uint8_t *aPayload, uint16_t &aLength, otMessageInfo &aMessageInfo) +otError receivePacket(int aFd, uint8_t *aPayload, uint16_t &aLength, otMessageInfo &aMessageInfo) { struct sockaddr_in6 peerAddr; uint8_t control[kMaxUdpSize]; @@ -228,6 +230,8 @@ exit: return rval > 0 ? OT_ERROR_NONE : OT_ERROR_FAILED; } +} // namespace + otError otPlatUdpSocket(otUdpSocket *aUdpSocket) { otError error = OT_ERROR_NONE; @@ -539,11 +543,14 @@ exit: return error; } -void platformUdpUpdateFdSet(otInstance *aInstance, fd_set *aReadFdSet, int *aMaxFd) +namespace ot { +namespace Posix { + +void Udp::Update(otSysMainloopContext &aContext) { VerifyOrExit(gNetifIndex != 0); - for (otUdpSocket *socket = otUdpGetSockets(aInstance); socket != nullptr; socket = socket->mNext) + for (otUdpSocket *socket = otUdpGetSockets(mInstance); socket != nullptr; socket = socket->mNext) { int fd; @@ -553,11 +560,11 @@ void platformUdpUpdateFdSet(otInstance *aInstance, fd_set *aReadFdSet, int *aMax } fd = FdFromHandle(socket->mHandle); - FD_SET(fd, aReadFdSet); + FD_SET(fd, &aContext.mReadFdSet); - if (aMaxFd != nullptr && *aMaxFd < fd) + if (aContext.mMaxFd < fd) { - *aMaxFd = fd; + aContext.mMaxFd = fd; } } @@ -565,7 +572,7 @@ exit: return; } -void platformUdpInit(const char *aIfName) +void Udp::Init(otInstance *aInstance, const char *aIfName) { if (aIfName == nullptr) { @@ -582,17 +589,35 @@ void platformUdpInit(const char *aIfName) } assert(gNetifIndex != 0); + + mInstance = aInstance; + Mainloop::Manager::Get().Add(*this); } -void platformUdpProcess(otInstance *aInstance, const fd_set *aReadFdSet) +void Udp::Deinit(void) +{ + // TODO All platform sockets should be closed + + mInstance = nullptr; + Mainloop::Manager::Get().Remove(*this); +} + +Udp &Udp::Get(void) +{ + static Udp sInstance; + + return sInstance; +} + +void Udp::Process(const otSysMainloopContext &aContext) { otMessageSettings msgSettings = {false, OT_MESSAGE_PRIORITY_NORMAL}; - for (otUdpSocket *socket = otUdpGetSockets(aInstance); socket != nullptr; socket = socket->mNext) + for (otUdpSocket *socket = otUdpGetSockets(mInstance); socket != nullptr; socket = socket->mNext) { int fd = FdFromHandle(socket->mHandle); - if (fd > 0 && FD_ISSET(fd, aReadFdSet)) + if (fd > 0 && FD_ISSET(fd, &aContext.mReadFdSet)) { otMessageInfo messageInfo; otMessage * message = nullptr; @@ -607,7 +632,7 @@ void platformUdpProcess(otInstance *aInstance, const fd_set *aReadFdSet) continue; } - message = otUdpNewMessage(aInstance, &msgSettings); + message = otUdpNewMessage(mInstance, &msgSettings); if (message == nullptr) { @@ -630,4 +655,6 @@ void platformUdpProcess(otInstance *aInstance, const fd_set *aReadFdSet) return; } +} // namespace Posix +} // namespace ot #endif // #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE diff --git a/src/posix/platform/udp.hpp b/src/posix/platform/udp.hpp new file mode 100644 index 000000000..208488b46 --- /dev/null +++ b/src/posix/platform/udp.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OT_POSIX_PLATFORM_UDP_HPP_ +#define OT_POSIX_PLATFORM_UDP_HPP_ + +#include "core/common/non_copyable.hpp" +#include "posix/platform/mainloop.hpp" + +namespace ot { +namespace Posix { + +class Udp : public Mainloop::Source, private NonCopyable +{ +public: + static Udp &Get(void); + + void Init(otInstance *aInstance, const char *aIfName); + void Deinit(void); + void Update(otSysMainloopContext &aContext) override; + void Process(const otSysMainloopContext &aContext) override; + +private: + otInstance *mInstance = nullptr; +}; + +} // namespace Posix +} // namespace ot + +#endif // OT_POSIX_PLATFORM_UDP_HPP_