This will have its first user in an upcoming commit. Signed-off-by: Ben Pfaff <b...@ovn.org> --- v1->v2: Note that FreeBSD also has sendmmsg. Fix sendmsg() return type.
configure.ac | 3 ++- include/sparse/sys/socket.h | 5 +++++ lib/socket-util.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/socket-util.h | 27 +++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6404b5fc1222..9ef6aad3a36e 100644 --- a/configure.ac +++ b/configure.ac @@ -106,7 +106,8 @@ AC_CHECK_DECLS([sys_siglist], [], [], [[#include <signal.h>]]) AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec], [], [], [[#include <sys/stat.h>]]) AC_CHECK_MEMBERS([struct ifreq.ifr_flagshigh], [], [], [[#include <net/if.h>]]) -AC_CHECK_FUNCS([mlockall strnlen getloadavg statvfs getmntent_r]) +AC_CHECK_MEMBERS([struct mmsghdr.msg_len], [], [], [[#include <sys/socket.h>]]) +AC_CHECK_FUNCS([mlockall strnlen getloadavg statvfs getmntent_r sendmmsg]) AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h stdatomic.h]) AC_CHECK_HEADERS([net/if_mib.h], [], [], [[#include <sys/types.h> #include <net/if.h>]]) diff --git a/include/sparse/sys/socket.h b/include/sparse/sys/socket.h index 3212bf4b7f13..88a5387e7f9b 100644 --- a/include/sparse/sys/socket.h +++ b/include/sparse/sys/socket.h @@ -75,6 +75,11 @@ __cmsg_nxthdr(struct msghdr *msg, struct cmsghdr *cmsg) : NULL); } +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; + enum { SCM_RIGHTS = 1 }; diff --git a/lib/socket-util.c b/lib/socket-util.c index 2c0f1e62bd99..7148ae3da67c 100644 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@ -1020,3 +1020,41 @@ sock_strerror(int error) return ovs_strerror(error); #endif } + +static int +emulate_sendmmsg(int fd, struct mmsghdr *msgs, unsigned int n, + unsigned int flags) +{ + for (unsigned int i = 0; i < n; i++) { + ssize_t retval = sendmsg(fd, &msgs[i].msg_hdr, flags); + if (retval < 0) { + return i ? i : retval; + } + msgs[i].msg_len = retval; + } + return n; +} + +#ifndef HAVE_SENDMMSG +int +sendmmsg(int fd, struct mmsghdr *msgs, unsigned int n, unsigned int flags) +{ + return emulate_sendmmsg(fd, msgs, n, flags); +} +#else +int +wrap_sendmmsg(int fd, struct mmsghdr *msgs, unsigned int n, unsigned int flags) +{ + static bool sendmmsg_broken = false; + if (!sendmmsg_broken) { + int save_errno = errno; + int retval = sendmmsg(fd, msgs, n, flags); + if (retval >= 0 || errno != ENOSYS) { + return retval; + } + sendmmsg_broken = true; + errno = save_errno; + } + return emulate_sendmmsg(fd, msgs, n, flags); +} +#endif diff --git a/lib/socket-util.h b/lib/socket-util.h index 5bf76a40eb84..ef316cb8cc72 100644 --- a/lib/socket-util.h +++ b/lib/socket-util.h @@ -87,6 +87,33 @@ 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. + * + * 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: + * + * - For platforms that lack sendmmsg entirely, we emulate it. + * + * - 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. + */ +#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); +#else +#define sendmmsg wrap_sendmmsg +int wrap_sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int); +#endif + /* Helpers for calling ioctl() on an AF_INET socket. */ struct ifreq; int af_inet_ioctl(unsigned long int command, const void *arg); -- 2.10.2 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev