[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 3/4] Establishing connection between any non-default source a
From: |
Daniel P . Berrangé |
Subject: |
Re: [PATCH 3/4] Establishing connection between any non-default source and destination pair |
Date: |
Thu, 16 Jun 2022 18:39:39 +0100 |
User-agent: |
Mutt/2.2.1 (2022-02-19) |
On Thu, Jun 09, 2022 at 07:33:04AM +0000, Het Gala wrote:
> i) Binding of the socket to source ip address and port on the non-default
> interface has been implemented for multi-FD connection, which was not
> necessary earlier because the binding was on the default interface itself.
>
> ii) Created an end to end connection between all multi-FD source and
> destination pairs.
>
> Suggested-by: Manish Mishra <manish.mishra@nutanix.com>
> Signed-off-by: Het Gala <het.gala@nutanix.com>
> ---
> chardev/char-socket.c | 4 +-
> include/io/channel-socket.h | 26 ++++++-----
> include/qemu/sockets.h | 6 ++-
> io/channel-socket.c | 50 ++++++++++++++------
> migration/socket.c | 15 +++---
> nbd/client-connection.c | 2 +-
> qemu-nbd.c | 4 +-
> scsi/pr-manager-helper.c | 1 +
> tests/unit/test-char.c | 8 ++--
> tests/unit/test-io-channel-socket.c | 4 +-
> tests/unit/test-util-sockets.c | 16 +++----
> ui/input-barrier.c | 2 +-
> ui/vnc.c | 3 +-
> util/qemu-sockets.c | 71 ++++++++++++++++++++---------
> 14 files changed, 135 insertions(+), 77 deletions(-)
>
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index dc4e218eeb..f3725238c5 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -932,7 +932,7 @@ static int tcp_chr_connect_client_sync(Chardev *chr,
> Error **errp)
> QIOChannelSocket *sioc = qio_channel_socket_new();
> tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
> tcp_chr_set_client_ioc_name(chr, sioc);
> - if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
> + if (qio_channel_socket_connect_sync(sioc, s->addr, NULL, errp) < 0) {
> tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
> object_unref(OBJECT(sioc));
> return -1;
> @@ -1120,7 +1120,7 @@ static void tcp_chr_connect_client_task(QIOTask *task,
> SocketAddress *addr = opaque;
> Error *err = NULL;
>
> - qio_channel_socket_connect_sync(ioc, addr, &err);
> + qio_channel_socket_connect_sync(ioc, addr, NULL, &err);
>
> qio_task_set_error(task, err);
> }
> diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h
> index 513c428fe4..59d5b1b349 100644
> --- a/include/io/channel-socket.h
> +++ b/include/io/channel-socket.h
> @@ -83,41 +83,45 @@ qio_channel_socket_new_fd(int fd,
> /**
> * qio_channel_socket_connect_sync:
> * @ioc: the socket channel object
> - * @addr: the address to connect to
> + * @dst_addr: the destination address to connect to
> + * @src_addr: the source address to be connected
> * @errp: pointer to a NULL-initialized error object
> *
> - * Attempt to connect to the address @addr. This method
> - * will run in the foreground so the caller will not regain
> - * execution control until the connection is established or
> + * Attempt to connect to the address @dst_addr with @src_addr.
> + * This method will run in the foreground so the caller will not
> + * regain execution control until the connection is established or
> * an error occurs.
> */
> int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
> - SocketAddress *addr,
> + SocketAddress *dst_addr,
> + SocketAddress *src_addr,
> Error **errp);
>
> /**
> * qio_channel_socket_connect_async:
> * @ioc: the socket channel object
> - * @addr: the address to connect to
> + * @dst_addr: the destination address to connect to
> * @callback: the function to invoke on completion
> * @opaque: user data to pass to @callback
> * @destroy: the function to free @opaque
> * @context: the context to run the async task. If %NULL, the default
> * context will be used.
> + * @src_addr: the source address to be connected
> *
> - * Attempt to connect to the address @addr. This method
> - * will run in the background so the caller will regain
> + * Attempt to connect to the address @dst_addr with the @src_addr.
> + * This method will run in the background so the caller will regain
> * execution control immediately. The function @callback
> - * will be invoked on completion or failure. The @addr
> + * will be invoked on completion or failure. The @dst_addr
> * parameter will be copied, so may be freed as soon
> * as this function returns without waiting for completion.
> */
> void qio_channel_socket_connect_async(QIOChannelSocket *ioc,
> - SocketAddress *addr,
> + SocketAddress *dst_addr,
> QIOTaskFunc callback,
> gpointer opaque,
> GDestroyNotify destroy,
> - GMainContext *context);
> + GMainContext *context,
> + SocketAddress *src_addr);
Lets avoid modifying these two methods, and thus avoid
updating countless callers.
In common with typical pattern in QIO code, lets add
a second variant
qio_channel_socket_connect_full
qio_channel_socket_connect_full_async
which has the extra parameters, then make the existing
simpler methods call the new ones.
ie qio_channel_socket_connect should call
qio_channel_socket_connect_full, pasing NULL for the
src_addr.
> diff --git a/io/channel-socket.c b/io/channel-socket.c
> index dc9c165de1..f8746ad646 100644
> --- a/io/channel-socket.c
> +++ b/io/channel-socket.c
> @@ -36,6 +36,12 @@
>
> #define SOCKET_MAX_FDS 16
>
> +struct SrcDestAddress {
> + SocketAddress *dst_addr;
> + SocketAddress *src_addr;
> +};
Nitpick, just call this 'struct ConnectData'.
> SocketAddress *
> qio_channel_socket_get_local_address(QIOChannelSocket *ioc,
> Error **errp)
> @@ -145,13 +151,14 @@ qio_channel_socket_new_fd(int fd,
>
>
> int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
> - SocketAddress *addr,
> + SocketAddress *dst_addr,
> + SocketAddress *src_addr,
> Error **errp)
> {
> int fd;
>
> - trace_qio_channel_socket_connect_sync(ioc, addr);
> - fd = socket_connect(addr, errp);
> + trace_qio_channel_socket_connect_sync(ioc, dst_addr);
> + fd = socket_connect(dst_addr, src_addr, errp);
> if (fd < 0) {
> trace_qio_channel_socket_connect_fail(ioc);
> return -1;
> @@ -177,39 +184,56 @@ int qio_channel_socket_connect_sync(QIOChannelSocket
> *ioc,
> }
>
>
> +static void qio_channel_socket_worker_free(gpointer opaque)
> +{
> + struct SrcDestAddress *data = opaque;
> + if (!data) {
> + return;
> + }
> + qapi_free_SocketAddress(data->dst_addr);
> + qapi_free_SocketAddress(data->src_addr);
> + g_free(data);
> +}
> +
> +
> static void qio_channel_socket_connect_worker(QIOTask *task,
> gpointer opaque)
> {
> QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
> - SocketAddress *addr = opaque;
> + struct SrcDestAddress *data = opaque;
> Error *err = NULL;
>
> - qio_channel_socket_connect_sync(ioc, addr, &err);
> + qio_channel_socket_connect_sync(ioc, data->dst_addr, data->src_addr,
> &err);
>
> qio_task_set_error(task, err);
> }
>
>
> void qio_channel_socket_connect_async(QIOChannelSocket *ioc,
> - SocketAddress *addr,
> + SocketAddress *dst_addr,
> QIOTaskFunc callback,
> gpointer opaque,
> GDestroyNotify destroy,
> - GMainContext *context)
> + GMainContext *context,
> + SocketAddress *src_addr)
> {
> QIOTask *task = qio_task_new(
> OBJECT(ioc), callback, opaque, destroy);
> - SocketAddress *addrCopy;
> -
> - addrCopy = QAPI_CLONE(SocketAddress, addr);
> + struct SrcDestAddress *data = g_new0(struct SrcDestAddress, 1);
>
> + data->dst_addr = QAPI_CLONE(SocketAddress, dst_addr);
> + if (src_addr) {
> + data->src_addr = QAPI_CLONE(SocketAddress, src_addr);
> + } else {
> + data->src_addr = NULL;
> + }
> /* socket_connect() does a non-blocking connect(), but it
> * still blocks in DNS lookups, so we must use a thread */
> - trace_qio_channel_socket_connect_async(ioc, addr);
> + trace_qio_channel_socket_connect_async(ioc, dst_addr);
> qio_task_run_in_thread(task,
> qio_channel_socket_connect_worker,
> - addrCopy,
> - (GDestroyNotify)qapi_free_SocketAddress,
> + data,
> + qio_channel_socket_worker_free,
> context);
> }
>
> diff --git a/migration/socket.c b/migration/socket.c
> index 21e0983df2..d0cb7cc6a6 100644
> --- a/migration/socket.c
> +++ b/migration/socket.c
> @@ -47,7 +47,7 @@ void socket_send_channel_create(QIOTaskFunc f, void *data)
> {
> QIOChannelSocket *sioc = qio_channel_socket_new();
> qio_channel_socket_connect_async(sioc, outgoing_args.saddr,
> - f, data, NULL, NULL);
> + f, data, NULL, NULL, NULL);
> }
>
> int socket_send_channel_destroy(QIOChannel *send)
> @@ -110,7 +110,7 @@ out:
>
> static void
> socket_start_outgoing_migration_internal(MigrationState *s,
> - SocketAddress *saddr,
> + SocketAddress *dst_addr,
> Error **errp)
> {
> QIOChannelSocket *sioc = qio_channel_socket_new();
> @@ -118,20 +118,17 @@ socket_start_outgoing_migration_internal(MigrationState
> *s,
>
> data->s = s;
>
> - /* in case previous migration leaked it */
> - qapi_free_SocketAddress(outgoing_args.saddr);
> - outgoing_args.saddr = saddr;
> -
> - if (saddr->type == SOCKET_ADDRESS_TYPE_INET) {
> - data->hostname = g_strdup(saddr->u.inet.host);
> + if (dst_addr->type == SOCKET_ADDRESS_TYPE_INET) {
> + data->hostname = g_strdup(dst_addr->u.inet.host);
> }
>
> qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-outgoing");
> qio_channel_socket_connect_async(sioc,
> - saddr,
> + dst_addr,
> socket_outgoing_migration,
> data,
> socket_connect_data_free,
> + NULL,
> NULL);
> }
>
> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> index 13b5b197f9..bbe0dc0ee0 100644
> --- a/util/qemu-sockets.c
> +++ b/util/qemu-sockets.c
> @@ -226,7 +226,7 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
> return -1;
> }
>
> - memset(&ai,0, sizeof(ai));
> + memset(&ai,0,sizeof(ai));
Add whitespace before the '0', rather than removing it after.
> ai.ai_flags = AI_PASSIVE;
> if (saddr->has_numeric && saddr->numeric) {
> ai.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
> @@ -282,8 +282,8 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
> e->ai_protocol = IPPROTO_MPTCP;
> }
> #endif
> - getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
> - uaddr,INET6_ADDRSTRLEN,uport,32,
> + getnameinfo((struct sockaddr *)e->ai_addr, e->ai_addrlen,
> + uaddr, INET6_ADDRSTRLEN, uport, 32,
> NI_NUMERICHOST | NI_NUMERICSERV);
Both thsi & the above whitespace changes should be a separate
patch from any functional changes
> @@ -371,8 +372,28 @@ static int inet_connect_addr(const InetSocketAddress
> *saddr,
> }
> socket_set_fast_reuse(sock);
>
> + /* to bind the socket if src_addr is available */
> +
> + if (src_addr) {
> + struct sockaddr_in servaddr;
> +
> + /* bind to a specific interface in the internet domain */
> + /* to make sure the sin_zero filed is cleared */
> + memset(&servaddr, 0, sizeof(servaddr));
> +
> + servaddr.sin_family = AF_INET;
> + servaddr.sin_addr.s_addr = inet_addr(src_addr->host);
We can't assume src_addr is a raw IPv4 address.
THis needs to go through getaddrinfo in the caller like the
dst address has done.
For sanity, we should also validate that there isn't a mismatch
of IPv4 vs IPv6 for thte src & dst addrs.
> + servaddr.sin_port = 0;
> +
> + if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
> + error_setg_errno(errp, errno, "Failed to bind socket");
> + return -1;
> + }
> + }
> +
> /* connect to peer */
> do {
> +
> rc = 0;
> if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
> rc = -errno;
> @@ -380,8 +401,14 @@ static int inet_connect_addr(const InetSocketAddress
> *saddr,
> } while (rc == -EINTR);
>
> if (rc < 0) {
> - error_setg_errno(errp, errno, "Failed to connect to '%s:%s'",
> - saddr->host, saddr->port);
> + if (src_addr) {
> + error_setg_errno(errp, errno, "Failed to connect '%s:%s' to "
> + "'%s:%s'", dst_addr->host, dst_addr->port,
> + src_addr->host, src_addr->port);
> + } else {
> + error_setg_errno(errp, errno, "Failed to connect '%s:%s'",
> + dst_addr->host, dst_addr->port);
> + }
> closesocket(sock);
> return -1;
> }
> @@ -506,7 +534,7 @@ static int inet_dgram_saddr(InetSocketAddress *sraddr,
> Error *err = NULL;
>
> /* lookup peer addr */
> - memset(&ai,0, sizeof(ai));
> + memset(&ai, 0, sizeof(ai));
> ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG;
> ai.ai_family = inet_ai_family_from_address(sraddr, &err);
> ai.ai_socktype = SOCK_DGRAM;
> @@ -533,7 +561,7 @@ static int inet_dgram_saddr(InetSocketAddress *sraddr,
> }
>
> /* lookup local addr */
> - memset(&ai,0, sizeof(ai));
> + memset(&ai, 0, sizeof(ai));
> ai.ai_flags = AI_PASSIVE;
> ai.ai_family = peer->ai_family;
> ai.ai_socktype = SOCK_DGRAM;
> @@ -574,7 +602,7 @@ static int inet_dgram_saddr(InetSocketAddress *sraddr,
> }
>
> /* connect to peer */
> - if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
> + if (connect(sock, peer->ai_addr, peer->ai_addrlen) < 0) {
> error_setg_errno(errp, errno, "Failed to connect to '%s:%s'",
> addr, port);
> goto err;
More whitespace changes for a separate patch
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 :|
- [PATCH 0/4] Multiple interface support on top of Multi-FD, Het Gala, 2022/06/09
- [PATCH 1/4] Modifying ‘migrate’ qmp command to add multi-FD socket on particular source and destination pair, Het Gala, 2022/06/09
- [PATCH 4/4] Adding support for multi-FD connections dynamically, Het Gala, 2022/06/09
- [PATCH 2/4] Adding multi-interface support for multi-FD on destination side, Het Gala, 2022/06/09
- [PATCH 3/4] Establishing connection between any non-default source and destination pair, Het Gala, 2022/06/09
- Re: [PATCH 3/4] Establishing connection between any non-default source and destination pair,
Daniel P . Berrangé <=
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Daniel P . Berrangé, 2022/06/09
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, manish.mishra, 2022/06/10
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Daniel P . Berrangé, 2022/06/15
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Dr. David Alan Gilbert, 2022/06/15
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Daniel P . Berrangé, 2022/06/16
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, manish.mishra, 2022/06/16
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Daniel P . Berrangé, 2022/06/16
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Daniel P . Berrangé, 2022/06/16
- Re: [PATCH 0/4] Multiple interface support on top of Multi-FD, Dr. David Alan Gilbert, 2022/06/16