tcp: Allow per-tcpcb keepintvl and keepcnt
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 16 Sep 2011 07:53:37 +0000 (15:53 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 16 Sep 2011 07:53:37 +0000 (15:53 +0800)
- Expose tcp_keepcnt
- Add t_keepintvl, t_keepcnt and t_maxidle to tcpcb.  t_keepintvl and
  t_keepcnt is initialized to tcp_keepintvl and tcp_keepcnt respectively.
  t_maxidle is initialized to t_keepcnt * t_keepintvl
- The accepted socket's t_keepintvl, t_keepcnt and t_maxidle is inherited
  from the listen socket
- Add IPPROTO_TCP/TCP_KEEPINTVL and IPPROTO_TCP.TCP_KEEPCNT socket options
  to get and set t_keepintvl and t_keepcnt.  TCP_KEEPINTVL's unit is
  milliseconds, which is as same as the unit of the sysctl node
  net.inet.tcp.keepintvl
- Remove no longer used tcp_maxidle

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

index 08bd745..070a0ec 100644 (file)
@@ -164,5 +164,7 @@ struct tcphdr {
 /* 0x40 unused */
 #define TCP_FASTKEEP   0x80
 #define TCP_KEEPIDLE   0x100
+#define TCP_KEEPINTVL  0x200
+#define TCP_KEEPCNT    0x400
 
 #endif
index e240ad6..4535dfc 100644 (file)
@@ -2285,7 +2285,7 @@ process_ACK:
                                if (so->so_state & SS_CANTRCVMORE) {
                                        soisdisconnected(so);
                                        tcp_callout_reset(tp, tp->tt_2msl,
-                                           tcp_maxidle, tcp_timer_2msl);
+                                           tp->t_maxidle, tcp_timer_2msl);
                                }
                                tp->t_state = TCPS_FIN_WAIT_2;
                        }
index 1125362..f846fff 100644 (file)
@@ -696,6 +696,9 @@ tcp_newtcpcb(struct inpcb *inp)
 
        tp->t_keepinit = tcp_keepinit;
        tp->t_keepidle = tcp_keepidle;
+       tp->t_keepintvl = tcp_keepintvl;
+       tp->t_keepcnt = tcp_keepcnt;
+       tp->t_maxidle = tp->t_keepintvl * tp->t_keepcnt;
 
        if (tcp_do_rfc1323)
                tp->t_flags = (TF_REQ_SCALE | TF_REQ_TSTMP);
index f6f44a6..c4ec3d5 100644 (file)
@@ -865,6 +865,9 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
        ltp = intotcpcb(linp);
        tp->t_keepinit = ltp->t_keepinit;
        tp->t_keepidle = ltp->t_keepidle;
+       tp->t_keepintvl = ltp->t_keepintvl;
+       tp->t_keepcnt = ltp->t_keepcnt;
+       tp->t_maxidle = ltp->t_maxidle;
 
        tcp_create_timermsg(tp, port);
        tcp_callout_reset(tp, tp->tt_keep, tp->t_keepinit, tcp_timer_keep);
index 9729c2b..62bab70 100644 (file)
@@ -187,15 +187,13 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW,
     &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections");
 
 /* max idle probes */
-static int     tcp_keepcnt = TCPTV_KEEPCNT;
+int    tcp_keepcnt = TCPTV_KEEPCNT;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW,
     &tcp_keepcnt, 0, "Maximum number of keepalive probes to be sent");
 
 /* max idle time in persist */
 int    tcp_maxpersistidle;
 
