All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] Socket reconnection.
@ 2009-11-26  0:31 Ian Molton
  2009-11-26  9:21 ` Gerd Hoffmann
                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Ian Molton @ 2009-11-26  0:31 UTC (permalink / raw)
  To: qemu-devel

Hi folks,

I need my source of data for virtio-rng to be reliable - IOW. if the
server dies and comes back up, I want qemu to reconnect and suck down
fresh entropy, rather than hand the rngd process on the guest.

I'm using the chardev 'socket' type to make the connection to the host.

Would a patch adding (optional) auto-reconnect (with a back-off delay)
to the socket chardev be acceptable ?

If not, I'll have to cook up a thread to handle EGD requests, but that
seems perverse...

-Ian

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

* Re: [Qemu-devel] Socket reconnection.
  2009-11-26  0:31 [Qemu-devel] Socket reconnection Ian Molton
@ 2009-11-26  9:21 ` Gerd Hoffmann
  2009-11-27  9:01 ` Jamie Lokier
  2009-11-30 17:18 ` Anthony Liguori
  2 siblings, 0 replies; 22+ messages in thread
From: Gerd Hoffmann @ 2009-11-26  9:21 UTC (permalink / raw)
  To: Ian Molton; +Cc: qemu-devel

   Hi,

> Would a patch adding (optional) auto-reconnect (with a back-off delay)
> to the socket chardev be acceptable ?

Sounds sensible to me.  And, yes, it should be an option (defaulting to 
off to maintain current behavior when not specified).

cheers,
   Gerd

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

* Re: [Qemu-devel] Socket reconnection.
  2009-11-26  0:31 [Qemu-devel] Socket reconnection Ian Molton
  2009-11-26  9:21 ` Gerd Hoffmann
@ 2009-11-27  9:01 ` Jamie Lokier
  2009-12-01 11:55   ` Ian Molton
  2009-11-30 17:18 ` Anthony Liguori
  2 siblings, 1 reply; 22+ messages in thread
From: Jamie Lokier @ 2009-11-27  9:01 UTC (permalink / raw)
  To: Ian Molton; +Cc: qemu-devel

Ian Molton wrote:
> Hi folks,
> 
> I need my source of data for virtio-rng to be reliable - IOW. if the
> server dies and comes back up, I want qemu to reconnect and suck down
> fresh entropy, rather than hand the rngd process on the guest.
> 
> I'm using the chardev 'socket' type to make the connection to the host.
> 
> Would a patch adding (optional) auto-reconnect (with a back-off delay)
> to the socket chardev be acceptable ?
> 
> If not, I'll have to cook up a thread to handle EGD requests, but that
> seems perverse...

I'm a bit puzzled.

Why isn't virtio-rng getting entropy from /dev/random on the host?

-- Jamie

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

* Re: [Qemu-devel] Socket reconnection.
  2009-11-26  0:31 [Qemu-devel] Socket reconnection Ian Molton
  2009-11-26  9:21 ` Gerd Hoffmann
  2009-11-27  9:01 ` Jamie Lokier
@ 2009-11-30 17:18 ` Anthony Liguori
  2009-12-01 11:54   ` Ian Molton
  2 siblings, 1 reply; 22+ messages in thread
From: Anthony Liguori @ 2009-11-30 17:18 UTC (permalink / raw)
  To: Ian Molton; +Cc: qemu-devel

Ian Molton wrote:
> Hi folks,
>
> I need my source of data for virtio-rng to be reliable - IOW. if the
> server dies and comes back up, I want qemu to reconnect and suck down
> fresh entropy, rather than hand the rngd process on the guest.
>
> I'm using the chardev 'socket' type to make the connection to the host.
>
> Would a patch adding (optional) auto-reconnect (with a back-off delay)
> to the socket chardev be acceptable ?
>
> If not, I'll have to cook up a thread to handle EGD requests, but that
> seems perverse...
>   

Hrm, I'm not sure.  What are the circumstances that this connection 
would die?  What happens while the connection is dead?

Regards,

Anthony Liguori
> -Ian
>
>
>   

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

