Message ID | 20170713003913.13571-1-blp@ovn.org |
---|---|
State | Accepted |
Headers | show |
LGTM. Thanks Zhenyu Gao 2017-07-13 8:39 GMT+08:00 Ben Pfaff <blp@ovn.org>: > This will have its first user in an upcoming commit. > > Signed-off-by: Ben Pfaff <blp@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 > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
Thanks. I applied this to master. On Thu, Jul 13, 2017 at 10:46:44AM +0800, Gao Zhenyu wrote: > LGTM. > > Thanks > Zhenyu Gao > > 2017-07-13 8:39 GMT+08:00 Ben Pfaff <blp@ovn.org>: > > > This will have its first user in an upcoming commit. > > > > Signed-off-by: Ben Pfaff <blp@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 > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >
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);
This will have its first user in an upcoming commit. Signed-off-by: Ben Pfaff <blp@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(-)