From 9a06a82455487991e6a71e5ce8e96c5bf3b8df3c Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Tue, 9 Nov 2021 21:22:54 -0800 Subject: tcp_timers: check for (INP_TIMEWAIT | INP_DROPPED) only once All timers keep inpcb locked through their execution. We need to check these flags only once. Checking for INP_TIMEWAIT earlier is is also safer, since such inpcbs point into tcptw rather than tcpcb, and any dereferences of inp_ppcb as tcpcb are erroneous. Reviewed by: rrs, hselasky Differential revision: https://reviews.freebsd.org/D32967 --- sys/netinet/tcp_timer.c | 41 ++++------------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) (limited to 'sys/netinet') diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 139e32172531..feea3765821c 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -328,7 +328,7 @@ tcp_timer_2msl(void *xtp) return; } callout_deactivate(&tp->t_timers->tt_2msl); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { INP_WUNLOCK(inp); CURVNET_RESTORE(); return; @@ -341,26 +341,14 @@ tcp_timer_2msl(void *xtp) * too long delete connection control block. Otherwise, check * again in a bit. * - * If in TIME_WAIT state just ignore as this timeout is handled in - * tcp_tw_2msl_scan(). - * * 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. * Ignore fact that there were recent incoming segments. */ - if ((inp->inp_flags & INP_TIMEWAIT) != 0) { - INP_WUNLOCK(inp); - CURVNET_RESTORE(); - return; - } if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 && tp->t_inpcb && tp->t_inpcb->inp_socket && (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) { TCPSTAT_INC(tcps_finwait2_drops); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - tcp_inpinfo_lock_del(inp, tp); - goto out; - } NET_EPOCH_ENTER(et); tp = tcp_close(tp); NET_EPOCH_EXIT(et); @@ -371,10 +359,6 @@ tcp_timer_2msl(void *xtp) callout_reset(&tp->t_timers->tt_2msl, TP_KEEPINTVL(tp), tcp_timer_2msl, tp); } else { - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - tcp_inpinfo_lock_del(inp, tp); - goto out; - } NET_EPOCH_ENTER(et); tp = tcp_close(tp); NET_EPOCH_EXIT(et); @@ -419,7 +403,7 @@ tcp_timer_keep(void *xtp) return; } callout_deactivate(&tp->t_timers->tt_keep); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { INP_WUNLOCK(inp); CURVNET_RESTORE(); return; @@ -498,10 +482,6 @@ tcp_timer_keep(void *xtp) dropit: TCPSTAT_INC(tcps_keepdrops); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - tcp_inpinfo_lock_del(inp, tp); - goto out; - } NET_EPOCH_ENTER(et); tp = tcp_drop(tp, ETIMEDOUT); @@ -513,7 +493,6 @@ dropit: TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); NET_EPOCH_EXIT(et); tcp_inpinfo_lock_del(inp, tp); - out: CURVNET_RESTORE(); } @@ -539,7 +518,7 @@ tcp_timer_persist(void *xtp) return; } callout_deactivate(&tp->t_timers->tt_persist); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { INP_WUNLOCK(inp); CURVNET_RESTORE(); return; @@ -562,10 +541,6 @@ tcp_timer_persist(void *xtp) (ticks - tp->t_rcvtime >= tcp_maxpersistidle || ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) { TCPSTAT_INC(tcps_persistdrop); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - tcp_inpinfo_lock_del(inp, tp); - goto out; - } NET_EPOCH_ENTER(et); tp = tcp_drop(tp, ETIMEDOUT); NET_EPOCH_EXIT(et); @@ -579,10 +554,6 @@ tcp_timer_persist(void *xtp) if (tp->t_state > TCPS_CLOSE_WAIT && (ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) { TCPSTAT_INC(tcps_persistdrop); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - tcp_inpinfo_lock_del(inp, tp); - goto out; - } NET_EPOCH_ENTER(et); tp = tcp_drop(tp, ETIMEDOUT); NET_EPOCH_EXIT(et); @@ -630,7 +601,7 @@ tcp_timer_rexmt(void * xtp) return; } callout_deactivate(&tp->t_timers->tt_rexmt); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { INP_WUNLOCK(inp); CURVNET_RESTORE(); return; @@ -651,10 +622,6 @@ tcp_timer_rexmt(void * xtp) if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { tp->t_rxtshift = TCP_MAXRXTSHIFT; TCPSTAT_INC(tcps_timeoutdrop); - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - tcp_inpinfo_lock_del(inp, tp); - goto out; - } NET_EPOCH_ENTER(et); tp = tcp_drop(tp, ETIMEDOUT); NET_EPOCH_EXIT(et); -- cgit v1.2.3