* Re: [Qemu-devel] Socket reconnection.
  2009-11-30 17:18 ` Anthony Liguori
@ 2009-12-01 11:54   ` Ian Molton
  2009-12-01 14:38     ` Krumme, Chris
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Molton @ 2009-12-01 11:54 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1539 bytes --]

Anthony Liguori wrote:
> Ian Molton wrote:
>> Hi folks,
>>
>> I need my source of data for virtio-rng to be reliable - IOW. if the
>> server dies and comes back up, I want qemu to reconnect and suck down
>> fresh entropy, rather than hand the rngd process on the guest.
>>
>> I'm using the chardev 'socket' type to make the connection to the host.
>>
>> Would a patch adding (optional) auto-reconnect (with a back-off delay)
>> to the socket chardev be acceptable ?
>>
>> If not, I'll have to cook up a thread to handle EGD requests, but that
>> seems perverse...
>>   
> 
> Hrm, I'm not sure.  What are the circumstances that this connection
> would die?  What happens while the connection is dead?

The most common would be the entropy gathering daemon being restarted,
perhaps due to an upgrade. Its hardly a good idea to require all the
guest VMs to reboot on this occuring. Next most common I guess would be
the daemon crashing, but again, not something you'd want taking out your
guest VMs...

Whilst the connection is down, the guests will potentially starve of
entropy - but that only means they'll block processes that try to use
/dev/random if they run out altogether.

Here are two patches that implement socket reconnection. This first
cleans up the APIs needed a little  and the second implements the guts.

If these patches are acceptable, I will repost my 4-patch series which
also includes the SIZE parameter patch and an updated virtio-rng patch
that uses the reconnection infrastructure to enhance its reliability.

-Ian

[-- Attachment #2: 0001-socket-Rationalise-function-declarations.patch --]
[-- Type: text/x-patch, Size: 2133 bytes --]

>From 44dc6eddf23713f34874c2cbfa5cba763983cf6f Mon Sep 17 00:00:00 2001
From: Ian Molton <ian.molton@collabora.co.uk>
Date: Tue, 1 Dec 2009 11:16:25 +0000
Subject: [PATCH 1/4] socket: Rationalise function declarations

	This patch rationalises the declaration of inet_listen_opts such that
it matches the other inet_{listen,connect}_opts functions.

This change is needed for a patch adding socket reconection support.

Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
---
 qemu-sockets.c |    9 +++++++--
 qemu_socket.h  |    2 +-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/qemu-sockets.c b/qemu-sockets.c
index 8801453..b655b3c 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -116,7 +116,7 @@ static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
     }
 }
 
-int inet_listen_opts(QemuOpts *opts, int port_offset)
+static int do_inet_listen(QemuOpts *opts, int port_offset)
 {
     struct addrinfo ai,*res,*e;
     const char *addr;
@@ -216,6 +216,11 @@ listen:
     return slisten;
 }
 
+int inet_listen_opts(QemuOpts *opts)
+{
+    return do_inet_listen(opts, 0);
+}
+
 int inet_connect_opts(QemuOpts *opts)
 {
     struct addrinfo ai,*res,*e;
@@ -465,7 +470,7 @@ int inet_listen(const char *str, char *ostr, int olen,
 
     opts = qemu_opts_create(&dummy_opts, NULL, 0);
     if (inet_parse(opts, str) == 0) {
-        sock = inet_listen_opts(opts, port_offset);
+        sock = do_inet_listen(opts, port_offset);
         if (sock != -1 && ostr) {
             optstr = strchr(str, ',');
             if (qemu_opt_get_bool(opts, "ipv6", 0)) {
diff --git a/qemu_socket.h b/qemu_socket.h
index c253b32..3b09e0a 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -36,7 +36,7 @@ void socket_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
 
 /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
-int inet_listen_opts(QemuOpts *opts, int port_offset);
+int inet_listen_opts(QemuOpts *opts);
 int inet_listen(const char *str, char *ostr, int olen,
                 int socktype, int port_offset);
 int inet_connect_opts(QemuOpts *opts);
-- 
1.6.5


[-- Attachment #3: 0002-socket-Add-a-reconnect-option.patch --]
[-- Type: text/x-patch, Size: 6992 bytes --]

>From 1641774343cec683a6e11c22ef2ab162ab2cb842 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian.molton@collabora.co.uk>
Date: Tue, 1 Dec 2009 11:18:41 +0000
Subject: [PATCH 2/4] socket: Add a reconnect option.

	Add a reconnect option that allows sockets to reconnect (after a
specified delay) to the specified server. This makes the virtio-rng driver
useful in production environments where the EGD server may need to be restarted.

Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
---
 qemu-char.c   |  118 ++++++++++++++++++++++++++++++++++++++-------------------
 qemu-char.h   |    1 +
 qemu-config.c |    3 +
 3 files changed, 83 insertions(+), 39 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index e202585..ec24c29 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1870,8 +1870,12 @@ typedef struct {
     int max_size;
     int do_telnetopt;
     int do_nodelay;
+    int reconnect;
     int is_unix;
     int msgfd;
+    QemuOpts *opts;
+    CharDriverState *chr;
+    int (*setup)(QemuOpts *opts);
 } TCPCharDriver;
 
 static void tcp_chr_accept(void *opaque);
@@ -2011,6 +2015,8 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 }
 #endif
 
+static int qemu_chr_connect_socket(TCPCharDriver *s);
+
 static void tcp_chr_read(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2030,10 +2036,18 @@ static void tcp_chr_read(void *opaque)
         if (s->listen_fd >= 0) {
             qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
         }
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        if (!s->reconnect)
+            qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
         closesocket(s->fd);
         s->fd = -1;
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        if (!s->reconnect) {
+            qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        } else {
+            do {
+                sleep(s->reconnect);
+            } while(!qemu_chr_connect_socket(s));
+            qemu_chr_event(chr, CHR_EVENT_RECONNECTED);
+        }
     } else if (size > 0) {
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2137,7 +2151,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
-    int fd = -1;
     int is_listen;
     int is_waitconnect;
     int do_nodelay;
@@ -2145,34 +2158,40 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     int is_telnet;
 
     is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    is_unix        = qemu_opt_get(opts, "path") != NULL;
+
     is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
     is_telnet      = qemu_opt_get_bool(opts, "telnet", 0);
     do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
-    is_unix        = qemu_opt_get(opts, "path") != NULL;
-    if (!is_listen)
+
+    if (!is_listen) {
         is_waitconnect = 0;
+    } else {
+        if (is_telnet)
+            s->do_telnetopt = 1;
+    }
+
 
-    chr = qemu_mallocz(sizeof(CharDriverState));
     s = qemu_mallocz(sizeof(TCPCharDriver));
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    s->opts = opts;
+
+    if (!is_listen && !is_telnet)
+        s->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
 
     if (is_unix) {
         if (is_listen) {
-            fd = unix_listen_opts(opts);
+            s->setup = unix_listen_opts;
         } else {
-            fd = unix_connect_opts(opts);
+            s->setup = unix_connect_opts;
         }
     } else {
         if (is_listen) {
-            fd = inet_listen_opts(opts, 0);
+            s->setup = inet_listen_opts;
         } else {
-            fd = inet_connect_opts(opts);
+            s->setup = inet_connect_opts;
         }
     }
-    if (fd < 0)
-        goto fail;
-
-    if (!is_waitconnect)
-        socket_set_nonblock(fd);
 
     s->connected = 0;
     s->fd = -1;
@@ -2186,19 +2205,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     chr->chr_close = tcp_chr_close;
     chr->get_msgfd = tcp_get_msgfd;
 
-    if (is_listen) {
-        s->listen_fd = fd;
-        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-        if (is_telnet)
-            s->do_telnetopt = 1;
-
-    } else {
-        s->connected = 1;
-        s->fd = fd;
-        socket_set_nodelay(fd);
-        tcp_chr_connect(chr);
-    }
-
     /* for "info chardev" monitor command */
     chr->filename = qemu_malloc(256);
     if (is_unix) {
@@ -2215,22 +2221,56 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
                  qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");
     }
 
-    if (is_listen && is_waitconnect) {
-        printf("QEMU waiting for connection on: %s\n",
-               chr->filename);
-        tcp_chr_accept(chr);
-        socket_set_nonblock(s->listen_fd);
-    }
-    return chr;
+    s->chr = chr;
+
+    if(qemu_chr_connect_socket(s))
+        return chr;
 
- fail:
-    if (fd >= 0)
-        closesocket(fd);
-    qemu_free(s);
     qemu_free(chr);
+    qemu_free(s);
+
     return NULL;
 }
 
+
+static int qemu_chr_connect_socket(TCPCharDriver *s)
+{
+    QemuOpts *opts = s->opts;
+    int is_listen;
+    int fd;
+    int is_waitconnect;
+    int do_nodelay;
+
+    is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
+    is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
+
+
+    fd = s->setup(s->opts);
+    if (fd < 0)
+        return 0;
+
+    if (!is_waitconnect)
+        socket_set_nonblock(fd);
+
+    if (is_listen) {
+        s->listen_fd = fd;
+        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, s->chr);
+        if (is_waitconnect) {
+            printf("QEMU waiting for connection on: %s\n",
+                   s->chr->filename);
+            tcp_chr_accept(s->chr);
+            socket_set_nonblock(s->listen_fd);
+        }
+    } else {
+        s->fd = fd;
+        socket_set_nodelay(fd);
+        tcp_chr_connect(s->chr);
+    }
+
+    return 1;
+}
+
 static QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
 {
     char host[65], port[33], width[8], height[8];
diff --git a/qemu-char.h b/qemu-char.h
index 9957db1..266536d 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -14,6 +14,7 @@
 #define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
 #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
 #define CHR_EVENT_CLOSED  5 /* connection closed */
+#define CHR_EVENT_RECONNECTED  6 /* reconnect event */
 
 
 #define CHR_IOCTL_SERIAL_SET_PARAMS   1
diff --git a/qemu-config.c b/qemu-config.c
index 590fc05..ff8b06e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -140,6 +140,9 @@ QemuOptsList qemu_chardev_opts = {
         },{
             .name = "signal",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "reconnect",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end if list */ }
     },
-- 
1.6.5


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

* Re: [Qemu-devel] Socket reconnection.
  2009-11-27  9:01 ` Jamie Lokier
@ 2009-12-01 11:55   ` Ian Molton
  2009-12-06 14:32     ` Jamie Lokier
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Molton @ 2009-12-01 11:55 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: qemu-devel

Jamie Lokier wrote:

> I'm a bit puzzled.
> 
> Why isn't virtio-rng getting entropy from /dev/random on the host?

/dev/random may not be available. Besides, not all entropy comes from
/dev/random.

-Ian

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

* RE: [Qemu-devel] Socket reconnection.
  2009-12-01 11:54   ` Ian Molton
@ 2009-12-01 14:38     ` Krumme, Chris
  2009-12-01 18:29       ` Ian Molton
  2009-12-01 18:54       ` Anthony Liguori
  0 siblings, 2 replies; 22+ messages in thread
From: Krumme, Chris @ 2009-12-01 14:38 UTC (permalink / raw)
  To: Ian Molton, Anthony Liguori; +Cc: qemu-devel


Hello Ian,

Since you did not inline your source I will paste in a chunk:


@@ -2030,10 +2036,18 @@ static void tcp_chr_read(void *opaque)
         if (s->listen_fd >= 0) {
             qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL,
chr);
         }
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        if (!s->reconnect)
+            qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
         closesocket(s->fd);
         s->fd = -1;
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        if (!s->reconnect) {
+            qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        } else {
+            do {
+                sleep(s->reconnect);
+            } while(!qemu_chr_connect_socket(s));
+            qemu_chr_event(chr, CHR_EVENT_RECONNECTED);
+        }
     } else if (size > 0) {
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);


Should you be introducing a while sleep loop into Qemu here?

I would think you should be returning 'no data', maybe after trying
once.

Hope this helps.

Chris

 

