From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lzc7r-0008Kk-KR for qemu-devel@nongnu.org; Thu, 30 Apr 2009 15:40:55 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lzc7m-0008Dj-HJ for qemu-devel@nongnu.org; Thu, 30 Apr 2009 15:40:54 -0400 Received: from [199.232.76.173] (port=44433 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lzc7m-0008DX-7T for qemu-devel@nongnu.org; Thu, 30 Apr 2009 15:40:50 -0400 Received: from rv-out-0708.google.com ([209.85.198.243]:8305) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Lzc7l-0002ct-Ko for qemu-devel@nongnu.org; Thu, 30 Apr 2009 15:40:49 -0400 Received: by rv-out-0708.google.com with SMTP id c5so1312680rvf.22 for ; Thu, 30 Apr 2009 12:40:48 -0700 (PDT) Message-ID: <49F9FEBA.6050901@gmail.com> Date: Thu, 30 Apr 2009 13:40:42 -0600 From: David Ahern MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------060104050102000408060901" Subject: [Qemu-devel] PATCH: enabling TCP keepalives - v3 List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------060104050102000408060901 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Did not see a response to the last version. 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 v2 -> v3 Removed duplicate definition and fixed typo in comments. Signed-off-by: David Ahern david --------------060104050102000408060901 Content-Type: text/plain; name="enable-tcp-keepalives-v3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="enable-tcp-keepalives-v3.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..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); } } --------------060104050102000408060901--