[ovs-dev] [PATCH] socket-util: Emulate recvmmsg() and sendmmsg() on Linux only.

Ben Pfaff blp at ovn.org
Mon Jan 13 18:03:04 UTC 2020


These functions failed to build on OS X because MSG_WAITFORONE is not
defined there.  There are pitfalls for trying to define our own MSG_*
constants, since it's hard to pick a constant that is not used by the
system already.  Because OVS only uses recvmmsg() and sendmmsg() on
Linux, it seems easiest to just emulate them there.

Reported-by: Ilya Maximets <i.maximets at ovn.org>
Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 lib/socket-util.c |  8 +++-----
 lib/socket-util.h | 20 ++++++++++----------
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/lib/socket-util.c b/lib/socket-util.c
index f6f6f3b0a33f..4f1ffecf5d6f 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -1241,7 +1241,7 @@ sock_strerror(int error)
 #endif
 }
 
-#ifndef _WIN32 /* Avoid using sendmsg on Windows entirely. */
+#ifdef __linux__
 static int
 emulate_sendmmsg(int fd, struct mmsghdr *msgs, unsigned int n,
                  unsigned int flags)
@@ -1282,9 +1282,7 @@ wrap_sendmmsg(int fd, struct mmsghdr *msgs, unsigned int n, unsigned int flags)
     return emulate_sendmmsg(fd, msgs, n, flags);
 }
 #endif
-#endif
-
-#ifndef _WIN32 /* Avoid using recvmsg on Windows entirely. */
+
 static int
 emulate_recvmmsg(int fd, struct mmsghdr *msgs, unsigned int n,
                  int flags, struct timespec *timeout OVS_UNUSED)
@@ -1338,4 +1336,4 @@ wrap_recvmmsg(int fd, struct mmsghdr *msgs, unsigned int n,
     return emulate_recvmmsg(fd, msgs, n, flags, timeout);
 }
 #endif
-#endif
+#endif /* __linux__ */
diff --git a/lib/socket-util.h b/lib/socket-util.h
index 71bd68926aaa..9ccb7d4cc41d 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -104,27 +104,26 @@ int make_unix_socket(int style, bool nonblock,
                      const char *bind_path, const char *connect_path);
 int get_unix_name_len(const struct sockaddr_un *sun, socklen_t sun_len);
 
-/* Universal sendmmsg and recvmmsg support.
+/* Universal sendmmsg and recvmmsg support on Linux.
  *
- * Some platforms, such as new enough Linux and FreeBSD, support sendmmsg and
- * recvmmsg, but other platforms (or older ones) do not.  We add the following
- * infrastructure to allow all code to use sendmmsg and recvmmsg, regardless of
- * platform support:
+ * New enough Linux supports sendmmsg and recvmmsg, but older versions do not.
+ * We add the following infrastructure to allow all code on Linux to use
+ * sendmmsg and recvmmsg, regardless of platform support:
  *
  * - For platforms that lack these functions entirely, we emulate them.
  *
- * - Some platforms have sendmmsg() and recvmmsg() in the C library but not in
- *   the kernel.  For example, this is true if a Linux system has a newer glibc
- *   with an old kernel.  To compensate, even if these functions appear to be
- *   available, we still wrap them with handlers that uses our emulation if the
- *   underlying function returns ENOSYS.
+ * - With newer glibc but an old kernel, sendmmsg() and recvmmsg() fail with
+ *   ENOSYS.  To compensate, even if these functions appear to be available, we
+ *   wrap them with handlers that use our emulation in this case.
  */
+#ifdef __linux__
 #ifndef HAVE_STRUCT_MMSGHDR_MSG_LEN
 struct mmsghdr {
     struct msghdr msg_hdr;
     unsigned int msg_len;
 };
 #endif
+
 #ifndef HAVE_SENDMMSG
 int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);
 int recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *);
@@ -134,6 +133,7 @@ int wrap_sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);
 #define recvmmsg wrap_recvmmsg
 int wrap_recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *);
 #endif
+#endif /* __linux__ */
 
 /* Helpers for calling ioctl() on an AF_INET socket. */
 struct ifreq;
-- 
2.23.0



More information about the dev mailing list