> -----Original Message-----
> From: 
> qemu-devel-bounces+chris.krumme=windriver.com@nongnu.org 
> [mailto:qemu-devel-bounces+chris.krumme=windriver.com@nongnu.o
> rg] On Behalf Of Ian Molton
> Sent: Tuesday, December 01, 2009 5:54 AM
> To: Anthony Liguori
> Cc: qemu-devel@nongnu.org
> Subject: Re: [Qemu-devel] Socket reconnection.
> 
> Anthony Liguori wrote:
> > Ian Molton wrote:
> >> Hi folks,
> >>
> >> I need my source of data for virtio-rng to be reliable - 
> IOW. if the
> >> server dies and comes back up, I want qemu to reconnect 
> and suck down
> >> fresh entropy, rather than hand the rngd process on the guest.
> >>
> >> I'm using the chardev 'socket' type to make the connection 
> to the host.
> >>
> >> Would a patch adding (optional) auto-reconnect (with a 
> back-off delay)
> >> to the socket chardev be acceptable ?
> >>
> >> If not, I'll have to cook up a thread to handle EGD 
> requests, but that
> >> seems perverse...
> >>   
> > 
> > Hrm, I'm not sure.  What are the circumstances that this connection
> > would die?  What happens while the connection is dead?
> 
> The most common would be the entropy gathering daemon being restarted,
> perhaps due to an upgrade. Its hardly a good idea to require all the
> guest VMs to reboot on this occuring. Next most common I 
> guess would be
> the daemon crashing, but again, not something you'd want 
> taking out your
> guest VMs...
> 
> Whilst the connection is down, the guests will potentially starve of
> entropy - but that only means they'll block processes that try to use
> /dev/random if they run out altogether.
> 
> Here are two patches that implement socket reconnection. This first
> cleans up the APIs needed a little  and the second implements 
> the guts.
> 
> If these patches are acceptable, I will repost my 4-patch series which
> also includes the SIZE parameter patch and an updated virtio-rng patch
> that uses the reconnection infrastructure to enhance its reliability.
> 
> -Ian
> 

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-01 14:38     ` Krumme, Chris
@ 2009-12-01 18:29       ` Ian Molton
  2009-12-01 18:54       ` Anthony Liguori
  1 sibling, 0 replies; 22+ messages in thread
From: Ian Molton @ 2009-12-01 18:29 UTC (permalink / raw)
  To: Krumme, Chris; +Cc: qemu-devel

Krumme, Chris wrote:
> Hello Ian,

Hi!

> Should you be introducing a while sleep loop into Qemu here?
> 
> I would think you should be returning 'no data', maybe after trying
> once.

Indeed.

I could have sworn I tried that. Too much crack, will re-do.

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-01 14:38     ` Krumme, Chris
  2009-12-01 18:29       ` Ian Molton
@ 2009-12-01 18:54       ` Anthony Liguori
  2009-12-02 10:40         ` Ian Molton
  1 sibling, 1 reply; 22+ messages in thread
From: Anthony Liguori @ 2009-12-01 18:54 UTC (permalink / raw)
  To: Krumme, Chris; +Cc: Ian Molton, qemu-devel

Krumme, Chris wrote:
> Hello Ian,
>
> Since you did not inline your source I will paste in a chunk:
>
>
> @@ -2030,10 +2036,18 @@ static void tcp_chr_read(void *opaque)
>          if (s->listen_fd >= 0) {
>              qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL,
> chr);
>          }
> -        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
> +        if (!s->reconnect)
> +            qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
>          closesocket(s->fd);
>          s->fd = -1;
> -        qemu_chr_event(chr, CHR_EVENT_CLOSED);
> +        if (!s->reconnect) {
> +            qemu_chr_event(chr, CHR_EVENT_CLOSED);
> +        } else {
> +            do {
> +                sleep(s->reconnect);
> +            } while(!qemu_chr_connect_socket(s));
> +            qemu_chr_event(chr, CHR_EVENT_RECONNECTED);
> +        }
>      } else if (size > 0) {
>          if (s->do_telnetopt)
>              tcp_chr_process_IAC_bytes(chr, s, buf, &size);
>
>
> Should you be introducing a while sleep loop into Qemu here?
>
> I would think you should be returning 'no data', maybe after trying
> once.
>
> Hope this helps.
>
> Chris
>   

sleep() in qemu is very, very wrong.  It will pause the guest's 
execution and all sorts of badness can ensue.

The right thing to do is set a timer and not generate data while 
disconnected.  I still am not confident this is really a great thing to do.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-01 18:54       ` Anthony Liguori
@ 2009-12-02 10:40         ` Ian Molton
  2009-12-02 12:04           ` [Qemu-devel] " Jan Kiszka
                             ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Ian Molton @ 2009-12-02 10:40 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Krumme, Chris, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 520 bytes --]

Anthony Liguori wrote:

> sleep() in qemu is very, very wrong.  It will pause the guest's
> execution and all sorts of badness can ensue.

Quite...

> The right thing to do is set a timer and not generate data while
> disconnected.

New patch attached, now with less crack...

>  I still am not confident this is really a great thing to do.

What other option is there than to drop the ability to feed entropy to
the guest when the hosts egd link drops?

btw. Does anyone know how to get t-bird to inline patches?

-Ian

[-- Attachment #2: 0002-socket-Add-a-reconnect-option.patch --]
[-- Type: text/x-patch, Size: 9254 bytes --]

>From e9d4be9cd0ef9e34c65939d4604874035c45bf34 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian.molton@collabora.co.uk>
Date: Tue, 1 Dec 2009 11:18:41 +0000
Subject: [PATCH 2/4] socket: Add a reconnect option.

	Add a reconnect option that allows sockets to reconnect (after a
specified delay) to the specified server. This makes the virtio-rng driver
useful in production environments where the EGD server may need to be restarted.

Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
---
 qemu-char.c   |  177 ++++++++++++++++++++++++++++++++++++++++++++-------------
 qemu-char.h   |    2 +
 qemu-config.c |    3 +
 vl.c          |    4 +
 4 files changed, 147 insertions(+), 39 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index e202585..714c119 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1870,8 +1870,12 @@ typedef struct {
     int max_size;
     int do_telnetopt;
     int do_nodelay;
+    int reconnect;
     int is_unix;
     int msgfd;
+    QemuOpts *opts;
+    CharDriverState *chr;
+    int (*setup)(QemuOpts *opts);
 } TCPCharDriver;
 
 static void tcp_chr_accept(void *opaque);
@@ -2011,6 +2015,69 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 }
 #endif
 
+struct reconnect_list {
+    TCPCharDriver *s;
+    uint64_t when;
+    struct reconnect_list *next;
+};
+
+static struct reconnect_list *rc_list;
+
+static int qemu_chr_sched_reconnect(TCPCharDriver *s)
+{
+    struct reconnect_list *new = qemu_malloc(sizeof(*new));
+    struct timeval tv;
+
+    if(!new)
+        return 1;
+
+    gettimeofday(&tv, NULL);
+    new->s = s;
+    new->when = (s->reconnect + tv.tv_sec) * 1000000 + tv.tv_usec;
+    new->next = rc_list;
+    rc_list = new;
+
+    return 0;
+}
+
+static int qemu_chr_connect_socket(TCPCharDriver *s);
+
+void qemu_chr_reconnect(void)
+{
+    struct reconnect_list *this = rc_list, *prev = NULL;
+    struct timeval tv;
+    uint64_t now;
+
+    if(!this)
+        return;
+
+    gettimeofday(&tv, NULL);
+    now = tv.tv_sec * 1000000 + tv.tv_usec;
+
+    while (this) {
+        if (this->when <= now) {
+            if(qemu_chr_connect_socket(this->s)) {
+                if(prev)
+                    prev->next = this->next;
+                else
+                    rc_list = NULL;
+                qemu_chr_event(this->s->chr, CHR_EVENT_RECONNECTED);
+                free(this);
+		if(prev)
+			this = prev;
+		else
+			this = NULL;
+            }
+            else {
+                this->when += this->s->reconnect * 1000000;
+            }
+        }
+        prev = this;
+	if(this)
+            this = this->next;
+    }
+}
+
 static void tcp_chr_read(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2030,10 +2097,16 @@ static void tcp_chr_read(void *opaque)
         if (s->listen_fd >= 0) {
             qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
         }
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        if (!s->reconnect)
+            qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
         closesocket(s->fd);
         s->fd = -1;
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        if (!s->reconnect) {
+            qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        } else if (qemu_chr_sched_reconnect(s)) {
+            printf("Unable to queue socket for reconnection.\n");
+            qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        }
     } else if (size > 0) {
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2137,7 +2210,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
-    int fd = -1;
     int is_listen;
     int is_waitconnect;
     int do_nodelay;
@@ -2145,34 +2217,40 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     int is_telnet;
 
     is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    is_unix        = qemu_opt_get(opts, "path") != NULL;
+
     is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
     is_telnet      = qemu_opt_get_bool(opts, "telnet", 0);
     do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
-    is_unix        = qemu_opt_get(opts, "path") != NULL;
-    if (!is_listen)
+
+    if (!is_listen) {
         is_waitconnect = 0;
+    } else {
+        if (is_telnet)
+            s->do_telnetopt = 1;
+    }
+
 
-    chr = qemu_mallocz(sizeof(CharDriverState));
     s = qemu_mallocz(sizeof(TCPCharDriver));
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    s->opts = opts;
+
+    if (!is_listen && !is_telnet)
+        s->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
 
     if (is_unix) {
         if (is_listen) {
-            fd = unix_listen_opts(opts);
+            s->setup = unix_listen_opts;
         } else {
-            fd = unix_connect_opts(opts);
+            s->setup = unix_connect_opts;
         }
     } else {
         if (is_listen) {
-            fd = inet_listen_opts(opts, 0);
+            s->setup = inet_listen_opts;
         } else {
-            fd = inet_connect_opts(opts);
+            s->setup = inet_connect_opts;
         }
     }
-    if (fd < 0)
-        goto fail;
-
-    if (!is_waitconnect)
-        socket_set_nonblock(fd);
 
     s->connected = 0;
     s->fd = -1;
@@ -2186,19 +2264,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     chr->chr_close = tcp_chr_close;
     chr->get_msgfd = tcp_get_msgfd;
 
-    if (is_listen) {
-        s->listen_fd = fd;
-        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-        if (is_telnet)
-            s->do_telnetopt = 1;
-
-    } else {
-        s->connected = 1;
-        s->fd = fd;
-        socket_set_nodelay(fd);
-        tcp_chr_connect(chr);
-    }
-
     /* for "info chardev" monitor command */
     chr->filename = qemu_malloc(256);
     if (is_unix) {
@@ -2215,22 +2280,56 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
                  qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");
     }
 
-    if (is_listen && is_waitconnect) {
-        printf("QEMU waiting for connection on: %s\n",
-               chr->filename);
-        tcp_chr_accept(chr);
-        socket_set_nonblock(s->listen_fd);
-    }
-    return chr;
+    s->chr = chr;
+
+    if(qemu_chr_connect_socket(s))
+        return chr;
 
- fail:
-    if (fd >= 0)
-        closesocket(fd);
-    qemu_free(s);
     qemu_free(chr);
+    qemu_free(s);
+
     return NULL;
 }
 
