add sysctl net.inet.tcp.always_keepalive, setting this to 1 acts
as if SO_KEEPALIVE were set on all TCP sockets.

based on code added to FreeBSD ~15 years ago, these days it's
enabled by default there and in dfbsd, here I've left the default
as being disabled.

useful for a client machine behind a NAT gateway or similar that
times out on inactivity too quickly, possibly removing the need for
the NOOP hack in ftp(1).

also useful on servers if you accumulate connections from
users whose net has gone away (for services not already setting
SO_KEEPALIVE).

for an easily-visible test, you could set something like this,
make a tcp connection and obverse network traffic with tcpdump.

net.inet.tcp.always_keepalive=1
net.inet.tcp.keepidle=28
net.inet.tcp.keepintvl=7

(N.B. unless my diff #1 is applied, keepintvtl will be ignored and
only keepidle will take effect).

keepidle/keepintvl values are in "net.inet.tcp.slowhz intervals
per second", i.e. usually half-seconds.

typical values for a client using this to keep NAT state alive
would be a bit higher e.g. maybe keepidle=300, keepintvtl=60

typical conservative values for a server would be something more
like the defaults.

comments?
ok?


Index: sys/netinet/tcp_timer.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_timer.c,v
retrieving revision 1.45
diff -u -p -r1.45 tcp_timer.c
--- sys/netinet/tcp_timer.c     3 Jul 2010 04:44:51 -0000       1.45
+++ sys/netinet/tcp_timer.c     14 Jun 2011 15:24:24 -0000
@@ -55,6 +55,7 @@
 #include <netinet/ip_icmp.h>
 #include <netinet/tcp_seq.h>
 
+int    tcp_always_keepalive;
 int    tcp_keepidle;
 int    tcp_keepintvl;
 int    tcp_maxpersistidle;     /* max idle time in persist */
@@ -435,7 +436,8 @@ tcp_timer_keep(void *arg)
        tcpstat.tcps_keeptimeo++;
        if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)
                goto dropit;
-       if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
+       if ((tcp_always_keepalive ||
+           tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
            tp->t_state <= TCPS_CLOSING) {
                if ((tcp_maxidle > 0) &&
                    ((tcp_now - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle))
Index: sys/netinet/tcp_timer.h
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_timer.h,v
retrieving revision 1.12
diff -u -p -r1.12 tcp_timer.h
--- sys/netinet/tcp_timer.h     8 Nov 2008 12:54:58 -0000       1.12
+++ sys/netinet/tcp_timer.h     14 Jun 2011 15:24:24 -0000
@@ -145,6 +145,7 @@ typedef void (*tcp_timer_func_t)(void *)
 extern const tcp_timer_func_t tcp_timer_funcs[TCPT_NTIMERS];
 
 extern int tcptv_keep_init;
+extern int tcp_always_keepalive;       /* assume SO_KEEPALIVE is always set */
 extern int tcp_keepidle;               /* time before keepalive probes begin */
 extern int tcp_keepintvl;              /* time between keepalive probes */
 extern int tcp_maxidle;                        /* time to drop after starting 
probes */
Index: sys/netinet/tcp_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.98
diff -u -p -r1.98 tcp_var.h
--- sys/netinet/tcp_var.h       7 Jan 2011 17:50:42 -0000       1.98
+++ sys/netinet/tcp_var.h       14 Jun 2011 15:24:24 -0000
@@ -473,7 +473,8 @@ struct      tcpstat {
 #define        TCPCTL_DROP            19 /* drop tcp connection */
 #define        TCPCTL_SACKHOLE_LIMIT  20 /* max entries for tcp sack queues */
 #define        TCPCTL_STATS           21 /* TCP statistics */
-#define        TCPCTL_MAXID           22
+#define TCPCTL_ALWAYS_KEEPALIVE 22 /* assume SO_KEEPALIVE is always set */
+#define        TCPCTL_MAXID           23
 
 #define        TCPCTL_NAMES { \
        { 0, 0 }, \
@@ -497,7 +498,8 @@ struct      tcpstat {
        { "reasslimit",         CTLTYPE_INT }, \
        { "drop",       CTLTYPE_STRUCT }, \
        { "sackholelimit",      CTLTYPE_INT }, \
-       { "stats",      CTLTYPE_STRUCT } \
+       { "stats",      CTLTYPE_STRUCT }, \
+       { "always_keepalive",   CTLTYPE_INT } \
 }
 
 #define        TCPCTL_VARS { \
Index: sbin/sysctl/sysctl.8
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.8,v
retrieving revision 1.158
diff -u -p -r1.158 sysctl.8
--- sbin/sysctl/sysctl.8        23 May 2011 07:18:45 -0000      1.158
+++ sbin/sysctl/sysctl.8        14 Jun 2011 15:24:24 -0000
@@ -257,6 +257,7 @@ and a few require a kernel compiled with
 .It net.inet.tcp.keepinittime  integer yes
 .It net.inet.tcp.keepidle      integer yes
 .It net.inet.tcp.keepintvl     integer yes
+.It net.inet.tcp.always_keepalive      integer yes
 .It net.inet.tcp.slowhz        integer no
 .It net.inet.tcp.baddynamic    array   yes
 .It net.inet.tcp.sack  integer yes

Reply via email to