Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_timer.c
Show First 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | tcp_timer_delack(void *xtp) | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
void | void | ||||
tcp_timer_2msl(void *xtp) | tcp_timer_2msl(void *xtp) | ||||
{ | { | ||||
struct tcpcb *tp = xtp; | struct tcpcb *tp = xtp; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
void *cookie; | |||||
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_INFO_RLOCK(&V_tcbinfo); | INP_INFO_EBR_RLOCK(&V_tcbinfo); | ||||
inp = tp->t_inpcb; | inp = tp->t_inpcb; | ||||
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
tcp_free_sackholes(tp); | tcp_free_sackholes(tp); | ||||
if (callout_pending(&tp->t_timers->tt_2msl) || | if (callout_pending(&tp->t_timers->tt_2msl) || | ||||
!callout_active(&tp->t_timers->tt_2msl)) { | !callout_active(&tp->t_timers->tt_2msl)) { | ||||
INP_WUNLOCK(tp->t_inpcb); | INP_WUNLOCK(tp->t_inpcb); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
callout_deactivate(&tp->t_timers->tt_2msl); | callout_deactivate(&tp->t_timers->tt_2msl); | ||||
if ((inp->inp_flags & INP_DROPPED) != 0) { | if ((inp->inp_flags & INP_DROPPED) != 0) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | ||||
("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ||||
KASSERT((tp->t_timers->tt_flags & TT_2MSL) != 0, | KASSERT((tp->t_timers->tt_flags & TT_2MSL) != 0, | ||||
("%s: tp %p 2msl callout should be running", __func__, tp)); | ("%s: tp %p 2msl callout should be running", __func__, tp)); | ||||
/* | /* | ||||
* 2 MSL timeout in shutdown went off. If we're closed but | * 2 MSL timeout in shutdown went off. If we're closed but | ||||
* still waiting for peer to close and connection has been idle | * still waiting for peer to close and connection has been idle | ||||
* too long delete connection control block. Otherwise, check | * too long delete connection control block. Otherwise, check | ||||
* again in a bit. | * again in a bit. | ||||
* | * | ||||
* If in TIME_WAIT state just ignore as this timeout is handled in | * If in TIME_WAIT state just ignore as this timeout is handled in | ||||
* tcp_tw_2msl_scan(). | * tcp_tw_2msl_scan(). | ||||
* | * | ||||
* If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed, | * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed, | ||||
* there's no point in hanging onto FIN_WAIT_2 socket. Just close it. | * there's no point in hanging onto FIN_WAIT_2 socket. Just close it. | ||||
* Ignore fact that there were recent incoming segments. | * Ignore fact that there were recent incoming segments. | ||||
*/ | */ | ||||
if ((inp->inp_flags & INP_TIMEWAIT) != 0) { | if ((inp->inp_flags & INP_TIMEWAIT) != 0) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 && | if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 && | ||||
tp->t_inpcb && tp->t_inpcb->inp_socket && | tp->t_inpcb && tp->t_inpcb->inp_socket && | ||||
(tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) { | (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) { | ||||
TCPSTAT_INC(tcps_finwait2_drops); | TCPSTAT_INC(tcps_finwait2_drops); | ||||
tp = tcp_close(tp); | tp = tcp_close(tp); | ||||
Show All 11 Lines | #ifdef TCPDEBUG | ||||
if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) | if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) | ||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, | 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); | ||||
if (tp != NULL) | if (tp != NULL) | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
void | void | ||||
tcp_timer_keep(void *xtp) | tcp_timer_keep(void *xtp) | ||||
{ | { | ||||
struct tcpcb *tp = xtp; | struct tcpcb *tp = xtp; | ||||
struct tcptemp *t_template; | struct tcptemp *t_template; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
void *cookie; | |||||
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_INFO_RLOCK(&V_tcbinfo); | INP_INFO_EBR_RLOCK(&V_tcbinfo); | ||||
inp = tp->t_inpcb; | inp = tp->t_inpcb; | ||||
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
if (callout_pending(&tp->t_timers->tt_keep) || | if (callout_pending(&tp->t_timers->tt_keep) || | ||||
!callout_active(&tp->t_timers->tt_keep)) { | !callout_active(&tp->t_timers->tt_keep)) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
callout_deactivate(&tp->t_timers->tt_keep); | callout_deactivate(&tp->t_timers->tt_keep); | ||||
if ((inp->inp_flags & INP_DROPPED) != 0) { | if ((inp->inp_flags & INP_DROPPED) != 0) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | ||||
("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ||||
KASSERT((tp->t_timers->tt_flags & TT_KEEP) != 0, | KASSERT((tp->t_timers->tt_flags & TT_KEEP) != 0, | ||||
("%s: tp %p keep callout should be running", __func__, tp)); | ("%s: tp %p keep callout should be running", __func__, tp)); | ||||
/* | /* | ||||
Show All 38 Lines | |||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
if (inp->inp_socket->so_options & SO_DEBUG) | if (inp->inp_socket->so_options & SO_DEBUG) | ||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, | 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); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
dropit: | dropit: | ||||
TCPSTAT_INC(tcps_keepdrops); | TCPSTAT_INC(tcps_keepdrops); | ||||
tp = tcp_drop(tp, ETIMEDOUT); | tp = tcp_drop(tp, ETIMEDOUT); | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) | if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) | ||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, | 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); | ||||
if (tp != NULL) | if (tp != NULL) | ||||
INP_WUNLOCK(tp->t_inpcb); | INP_WUNLOCK(tp->t_inpcb); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
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; | ||||
void *cookie; | |||||
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_INFO_RLOCK(&V_tcbinfo); | INP_INFO_EBR_RLOCK(&V_tcbinfo); | ||||
inp = tp->t_inpcb; | inp = tp->t_inpcb; | ||||
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
if (callout_pending(&tp->t_timers->tt_persist) || | if (callout_pending(&tp->t_timers->tt_persist) || | ||||
!callout_active(&tp->t_timers->tt_persist)) { | !callout_active(&tp->t_timers->tt_persist)) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
callout_deactivate(&tp->t_timers->tt_persist); | callout_deactivate(&tp->t_timers->tt_persist); | ||||
if ((inp->inp_flags & INP_DROPPED) != 0) { | if ((inp->inp_flags & INP_DROPPED) != 0) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | ||||
("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ||||
KASSERT((tp->t_timers->tt_flags & TT_PERSIST) != 0, | KASSERT((tp->t_timers->tt_flags & TT_PERSIST) != 0, | ||||
("%s: tp %p persist callout should be running", __func__, tp)); | ("%s: tp %p persist callout should be running", __func__, tp)); | ||||
/* | /* | ||||
Show All 33 Lines | |||||
out: | out: | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG) | if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG) | ||||
tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); | tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); | ||||
#endif | #endif | ||||
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); | TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); | ||||
if (tp != NULL) | if (tp != NULL) | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
void | void | ||||
tcp_timer_rexmt(void * xtp) | tcp_timer_rexmt(void * xtp) | ||||
{ | { | ||||
struct tcpcb *tp = xtp; | struct tcpcb *tp = xtp; | ||||
CURVNET_SET(tp->t_vnet); | CURVNET_SET(tp->t_vnet); | ||||
int rexmt; | int rexmt; | ||||
int headlocked; | int headlocked; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
void *cookie; | |||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
int ostate; | int ostate; | ||||
ostate = tp->t_state; | ostate = tp->t_state; | ||||
#endif | #endif | ||||
INP_INFO_RLOCK(&V_tcbinfo); | INP_INFO_EBR_RLOCK(&V_tcbinfo); | ||||
inp = tp->t_inpcb; | inp = tp->t_inpcb; | ||||
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
if (callout_pending(&tp->t_timers->tt_rexmt) || | if (callout_pending(&tp->t_timers->tt_rexmt) || | ||||
!callout_active(&tp->t_timers->tt_rexmt)) { | !callout_active(&tp->t_timers->tt_rexmt)) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
callout_deactivate(&tp->t_timers->tt_rexmt); | callout_deactivate(&tp->t_timers->tt_rexmt); | ||||
if ((inp->inp_flags & INP_DROPPED) != 0) { | if ((inp->inp_flags & INP_DROPPED) != 0) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
} | } | ||||
KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, | ||||
("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); | ||||
KASSERT((tp->t_timers->tt_flags & TT_REXMT) != 0, | KASSERT((tp->t_timers->tt_flags & TT_REXMT) != 0, | ||||
("%s: tp %p rexmt callout should be running", __func__, tp)); | ("%s: tp %p rexmt callout should be running", __func__, tp)); | ||||
tcp_free_sackholes(tp); | tcp_free_sackholes(tp); | ||||
Show All 10 Lines | if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { | ||||
tp->t_rxtshift = TCP_MAXRXTSHIFT; | tp->t_rxtshift = TCP_MAXRXTSHIFT; | ||||
TCPSTAT_INC(tcps_timeoutdrop); | TCPSTAT_INC(tcps_timeoutdrop); | ||||
tp = tcp_drop(tp, tp->t_softerror ? | tp = tcp_drop(tp, tp->t_softerror ? | ||||
tp->t_softerror : ETIMEDOUT); | tp->t_softerror : ETIMEDOUT); | ||||
headlocked = 1; | headlocked = 1; | ||||
goto out; | goto out; | ||||
} | } | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
headlocked = 0; | headlocked = 0; | ||||
if (tp->t_state == TCPS_SYN_SENT) { | if (tp->t_state == TCPS_SYN_SENT) { | ||||
/* | /* | ||||
* If the SYN was retransmitted, indicate CWND to be | * If the SYN was retransmitted, indicate CWND to be | ||||
* limited to 1 segment in cc_conn_init(). | * limited to 1 segment in cc_conn_init(). | ||||
*/ | */ | ||||
tp->snd_cwnd = 1; | tp->snd_cwnd = 1; | ||||
} else if (tp->t_rxtshift == 1) { | } else if (tp->t_rxtshift == 1) { | ||||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | #ifdef TCPDEBUG | ||||
if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) | if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) | ||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, | 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); | ||||
if (tp != NULL) | if (tp != NULL) | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
if (headlocked) | if (headlocked) | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_EBR_RUNLOCK(&V_tcbinfo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
void | void | ||||
tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) | tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) | ||||
{ | { | ||||
struct callout *t_callout; | struct callout *t_callout; | ||||
timeout_t *f_callout; | timeout_t *f_callout; | ||||
▲ Show 20 Lines • Show All 174 Lines • Show Last 20 Lines |