LGTM. Thanks Zhenyu Gao
2017-07-13 8:39 GMT+08:00 Ben Pfaff <[email protected]>: > This will have its first user in an upcoming commit. > > Signed-off-by: Ben Pfaff <[email protected]> > --- > 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 > [email protected] > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
