qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] PATCH: enabling TCP keepalives v2


From: David Ahern
Subject: [Qemu-devel] PATCH: enabling TCP keepalives v2
Date: Tue, 28 Apr 2009 11:42:11 -0600
User-agent: Thunderbird 2.0.0.21 (X11/20090320)

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

Default parameters have keep alive probes sent after 60-seconds of idle
time. Probes are sent every 12 seconds with the connection resetting
after 5 failed probes (ie., connection is closed if no response received
in 60-seconds).

Changes v1 -> v2:
- Added probes to configure
- Moved setsockopt calls into a generic handler named
enable_tcp_keepalive in net.c
- Added call to enable_tcp_keepalive() to vnc and qemu-char

Signed-off-by: David Ahern <address@hidden>


david
diff --git a/configure b/configure
index 1cbeabc..b932fc3 100755
--- a/configure
+++ b/configure
@@ -1673,6 +1673,37 @@ 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
+cat > $TMPC << EOF
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+int main(void) {
+  int val = 1;
+  if (setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0)
+    return 1;
+  if (setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0)
+    return 1;
+  if (setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, &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_TCP_KEEPXXXX 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..bb85889 100644
--- a/net.c
+++ b/net.c
@@ -2209,3 +2209,36 @@ void net_client_check(void)
                     vlan->id);
     }
 }
+
+int enable_tcp_keepalive(int sd, int keepidle, int keepintvl, int keepcnt)
+{
+#ifdef HAVE_SO_KEEPALIVE
+    int val = 1;
+
+    if (setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) {
+               return -1;
+    }
+
+#ifdef HAVE_TCP_KEEPXXXX
+    val = keepidle;
+    if ((val > 0) &&
+           (setsockopt(sd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0)) 
{
+        fprintf(stderr, "failed to set tcp idle interval on fd %d\n", sd);
+    }
+
+    val = keepintvl;
+    if ((val > 0) &&
+        (setsockopt(sd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0)) {
+        fprintf(stderr, "failed to set tcp probe interval on fd %d\n", sd);
+    }
+
+    val = keepcnt;
+    if ((val > 0) &&
+        (setsockopt(sd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0)) {
+        fprintf(stderr, "failed to set tcp missed probe count on fd %d\n", sd);
+    }
+#endif
+#endif
+
+    return 0;
+}
diff --git a/net.h b/net.h
index cdf63a4..c7dbadf 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, int keepidle, int keepintvl, int keepcnt);
+
 #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..d52ca78 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -103,6 +103,15 @@
 
 #include "qemu_socket.h"
 
+/* timers for TCP keepalives: start probes after VNC_TCP_KEEPIDLE
+ * seconds of no activity, send probes every VNC_TCP_KEEPINTVL seconds,
+ * close connection after VNC_TCP_KEEPCNT failed probes
+ */
+#define CHAR_TCP_KEEPIDLE  60
+#define CHAR_TCP_KEEPIDLE  60
+#define CHAR_TCP_KEEPINTVL 12
+#define CHAR_TCP_KEEPCNT    5
+
 /***********************************************************/
 /* character device */
 
@@ -1990,6 +1999,10 @@ static void tcp_chr_accept(void *opaque)
         if (fd < 0 && errno != EINTR) {
             return;
         } else if (fd >= 0) {
+            if (enable_tcp_keepalive(fd, CHAR_TCP_KEEPIDLE,
+                                  CHAR_TCP_KEEPINTVL, CHAR_TCP_KEEPCNT) != 0) {
+                fprintf(stderr, "VNC: failed to enable TCP keep alives\n");
+            }
             if (s->do_telnetopt)
                 tcp_chr_telnet_init(fd);
             break;
diff --git a/vnc.c b/vnc.c
index ab1f044..c42cba9 100644
--- a/vnc.c
+++ b/vnc.c
@@ -32,6 +32,14 @@
 
 #define VNC_REFRESH_INTERVAL (1000 / 30)
 
+/* timers for TCP keepalives: start probes after VNC_TCP_KEEPIDLE
+ * seconds of no activity, send probes every VNC_TCP_KEEPINTVL seconds,
+ * close connection after VNC_TCP_KEEPCNT failed probes
+ */
+#define VNC_TCP_KEEPIDLE  60
+#define VNC_TCP_KEEPINTVL 12
+#define VNC_TCP_KEEPCNT    5
+
 #include "vnc_keysym.h"
 #include "d3des.h"
 
@@ -2021,6 +2029,11 @@ static void vnc_listen_read(void *opaque)
 
     int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
     if (csock != -1) {
+        if (enable_tcp_keepalive(csock, VNC_TCP_KEEPIDLE, 
+                                 VNC_TCP_KEEPINTVL, VNC_TCP_KEEPCNT) != 0) {
+            fprintf(stderr, "VNC: failed to enable TCP keep alives\n");
+        }
+
         vnc_connect(vs, csock);
     }
 }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]