+
+static int qemu_chr_connect_socket(TCPCharDriver *s)
+{
+    QemuOpts *opts = s->opts;
+    int is_listen;
+    int fd;
+    int is_waitconnect;
+    int do_nodelay;
+
+    is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
+    is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
+
+
+    fd = s->setup(s->opts);
+    if (fd < 0)
+        return 0;
+
+    if (!is_waitconnect)
+        socket_set_nonblock(fd);
+
+    if (is_listen) {
+        s->listen_fd = fd;
+        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, s->chr);
+        if (is_waitconnect) {
+            printf("QEMU waiting for connection on: %s\n",
+                   s->chr->filename);
+            tcp_chr_accept(s->chr);
+            socket_set_nonblock(s->listen_fd);
+        }
+    } else {
+        s->fd = fd;
+        socket_set_nodelay(fd);
+        tcp_chr_connect(s->chr);
+    }
+
+    return 1;
+}
+
 static QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
 {
     char host[65], port[33], width[8], height[8];
diff --git a/qemu-char.h b/qemu-char.h
index 9957db1..dc954e2 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -14,6 +14,7 @@
 #define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
 #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
 #define CHR_EVENT_CLOSED  5 /* connection closed */
+#define CHR_EVENT_RECONNECTED  6 /* reconnect event */
 
 
 #define CHR_IOCTL_SERIAL_SET_PARAMS   1
@@ -73,6 +74,7 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s));
 CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
 void qemu_chr_close(CharDriverState *chr);
+void qemu_chr_reconnect(void);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
diff --git a/qemu-config.c b/qemu-config.c
index 590fc05..ff8b06e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -140,6 +140,9 @@ QemuOptsList qemu_chardev_opts = {
         },{
             .name = "signal",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "reconnect",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end if list */ }
     },
diff --git a/vl.c b/vl.c
index 44763af..5876c3e 100644
--- a/vl.c
+++ b/vl.c
@@ -3795,6 +3795,10 @@ void main_loop_wait(int timeout)
 
     host_main_loop_wait(&timeout);
 
+    /* Reconnect any disconnected sockets, if necessary */
+
+    qemu_chr_reconnect();
+
     /* poll any events */
     /* XXX: separate device handlers from system ones */
     nfds = -1;
-- 
1.6.5


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

* [Qemu-devel] Re: Socket reconnection.
  2009-12-02 10:40         ` Ian Molton
@ 2009-12-02 12:04           ` Jan Kiszka
  2009-12-02 19:56           ` [Qemu-devel] " Anthony Liguori
  2009-12-02 22:35           ` Krumme, Chris
  2 siblings, 0 replies; 22+ messages in thread
From: Jan Kiszka @ 2009-12-02 12:04 UTC (permalink / raw)
  To: Ian Molton; +Cc: Krumme, Chris, qemu-devel

Ian Molton wrote:
> btw. Does anyone know how to get t-bird to inline patches?

I'm using Thunderbird for single patches. For a fairly efficient
workflow, I've installed Toggle Word Wrap [1] and defined a short-cut
for it (here: Alt-W). After copy&pasting a patch into the editor window,
I simply switch off the wrapping and can then send out a properly
formatted patch. The only pitfall is to forget to switch (some visual
indication of the wrapping mode in the status bar or so would be nice).

Jan

[1] https://addons.mozilla.org/de/firefox/addon/2351

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-02 10:40         ` Ian Molton
  2009-12-02 12:04           ` [Qemu-devel] " Jan Kiszka
@ 2009-12-02 19:56           ` Anthony Liguori
  2009-12-02 22:35           ` Krumme, Chris
  2 siblings, 0 replies; 22+ messages in thread
From: Anthony Liguori @ 2009-12-02 19:56 UTC (permalink / raw)
  To: Ian Molton; +Cc: Krumme, Chris, qemu-devel

Ian Molton wrote:
> Anthony Liguori wrote:
>
>   
>> sleep() in qemu is very, very wrong.  It will pause the guest's
>> execution and all sorts of badness can ensue.
>>     
>
> Quite...
>
>   
>> The right thing to do is set a timer and not generate data while
>> disconnected.
>>     
>
> New patch attached, now with less crack...
>
>   
>>  I still am not confident this is really a great thing to do.
>>     
>
> What other option is there than to drop the ability to feed entropy to
> the guest when the hosts egd link drops?
>
> btw. Does anyone know how to get t-bird to inline patches?
>
> -Ian
>   

Ah, your mailer didn't attach it correctly...

Anyway, it's broken wrt CodingStyle.

Regards,

Anthony Liguori

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

