From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LzuAR-00010d-Cl for qemu-devel@nongnu.org; Fri, 01 May 2009 10:56:47 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LzuAN-0000zU-RV for qemu-devel@nongnu.org; Fri, 01 May 2009 10:56:47 -0400 Received: from [199.232.76.173] (port=37952 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LzuAN-0000zD-Mk for qemu-devel@nongnu.org; Fri, 01 May 2009 10:56:43 -0400 Received: from wf-out-1314.google.com ([209.85.200.171]:43127) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LzuAN-0004tu-4D for qemu-devel@nongnu.org; Fri, 01 May 2009 10:56:43 -0400 Received: by wf-out-1314.google.com with SMTP id 26so1823317wfd.4 for ; Fri, 01 May 2009 07:56:42 -0700 (PDT) Message-ID: <49FB0DA5.9070807@gmail.com> Date: Fri, 01 May 2009 08:56:37 -0600 From: David Ahern MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050409080501010004050509" Subject: [Qemu-devel] PATCH: enabling TCP keepalives - v4 List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, Anthony Liguori , "Richard W.M. Jones" This is a multi-part message in MIME format. --------------050409080501010004050509 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 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 v3 -> v4 Fixed warning introduced in vnc.c Signed-off-by: David Ahern Rich: BTW, this should not have any impacts to migration; it only enables keepalives for VNC and TCP-based char devices. david --------------050409080501010004050509 Content-Type: text/plain; name="enable-tcp-keepalives-v4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="enable-tcp-keepalives-v4.patch" diff --git a/configure b/configure index 82fb60a..41ba86a 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 +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 +#include +#include +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..e1411c4 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -103,6 +103,14 @@ #include "qemu_socket.h" +/* timers for TCP keepalives: start probes after CHAR_TCP_KEEPIDLE + * seconds of no activity, send probes every CHAR_TCP_KEEPINTVL seconds, + * close connection after CHAR_TCP_KEEPCNT failed probes + */ +#define CHAR_TCP_KEEPIDLE 60 +#define CHAR_TCP_KEEPINTVL 12 +#define CHAR_TCP_KEEPCNT 5 + /***********************************************************/ /* character device */ @@ -1990,6 +1998,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..166eac0 100644 --- a/vnc.c +++ b/vnc.c @@ -29,9 +29,18 @@ #include "qemu_socket.h" #include "qemu-timer.h" #include "acl.h" +#include "net.h" #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 +2030,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); } } --------------050409080501010004050509--