Page MenuHomeFreeBSD

D36716.id110995.diff
No OneTemporary

D36716.id110995.diff

Index: sys/netinet/tcp_timer.h
===================================================================
--- sys/netinet/tcp_timer.h
+++ sys/netinet/tcp_timer.h
@@ -86,7 +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_MAXUNACKTIME 0 /* max time without making progress */
#define TCPTV_FINWAIT2_TIMEOUT (60*hz) /* FIN_WAIT_2 timeout if no receiver */
/*
@@ -183,6 +183,9 @@
#define TP_KEEPINTVL(tp) ((tp)->t_keepintvl ? (tp)->t_keepintvl : tcp_keepintvl)
#define TP_KEEPCNT(tp) ((tp)->t_keepcnt ? (tp)->t_keepcnt : tcp_keepcnt)
#define TP_MAXIDLE(tp) (TP_KEEPCNT(tp) * TP_KEEPINTVL(tp))
+#define TP_MAXUNACKTIME(tp) \
+ ((tp)->t_maxunacktime ? (tp)->t_maxunacktime : tcp_maxunacktime)
+
extern int tcp_persmin; /* minimum persist interval */
extern int tcp_persmax; /* maximum persist interval */
@@ -191,6 +194,7 @@
extern int tcp_keepintvl; /* time between keepalive probes */
extern int tcp_keepcnt; /* number of keepalives */
extern int tcp_delacktime; /* time before sending a delayed ACK */
+extern int tcp_maxunacktime; /* max time without making progress */
extern int tcp_maxpersistidle;
extern int tcp_rexmit_initial;
extern int tcp_rexmit_min;
Index: sys/netinet/tcp_timer.c
===================================================================
--- sys/netinet/tcp_timer.c
+++ sys/netinet/tcp_timer.c
@@ -167,6 +167,12 @@
&tcp_rexmit_drop_options, 0,
"Drop TCP options from 3rd and later retransmitted SYN");
+int tcp_maxunacktime = TCPTV_MAXUNACKTIME;
+SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxunacktime,
+ CTLTYPE_INT|CTLFLAG_RW | CTLFLAG_NEEDGIANT,
+ &tcp_maxunacktime, 0, sysctl_msec_to_ticks, "I",
+ "Maximum time (in ms) that a session can linger without making progress");
+
VNET_DEFINE(int, tcp_pmtud_blackhole_detect);
SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
CTLFLAG_RW|CTLFLAG_VNET,
@@ -503,12 +509,38 @@
CURVNET_RESTORE();
}
+/*
+ * Has this session exceeded the maximum time without seeing a substantive
+ * acknowledgement? If so, return true; otherwise false.
+ */
+static bool
+tcp_maxunacktime_check(struct tcpcb *tp)
+{
+
+ /* Are we tracking this timer for this session? */
+ if (TP_MAXUNACKTIME(tp) == 0)
+ return false;
+
+ /* Do we have a current measurement. */
+ if (tp->t_acktime == 0)
+ return false;
+
+ /* Are we within the acceptable range? */
+ if (TSTMP_GT(TP_MAXUNACKTIME(tp) + tp->t_acktime, (u_int)ticks))
+ return false;
+
+ /* We exceeded the timer. */
+ TCPSTAT_INC(tcps_progdrops);
+ return true;
+}
+
void
tcp_timer_persist(void *xtp)
{
struct tcpcb *tp = xtp;
struct inpcb *inp;
struct epoch_tracker et;
+ bool progdrop;
int outrv;
CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
@@ -545,10 +577,12 @@
* (no responses to probes) reaches the maximum
* backoff that we would use if retransmitting.
*/
- if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
+ progdrop = tcp_maxunacktime_check(tp);
+ if (progdrop || (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
(ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
- ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
- TCPSTAT_INC(tcps_persistdrop);
+ ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff))) {
+ if (!progdrop)
+ TCPSTAT_INC(tcps_persistdrop);
NET_EPOCH_ENTER(et);
tp = tcp_drop(tp, ETIMEDOUT);
NET_EPOCH_EXIT(et);
@@ -626,8 +660,12 @@
* Retransmission timer went off. Message has not
* been acked within retransmit interval. Back off
* to a longer retransmit interval and retransmit one segment.
+ *
+ * If we've either exceeded the maximum number of retransmissions,
+ * or we've gone long enough without making progress, then drop
+ * the session.
*/
- if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
+ if (++tp->t_rxtshift > TCP_MAXRXTSHIFT || tcp_maxunacktime_check(tp)) {
tp->t_rxtshift = TCP_MAXRXTSHIFT;
TCPSTAT_INC(tcps_timeoutdrop);
NET_EPOCH_ENTER(et);
Index: sys/netinet/tcp_usrreq.c
===================================================================
--- sys/netinet/tcp_usrreq.c
+++ sys/netinet/tcp_usrreq.c
@@ -2375,7 +2375,7 @@
error = ktls_enable_rx(so, &tls);
break;
#endif
-
+ case TCP_MAXUNACKTIME:
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
case TCP_KEEPINIT:
@@ -2392,6 +2392,10 @@
INP_WLOCK_RECHECK(inp);
switch (sopt->sopt_name) {
+ case TCP_MAXUNACKTIME:
+ tp->t_maxunacktime = ui;
+ break;
+
case TCP_KEEPIDLE:
tp->t_keepidle = ui;
/*
@@ -2658,11 +2662,15 @@
INP_WUNLOCK(inp);
error = sooptcopyout(sopt, buf, len + 1);
break;
+ case TCP_MAXUNACKTIME:
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
case TCP_KEEPINIT:
case TCP_KEEPCNT:
switch (sopt->sopt_name) {
+ case TCP_MAXUNACKTIME:
+ ui = TP_MAXUNACKTIME(tp) / hz;
+ break;
case TCP_KEEPIDLE:
ui = TP_KEEPIDLE(tp) / hz;
break;
Index: sys/netinet/tcp_var.h
===================================================================
--- sys/netinet/tcp_var.h
+++ sys/netinet/tcp_var.h
@@ -707,6 +707,7 @@
uint64_t tcps_keeptimeo; /* keepalive timeouts */
uint64_t tcps_keepprobe; /* keepalive probes sent */
uint64_t tcps_keepdrops; /* connections dropped in keepalive */
+ uint64_t tcps_progdrops; /* drops due to no progress */
uint64_t tcps_sndtotal; /* total packets sent */
uint64_t tcps_sndpack; /* data packets sent */

File Metadata

Mime Type
text/plain
Expires
Sun, May 17, 8:27 PM (7 h, 57 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33207747
Default Alt Text
D36716.id110995.diff (5 KB)

Event Timeline