From f7f5aa08318631e00960e2dec96cf829ce1412fc Mon Sep 17 00:00:00 2001 From: Thad House Date: Tue, 10 Aug 2021 11:45:00 -0700 Subject: [PATCH 1/3] Add shim for sendmmsg when sendmmsg does not exist Some users have asked to build with glibc versions that do not have sendmmsg. This change checks for the existance of sendmmsg, and if its missing implements a shim version that has identical functionality --- CMakeLists.txt | 15 +++++++++++++++ src/platform/datapath_epoll.c | 28 +++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 141502f05d..16de935f89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,6 +245,18 @@ else() message(STATUS "SO_ATTACH_REUSEPORT_CBPF is missing. Server receive performance will be reduced") endif() + check_c_source_compiles( + " + #define _GNU_SOURCE + #include + #include + int main() { return sendmmsg(0, NULL, 0, 0); } + " + HAS_SENDMMSG) + if(NOT HAS_SENDMMSG) + message(STATUS "sendmmsg is missing. Send performance will be reduced") + endif() + # Error if flags are missing in CI if(QUIC_CI AND NOT QUIC_SKIP_CI_CHECKS) if (NOT HAS_UDP_SEGMENT) @@ -276,6 +288,9 @@ else() set(QUIC_COMMON_FLAGS "") set(QUIC_COMMON_DEFINES _GNU_SOURCE) + if (HAS_SENDMMSG) + list(APPEND QUIC_COMMON_DEFINES HAS_SENDMMSG) + endif() set(QUIC_WARNING_FLAGS -Werror -Wall -Wextra -Wformat=2 -Wno-type-limits -Wno-unknown-pragmas -Wno-multichar -Wno-missing-field-initializers CACHE INTERNAL "") diff --git a/src/platform/datapath_epoll.c b/src/platform/datapath_epoll.c index 60e156061b..63adc90b7b 100644 --- a/src/platform/datapath_epoll.c +++ b/src/platform/datapath_epoll.c @@ -28,6 +28,32 @@ CXPLAT_STATIC_ASSERT((SIZEOF_STRUCT_MEMBER(QUIC_BUFFER, Length) <= sizeof(size_t)), "(sizeof(QUIC_BUFFER.Length) == sizeof(size_t) must be TRUE."); CXPLAT_STATIC_ASSERT((SIZEOF_STRUCT_MEMBER(QUIC_BUFFER, Buffer) == sizeof(void*)), "(sizeof(QUIC_BUFFER.Buffer) == sizeof(void*) must be TRUE."); +#ifdef HAS_SENDMMSG +#define CXPLAT_SENDMMSG sendmmsg +#else +static +ssize_t +cxplat_sendmmsg_shim( + int fd, + struct mmsghdr* Messages, + unsigned int MessageLen, + int Flags + ) +{ + unsigned int SuccessCount = 0; + while (SuccessCount < MessageLen) { + int Result = sendmsg(fd, &Messages[SuccessCount].msg_hdr, Flags); + if (Result < 0) { + return SuccessCount == 0 ? Result : (ssize_t)SuccessCount; + } + Messages[SuccessCount].msg_len = Result; + SuccessCount++; + } + return SuccessCount; +} +#define CXPLAT_SENDMMSG cxplat_sendmmsg_shim +#endif + #define CXPLAT_MAX_BATCH_SEND 1 #define CXPLAT_MAX_BATCH_RECEIVE 43 @@ -2564,7 +2590,7 @@ CxPlatSocketSendInternal( while (SendData->SentMessagesCount < TotalMessagesCount) { int SuccessfullySentMessages = - sendmmsg( + CXPLAT_SENDMMSG( SocketContext->SocketFd, Mhdrs + SendData->SentMessagesCount, (unsigned int)(TotalMessagesCount - SendData->SentMessagesCount), From c97fe75f74ab5fc7d2315463cbe3015a78ae2da7 Mon Sep 17 00:00:00 2001 From: Thad House Date: Tue, 10 Aug 2021 12:46:35 -0700 Subject: [PATCH 2/3] Fix shim signature --- src/platform/datapath_epoll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/datapath_epoll.c b/src/platform/datapath_epoll.c index 63adc90b7b..ee0379b0c0 100644 --- a/src/platform/datapath_epoll.c +++ b/src/platform/datapath_epoll.c @@ -32,7 +32,7 @@ CXPLAT_STATIC_ASSERT((SIZEOF_STRUCT_MEMBER(QUIC_BUFFER, Buffer) == sizeof(void*) #define CXPLAT_SENDMMSG sendmmsg #else static -ssize_t +int cxplat_sendmmsg_shim( int fd, struct mmsghdr* Messages, @@ -44,7 +44,7 @@ cxplat_sendmmsg_shim( while (SuccessCount < MessageLen) { int Result = sendmsg(fd, &Messages[SuccessCount].msg_hdr, Flags); if (Result < 0) { - return SuccessCount == 0 ? Result : (ssize_t)SuccessCount; + return SuccessCount == 0 ? Result : (int)SuccessCount; } Messages[SuccessCount].msg_len = Result; SuccessCount++; @@ -138,7 +138,7 @@ typedef struct CXPLAT_SEND_DATA { // // The number of messages of this buffer that have been sent. // - size_t SentMessagesCount; + ssize_t SentMessagesCount; // // The send segmentation size; zero if segmentation is not performed. From 47ab391d6ae046b50e79b1f4524c8f6f82fafb6a Mon Sep 17 00:00:00 2001 From: Thad House Date: Tue, 10 Aug 2021 12:55:47 -0700 Subject: [PATCH 3/3] 1 more fix --- src/platform/datapath_epoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/datapath_epoll.c b/src/platform/datapath_epoll.c index ee0379b0c0..edda452947 100644 --- a/src/platform/datapath_epoll.c +++ b/src/platform/datapath_epoll.c @@ -138,7 +138,7 @@ typedef struct CXPLAT_SEND_DATA { // // The number of messages of this buffer that have been sent. // - ssize_t SentMessagesCount; + size_t SentMessagesCount; // // The send segmentation size; zero if segmentation is not performed.