From 5d61ded35bd94d9440aaccdd9bbe91ce94be7eb7 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Fri, 16 Sep 2011 15:53:37 +0800 Subject: [PATCH] tcp: Allow per-tcpcb keepintvl and keepcnt - 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 | 2 ++ sys/netinet/tcp_input.c | 2 +- sys/netinet/tcp_subr.c | 3 +++ sys/netinet/tcp_syncache.c | 3 +++ sys/netinet/tcp_timer.c | 15 +++++---------- sys/netinet/tcp_timer.h | 2 +- sys/netinet/tcp_timer2.h | 2 +- sys/netinet/tcp_usrreq.c | 27 ++++++++++++++++++++++++++- sys/netinet/tcp_var.h | 3 +++ 9 files changed, 45 insertions(+), 14 deletions(-) diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h index 08bd7450e8..070a0ec61f 100644 --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -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 diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index e240ad64a6..4535dfc6b7 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -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; } diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 112536299c..f846fffd8c 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -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); diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index f6f44a65fc..c4ec3d589f 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -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); diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 9729c2bf84..62bab700a2 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -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, diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index 78eac74ea7..93cec22c20 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -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; diff --git a/sys/netinet/tcp_timer2.h b/sys/netinet/tcp_timer2.h index 29bbd534ef..1f17080dd2 100644 --- a/sys/netinet/tcp_timer2.h +++ b/sys/netinet/tcp_timer2.h @@ -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); } diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 5f930f44c0..1631f3bcc9 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -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); } } diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index e271d29ced..fc9777fa5f 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -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) -- 2.41.0