network - Add a tcp socket for faster keepalive timeouts
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 24 Sep 2010 05:35:16 +0000 (22:35 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 24 Sep 2010 05:35:16 +0000 (22:35 -0700)
* Add a new socket opt, TCP_FASTKEEP, which enables faster keepalive
  timeouts on a tcp socket.  This will be used by NFS.

sys/netinet/tcp.h
sys/netinet/tcp_input.c
sys/netinet/tcp_timer.c
sys/netinet/tcp_timer2.h
sys/netinet/tcp_usrreq.c
sys/netinet/tcp_var.h
sys/sys/socket.h

index 7caa576..067addd 100644 (file)
@@ -163,5 +163,6 @@ struct tcphdr {
 #define TCP_NOPUSH     0x04    /* don't push last block of write */
 #define TCP_NOOPT      0x08    /* don't use TCP options */
 #define TCP_SIGNATURE_ENABLE    0x10    /* use MD5 digests (RFC2385) */
+#define TCP_FASTKEEP   0x80
 
 #endif
index f2f79a1..cdb09c4 100644 (file)
@@ -1124,7 +1124,8 @@ after_listen:
                } else {
                        tp->t_rcvtime = ticks;
                        tp->t_flags &= ~TF_KEEPALIVE;
-                       tcp_callout_reset(tp, tp->tt_keep, tcp_keepidle,
+                       tcp_callout_reset(tp, tp->tt_keep,
+                                         tcp_getkeepidle(tp),
                                          tcp_timer_keep);
                }
        }
@@ -1523,8 +1524,9 @@ after_listen:
                                thflags &= ~TH_SYN;
                        } else {
                                tp->t_state = TCPS_ESTABLISHED;
-                               tcp_callout_reset(tp, tp->tt_keep, tcp_keepidle,
-                                   tcp_timer_keep);
+                               tcp_callout_reset(tp, tp->tt_keep,
+                                                 tcp_getkeepidle(tp),
+                                                 tcp_timer_keep);
                        }
                } else {
                        /*
@@ -1896,8 +1898,9 @@ trimthenstep6:
                        tp->t_flags &= ~TF_NEEDFIN;
                } else {
                        tp->t_state = TCPS_ESTABLISHED;
-                       tcp_callout_reset(tp, tp->tt_keep, tcp_keepidle,
-                           tcp_timer_keep);
+                       tcp_callout_reset(tp, tp->tt_keep,
+                                         tcp_getkeepidle(tp),
+                                         tcp_timer_keep);
                }
                /*
                 * If segment contains data or ACK, will call tcp_reass()
index eb45646..444cf82 100644 (file)
@@ -326,6 +326,7 @@ tcp_timer_keep_handler(struct tcpcb *tp)
 #ifdef TCPDEBUG
        int ostate;
 #endif
+       int keepidle = tcp_getkeepidle(tp);
 
 #ifdef TCPDEBUG
        ostate = tp->t_state;
@@ -340,7 +341,7 @@ tcp_timer_keep_handler(struct tcpcb *tp)
        if ((always_keepalive || (tp->t_flags & TF_KEEPALIVE) ||
             (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE)) &&
            tp->t_state <= TCPS_CLOSING) {
-               if ((ticks - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle)
+               if ((ticks - tp->t_rcvtime) >= keepidle + tcp_maxidle)
                        goto dropit;
                /*
                 * Send a packet designed to force a response
@@ -365,7 +366,7 @@ tcp_timer_keep_handler(struct tcpcb *tp)
                tcp_callout_reset(tp, tp->tt_keep, tcp_keepintvl,
                                  tcp_timer_keep);
        } else {
-               tcp_callout_reset(tp, tp->tt_keep, tcp_keepidle,
+               tcp_callout_reset(tp, tp->tt_keep, keepidle,
                                  tcp_timer_keep);
        }
 
index 32abc96..2ac6501 100644 (file)
 #include <netinet/tcp_timer.h>
 #endif
 
+/*
+ * The TCP_FASTKEEP option uses keepintvl for the initial keepidle timeout
+ * instead of keepidle.
+ */
+static __inline int
+tcp_getkeepidle(struct tcpcb *_tp)
+{
+       if (_tp->t_flags & TF_FASTKEEP)
+               return (tcp_keepintvl);
+       else
+               return (tcp_keepidle);
+}
+
 static __inline void
 tcp_callout_stop(struct tcpcb *_tp, struct tcp_callout *_tc)
 {
index a1d30d2..667fee1 100644 (file)
@@ -1312,6 +1312,12 @@ tcp_ctloutput(netmsg_t msg)
                if (error)
                        break;
                switch (sopt->sopt_name) {
+               case TCP_FASTKEEP:
+                       if (optval > 0)
+                               tp->t_flags |= TF_FASTKEEP;
+                       else
+                               tp->t_flags &= ~TF_FASTKEEP;
+                       break;
 #ifdef TCP_SIGNATURE
                case TCP_SIGNATURE_ENABLE:
                        if (optval > 0)
index 20810b9..abab982 100644 (file)
@@ -160,7 +160,8 @@ struct tcpcb {
 #define        TF_NEEDFIN      0x00000800      /* send FIN (implicit state) */
 #define        TF_NOPUSH       0x00001000      /* don't push */
 #define TF_SYNCACHE    0x00002000      /* syncache present */
-#define TF_SIGNATURE 0x00004000  /* require MD5 digests (RFC2385) */
+#define TF_SIGNATURE   0x00004000      /* require MD5 digests (RFC2385) */
+#define TF_FASTKEEP    0x00008000      /* use a faster tcp_keepidle */
 #define        TF_MORETOCOME   0x00010000      /* More data to be appended to sock */
 #define        TF_LQ_OVERFLOW  0x00020000      /* listen queue overflow */
 #define        TF_LASTIDLE     0x00040000      /* connection was previously idle */
index 0acc34e..a41c30d 100644 (file)
@@ -89,6 +89,7 @@ typedef __socklen_t   socklen_t;
 #define        SO_OOBINLINE    0x0100          /* leave received OOB data in line */
 #define        SO_REUSEPORT    0x0200          /* allow local address & port reuse */
 #define        SO_TIMESTAMP    0x0400          /* timestamp received dgram traffic */
+#define SO_UNUSED0800  0x0800
 #define        SO_ACCEPTFILTER 0x1000          /* there is an accept filter */
 
 /*