* RE: [Qemu-devel] Socket reconnection.
  2009-12-02 10:40         ` Ian Molton
  2009-12-02 12:04           ` [Qemu-devel] " Jan Kiszka
  2009-12-02 19:56           ` [Qemu-devel] " Anthony Liguori
@ 2009-12-02 22:35           ` Krumme, Chris
  2009-12-03 10:04             ` Ian Molton
  2 siblings, 1 reply; 22+ messages in thread
From: Krumme, Chris @ 2009-12-02 22:35 UTC (permalink / raw)
  To: Ian Molton, Anthony Liguori; +Cc: qemu-devel


Hello Ian,

Pasting chunks, then commenting:

+static int qemu_chr_sched_reconnect(TCPCharDriver *s)
+{
+    struct reconnect_list *new = qemu_malloc(sizeof(*new));
+    struct timeval tv;
+
+    if(!new)
+        return 1;


Qemu_malloc will never return 0, so sched function can return void.


+    while (this) {
+        if (this->when <= now) {
+            if(qemu_chr_connect_socket(this->s)) {
+                if(prev)
+                    prev->next = this->next;
+                else
+                    rc_list = NULL;
+                qemu_chr_event(this->s->chr, CHR_EVENT_RECONNECTED);
+                free(this);
+		if(prev)
+			this = prev;
+		else
+			this = NULL;
+            }
+            else {
+                this->when += this->s->reconnect * 1000000;
+            }
+        }
+        prev = this;
+	if(this)
+            this = this->next;

This is a mixture of tabs and spaces, for new code pick one.

The if(prev) can just be this = prev;  if prev is NULL you want NULL
anyway.

Thanks

Chris
 

> -----Original Message-----
> From: Ian Molton [mailto:ian.molton@collabora.co.uk] 
> Sent: Wednesday, December 02, 2009 4:41 AM
> To: Anthony Liguori
> Cc: Krumme, Chris; qemu-devel@nongnu.org
> Subject: Re: [Qemu-devel] Socket reconnection.
> 
> Anthony Liguori wrote:
> 
> > sleep() in qemu is very, very wrong.  It will pause the guest's
> > execution and all sorts of badness can ensue.
> 
> Quite...
> 
> > The right thing to do is set a timer and not generate data while
> > disconnected.
> 
> New patch attached, now with less crack...
> 
> >  I still am not confident this is really a great thing to do.
> 
> What other option is there than to drop the ability to feed entropy to
> the guest when the hosts egd link drops?
> 
> btw. Does anyone know how to get t-bird to inline patches?
> 
> -Ian
> 

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-02 22:35           ` Krumme, Chris
@ 2009-12-03 10:04             ` Ian Molton
  2009-12-03 10:23               ` Kevin Wolf
  2009-12-03 14:22               ` Anthony Liguori
  0 siblings, 2 replies; 22+ messages in thread
From: Ian Molton @ 2009-12-03 10:04 UTC (permalink / raw)
  To: Krumme, Chris; +Cc: qemu-devel

Krumme, Chris wrote:
> Hello Ian,

Hello!

> Qemu_malloc will never return 0, so sched function can return void.

Gah! nasty. Check removed.

> This is a mixture of tabs and spaces, for new code pick one.

I've been sticking with spaces generally. I can't find 'CodingStyle' so
I copied. I think spaces suck for this though. What is acceptable?
linux kernel style ?
 
> The if(prev) can just be this = prev;  if prev is NULL you want NULL
> anyway.

Quite. Fixed.

> Thanks

Likewise.

Fresh patch attached. Anthony, if this is ok, I can rebase this and its
prerequisite.

>From 05581c5badd693b7537fe57f85a2ff5ddcb7972d Mon Sep 17 00:00:00 2001
From: Ian Molton <ian.molton@collabora.co.uk>
Date: Tue, 1 Dec 2009 11:18:41 +0000
Subject: [PATCH 2/4] socket: Add a reconnect option.

	Add a reconnect option that allows sockets to reconnect (after a
specified delay) to the specified server. This makes the virtio-rng driver
useful in production environments where the EGD server may need to be restarted.

Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
---
 qemu-char.c   |  169 ++++++++++++++++++++++++++++++++++++++++++++-------------
 qemu-char.h   |    2 +
 qemu-config.c |    3 +
 vl.c          |    4 ++
 4 files changed, 139 insertions(+), 39 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index e202585..f20d697 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1870,8 +1870,12 @@ typedef struct {
     int max_size;
     int do_telnetopt;
     int do_nodelay;
+    int reconnect;
     int is_unix;
     int msgfd;
+    QemuOpts *opts;
+    CharDriverState *chr;
+    int (*setup)(QemuOpts *opts);
 } TCPCharDriver;
 
 static void tcp_chr_accept(void *opaque);
@@ -2011,6 +2015,61 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 }
 #endif
 
+struct reconnect_list {
+    TCPCharDriver *s;
+    uint64_t when;
+    struct reconnect_list *next;
+};
+
+static struct reconnect_list *rc_list;
+
+static void qemu_chr_sched_reconnect(TCPCharDriver *s)
+{
+    struct reconnect_list *new = qemu_malloc(sizeof(*new));
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    new->s = s;
+    new->when = (s->reconnect + tv.tv_sec) * 1000000 + tv.tv_usec;
+    new->next = rc_list;
+    rc_list = new;
+}
+
+static int qemu_chr_connect_socket(TCPCharDriver *s);
+
+void qemu_chr_reconnect(void)
+{
+    struct reconnect_list *this = rc_list, *prev = NULL;
+    struct timeval tv;
+    uint64_t now;
+
+    if (!this)
+        return;
+
+    gettimeofday(&tv, NULL);
+    now = tv.tv_sec * 1000000 + tv.tv_usec;
+
+    while (this) {
+        if (this->when <= now) {
+            if (qemu_chr_connect_socket(this->s)) {
+                if (prev)
+                    prev->next = this->next;
+                else
+                    rc_list = NULL;
+                qemu_chr_event(this->s->chr, CHR_EVENT_RECONNECTED);
+                free(this);
+                this = prev;
+            }
+            else {
+                this->when += this->s->reconnect * 1000000;
+            }
+        }
+        prev = this;
+	if (this)
+            this = this->next;
+    }
+}
+
 static void tcp_chr_read(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2030,10 +2089,16 @@ static void tcp_chr_read(void *opaque)
         if (s->listen_fd >= 0) {
             qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
         }
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        if (!s->reconnect) {
+            qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        }
         closesocket(s->fd);
         s->fd = -1;
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        if (s->reconnect) {
+            qemu_chr_sched_reconnect(s);
+        } else {
+            qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        }
     } else if (size > 0) {
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2137,7 +2202,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
-    int fd = -1;
     int is_listen;
     int is_waitconnect;
     int do_nodelay;
@@ -2145,34 +2209,40 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     int is_telnet;
 
     is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    is_unix        = qemu_opt_get(opts, "path") != NULL;
+
     is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
     is_telnet      = qemu_opt_get_bool(opts, "telnet", 0);
     do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
-    is_unix        = qemu_opt_get(opts, "path") != NULL;
-    if (!is_listen)
+
+    if (!is_listen) {
         is_waitconnect = 0;
+    } else {
+        if (is_telnet)
+            s->do_telnetopt = 1;
+    }
+
 
-    chr = qemu_mallocz(sizeof(CharDriverState));
     s = qemu_mallocz(sizeof(TCPCharDriver));
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    s->opts = opts;
+
+    if (!is_listen && !is_telnet)
+        s->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
 
     if (is_unix) {
         if (is_listen) {
-            fd = unix_listen_opts(opts);
+            s->setup = unix_listen_opts;
         } else {
-            fd = unix_connect_opts(opts);
+            s->setup = unix_connect_opts;
         }
     } else {
         if (is_listen) {
-            fd = inet_listen_opts(opts, 0);
+            s->setup = inet_listen_opts;
         } else {
-            fd = inet_connect_opts(opts);
+            s->setup = inet_connect_opts;
         }
     }
-    if (fd < 0)
-        goto fail;
-
-    if (!is_waitconnect)
-        socket_set_nonblock(fd);
 
     s->connected = 0;
     s->fd = -1;
@@ -2186,19 +2256,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     chr->chr_close = tcp_chr_close;
     chr->get_msgfd = tcp_get_msgfd;
 
-    if (is_listen) {
-        s->listen_fd = fd;
-        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-        if (is_telnet)
-            s->do_telnetopt = 1;
-
-    } else {
-        s->connected = 1;
-        s->fd = fd;
-        socket_set_nodelay(fd);
-        tcp_chr_connect(chr);
-    }
-
     /* for "info chardev" monitor command */
     chr->filename = qemu_malloc(256);
     if (is_unix) {
@@ -2215,22 +2272,56 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
                  qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");
     }
 
-    if (is_listen && is_waitconnect) {
-        printf("QEMU waiting for connection on: %s\n",
-               chr->filename);
-        tcp_chr_accept(chr);
-        socket_set_nonblock(s->listen_fd);
-    }
-    return chr;
+    s->chr = chr;
+
+    if(qemu_chr_connect_socket(s))
+        return chr;
 
- fail:
-    if (fd >= 0)
-        closesocket(fd);
-    qemu_free(s);
     qemu_free(chr);
+    qemu_free(s);
+
     return NULL;
 }
 
+
+static int qemu_chr_connect_socket(TCPCharDriver *s)
+{
+    QemuOpts *opts = s->opts;
+    int is_listen;
+    int fd;
+    int is_waitconnect;
+    int do_nodelay;
+
+    is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
+    is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
+
+
+    fd = s->setup(s->opts);
+    if (fd < 0)
+        return 0;
+
+    if (!is_waitconnect)
+        socket_set_nonblock(fd);
+
+    if (is_listen) {
+        s->listen_fd = fd;
+        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, s->chr);
+        if (is_waitconnect) {
+            printf("QEMU waiting for connection on: %s\n",
+                   s->chr->filename);
+            tcp_chr_accept(s->chr);
+            socket_set_nonblock(s->listen_fd);
+        }
+    } else {
+        s->fd = fd;
+        socket_set_nodelay(fd);
+        tcp_chr_connect(s->chr);
+    }
+
+    return 1;
+}
+
 static QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
 {
     char host[65], port[33], width[8], height[8];
diff --git a/qemu-char.h b/qemu-char.h
index 9957db1..dc954e2 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -14,6 +14,7 @@
 #define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
 #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
 #define CHR_EVENT_CLOSED  5 /* connection closed */
+#define CHR_EVENT_RECONNECTED  6 /* reconnect event */
 
 
 #define CHR_IOCTL_SERIAL_SET_PARAMS   1
@@ -73,6 +74,7 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s));
 CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
 void qemu_chr_close(CharDriverState *chr);
+void qemu_chr_reconnect(void);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
diff --git a/qemu-config.c b/qemu-config.c
index 590fc05..ff8b06e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -140,6 +140,9 @@ QemuOptsList qemu_chardev_opts = {
         },{
             .name = "signal",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "reconnect",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end if list */ }
     },
diff --git a/vl.c b/vl.c
index 44763af..5876c3e 100644
--- a/vl.c
+++ b/vl.c
@@ -3795,6 +3795,10 @@ void main_loop_wait(int timeout)
 
     host_main_loop_wait(&timeout);
 
+    /* Reconnect any disconnected sockets, if necessary */
+
+    qemu_chr_reconnect();
+
     /* poll any events */
     /* XXX: separate device handlers from system ones */
     nfds = -1;
-- 
1.6.5

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-03 10:04             ` Ian Molton
@ 2009-12-03 10:23               ` Kevin Wolf
  2009-12-03 14:22               ` Anthony Liguori
  1 sibling, 0 replies; 22+ messages in thread
