Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_timer.c
Show First 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0, | ||||
/* max idle probes */ | /* max idle probes */ | ||||
int tcp_maxpersistidle; | int tcp_maxpersistidle; | ||||
int tcp_rexmit_drop_options = 0; | int tcp_rexmit_drop_options = 0; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW, | ||||
&tcp_rexmit_drop_options, 0, | &tcp_rexmit_drop_options, 0, | ||||
"Drop TCP options from 3rd and later retransmitted SYN"); | "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); | VNET_DEFINE(int, tcp_pmtud_blackhole_detect); | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection, | ||||
CTLFLAG_RW|CTLFLAG_VNET, | CTLFLAG_RW|CTLFLAG_VNET, | ||||
&VNET_NAME(tcp_pmtud_blackhole_detect), 0, | &VNET_NAME(tcp_pmtud_blackhole_detect), 0, | ||||
"Path MTU Discovery Black Hole Detection Enabled"); | "Path MTU Discovery Black Hole Detection Enabled"); | ||||
#ifdef INET | #ifdef INET | ||||
VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200; | VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200; | ||||
▲ Show 20 Lines • Show All 322 Lines • ▼ Show 20 Lines | tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, | ||||
PRU_SLOWTIMO); | PRU_SLOWTIMO); | ||||
#endif | #endif | ||||
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); | TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
tcp_inpinfo_lock_del(inp, tp); | tcp_inpinfo_lock_del(inp, tp); | ||||
CURVNET_RESTORE(); | 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 | void | ||||
tcp_timer_persist(void *xtp) | tcp_timer_persist(void *xtp) | ||||
{ | { | ||||
struct tcpcb *tp = xtp; | struct tcpcb *tp = xtp; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
bool progdrop; | |||||
int outrv; | int outrv; | ||||
CURVNET_SET(tp->t_vnet); | CURVNET_SET(tp->t_vnet); | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
int ostate; | int ostate; | ||||
ostate = tp->t_state; | ostate = tp->t_state; | ||||
#endif | #endif | ||||
inp = tp->t_inpcb; | inp = tp->t_inpcb; | ||||
Show All 19 Lines | #endif | ||||
*/ | */ | ||||
TCPSTAT_INC(tcps_persisttimeo); | TCPSTAT_INC(tcps_persisttimeo); | ||||
/* | /* | ||||
* Hack: if the peer is dead/unreachable, we do not | * Hack: if the peer is dead/unreachable, we do not | ||||
* time out if the window is closed. After a full | * time out if the window is closed. After a full | ||||
* backoff, drop the connection if the idle time | * backoff, drop the connection if the idle time | ||||
* (no responses to probes) reaches the maximum | * (no responses to probes) reaches the maximum | ||||
* backoff that we would use if retransmitting. | * backoff that we would use if retransmitting. | ||||
* Also, drop the connection if we haven't been making | |||||
* progress. | |||||
*/ | */ | ||||
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_maxpersistidle || | ||||
ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) { | ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff))) { | ||||
if (!progdrop) | |||||
TCPSTAT_INC(tcps_persistdrop); | TCPSTAT_INC(tcps_persistdrop); | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX); | tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX); | ||||
tp = tcp_drop(tp, ETIMEDOUT); | tp = tcp_drop(tp, ETIMEDOUT); | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
tcp_inpinfo_lock_del(inp, tp); | tcp_inpinfo_lock_del(inp, tp); | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | #endif | ||||
if (tp->t_fb->tfb_tcp_rexmit_tmr) { | if (tp->t_fb->tfb_tcp_rexmit_tmr) { | ||||
/* The stack has a timer action too. */ | /* The stack has a timer action too. */ | ||||
(*tp->t_fb->tfb_tcp_rexmit_tmr)(tp); | (*tp->t_fb->tfb_tcp_rexmit_tmr)(tp); | ||||
} | } | ||||
/* | /* | ||||
* Retransmission timer went off. Message has not | * Retransmission timer went off. Message has not | ||||
* been acked within retransmit interval. Back off | * been acked within retransmit interval. Back off | ||||
* to a longer retransmit interval and retransmit one segment. | * 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; | if (tp->t_rxtshift > TCP_MAXRXTSHIFT) | ||||
TCPSTAT_INC(tcps_timeoutdrop); | TCPSTAT_INC(tcps_timeoutdrop); | ||||
tp->t_rxtshift = TCP_MAXRXTSHIFT; | |||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
tcp_log_end_status(tp, TCP_EI_STATUS_RETRAN); | tcp_log_end_status(tp, TCP_EI_STATUS_RETRAN); | ||||
tp = tcp_drop(tp, ETIMEDOUT); | tp = tcp_drop(tp, ETIMEDOUT); | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
tcp_inpinfo_lock_del(inp, tp); | tcp_inpinfo_lock_del(inp, tp); | ||||
goto out; | goto out; | ||||
} | } | ||||
if (tp->t_state == TCPS_SYN_SENT) { | if (tp->t_state == TCPS_SYN_SENT) { | ||||
▲ Show 20 Lines • Show All 479 Lines • Show Last 20 Lines |