diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -2268,11 +2268,11 @@ V_tcp_mssdflt; /* Set up our timeouts. */ - callout_init(&tp->t_timers->tt_rexmt, 1); - callout_init(&tp->t_timers->tt_persist, 1); - callout_init(&tp->t_timers->tt_keep, 1); - callout_init(&tp->t_timers->tt_2msl, 1); - callout_init(&tp->t_timers->tt_delack, 1); + callout_init_rw(&tp->t_timers->tt_rexmt, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); + callout_init_rw(&tp->t_timers->tt_persist, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); + callout_init_rw(&tp->t_timers->tt_keep, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); + callout_init_rw(&tp->t_timers->tt_2msl, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); + callout_init_rw(&tp->t_timers->tt_delack, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); if (V_tcp_do_rfc1323) tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP); @@ -2353,6 +2353,16 @@ return (tcp_close(tp)); } +void +tcp_timer_stop_all(struct tcpcb *tp) +{ + tcp_timer_stop(tp, TT_REXMT); + tcp_timer_stop(tp, TT_PERSIST); + tcp_timer_stop(tp, TT_KEEP); + tcp_timer_stop(tp, TT_2MSL); + tcp_timer_stop(tp, TT_DELACK); +} + void tcp_discardcb(struct tcpcb *tp) { @@ -2369,11 +2379,7 @@ * deleting the tcpcb. */ tp->t_timers->tt_draincnt = 0; - tcp_timer_stop(tp, TT_REXMT); - tcp_timer_stop(tp, TT_PERSIST); - tcp_timer_stop(tp, TT_KEEP); - tcp_timer_stop(tp, TT_2MSL); - tcp_timer_stop(tp, TT_DELACK); + tcp_timer_stop_all(tp); if (tp->t_fb->tfb_tcp_timer_stop_all) { /* * Call the stop-all function of the methods, @@ -2544,6 +2550,7 @@ #ifdef TCPHPTS tcp_hpts_remove(inp); #endif + tcp_timer_stop_all(tp); in_pcbdrop(inp); TCPSTAT_INC(tcps_closed); if (tp->t_state != TCPS_CLOSED) @@ -4053,18 +4060,18 @@ (tp->t_flags2 & TF2_ACE_PERMIT) ? 2 : 0; now = getsbinuptime(); -#define COPYTIMER(ttt) do { \ - if (callout_active(&tp->t_timers->ttt)) \ +#define COPYTIMER(ttt,TTT) do { \ + if (tp->t_timers->tt_flags & TTT) \ xt->ttt = (tp->t_timers->ttt.c_time - now) / \ SBT_1MS; \ else \ xt->ttt = 0; \ } while (0) - COPYTIMER(tt_delack); - COPYTIMER(tt_rexmt); - COPYTIMER(tt_persist); - COPYTIMER(tt_keep); - COPYTIMER(tt_2msl); + COPYTIMER(tt_delack, TT_DELACK); + COPYTIMER(tt_rexmt, TT_REXMT); + COPYTIMER(tt_persist, TT_PERSIST); + COPYTIMER(tt_keep, TT_KEEP); + COPYTIMER(tt_2msl, TT_2MSL); #undef COPYTIMER xt->t_rcvtime = 1000 * (ticks - tp->t_rcvtime) / hz; diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -282,21 +282,9 @@ struct inpcb *inp; CURVNET_SET(tp->t_vnet); + tp->t_timers->tt_flags &= ~TT_DELACK; inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); - INP_WLOCK(inp); - if (callout_pending(&tp->t_timers->tt_delack) || - !callout_active(&tp->t_timers->tt_delack)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } - callout_deactivate(&tp->t_timers->tt_delack); - if ((inp->inp_flags & INP_DROPPED) != 0) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } tp->t_flags |= TF_ACKNOW; TCPSTAT_INC(tcps_delack); NET_EPOCH_ENTER(et); @@ -324,22 +312,11 @@ ostate = tp->t_state; #endif + tp->t_timers->tt_flags &= ~TT_2MSL; inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); - INP_WLOCK(inp); + tcp_free_sackholes(tp); - if (callout_pending(&tp->t_timers->tt_2msl) || - !callout_active(&tp->t_timers->tt_2msl)) { - INP_WUNLOCK(tp->t_inpcb); - CURVNET_RESTORE(); - return; - } - callout_deactivate(&tp->t_timers->tt_2msl); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); /* @@ -363,6 +340,7 @@ goto out; } else { if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) { + tp->t_timers->tt_flags |= TT_2MSL; callout_reset(&tp->t_timers->tt_2msl, TP_KEEPINTVL(tp), tcp_timer_2msl, tp); } else { @@ -400,21 +378,10 @@ ostate = tp->t_state; #endif + tp->t_timers->tt_flags &= ~TT_KEEP; inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); - INP_WLOCK(inp); - if (callout_pending(&tp->t_timers->tt_keep) || - !callout_active(&tp->t_timers->tt_keep)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } - callout_deactivate(&tp->t_timers->tt_keep); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } + KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); @@ -429,6 +396,7 @@ idletime = ticks - tp->t_rcvtime; if (idletime < TP_KEEPIDLE(tp)) { + tp->t_timers->tt_flags |= TT_KEEP; callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp) - idletime, tcp_timer_keep, tp); INP_WUNLOCK(inp); @@ -471,11 +439,14 @@ NET_EPOCH_EXIT(et); free(t_template, M_TEMP); } + tp->t_timers->tt_flags |= TT_KEEP; callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), tcp_timer_keep, tp); - } else + } else { + tp->t_timers->tt_flags |= TT_KEEP; callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), tcp_timer_keep, tp); + } #ifdef TCPDEBUG if (inp->inp_socket->so_options & SO_DEBUG) @@ -516,21 +487,9 @@ ostate = tp->t_state; #endif + tp->t_timers->tt_flags &= ~TT_PERSIST; inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); - INP_WLOCK(inp); - if (callout_pending(&tp->t_timers->tt_persist) || - !callout_active(&tp->t_timers->tt_persist)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } - callout_deactivate(&tp->t_timers->tt_persist); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); /* @@ -599,21 +558,9 @@ ostate = tp->t_state; #endif + tp->t_timers->tt_flags &= ~TT_REXMT; inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); - INP_WLOCK(inp); - if (callout_pending(&tp->t_timers->tt_rexmt) || - !callout_active(&tp->t_timers->tt_rexmt)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } - callout_deactivate(&tp->t_timers->tt_rexmt); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); tcp_free_sackholes(tp); @@ -902,15 +849,15 @@ f_callout = tcp_timer_2msl; break; default: - if (tp->t_fb->tfb_tcp_timer_activate) { - tp->t_fb->tfb_tcp_timer_activate(tp, timer_type, delta); - return; - } - panic("tp %p bad timer_type %#x", tp, timer_type); - } + MPASS(tp->t_fb->tfb_tcp_timer_activate != NULL); + tp->t_fb->tfb_tcp_timer_activate(tp, timer_type, delta); + return; + } if (delta == 0) { + tp->t_timers->tt_flags &= ~timer_type; callout_stop(t_callout); } else { + tp->t_timers->tt_flags |= timer_type; callout_reset_on(t_callout, delta, f_callout, tp, cpu); } } @@ -918,31 +865,17 @@ int tcp_timer_active(struct tcpcb *tp, uint32_t timer_type) { - struct callout *t_callout; - switch (timer_type) { - case TT_DELACK: - t_callout = &tp->t_timers->tt_delack; - break; - case TT_REXMT: - t_callout = &tp->t_timers->tt_rexmt; - break; - case TT_PERSIST: - t_callout = &tp->t_timers->tt_persist; - break; - case TT_KEEP: - t_callout = &tp->t_timers->tt_keep; - break; - case TT_2MSL: - t_callout = &tp->t_timers->tt_2msl; - break; - default: - if (tp->t_fb->tfb_tcp_timer_active) { - return(tp->t_fb->tfb_tcp_timer_active(tp, timer_type)); - } - panic("tp %p bad timer_type %#x", tp, timer_type); - } - return callout_active(t_callout); + case TT_DELACK: + case TT_REXMT: + case TT_PERSIST: + case TT_KEEP: + case TT_2MSL: + return ((tp->t_timers->tt_flags & timer_type) ? 1 : 0); + default: + MPASS(tp->t_fb->tfb_tcp_timer_active != NULL); + return (tp->t_fb->tfb_tcp_timer_active(tp, timer_type)); + } } /* @@ -1006,7 +939,7 @@ if (tp->t_timers->tt_flags & TT_REXMT_SUS) { tp->t_timers->tt_flags &= ~TT_REXMT_SUS; if (SEQ_GT(tp->snd_max, tp->snd_una) && - (tcp_timer_active((tp), TT_PERSIST) == 0) && + (tcp_timer_active(tp, TT_PERSIST) == 0) && tp->snd_wnd) { /* We have outstanding data activate a timer */ tcp_timer_activate(tp, TT_REXMT, diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1195,6 +1195,7 @@ void tcp_timers_unsuspend(struct tcpcb *, uint32_t); int tcp_timer_active(struct tcpcb *, uint32_t); void tcp_timer_stop(struct tcpcb *, uint32_t); +void tcp_timer_stop_all(struct tcpcb *); void tcp_trace(short, short, struct tcpcb *, void *, struct tcphdr *, int); int inp_to_cpuid(struct inpcb *inp); /*