From: Kevin Wolf @ 2009-12-03 10:23 UTC (permalink / raw)
  To: Ian Molton; +Cc: Krumme, Chris, qemu-devel

Am 03.12.2009 11:04, schrieb Ian Molton:
> Krumme, Chris wrote:
>> This is a mixture of tabs and spaces, for new code pick one.
> 
> I've been sticking with spaces generally. I can't find 'CodingStyle' so
> I copied. I think spaces suck for this though. What is acceptable?
> linux kernel style ?

Four spaces. The file is called CODING_STYLE and it's in the top level
directory.

Kevin

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-03 10:04             ` Ian Molton
  2009-12-03 10:23               ` Kevin Wolf
@ 2009-12-03 14:22               ` Anthony Liguori
  2009-12-03 18:37                 ` [Qemu-devel] [PATCH]Socket reconnection Ian Molton
  1 sibling, 1 reply; 22+ messages in thread
From: Anthony Liguori @ 2009-12-03 14:22 UTC (permalink / raw)
  To: Ian Molton; +Cc: Krumme, Chris, qemu-devel

Ian Molton wrote:
> Fresh patch attached. Anthony, if this is ok, I can rebase this and its
> prerequisite.
>
> From 05581c5badd693b7537fe57f85a2ff5ddcb7972d Mon Sep 17 00:00:00 2001
> From: Ian Molton <ian.molton@collabora.co.uk>
> Date: Tue, 1 Dec 2009 11:18:41 +0000
> Subject: [PATCH 2/4] socket: Add a reconnect option.
>
> 	Add a reconnect option that allows sockets to reconnect (after a
> specified delay) to the specified server. This makes the virtio-rng driver
> useful in production environments where the EGD server may need to be restarted.
>
> Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
> ---
>  qemu-char.c   |  169 ++++++++++++++++++++++++++++++++++++++++++++-------------
>  qemu-char.h   |    2 +
>  qemu-config.c |    3 +
>  vl.c          |    4 ++
>  4 files changed, 139 insertions(+), 39 deletions(-)
>
> diff --git a/qemu-char.c b/qemu-char.c
> index e202585..f20d697 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -1870,8 +1870,12 @@ typedef struct {
>      int max_size;
>      int do_telnetopt;
>      int do_nodelay;
> +    int reconnect;
>      int is_unix;
>      int msgfd;
> +    QemuOpts *opts;
> +    CharDriverState *chr;
> +    int (*setup)(QemuOpts *opts);
>  } TCPCharDriver;
>  
>  static void tcp_chr_accept(void *opaque);
> @@ -2011,6 +2015,61 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
>  }
>  #endif
>  
> +struct reconnect_list {
>   

CODING_STYLE is off (as I mentioned before).

> +    TCPCharDriver *s;
> +    uint64_t when;
> +    struct reconnect_list *next;
> +};
> +
> +static struct reconnect_list *rc_list;
> +
> +static void qemu_chr_sched_reconnect(TCPCharDriver *s)
> +{
> +    struct reconnect_list *new = qemu_malloc(sizeof(*new));
> +    struct timeval tv;
> +
> +    gettimeofday(&tv, NULL);
>   

This will break Win32 (use qemu_gettimeofday).

> +    new->s = s;
> +    new->when = (s->reconnect + tv.tv_sec) * 1000000 + tv.tv_usec;
> +    new->next = rc_list;
> +    rc_list = new;
>   

Don't open code a list, use one of the sys-queue types.

> +}
> +
> +static int qemu_chr_connect_socket(TCPCharDriver *s);
>   

Forward declarations usually imply some form of code motion is required.

> +void qemu_chr_reconnect(void)
> +{
> +    struct reconnect_list *this = rc_list, *prev = NULL;
> +    struct timeval tv;
> +    uint64_t now;
> +
> +    if (!this)
> +        return;
> +
> +    gettimeofday(&tv, NULL);
> +    now = tv.tv_sec * 1000000 + tv.tv_usec;
> +
> +    while (this) {
> +        if (this->when <= now) {
> +            if (qemu_chr_connect_socket(this->s)) {
> +                if (prev)
> +                    prev->next = this->next;
> +                else
> +                    rc_list = NULL;
> +                qemu_chr_event(this->s->chr, CHR_EVENT_RECONNECTED);
> +                free(this);
> +                this = prev;
> +            }
> +            else {
> +                this->when += this->s->reconnect * 1000000;
> +            }
> +        }
> +        prev = this;
> +	if (this)
> +            this = this->next;
> +    }
> +}
> +
>   