-int    tcp_maxidle;
-
 /*
  * Tcp protocol timeout routine called every 500 ms.
  * Updates timestamps used for TCP
@@ -204,9 +202,6 @@ int tcp_maxidle;
 void
 tcp_slowtimo(void)
 {
-       crit_enter();
-       tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
-       crit_exit();
 }
 
 /*
@@ -292,8 +287,8 @@ tcp_timer_2msl_handler(struct tcpcb *tp)
         * control block.  Otherwise, check again in a bit.
         */
        if (tp->t_state != TCPS_TIME_WAIT &&
-           (ticks - tp->t_rcvtime) <= tcp_maxidle) {
-               tcp_callout_reset(tp, tp->tt_2msl, tcp_keepintvl,
+           (ticks - tp->t_rcvtime) <= tp->t_maxidle) {
+               tcp_callout_reset(tp, tp->tt_2msl, tp->t_keepintvl,
                                  tcp_timer_2msl);
        } else {
                tp = tcp_close(tp);
@@ -345,7 +340,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) >= keepidle + tcp_maxidle)
+               if ((ticks - tp->t_rcvtime) >= keepidle + tp->t_maxidle)
                        goto dropit;
                /*
                 * Send a packet designed to force a response
@@ -367,7 +362,7 @@ tcp_timer_keep_handler(struct tcpcb *tp)
                                    tp->rcv_nxt, tp->snd_una - 1, 0);
                        tcp_freetemplate(t_template);
                }
-               tcp_callout_reset(tp, tp->tt_keep, tcp_keepintvl,
+               tcp_callout_reset(tp, tp->tt_keep, tp->t_keepintvl,
                                  tcp_timer_keep);
        } else {
                tcp_callout_reset(tp, tp->tt_keep, keepidle,
index 78eac74..93cec22 100644 (file)
@@ -149,7 +149,7 @@ struct tcp_callout {
 extern int tcp_keepinit;               /* time to establish connection */
 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 */
+extern int tcp_keepcnt;                        /* aximum number of keepalive probes */
 extern int tcp_delacktime;             /* time before sending a delayed ACK */
 extern int tcp_maxpersistidle;
 extern int tcp_rexmit_min;
index 29bbd53..1f17080 100644 (file)
@@ -72,7 +72,7 @@ static __inline int
 tcp_getkeepidle(struct tcpcb *_tp)
 {
        if (_tp->t_flags & TF_FASTKEEP)
-               return (tcp_keepintvl);
+               return (_tp->t_keepintvl);
        else
                return (_tp->t_keepidle);
 }
index 5f930f4..1631f3b 100644 (file)
@@ -1437,6 +1437,25 @@ tcp_ctloutput(netmsg_t msg)
                                error = EINVAL;
                        break;
 
+               case TCP_KEEPINTVL:
+                       opthz = ((int64_t)optval * hz) / 1000;
+                       if (opthz >= 1) {
+                               tp->t_keepintvl = opthz;
+                               tp->t_maxidle = tp->t_keepintvl * tp->t_keepcnt;
+                       } else {
+                               error = EINVAL;
+                       }
+                       break;
+
+               case TCP_KEEPCNT:
+                       if (optval > 0) {
+                               tp->t_keepcnt = optval;
+                               tp->t_maxidle = tp->t_keepintvl * tp->t_keepcnt;
+                       } else {
+                               error = EINVAL;
+                       }
+                       break;
+
                default:
                        error = ENOPROTOOPT;
                        break;
@@ -1468,6 +1487,12 @@ tcp_ctloutput(netmsg_t msg)
                case TCP_KEEPIDLE:
                        optval = ((int64_t)tp->t_keepidle * 1000) / hz;
                        break;
+               case TCP_KEEPINTVL:
+                       optval = ((int64_t)tp->t_keepintvl * 1000) / hz;
+                       break;
+               case TCP_KEEPCNT:
+                       optval = tp->t_keepcnt;
+                       break;
                default:
                        error = ENOPROTOOPT;
                        break;
@@ -1626,7 +1651,7 @@ tcp_usrclosed(struct tcpcb *tp)
                soisdisconnected(tp->t_inpcb->inp_socket);
                /* To prevent the connection hanging in FIN_WAIT_2 forever. */
                if (tp->t_state == TCPS_FIN_WAIT_2) {
-                       tcp_callout_reset(tp, tp->tt_2msl, tcp_maxidle,
+                       tcp_callout_reset(tp, tp->tt_2msl, tp->t_maxidle,
                            tcp_timer_2msl);
                }
        }
index e271d29..fc9777f 100644 (file)
@@ -273,6 +273,9 @@ struct tcpcb {
        int     t_keepinit;
 
        int     t_keepidle;
+       int     t_keepintvl;
+       int     t_keepcnt;
+       int     t_maxidle;
 };
 
 #define        IN_FASTRECOVERY(tp)     (tp->t_flags & TF_FASTRECOVERY)