[ovs-dev] 答复: [PATCH] socket-util: Introduce emulation and wrapper for recvmmsg().

=?gb2312?B?WWkgWWFuZyAo0e6gRCkt1Ma3/s7xvK/NxQ==?= yangyi01 at inspur.com
Fri Dec 20 01:25:29 UTC 2019


Current ovs matser has included sendmmsg declaration in
include/sparse/sys/socket.h

int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);

I saw  "+^L" in your patch.

--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -1283,3 +1283,59 @@ wrap_sendmmsg(int fd, struct mmsghdr *msgs, unsigned
int n, unsigned int flags)
 }
 #endif
 #endif
+^L
+#ifndef _WIN32 /* Avoid using recvmsg on Windows entirely. */

+#undef recvmmsg
+int
+wrap_recvmmsg(int fd, struct mmsghdr *msgs, unsigned int n,
+              int flags, struct timespec *timeout)
+{
+    ovs_assert(!timeout);       /* XXX not emulated */
+
+    static bool recvmmsg_broken = false;
+    if (!recvmmsg_broken) {
+        int save_errno = errno;
+        int retval = recvmmsg(fd, msgs, n, flags, timeout);
+        if (retval >= 0 || errno != ENOSYS) {
+            return retval;
+        }
+        recvmmsg_broken = true;
+        errno = save_errno;
+    }
+    return emulate_recvmmsg(fd, msgs, n, flags, timeout);
+}
+#endif

I don't understand why call recvmmsg here although we have known recvmmsg
isn't defined, I don't think "static bool recvmmsg_broken" is thread-safe. I
think we can completely remove the below part if we do know recvmmsg isn't
defined (I think autoconf can detect it very precisely, we needn't to do
runtime check for this)
+    static bool recvmmsg_broken = false;
+    if (!recvmmsg_broken) {
+        int save_errno = errno;
+        int retval = recvmmsg(fd, msgs, n, flags, timeout);
+        if (retval >= 0 || errno != ENOSYS) {
+            return retval;
+        }
+        recvmmsg_broken = true;
+        errno = save_errno;
+    }


-----ÓʼþÔ­¼þ-----
·¢¼þÈË: Ben Pfaff [mailto:blp at ovn.org] 
·¢ËÍʱ¼ä: 2019Äê12ÔÂ18ÈÕ 4:39
ÊÕ¼þÈË: dev at openvswitch.org
³­ËÍ: Ben Pfaff <blp at ovn.org>; Yi Yang (Ñî D)-ÔÆ·þÎñ¼¯ÍÅ
<yangyi01 at inspur.com>
Ö÷Ìâ: [PATCH] socket-util: Introduce emulation and wrapper for recvmmsg().

Not every system will have recvmmsg(), so introduce compatibility code that
will allow it to be used blindly from the rest of the tree.

This assumes that recvmmsg() and sendmmsg() are either both present or both
absent in system libraries and headers.

CC: Yi Yang <yangyi01 at inspur.com>
Signed-off-by: Ben Pfaff <blp at ovn.org>
---
I haven't actually tested this!

 include/sparse/sys/socket.h |  7 ++++-
 lib/socket-util.c           | 56 +++++++++++++++++++++++++++++++++++++
 lib/socket-util.h           | 24 +++++++++-------
 3 files changed, 76 insertions(+), 11 deletions(-)

diff --git a/include/sparse/sys/socket.h b/include/sparse/sys/socket.h index
4178f57e2bda..6ff245ae939b 100644
--- a/include/sparse/sys/socket.h
+++ b/include/sparse/sys/socket.h
@@ -27,6 +27,7 @@
 
 typedef unsigned short int sa_family_t;  typedef __socklen_t socklen_t;
+struct timespec;
 
 struct sockaddr {
     sa_family_t sa_family;
@@ -126,7 +127,8 @@ enum {
     MSG_PEEK,
     MSG_TRUNC,
     MSG_WAITALL,
-    MSG_DONTWAIT
+    MSG_DONTWAIT,
+    MSG_WAITFORONE
 };
 
 enum {
@@ -171,4 +173,7 @@ int sockatmark(int);  int socket(int, int, int);  int
socketpair(int, int, int, int[2]);
 
+int sendmmsg(int, struct mmsghdr *, unsigned int, int); int 
+recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *);
+
 #endif /* <sys/socket.h> for sparse */
diff --git a/lib/socket-util.c b/lib/socket-util.c index
6b7378de934b..f6f6f3b0a33f 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -1283,3 +1283,59 @@ wrap_sendmmsg(int fd, struct mmsghdr *msgs, unsigned
int n, unsigned int 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) {
+    ovs_assert(!timeout);       /* XXX not emulated */
+
+    bool waitforone = flags & MSG_WAITFORONE;
+    flags &= ~MSG_WAITFORONE;
+
+    for (unsigned int i = 0; i < n; i++) {
+        ssize_t retval = recvmsg(fd, &msgs[i].msg_hdr, flags);
+        if (retval < 0) {
+            return i ? i : retval;
+        }
+        msgs[i].msg_len = retval;
+
+        if (waitforone) {
+            flags |= MSG_DONTWAIT;
+        }
+    }
+    return n;
+}
+
+#ifndef HAVE_SENDMMSG
+int
+recvmmsg(int fd, struct mmsghdr *msgs, unsigned int n,
+         int flags, struct timespec *timeout) {
+    return emulate_recvmmsg(fd, msgs, n, flags, timeout); } #else
+/* recvmmsg was redefined in lib/socket-util.c, should undef recvmmsg 
+here
+ * to avoid recursion */
+#undef recvmmsg
+int
+wrap_recvmmsg(int fd, struct mmsghdr *msgs, unsigned int n,
+              int flags, struct timespec *timeout) {
+    ovs_assert(!timeout);       /* XXX not emulated */
+
+    static bool recvmmsg_broken = false;
+    if (!recvmmsg_broken) {
+        int save_errno = errno;
+        int retval = recvmmsg(fd, msgs, n, flags, timeout);
+        if (retval >= 0 || errno != ENOSYS) {
+            return retval;
+        }
+        recvmmsg_broken = true;
+        errno = save_errno;
+    }
+    return emulate_recvmmsg(fd, msgs, n, flags, timeout); } #endif 
+#endif
diff --git a/lib/socket-util.h b/lib/socket-util.h index
a65433d90738..71bd68926aaa 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -104,19 +104,20 @@ 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 support.
+/* Universal sendmmsg and recvmmsg support.
  *
- * Some platforms, such as new enough Linux and FreeBSD, support sendmmsg,
but
- * other platforms (or older ones) do not.  We add the following
infrastructure
- * to allow all code to use sendmmsg, regardless of platform support:
+ * 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:
  *
- *   - For platforms that lack sendmmsg entirely, we emulate it.
+ * - For platforms that lack these functions entirely, we emulate them.
  *
- *   - Some platforms have sendmmsg() 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 sendmmsg() appears to be
available,
- *     we still wrap it with a handler that uses our emulation if
sendmmsg()
- *     returns ENOSYS.
+ * - 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.
  */
 #ifndef HAVE_STRUCT_MMSGHDR_MSG_LEN
 struct mmsghdr {
@@ -126,9 +127,12 @@ struct mmsghdr {
 #endif
 #ifndef HAVE_SENDMMSG
 int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);
+int recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec 
+*);
 #else
 #define sendmmsg wrap_sendmmsg
 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
 
 /* Helpers for calling ioctl() on an AF_INET socket. */
--
2.23.0



More information about the dev mailing list