[ovs-dev] [PATCH] socket-util: Support sendmmsg() on Linux and non-Linux platforms.

Takashi YAMAMOTO yamamoto at ovn.org
Wed Jul 12 23:45:21 UTC 2017


On Thu, Jul 13, 2017 at 1:23 AM, Ben Pfaff <blp at ovn.org> wrote:

> This will have its first user in an upcoming commit.
>
> Signed-off-by: Ben Pfaff <blp at ovn.org>
> ---
>  configure.ac                |  3 ++-
>  include/sparse/sys/socket.h |  5 +++++
>  lib/socket-util.c           | 38 ++++++++++++++++++++++++++++++++++++++
>  lib/socket-util.h           | 25 +++++++++++++++++++++++++
>  4 files changed, 70 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..0927ac9ac6c4 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++) {
> +        int retval = sendmsg(fd, &msgs[i].msg_hdr, flags);
>

ssize_t?

+        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..0041345b0ba2 100644
> --- a/lib/socket-util.h
> +++ b/lib/socket-util.h
> @@ -87,6 +87,31 @@ 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);
>
> +/* sendmmsg support.
> + *
> + * We add the following infrastructure to allow all code to use sendmmsg()
> + * without caring what platform it runs on:
> + *
> + *   - Non-Linux platforms do not have sendmmsg.  For these, we emulate
> it.
>

FYI, it's available on non-linux platforms these days.
https://www.freebsd.org/cgi/man.cgi?query=sendmmsg&apropos=0&sektion=0&manpath=FreeBSD+11.0-RELEASE+and+Ports&arch=default&format=html
http://netbsd.gw.com/cgi-bin/man-cgi?sendmmsg++NetBSD-current

+ *
> + *   - Linux platforms might have sendmmsg in their C library but not in
> the
> + *     kernel, which means that it will always return ENOSYS.  To
> compensate,
> + *     we wrap sendmmsg() 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 at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>


More information about the dev mailing list