/* 0x40 unused */
#define TCP_FASTKEEP 0x80
#define TCP_KEEPIDLE 0x100
+#define TCP_KEEPINTVL 0x200
+#define TCP_KEEPCNT 0x400
#endif
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;
}
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);
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);
&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
void
tcp_slowtimo(void)
{
- crit_enter();
- tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
- crit_exit();
}
/*
* 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);
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
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,
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;
tcp_getkeepidle(struct tcpcb *_tp)
{
if (_tp->t_flags & TF_FASTKEEP)
- return (tcp_keepintvl);
+ return (_tp->t_keepintvl);
else
return (_tp->t_keepidle);
}
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;
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;
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);
}
}
int t_keepinit;
int t_keepidle;
+ int t_keepintvl;
+ int t_keepcnt;
+ int t_maxidle;
};
#define IN_FASTRECOVERY(tp) (tp->t_flags & TF_FASTRECOVERY)