This will have its first user in an upcoming commit.
Signed-off-by: Ben Pfaff <blp@ovn.org>
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>]])
: NULL);
}
+struct mmsghdr {
+ struct msghdr msg_hdr;
+ unsigned int msg_len;
+};
+
enum {
SCM_RIGHTS = 1
};
return ovs_strerror(error);
#endif
}
+\f
+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
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);