Page MenuHomeFreeBSD

D14387.diff
No OneTemporary

D14387.diff

Index: sys/netinet/tcp_timer.h
===================================================================
--- sys/netinet/tcp_timer.h
+++ sys/netinet/tcp_timer.h
@@ -86,6 +86,7 @@
#define TCPTV_KEEP_IDLE (120*60*hz) /* dflt time before probing */
#define TCPTV_KEEPINTVL ( 75*hz) /* default probe interval */
#define TCPTV_KEEPCNT 8 /* max probes before drop */
+#define TCPTV_KEEPSLOP 2 /* idle time max % variance */
#define TCPTV_FINWAIT2_TIMEOUT (60*hz) /* FIN_WAIT_2 timeout if no receiver */
Index: sys/netinet/tcp_timer.c
===================================================================
--- sys/netinet/tcp_timer.c
+++ sys/netinet/tcp_timer.c
@@ -135,6 +135,10 @@
SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
"Number of keepalive probes to send");
+int tcp_keepslop = TCPTV_KEEPSLOP;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepslop, CTLFLAG_RW, &tcp_keepslop, 0,
+ "Percentage variance allowed in the idle time (0-100)");
+
/* max idle probes */
int tcp_maxpersistidle;
@@ -421,6 +425,7 @@
struct tcpcb *tp = xtp;
struct tcptemp *t_template;
struct inpcb *inp;
+ int earlytime, idletime;
CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
int ostate;
@@ -446,25 +451,6 @@
("%s: tp %p tcpcb can't be stopped here", __func__, tp));
/*
- * Because we don't regularly reset the keepalive callout in
- * the ESTABLISHED state, it may be that we don't actually need
- * to send a keepalive yet. If that occurs, schedule another
- * call for the next time the keepalive timer might expire.
- */
- if (TCPS_HAVEESTABLISHED(tp->t_state)) {
- u_int idletime;
-
- idletime = ticks - tp->t_rcvtime;
- if (idletime < TP_KEEPIDLE(tp)) {
- callout_reset(&tp->t_timers->tt_keep,
- TP_KEEPIDLE(tp) - idletime, tcp_timer_keep, tp);
- INP_WUNLOCK(inp);
- CURVNET_RESTORE();
- return;
- }
- }
-
- /*
* Keep-alive timer went off; send something
* or drop connection if idle for too long.
*/
@@ -474,9 +460,32 @@
if ((tcp_always_keepalive ||
inp->inp_socket->so_options & SO_KEEPALIVE) &&
tp->t_state <= TCPS_CLOSING) {
- if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp))
+ idletime = ticks - tp->t_rcvtime;
+
+ if (idletime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp))
goto dropit;
/*
+ * Because we don't regularly reset the keepalive callout in
+ * the ESTABLISHED state, it may be that we don't actually need
+ * to send a keepalive yet. If that occurs, schedule another
+ * call for the next time the keepalive timer might expire.
+ * However, to avoid unnecessarily rescheduling the keepalive
+ * timer to fire again in the very near future, let's proceed
+ * to send a keepalive early if we are "close" (as defined
+ * by tcp_keepslop) of the allowed time.
+ */
+ idletime = ticks - tp->t_rcvtime;
+ if (idletime < TP_KEEPIDLE(tp) -
+ tcp_keepslop * (TP_KEEPIDLE(tp) / 100)) {
+ callout_reset(&tp->t_timers->tt_keep,
+ TP_KEEPIDLE(tp) - idletime, tcp_timer_keep, tp);
+ goto done;
+ } else if (idletime < TP_KEEPIDLE(tp))
+ earlytime = TP_KEEPIDLE(tp) - idletime;
+ else
+ earlytime = 0;
+
+ /*
* Send a packet designed to force a response
* if the peer is up and reachable:
* either an ACK if the connection is still alive,
@@ -496,8 +505,8 @@
tp->rcv_nxt, tp->snd_una - 1, 0);
free(t_template, M_TEMP);
}
- callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp),
- tcp_timer_keep, tp);
+ callout_reset(&tp->t_timers->tt_keep,
+ TP_KEEPINTVL(tp) + earlytime, tcp_timer_keep, tp);
} else
callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp),
tcp_timer_keep, tp);
@@ -508,6 +517,7 @@
PRU_SLOWTIMO);
#endif
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
+done:
INP_WUNLOCK(inp);
CURVNET_RESTORE();
return;

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 21, 2:38 PM (2 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24021319
Default Alt Text
D14387.diff (3 KB)

Event Timeline