Mixing tabs and spaces.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [PATCH]Socket reconnection.
  2009-12-03 14:22               ` Anthony Liguori
@ 2009-12-03 18:37                 ` Ian Molton
  2009-12-05 22:03                   ` Ian Molton
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Molton @ 2009-12-03 18:37 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Krumme, Chris, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 678 bytes --]

Anthony Liguori wrote:

New patch attached, addressing the below. Thanks!

> CODING_STYLE is off (as I mentioned before).

Hopefully fixed now.

>> +    gettimeofday(&tv, NULL);
>>   
> 
> This will break Win32 (use qemu_gettimeofday).
 
Done

> Don't open code a list, use one of the sys-queue types.

I only wanted a singly linked list. However, changed to a QLIST

>> +static int qemu_chr_connect_socket(TCPCharDriver *s);
>>   
> 
> Forward declarations usually imply some form of code motion is required.

Cant see any way around it here. I've reordered it so the new code needs
the forward dec. rather than adding one for the old code.
 
> Mixing tabs and spaces.

fixed.

[-- Attachment #2: 0002-socket-Add-a-reconnect-option.patch --]
[-- Type: text/x-patch, Size: 8949 bytes --]

>From 8d12cabf09996eef9adcc121ea3cbec70d48b3b4 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian.molton@collabora.co.uk>
Date: Tue, 1 Dec 2009 11:18:41 +0000
Subject: [PATCH 2/4] socket: Add a reconnect option.

	Add a reconnect option that allows sockets to reconnect (after a
specified delay) to the specified server. This makes the virtio-rng driver
useful in production environments where the EGD server may need to be restarted.

Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
---
 qemu-char.c   |  159 +++++++++++++++++++++++++++++++++++++++++++--------------
 qemu-char.h   |    2 +
 qemu-config.c |    3 +
 vl.c          |    4 ++
 4 files changed, 129 insertions(+), 39 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index e202585..45c9f3d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1870,8 +1870,12 @@ typedef struct {
     int max_size;
     int do_telnetopt;
     int do_nodelay;
+    int reconnect;
     int is_unix;
     int msgfd;
+    QemuOpts *opts;
+    CharDriverState *chr;
+    int (*setup)(QemuOpts *opts);
 } TCPCharDriver;
 
 static void tcp_chr_accept(void *opaque);
@@ -2011,6 +2015,8 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 }
 #endif
 
+static void qemu_chr_sched_reconnect(TCPCharDriver *s);
+
 static void tcp_chr_read(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2030,10 +2036,16 @@ static void tcp_chr_read(void *opaque)
         if (s->listen_fd >= 0) {
             qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
         }
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        if (!s->reconnect) {
+            qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        }
         closesocket(s->fd);
         s->fd = -1;
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        if (s->reconnect) {
+            qemu_chr_sched_reconnect(s);
+        } else {
+            qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        }
     } else if (size > 0) {
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2133,11 +2145,92 @@ static void tcp_chr_close(CharDriverState *chr)
     qemu_chr_event(chr, CHR_EVENT_CLOSED);
 }
 
+static int qemu_chr_connect_socket(TCPCharDriver *s)
+{
+    QemuOpts *opts = s->opts;
+    int is_listen;
+    int fd;
+    int is_waitconnect;
+    int do_nodelay;
+
+    is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
+    is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
+
+
+    fd = s->setup(s->opts);
+    if (fd < 0)
+        return 0;
+
+    if (!is_waitconnect)
+        socket_set_nonblock(fd);
+
+    if (is_listen) {
+        s->listen_fd = fd;
+        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, s->chr);
+        if (is_waitconnect) {
+            printf("QEMU waiting for connection on: %s\n",
+                   s->chr->filename);
+            tcp_chr_accept(s->chr);
+            socket_set_nonblock(s->listen_fd);
+        }
+    } else {
+        s->fd = fd;
+        socket_set_nodelay(fd);
+        tcp_chr_connect(s->chr);
+    }
+
+    return 1;
+}
+
+static QLIST_HEAD(reconnect_list_head, reconnect_list_entry) rcl_head;
+
+typedef struct reconnect_list_entry {
+    TCPCharDriver *s;
+    uint64_t when;
+    QLIST_ENTRY(reconnect_list_entry) entries;
+} reconnect_list_entry;
+
+static void qemu_chr_sched_reconnect(TCPCharDriver *s)
+{
+    reconnect_list_entry *new = qemu_malloc(sizeof(*new));
+    struct timeval tv;
+
+    qemu_gettimeofday(&tv);
+    new->s = s;
+    new->when = (s->reconnect + tv.tv_sec) * 1000000 + tv.tv_usec;
+    QLIST_INSERT_HEAD(&rcl_head, new, entries);
+}
+
+void qemu_chr_reconnect(void)
+{
+    struct timeval tv;
+    uint64_t now;
+    reconnect_list_entry *np;
+
+    if (!rcl_head.lh_first)
+        return;
+
+    gettimeofday(&tv, NULL);
+    now = tv.tv_sec * 1000000 + tv.tv_usec;
+
+    for (np = rcl_head.lh_first; np != NULL; np = np->entries.le_next) {
+        if (np->when <= now) {
+            if (qemu_chr_connect_socket(np->s)) {
+                qemu_chr_event(np->s->chr, CHR_EVENT_RECONNECTED);
+                QLIST_REMOVE(np, entries);
+            }
+            else {
+                np->when += np->s->reconnect * 1000000;
+            }
+        }
+    }
+}
+
 static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
-    int fd = -1;
     int is_listen;
     int is_waitconnect;
     int do_nodelay;
@@ -2145,34 +2238,40 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     int is_telnet;
 
     is_listen      = qemu_opt_get_bool(opts, "server", 0);
+    is_unix        = qemu_opt_get(opts, "path") != NULL;
+
     is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
     is_telnet      = qemu_opt_get_bool(opts, "telnet", 0);
     do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);
-    is_unix        = qemu_opt_get(opts, "path") != NULL;
-    if (!is_listen)
+
+    if (!is_listen) {
         is_waitconnect = 0;
+    } else {
+        if (is_telnet)
+            s->do_telnetopt = 1;
+    }
+
 
-    chr = qemu_mallocz(sizeof(CharDriverState));
     s = qemu_mallocz(sizeof(TCPCharDriver));
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    s->opts = opts;
+
+    if (!is_listen && !is_telnet)
+        s->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
 
     if (is_unix) {
         if (is_listen) {
-            fd = unix_listen_opts(opts);
+            s->setup = unix_listen_opts;
         } else {
-            fd = unix_connect_opts(opts);
+            s->setup = unix_connect_opts;
         }
     } else {
         if (is_listen) {
-            fd = inet_listen_opts(opts, 0);
+            s->setup = inet_listen_opts;
         } else {
-            fd = inet_connect_opts(opts);
+            s->setup = inet_connect_opts;
         }
     }
-    if (fd < 0)
-        goto fail;
-
-    if (!is_waitconnect)
-        socket_set_nonblock(fd);
 
     s->connected = 0;
     s->fd = -1;
@@ -2186,19 +2285,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     chr->chr_close = tcp_chr_close;
     chr->get_msgfd = tcp_get_msgfd;
 
-    if (is_listen) {
-        s->listen_fd = fd;
-        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-        if (is_telnet)
-            s->do_telnetopt = 1;
-
-    } else {
-        s->connected = 1;
-        s->fd = fd;
-        socket_set_nodelay(fd);
-        tcp_chr_connect(chr);
-    }
-
     /* for "info chardev" monitor command */
     chr->filename = qemu_malloc(256);
     if (is_unix) {
@@ -2215,19 +2301,14 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
                  qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");
     }
 
-    if (is_listen && is_waitconnect) {
-        printf("QEMU waiting for connection on: %s\n",
-               chr->filename);
-        tcp_chr_accept(chr);
-        socket_set_nonblock(s->listen_fd);
-    }
-    return chr;
+    s->chr = chr;
+
+    if(qemu_chr_connect_socket(s))
+        return chr;
 
- fail:
-    if (fd >= 0)
-        closesocket(fd);
-    qemu_free(s);
     qemu_free(chr);
+    qemu_free(s);
+
     return NULL;
 }
 
diff --git a/qemu-char.h b/qemu-char.h
index 9957db1..dc954e2 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -14,6 +14,7 @@
 #define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
 #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
 #define CHR_EVENT_CLOSED  5 /* connection closed */
+#define CHR_EVENT_RECONNECTED  6 /* reconnect event */
 
 
 #define CHR_IOCTL_SERIAL_SET_PARAMS   1
@@ -73,6 +74,7 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s));
 CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
 void qemu_chr_close(CharDriverState *chr);
+void qemu_chr_reconnect(void);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
diff --git a/qemu-config.c b/qemu-config.c
index 590fc05..ff8b06e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -140,6 +140,9 @@ QemuOptsList qemu_chardev_opts = {
         },{
             .name = "signal",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "reconnect",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end if list */ }
     },
diff --git a/vl.c b/vl.c
index 44763af..5876c3e 100644
--- a/vl.c
+++ b/vl.c
@@ -3795,6 +3795,10 @@ void main_loop_wait(int timeout)
 
     host_main_loop_wait(&timeout);
 
+    /* Reconnect any disconnected sockets, if necessary */
+
+    qemu_chr_reconnect();
+
     /* poll any events */
     /* XXX: separate device handlers from system ones */
     nfds = -1;
-- 
1.6.5


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

* Re: [Qemu-devel] [PATCH]Socket reconnection.
  2009-12-03 18:37                 ` [Qemu-devel] [PATCH]Socket reconnection Ian Molton
@ 2009-12-05 22:03                   ` Ian Molton
  0 siblings, 0 replies; 22+ messages in thread
From: Ian Molton @ 2009-12-05 22:03 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Krumme, Chris, qemu-devel

Ian Molton wrote:
> Anthony Liguori wrote:
> 
> New patch attached, addressing the below. Thanks!

Did this patch make it? I cant seem to find my earlier patches in the
.git repo you mentioned, does that mean they have been dropped, or that
they have been merged upstream ?

I can repost all four patches in dependency order if you prefer,
especially as the current version of the virtio-rng patch has been
modified to work with the socket reconnect support.

Thanks,

-Ian

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-01 11:55   ` Ian Molton
@ 2009-12-06 14:32     ` Jamie Lokier
  2009-12-06 16:33       ` Ian Molton
  0 siblings, 1 reply; 22+ messages in thread
From: Jamie Lokier @ 2009-12-06 14:32 UTC (permalink / raw)
  To: Ian Molton; +Cc: qemu-devel

Ian Molton wrote:
> Jamie Lokier wrote:
> 
> > I'm a bit puzzled.
> > 
> > Why isn't virtio-rng getting entropy from /dev/random on the host?
> 
> /dev/random may not be available.

Understood on a non-Linux host.

> Besides, not all entropy comes from /dev/random.

On a Linux host, why isn't rngd simply injecting it's entropy into
/dev/random where it would be more convenient to access?  (No need for
socket reconnection code, for example).

