All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David S. Ahern" <daahern@cisco.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] re-send: enabling TCP keepalives - v5
Date: Sun, 10 May 2009 20:22:17 -0600	[thread overview]
Message-ID: <4A078BD9.3070507@cisco.com> (raw)

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

I did not see a response to this a week+ ago. Any objections to this
minimalist version?

david


This patch enables TCP keepalives on VNC connections and TCP-based char
devices.

Changes v4 -> v5
- removed settings for the timers and counter such that OS defaults are
used once the keepalive option is enabled
- enabling keepalives is now an option for TCP char devices
(piggy-backed on the nodelay option Paul mentioned)
- forced on for vnc (making it an option for vnc is a big can of works
that does not need to be opened)

Signed-off-by: David Ahern <dsahern@gmail.com>


[-- Attachment #2: enable-tcp-keepalives-v5.patch --]
[-- Type: text/plain, Size: 5932 bytes --]

diff --git a/configure b/configure
index 82fb60a..5ce0236 100755
--- a/configure
+++ b/configure
@@ -1673,6 +1673,19 @@ if test "$fdt" = "yes" ; then
   echo "FDT_LIBS=-lfdt" >> $config_mak
 fi
 
+cat > $TMPC << EOF
+#include <sys/socket.h>
+int main(void) {
+  int val = 1;
+  if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0)
+    return 1;
+  return 0;
+}
+EOF
+if $cc $ARCH_CFLAGS -o $TMPE $TMPC >/dev/null 2> /dev/null ; then
+  echo "#define HAVE_SO_KEEPALIVE 1" >> $config_h
+fi
+
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
   echo "#define O_LARGEFILE 0" >> $config_h
diff --git a/net.c b/net.c
index 7ae1e6d..e787883 100644
--- a/net.c
+++ b/net.c
@@ -2209,3 +2209,18 @@ void net_client_check(void)
                     vlan->id);
     }
 }
+
+int enable_tcp_keepalive(int sd)
+{
+#ifdef HAVE_SO_KEEPALIVE
+    int val = 1;
+
+    if (setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) {
+        return -1;
+    }
+#else
+    fprintf(stderr, "Warning: TCP keepalives not supported\n");
+#endif
+
+    return 0;
+}
diff --git a/net.h b/net.h
index cdf63a4..29d00fa 100644
--- a/net.h
+++ b/net.h
@@ -119,6 +119,8 @@ void net_client_check(void);
 void net_host_device_add(Monitor *mon, const char *device, const char *opts);
 void net_host_device_remove(Monitor *mon, int vlan_id, const char *device);
 
+int enable_tcp_keepalive(int sd);
+
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
 #ifdef __sun__
diff --git a/qemu-char.c b/qemu-char.c
index 664cbfd..2d21022 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1825,6 +1825,7 @@ typedef struct {
     int max_size;
     int do_telnetopt;
     int do_nodelay;
+    int do_keepalive;
     int is_unix;
 } TCPCharDriver;
 
@@ -1998,6 +1999,10 @@ static void tcp_chr_accept(void *opaque)
     socket_set_nonblock(fd);
     if (s->do_nodelay)
         socket_set_nodelay(fd);
+    if (s->do_keepalive && enable_tcp_keepalive(fd) != 0) {
+        fprintf(stderr,
+                "tcp_chr_accept: failed to enable TCP keepalive probes\n");
+    }
     s->fd = fd;
     qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
     tcp_chr_connect(chr);
@@ -2027,6 +2032,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     int is_listen = 0;
     int is_waitconnect = 1;
     int do_nodelay = 0;
+    int do_keepalive = 0;
     const char *ptr;
 
     ptr = host_str;
@@ -2038,6 +2044,8 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
             is_waitconnect = 0;
         } else if (!strncmp(ptr,"nodelay",6)) {
             do_nodelay = 1;
+        } else if (!strncmp(ptr,"keepalive",9) && !is_unix) {
+            do_keepalive = 1;
         } else if (!strncmp(ptr,"to=",3)) {
             /* nothing, inet_listen() parses this one */;
         } else if (!strncmp(ptr,"ipv4",4)) {
@@ -2091,6 +2099,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     s->listen_fd = -1;
     s->is_unix = is_unix;
     s->do_nodelay = do_nodelay && !is_unix;
+    s->do_keepalive = do_keepalive;
 
     chr->opaque = s;
     chr->chr_write = tcp_chr_write;
@@ -2105,6 +2114,10 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
         s->connected = 1;
         s->fd = fd;
         socket_set_nodelay(fd);
+        if (s->do_keepalive && enable_tcp_keepalive(fd) != 0) {
+            fprintf(stderr,
+                    "failed to enable TCP keepalive probes on %d\n", fd);
+        }
         tcp_chr_connect(chr);
     }
 
diff --git a/qemu-options.hx b/qemu-options.hx
index aa786e3..a57e335 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1165,16 +1165,16 @@ telnet on port 5555 to access the qemu port.
 localhost 5555
 @end table
 
-@item tcp:[@var{host}]:@var{port}[,@var{server}][,nowait][,nodelay]
+@item tcp:[@var{host}]:@var{port}[,@var{server}][,nowait][,nodelay][,keepalive]
 The TCP Net Console has two modes of operation.  It can send the serial
 I/O to a location or wait for a connection from a location.  By default
 the TCP Net Console is sent to @var{host} at the @var{port}.  If you use
 the @var{server} option QEMU will wait for a client socket application
 to connect to the port before continuing, unless the @code{nowait}
 option was specified.  The @code{nodelay} option disables the Nagle buffering
-algorithm.  If @var{host} is omitted, 0.0.0.0 is assumed. Only
-one TCP connection at a time is accepted. You can use @code{telnet} to
-connect to the corresponding character device.
+algorithm.  The @code{keepalive} option enables TCP keepalives. If @var{host}
+is omitted, 0.0.0.0 is assumed. Only one TCP connection at a time is accepted.
+You can use @code{telnet} to connect to the corresponding character device.
 @table @code
 @item Example to send tcp console to 192.168.0.2 port 4444
 -serial tcp:192.168.0.2:4444
@@ -1184,7 +1184,7 @@ connect to the corresponding character device.
 -serial tcp:192.168.0.100:4444,server,nowait
 @end table
 
-@item telnet:@var{host}:@var{port}[,server][,nowait][,nodelay]
+@item telnet:@var{host}:@var{port}[,server][,nowait][,nodelay][,keepalive]
 The telnet protocol is used instead of raw tcp sockets.  The options
 work the same as if you had specified @code{-serial tcp}.  The
 difference is that the port acts like a telnet server or client using
diff --git a/vnc.c b/vnc.c
index ab1f044..52af93d 100644
--- a/vnc.c
+++ b/vnc.c
@@ -29,6 +29,7 @@
 #include "qemu_socket.h"
 #include "qemu-timer.h"
 #include "acl.h"
+#include "net.h"
 
 #define VNC_REFRESH_INTERVAL (1000 / 30)
 
@@ -2021,6 +2022,10 @@ static void vnc_listen_read(void *opaque)
 
     int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
     if (csock != -1) {
+        if (enable_tcp_keepalive(csock) != 0) {
+            fprintf(stderr, "VNC: failed to enable TCP keepalive probes\n");
+        }
+
         vnc_connect(vs, csock);
     }
 }

                 reply	other threads:[~2009-05-11  2:22 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A078BD9.3070507@cisco.com \
    --to=daahern@cisco.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.