From: "Daniel P. Berrangé" <berrange@redhat.com>
To: Vitaly Cheptsov <cheptsov@ispras.ru>
Cc: qemu-devel@nongnu.org, "Jason Wang" <jasowang@redhat.com>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>
Subject: Re: [PATCH] net: fix multicast support with BSD (macOS) socket implementations
Date: Tue, 3 May 2022 14:13:05 +0100 [thread overview]
Message-ID: <YnEqYRUpnZCIBfet@redhat.com> (raw)
In-Reply-To: <20220502003830.31062-1-cheptsov@ispras.ru>
On Mon, May 02, 2022 at 03:38:30AM +0300, Vitaly Cheptsov wrote:
> This patch fixes socket communication with QEMU -> host on macOS,
> which was originally impossible due to QEMU and host program
> having to bind to the same ip/port in a way not supported by BSD
> sockets. The change was tested on both Linux and macOS.
>
> As per BSD manual pages SO_REUSEPORT allows completely duplicate
> bindings by multiple processes, permitting multiple instances of
> a program to each receive UDP/IP multicast datagrams destined
> for the bound port. Without this option macOS, unlike Linux,
> which (ab)uses SO_REUSEADDR for this purpose, will return
> "Address already in use" on bind().
When looking in Google there's a comprehensive looking
description of SO_REUSEADDR + SO_REUSEPORT across all the
different OS which insists that SO_REUSEPORT and SO_REUSEADDR
are functionally equivalent for multicast IP addresses:
https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ
And AFAIK, macOS should behave the same way, which suggests
this patch is not needed.
Oddly though, I don't find this in the FreeBSD man page - its
description seems fairly clear that SO_REUSEPORT is needed for
multicast
[quote]
SO_REUSEPORT allows completely duplicate bindings by multiple processes
if they all set SO_REUSEPORT before binding the port. This option
permits multiple instances of a program to each receive UDP/IP multicast
or broadcast datagrams destined for the bound port.
[/quote]
>
> As per BSD manual pages binding to any address, even one not bound
> to any available network interface in the system, should be
> IP_BINDANY. Without binding to INADDR_ANY macOS will return
> "Can't assign requested address" on send().
I didn't find a quote about this in the FreeBSD man pages I looked
at, and it feels dubious to me. If the user gives QEMU a address to
bind to, we should surely be honouring that, not changing it to
INADDR_ANY.
If using INADDR_ANY though, thsi could explain the need for
SO_REUSEPORT, since INADDR_ANY is not a designated mcast address.
> Cc: Jason Wang <jasowang@redhat.com>
> Cc: Daniel P. Berrange <berrange@redhat.com>
> Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Signed-off-by: Vitaly Cheptsov <cheptsov@ispras.ru>
> ---
> net/socket.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/net/socket.c b/net/socket.c
> index ea5220a2eb..8b2c6c4bb8 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -252,10 +252,24 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
> goto fail;
> }
>
> - ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
> + val = 1;
> + ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
> + if (ret < 0) {
> + error_setg_errno(errp, errno,
> + "can't set socket option SO_REUSEPORT");
> + goto fail;
> + }
AFAIK, this likely won't compile on Windows since it lacks SO_REUSEPORT
> +
> + struct sockaddr_in bindaddr;
> + memset(&bindaddr, 0, sizeof(bindaddr));
> + bindaddr.sin_family = AF_INET;
> + bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
> + bindaddr.sin_port = mcastaddr->sin_port;
> + ret = bind(fd, (struct sockaddr *)&bindaddr, sizeof(bindaddr));
> +
> if (ret < 0) {
> error_setg_errno(errp, errno, "can't bind ip=%s to socket",
> - inet_ntoa(mcastaddr->sin_addr));
> + inet_ntoa(bindaddr.sin_addr));
> goto fail;
> }
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
next prev parent reply other threads:[~2022-05-03 15:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-02 0:38 [PATCH] net: fix multicast support with BSD (macOS) socket implementations Vitaly Cheptsov
2022-05-03 13:13 ` Daniel P. Berrangé [this message]
2022-05-03 16:10 ` Vitaly Cheptsov
2022-05-16 14:42 ` Vitaly Cheptsov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YnEqYRUpnZCIBfet@redhat.com \
--to=berrange@redhat.com \
--cc=cheptsov@ispras.ru \
--cc=f4bug@amsat.org \
--cc=jasowang@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.