All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/1] Enable full IPv4/IPv6 dual stack support in chardevs
@ 2017-12-18 13:54 Daniel P. Berrange
  2017-12-18 13:54 ` [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener Daniel P. Berrange
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel P. Berrange @ 2017-12-18 13:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrange

Previously posted as part of a larger series:

  https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg02064.html

The common code has merged, so this is just the patch that needs to go via the
chardev maintainer's tree.

With this change, the chardev socket server honours multiple IP addresses
returned by getaddrinfo instead of only binding on the first. This makes dual
stack work fully, and also improves support with multi-homed hosts.

No changes in v1, except for rebasing.

Daniel P. Berrange (1):
  chardev: convert the socket server to QIONetListener

 chardev/char-socket.c | 72 +++++++++++++++++++++------------------------------
 1 file changed, 29 insertions(+), 43 deletions(-)

-- 
2.14.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener
  2017-12-18 13:54 [Qemu-devel] [PATCH v2 0/1] Enable full IPv4/IPv6 dual stack support in chardevs Daniel P. Berrange
@ 2017-12-18 13:54 ` Daniel P. Berrange
  2017-12-19  8:48   ` Paolo Bonzini
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel P. Berrange @ 2017-12-18 13:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrange

Instead of creating a QIOChannelSocket directly for the chardev
server socket, use a QIONetListener. This provides the ability
to listen on multiple sockets at the same time, so enables
full support for IPv4/IPv6 dual stack.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 chardev/char-socket.c | 72 +++++++++++++++++++++------------------------------
 1 file changed, 29 insertions(+), 43 deletions(-)

diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 53eda8ef00..2d2252ab0a 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -25,6 +25,7 @@
 #include "chardev/char.h"
 #include "io/channel-socket.h"
 #include "io/channel-tls.h"
+#include "io/net-listener.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qapi/clone-visitor.h"
@@ -40,8 +41,7 @@ typedef struct {
     Chardev parent;
     QIOChannel *ioc; /* Client I/O channel */
     QIOChannelSocket *sioc; /* Client master channel */
-    QIOChannelSocket *listen_ioc;
-    guint listen_tag;
+    QIONetListener *listener;
     QCryptoTLSCreds *tls_creds;
     int connected;
     int max_size;
@@ -93,9 +93,9 @@ static void check_report_connect_error(Chardev *chr,
     qemu_chr_socket_restart_timer(chr);
 }
 
-static gboolean tcp_chr_accept(QIOChannel *chan,
-                               GIOCondition cond,
-                               void *opaque);
+static void tcp_chr_accept(QIONetListener *listener,
+                           QIOChannelSocket *cioc,
+                           void *opaque);
 
 static int tcp_chr_read_poll(void *opaque);
 static void tcp_chr_disconnect(Chardev *chr);
@@ -401,9 +401,9 @@ static void tcp_chr_disconnect(Chardev *chr)
 
     tcp_chr_free_connection(chr);
 
-    if (s->listen_ioc && s->listen_tag == 0) {
-        s->listen_tag = qio_channel_add_watch(
-            QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
+    if (s->listener) {
+        qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
+                                         chr, NULL);
     }
     update_disconnected_filename(s);
     if (emit_close) {
@@ -702,9 +702,8 @@ static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
     if (s->do_nodelay) {
         qio_channel_set_delay(s->ioc, false);
     }
-    if (s->listen_tag) {
-        g_source_remove(s->listen_tag);
-        s->listen_tag = 0;
+    if (s->listener) {
+        qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
     }
 
     if (s->tls_creds) {
@@ -736,24 +735,14 @@ static int tcp_chr_add_client(Chardev *chr, int fd)
     return ret;
 }
 
-static gboolean tcp_chr_accept(QIOChannel *channel,
-                               GIOCondition cond,
-                               void *opaque)
+static void tcp_chr_accept(QIONetListener *listener,
+                           QIOChannelSocket *cioc,
+                           void *opaque)
 {
     Chardev *chr = CHARDEV(opaque);
-    QIOChannelSocket *sioc;
-
-    sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(channel),
-                                     NULL);
-    if (!sioc) {
-        return TRUE;
-    }
-
-    tcp_chr_new_client(chr, sioc);
 
-    object_unref(OBJECT(sioc));
-
-    return TRUE;
+    tcp_chr_set_client_ioc_name(chr, cioc);
+    tcp_chr_new_client(chr, cioc);
 }
 
 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
@@ -767,9 +756,10 @@ static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
         if (s->is_listen) {
             info_report("QEMU waiting for connection on: %s",
                         chr->filename);
-            qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), true, NULL);
-            tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
-            qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
+            sioc = qio_net_listener_wait_client(s->listener);
+            tcp_chr_set_client_ioc_name(chr, sioc);
+            tcp_chr_new_client(chr, sioc);
+            object_unref(OBJECT(sioc));
         } else {
             sioc = qio_channel_socket_new();
             tcp_chr_set_client_ioc_name(chr, sioc);
@@ -797,12 +787,9 @@ static void char_socket_finalize(Object *obj)
         s->reconnect_timer = 0;
     }
     qapi_free_SocketAddress(s->addr);
-    if (s->listen_tag) {
-        g_source_remove(s->listen_tag);
-        s->listen_tag = 0;
-    }
-    if (s->listen_ioc) {
-        object_unref(OBJECT(s->listen_ioc));
+    if (s->listener) {
+        qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
+        object_unref(OBJECT(s->listener));
     }
     if (s->tls_creds) {
         object_unref(OBJECT(s->tls_creds));
@@ -935,29 +922,28 @@ static void qmp_chardev_open_socket(Chardev *chr,
     } else {
         if (s->is_listen) {
             char *name;
-            sioc = qio_channel_socket_new();
+            s->listener = qio_net_listener_new();
 
             name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
-            qio_channel_set_name(QIO_CHANNEL(sioc), name);
+            qio_net_listener_set_name(s->listener, name);
             g_free(name);
 
-            if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
+            if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
+                object_unref(OBJECT(s->listener));
                 goto error;
             }
 
             qapi_free_SocketAddress(s->addr);
-            s->addr = socket_local_address(sioc->fd, errp);
+            s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
             update_disconnected_filename(s);
 
-            s->listen_ioc = sioc;
             if (is_waitconnect &&
                 qemu_chr_wait_connected(chr, errp) < 0) {
                 return;
             }
             if (!s->ioc) {
-                s->listen_tag = qio_channel_add_watch(
-                    QIO_CHANNEL(s->listen_ioc), G_IO_IN,
-                    tcp_chr_accept, chr, NULL);
+                qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
+                                                 chr, NULL);
             }
         } else if (qemu_chr_wait_connected(chr, errp) < 0) {
             goto error;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener
  2017-12-18 13:54 ` [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener Daniel P. Berrange
@ 2017-12-19  8:48   ` Paolo Bonzini
  2017-12-20 16:23     ` Paolo Bonzini
  0 siblings, 1 reply; 5+ messages in thread
From: Paolo Bonzini @ 2017-12-19  8:48 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Marc-André Lureau

On 18/12/2017 14:54, Daniel P. Berrange wrote:
> Instead of creating a QIOChannelSocket directly for the chardev
> server socket, use a QIONetListener. This provides the ability
> to listen on multiple sockets at the same time, so enables
> full support for IPv4/IPv6 dual stack.
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  chardev/char-socket.c | 72 +++++++++++++++++++++------------------------------
>  1 file changed, 29 insertions(+), 43 deletions(-)

Queued, thanks.

As a follow-up, it's probably worth creating two new functions for
respectively tcp_chr_set_client_ioc_name+tcp_chr_new_client and
tcp_chr_set_client_ioc_name+qio_channel_socket_connect_async
(with tcp_chr_set_client_ioc_name inlined).

Paolo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener
  2017-12-19  8:48   ` Paolo Bonzini
@ 2017-12-20 16:23     ` Paolo Bonzini
  2017-12-20 16:25       ` Daniel P. Berrange
  0 siblings, 1 reply; 5+ messages in thread
From: Paolo Bonzini @ 2017-12-20 16:23 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Marc-André Lureau

On 19/12/2017 09:48, Paolo Bonzini wrote:
> On 18/12/2017 14:54, Daniel P. Berrange wrote:
>> Instead of creating a QIOChannelSocket directly for the chardev
>> server socket, use a QIONetListener. This provides the ability
>> to listen on multiple sockets at the same time, so enables
>> full support for IPv4/IPv6 dual stack.
>>
>> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
>> ---
>>  chardev/char-socket.c | 72 +++++++++++++++++++++------------------------------
>>  1 file changed, 29 insertions(+), 43 deletions(-)
> 
> Queued, thanks.

I think this has to be squashed in to avoid use-after-free issues left and right
(visible with test-hmp):

diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 2d2252a..630a7f2 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -930,6 +930,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
 
             if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
                 object_unref(OBJECT(s->listener));
+                s->listener = NULL;
                 goto error;
             }
 

Paolo

> 
> As a follow-up, it's probably worth creating two new functions for
> respectively tcp_chr_set_client_ioc_name+tcp_chr_new_client and
> tcp_chr_set_client_ioc_name+qio_channel_socket_connect_async
> (with tcp_chr_set_client_ioc_name inlined).
> 
> Paolo
> 

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener
  2017-12-20 16:23     ` Paolo Bonzini
@ 2017-12-20 16:25       ` Daniel P. Berrange
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel P. Berrange @ 2017-12-20 16:25 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, Marc-André Lureau

On Wed, Dec 20, 2017 at 05:23:17PM +0100, Paolo Bonzini wrote:
> On 19/12/2017 09:48, Paolo Bonzini wrote:
> > On 18/12/2017 14:54, Daniel P. Berrange wrote:
> >> Instead of creating a QIOChannelSocket directly for the chardev
> >> server socket, use a QIONetListener. This provides the ability
> >> to listen on multiple sockets at the same time, so enables
> >> full support for IPv4/IPv6 dual stack.
> >>
> >> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> >> ---
> >>  chardev/char-socket.c | 72 +++++++++++++++++++++------------------------------
> >>  1 file changed, 29 insertions(+), 43 deletions(-)
> > 
> > Queued, thanks.
> 
> I think this has to be squashed in to avoid use-after-free issues left and right
> (visible with test-hmp):
> 
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index 2d2252a..630a7f2 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -930,6 +930,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
>  
>              if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
>                  object_unref(OBJECT(s->listener));
> +                s->listener = NULL;
>                  goto error;
>              }

Yes, that makes sense given the context, though I can't reproduce the test
failures myself yet. Any, please do squash it into the patch, as it makes
sense. Reviewed-by: Daniel P. Berrange <berrange@redhat.com>



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 :|

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-12-20 16:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-18 13:54 [Qemu-devel] [PATCH v2 0/1] Enable full IPv4/IPv6 dual stack support in chardevs Daniel P. Berrange
2017-12-18 13:54 ` [Qemu-devel] [PATCH v2 1/1] chardev: convert the socket server to QIONetListener Daniel P. Berrange
2017-12-19  8:48   ` Paolo Bonzini
2017-12-20 16:23     ` Paolo Bonzini
2017-12-20 16:25       ` Daniel P. Berrange

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.