-- Jamie

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-06 14:32     ` Jamie Lokier
@ 2009-12-06 16:33       ` Ian Molton
  2009-12-07  2:29         ` Jamie Lokier
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Molton @ 2009-12-06 16:33 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: qemu-devel

Jamie Lokier wrote:
> Ian Molton wrote:
>> Jamie Lokier wrote:
>>
>>> I'm a bit puzzled.
>>>
>>> Why isn't virtio-rng getting entropy from /dev/random on the host?
>> /dev/random may not be available.
> 
> Understood on a non-Linux host.

Or a linux host with a user with insufficient privs...

>> Besides, not all entropy comes from /dev/random.
> 
> On a Linux host, why isn't rngd simply injecting it's entropy into
> /dev/random where it would be more convenient to access?  (No need for
> socket reconnection code, for example).

Who knows? lack of privs, an admin who only uses egd, a machine which is
being fed entropy by egd via a tunnel. User doesnt trust /dev/random,
/dev/random known to be failing FIPS tests on a shared machine - there
could be any number of reasons. In our case, entropy is comming from
hardware via egd, to be used in the guest VMs. why feed it into RNGD,
then the hosts entropy pool, THEN the guests - just feed them directly.
the egd daemon in this case also offers load balancing to all consumers
of entropy.

Since we need this on hosts without /dev/random anyway, I dont see why
we would need to deliberately cripple qemu on linux hosts...

-Ian

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-06 16:33       ` Ian Molton
@ 2009-12-07  2:29         ` Jamie Lokier
  2009-12-07  9:29           ` Ian Molton
  0 siblings, 1 reply; 22+ messages in thread
From: Jamie Lokier @ 2009-12-07  2:29 UTC (permalink / raw)
  To: Ian Molton; +Cc: qemu-devel

Ian Molton wrote:
> >> Besides, not all entropy comes from /dev/random.
> > 
> > On a Linux host, why isn't rngd simply injecting it's entropy into
> > /dev/random where it would be more convenient to access?  (No need for
> > socket reconnection code, for example).
> 
> Who knows? lack of privs, an admin who only uses egd, a machine which is
> being fed entropy by egd via a tunnel. User doesnt trust /dev/random,
> /dev/random known to be failing FIPS tests on a shared machine - there
> could be any number of reasons. In our case, entropy is comming from
> hardware via egd, to be used in the guest VMs. why feed it into RNGD,
> then the hosts entropy pool, THEN the guests - just feed them directly.
> the egd daemon in this case also offers load balancing to all consumers
> of entropy.

Those arguments are weak because they also apply the other way: an
admin who only uses /dev/random (got lots of those), a machine which
is being fed entropy into /dev/random via a tunnel (been there), user
doesn't trust egd (why should I trust it more than the kernel?
userspace is more easily corrupted - and with a socket, it might not
even be egd running), etc.

I grant you there are advantages sometimes, but also disadvantages.
Why would I run egd on a guest VM running an embedded system with 16MB
RAM, where every process is precious, for example?  But those systems
need entropy too.

As for why feed it "directly" via hardware -> egd -> guest", the
reason surely is because most clients read /dev/random or
/dev/urandom, so entropy that isn't injected into /dev/random is wasted.

Anyway, I've just read the rngd manual, and it does inject it's
entropy into /dev/random so that's the end of that discussion :-)

But the main issue is below.  On all host systems I have access to,
there is _no_ entropy available from egd/rngd...

> Since we need this on hosts without /dev/random anyway, I dont see why
> we would need to deliberately cripple qemu on linux hosts...

Since nobody has asked you to cripple anything, that is irrelevant.
Options don't cripple.

The lack of option is crippling qemu on linux hosts which don't run egd.

Which hosts are those?  Well, I've just checked five live systems,
four servers and one laptop, running:

    Ubuntu 9.10 (Karmic)  - no egd running, no rngd running
    Ubuntu 9.04 (Jaunty)  - no egd running, no rngd running
    Debian 4.0 (Etch)     - no egd running, no rngd running
    CentOS 4.0            - no egd running, no rngd running
    RHEL 4.0              - no egd running, no rngd running

So if I understand right, the virtio-rng host driver won't work on any
host system I have access to?  Is that correct?

Btw, /dev/random is available on virtually every host - Linux,
Solaris, FreeBSD, Mac OS X, NetBSD, OpenBSD, Tru64, HP-UX, AIX, and
there's even a similar device for Windows :-)

I grant you the egd/rngd entropy is preferable on a system that's
running it.  It is much more careful.  (Let's ignore this in rngd's
man page: "Do not do that unless you trust rngd's source of random
data").  So a good default would be to use the egd/rngd socket when
available, and fall back to /dev/random or even /dev/urandom (at user
request) when not.

My tests show that egd/rngd are not running on any host system I have
access to - and that's quite a diverse range of Linuxes.  It would
have to be run specially, which sounds problematic as qemu would be
the only process using it.

-- Jamie

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

* Re: [Qemu-devel] Socket reconnection.
  2009-12-07  2:29         ` Jamie Lokier
@ 2009-12-07  9:29           ` Ian Molton
  0 siblings, 0 replies; 22+ messages in thread
From: Ian Molton @ 2009-12-07  9:29 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: qemu-devel

Jamie Lokier wrote:
> Ian Molton wrote:
>>>> Besides, not all entropy comes from /dev/random.

> Those arguments are weak.

No worse than the counterarguments.

If nothing else, qemu is a useful tool for testing kernel subsystems and
in fact the virtio code triggered and caused to be fixed a number of
bugs / flaws in the kernels hw random core and virtio driver. That alone
I think shows it has value.

> I grant you there are advantages sometimes, but also disadvantages.
> Why would I run egd on a guest VM running an embedded system with 16MB
> RAM, where every process is precious, for example?  But those systems
> need entropy too.

I have no idea - too much crack? :-)

one might run rngd, or use /dev/hwrng directly, but I cant see why you'd
want to run egd on it.

> As for why feed it "directly" via hardware -> egd -> guest", the
> reason surely is because most clients read /dev/random or
> /dev/urandom, so entropy that isn't injected into /dev/random is wasted.

Im not proposing that. I'm saying the HOST machine would be getting
entropy from egd, directly into qemu. That entropy comes out of the
guests /dev/hwrng.

I can see value there too - the hosts /dev/random pool cannot be
compromised by the guest OS. But nothings stopping you specifying
/dev/random as qemus entropy source.

> But the main issue is below.  On all host systems I have access to,
> there is _no_ entropy available from egd/rngd...

I have no system here with that hardware either - however I had access
(via an ssh tunnel) to another machine that did have it, and could feed
qemu direct from that stream. qemu spoke egd over the tunnel, and fed
the guests /dev/hwrng. The guest was passing FIPS tests at the same
speed the hardware could produce entropy. Are you suggesting that I
should have fed the hosts entropy pool (via RNGD) and then fed that to
the guest ia qemu? why?

>> Since we need this on hosts without /dev/random anyway, I dont see why
>> we would need to deliberately cripple qemu on linux hosts...
>
> The lack of option is crippling qemu on linux hosts which don't run egd.

Sorry, what?

> Which hosts are those?  Well, I've just checked five live systems,
> four servers and one laptop, running:
> 
>     Ubuntu 9.10 (Karmic)  - no egd running, no rngd running
>     Ubuntu 9.04 (Jaunty)  - no egd running, no rngd running
>     Debian 4.0 (Etch)     - no egd running, no rngd running

apt-get install rng-tools

>     CentOS 4.0            - no egd running, no rngd running
>     RHEL 4.0              - no egd running, no rngd running

Presumably one can install rngd easily on these systems too.

I have a machine here that is not running X - does that make X worthless?

> So if I understand right, the virtio-rng host driver won't work on any
> host system I have access to?  Is that correct?

No, because it is just as happy reading raw data from /dev/random as it
it to speak EGD protocol over a socket. Have you actually tried the patch?

-Ian

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

end of thread, other threads:[~2009-12-07  9:30 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-26  0:31 [Qemu-devel] Socket reconnection Ian Molton
2009-11-26  9:21 ` Gerd Hoffmann
2009-11-27  9:01 ` Jamie Lokier
2009-12-01 11:55   ` Ian Molton
2009-12-06 14:32     ` Jamie Lokier
2009-12-06 16:33       ` Ian Molton
2009-12-07  2:29         ` Jamie Lokier
2009-12-07  9:29           ` Ian Molton
2009-11-30 17:18 ` Anthony Liguori
2009-12-01 11:54   ` Ian Molton
2009-12-01 14:38     ` Krumme, Chris
2009-12-01 18:29       ` Ian Molton
2009-12-01 18:54       ` Anthony Liguori
2009-12-02 10:40         ` Ian Molton
2009-12-02 12:04           ` [Qemu-devel] " Jan Kiszka
2009-12-02 19:56           ` [Qemu-devel] " Anthony Liguori
2009-12-02 22:35           ` Krumme, Chris
2009-12-03 10:04             ` Ian Molton
2009-12-03 10:23               ` Kevin Wolf
2009-12-03 14:22               ` Anthony Liguori
2009-12-03 18:37                 ` [Qemu-devel] [PATCH]Socket reconnection Ian Molton
2009-12-05 22:03                   ` Ian Molton

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.