1139823Simp/*-
211150Swollman * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes *
2911150Swollman *	@(#)tcp_timer.c	8.2 (Berkeley) 5/24/95
301541Srgrimes */
311541Srgrimes
32172467Ssilby#include <sys/cdefs.h>
33172467Ssilby__FBSDID("$FreeBSD: stable/10/sys/netinet/tcp_timer.c 330303 2018-03-03 00:54:12Z jhb $");
34172467Ssilby
35243603Snp#include "opt_inet.h"
3655679Sshin#include "opt_inet6.h"
3729514Sjoerg#include "opt_tcpdebug.h"
3829514Sjoerg
391541Srgrimes#include <sys/param.h>
4012172Sphk#include <sys/kernel.h>
41102967Sbde#include <sys/lock.h>
4278642Ssilby#include <sys/mbuf.h>
43102967Sbde#include <sys/mutex.h>
44102967Sbde#include <sys/protosw.h>
45205391Skmacy#include <sys/smp.h>
461541Srgrimes#include <sys/socket.h>
471541Srgrimes#include <sys/socketvar.h>
48102967Sbde#include <sys/sysctl.h>
49102967Sbde#include <sys/systm.h>
501541Srgrimes
51185571Sbz#include <net/if.h>
521541Srgrimes#include <net/route.h>
53196019Srwatson#include <net/vnet.h>
541541Srgrimes
55215166Slstewart#include <netinet/cc.h>
561541Srgrimes#include <netinet/in.h>
57102967Sbde#include <netinet/in_pcb.h>
581541Srgrimes#include <netinet/in_systm.h>
5955679Sshin#ifdef INET6
6055679Sshin#include <netinet6/in6_pcb.h>
6155679Sshin#endif
621541Srgrimes#include <netinet/ip_var.h>
631541Srgrimes#include <netinet/tcp_fsm.h>
641541Srgrimes#include <netinet/tcp_timer.h>
651541Srgrimes#include <netinet/tcp_var.h>
66273838Ssbruno#ifdef INET6
67273838Ssbruno#include <netinet6/tcp6_var.h>
68273838Ssbruno#endif
691541Srgrimes#include <netinet/tcpip.h>
7017138Sdg#ifdef TCPDEBUG
7117138Sdg#include <netinet/tcp_debug.h>
7217138Sdg#endif
731541Srgrimes
74295015Shirenint    tcp_persmin;
75295015ShirenSYSCTL_PROC(_net_inet_tcp, OID_AUTO, persmin, CTLTYPE_INT|CTLFLAG_RW,
76295015Shiren    &tcp_persmin, 0, sysctl_msec_to_ticks, "I", "minimum persistence interval");
77295015Shiren
78295015Shirenint    tcp_persmax;
79295015ShirenSYSCTL_PROC(_net_inet_tcp, OID_AUTO, persmax, CTLTYPE_INT|CTLFLAG_RW,
80295015Shiren    &tcp_persmax, 0, sysctl_msec_to_ticks, "I", "maximum persistence interval");
81295015Shiren
8250673Sjlemonint	tcp_keepinit;
8350682SjlemonSYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit, CTLTYPE_INT|CTLFLAG_RW,
84180631Strhodes    &tcp_keepinit, 0, sysctl_msec_to_ticks, "I", "time to establish connection");
8518280Spst
8650673Sjlemonint	tcp_keepidle;
8750682SjlemonSYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle, CTLTYPE_INT|CTLFLAG_RW,
88180631Strhodes    &tcp_keepidle, 0, sysctl_msec_to_ticks, "I", "time before keepalive probes begin");
8912172Sphk
9050673Sjlemonint	tcp_keepintvl;
9150682SjlemonSYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl, CTLTYPE_INT|CTLFLAG_RW,
92180631Strhodes    &tcp_keepintvl, 0, sysctl_msec_to_ticks, "I", "time between keepalive probes");
9312172Sphk
9450673Sjlemonint	tcp_delacktime;
95167721SandreSYSCTL_PROC(_net_inet_tcp, TCPCTL_DELACKTIME, delacktime, CTLTYPE_INT|CTLFLAG_RW,
96167721Sandre    &tcp_delacktime, 0, sysctl_msec_to_ticks, "I",
9750682Sjlemon    "Time before a delayed ACK is sent");
98133874Srwatson
9950673Sjlemonint	tcp_msl;
10050682SjlemonSYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW,
10150682Sjlemon    &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime");
10250673Sjlemon
103100335Sdillonint	tcp_rexmit_min;
104100335SdillonSYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW,
105167721Sandre    &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I",
106167721Sandre    "Minimum Retransmission Timeout");
107100335Sdillon
108100335Sdillonint	tcp_rexmit_slop;
109100335SdillonSYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_slop, CTLTYPE_INT|CTLFLAG_RW,
110167721Sandre    &tcp_rexmit_slop, 0, sysctl_msec_to_ticks, "I",
111167721Sandre    "Retransmission Timer Slop");
112100335Sdillon
113330303Sjhbint	tcp_always_keepalive = 1;
114133874SrwatsonSYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW,
115330303Sjhb    &tcp_always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections");
116330303Sjhb__strong_reference(tcp_always_keepalive, always_keepalive);
11715039Sphk
118167036Smohansint    tcp_fast_finwait2_recycle = 0;
119167036SmohansSYSCTL_INT(_net_inet_tcp, OID_AUTO, fast_finwait2_recycle, CTLFLAG_RW,
120167721Sandre    &tcp_fast_finwait2_recycle, 0,
121167721Sandre    "Recycle closed FIN_WAIT_2 connections faster");
122167036Smohans
123167036Smohansint    tcp_finwait2_timeout;
124167036SmohansSYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout, CTLTYPE_INT|CTLFLAG_RW,
125167721Sandre    &tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I", "FIN-WAIT2 timeout");
126167036Smohans
127231025Sglebiusint	tcp_keepcnt = TCPTV_KEEPCNT;
128231025SglebiusSYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
129231025Sglebius    "Number of keepalive probes to send");
130167036Smohans
13112296Sphk	/* max idle probes */
13250673Sjlemonint	tcp_maxpersistidle;
13311150Swollman
134245238Sjhbstatic int	tcp_rexmit_drop_options = 0;
135245238SjhbSYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
136245238Sjhb    &tcp_rexmit_drop_options, 0,
137245238Sjhb    "Drop TCP options from 3rd and later retransmitted SYN");
138245238Sjhb
139273838Ssbrunostatic VNET_DEFINE(int, tcp_pmtud_blackhole_detect);
140273838Ssbruno#define	V_tcp_pmtud_blackhole_detect	VNET(tcp_pmtud_blackhole_detect)
141273838SsbrunoSYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
142273838Ssbruno    CTLFLAG_RW,
143273838Ssbruno    &VNET_NAME(tcp_pmtud_blackhole_detect), 0,
144273838Ssbruno    "Path MTU Discovery Black Hole Detection Enabled");
145273838Ssbruno
146273838Ssbrunostatic VNET_DEFINE(int, tcp_pmtud_blackhole_activated);
147273838Ssbruno#define	V_tcp_pmtud_blackhole_activated \
148273838Ssbruno    VNET(tcp_pmtud_blackhole_activated)
149273838SsbrunoSYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated,
150273838Ssbruno    CTLFLAG_RD,
151273838Ssbruno    &VNET_NAME(tcp_pmtud_blackhole_activated), 0,
152273838Ssbruno    "Path MTU Discovery Black Hole Detection, Activation Count");
153273838Ssbruno
154273838Ssbrunostatic VNET_DEFINE(int, tcp_pmtud_blackhole_activated_min_mss);
155273838Ssbruno#define	V_tcp_pmtud_blackhole_activated_min_mss \
156273838Ssbruno    VNET(tcp_pmtud_blackhole_activated_min_mss)
157273838SsbrunoSYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated_min_mss,
158273838Ssbruno    CTLFLAG_RD,
159273838Ssbruno    &VNET_NAME(tcp_pmtud_blackhole_activated_min_mss), 0,
160273838Ssbruno    "Path MTU Discovery Black Hole Detection, Activation Count at min MSS");
161273838Ssbruno
162273838Ssbrunostatic VNET_DEFINE(int, tcp_pmtud_blackhole_failed);
163273838Ssbruno#define	V_tcp_pmtud_blackhole_failed	VNET(tcp_pmtud_blackhole_failed)
164273838SsbrunoSYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_failed,
165273838Ssbruno    CTLFLAG_RD,
166273838Ssbruno    &VNET_NAME(tcp_pmtud_blackhole_failed), 0,
167273838Ssbruno    "Path MTU Discovery Black Hole Detection, Failure Count");
168273838Ssbruno
169273838Ssbruno#ifdef INET
170273838Ssbrunostatic VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200;
171273838Ssbruno#define	V_tcp_pmtud_blackhole_mss	VNET(tcp_pmtud_blackhole_mss)
172273838SsbrunoSYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_mss,
173273838Ssbruno    CTLFLAG_RW,
174273838Ssbruno    &VNET_NAME(tcp_pmtud_blackhole_mss), 0,
175273838Ssbruno    "Path MTU Discovery Black Hole Detection lowered MSS");
176273838Ssbruno#endif
177273838Ssbruno
178273838Ssbruno#ifdef INET6
179273838Ssbrunostatic VNET_DEFINE(int, tcp_v6pmtud_blackhole_mss) = 1220;
180273838Ssbruno#define	V_tcp_v6pmtud_blackhole_mss	VNET(tcp_v6pmtud_blackhole_mss)
181273838SsbrunoSYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, v6pmtud_blackhole_mss,
182273838Ssbruno    CTLFLAG_RW,
183273838Ssbruno    &VNET_NAME(tcp_v6pmtud_blackhole_mss), 0,
184273838Ssbruno    "Path MTU Discovery IPv6 Black Hole Detection lowered MSS");
185273838Ssbruno#endif
186273838Ssbruno
187205391Skmacystatic int	per_cpu_timers = 0;
188205391SkmacySYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW,
189205391Skmacy    &per_cpu_timers , 0, "run tcp timers on all cpus");
190205391Skmacy
191205391Skmacy#define	INP_CPU(inp)	(per_cpu_timers ? (!CPU_ABSENT(((inp)->inp_flowid % (mp_maxid+1))) ? \
192205391Skmacy		((inp)->inp_flowid % (mp_maxid+1)) : curcpu) : 0)
193205391Skmacy
1941541Srgrimes/*
1951541Srgrimes * Tcp protocol timeout routine called every 500 ms.
19650673Sjlemon * Updates timestamps used for TCP
1971541Srgrimes * causes finite state machine actions if timers expire.
1981541Srgrimes */
1991541Srgrimesvoid
200172309Ssilbytcp_slowtimo(void)
2011541Srgrimes{
202183550Szec	VNET_ITERATOR_DECL(vnet_iter);
2031541Srgrimes
204195760Srwatson	VNET_LIST_RLOCK_NOSLEEP();
205183550Szec	VNET_FOREACH(vnet_iter) {
206183550Szec		CURVNET_SET(vnet_iter);
207183550Szec		(void) tcp_tw_2msl_scan(0);
208183550Szec		CURVNET_RESTORE();
209183550Szec	}
210195760Srwatson	VNET_LIST_RUNLOCK_NOSLEEP();
2111541Srgrimes}
2121541Srgrimes
21373110Sjlemonint	tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
21473110Sjlemon    { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 };
21573110Sjlemon
2161541Srgrimesint	tcp_backoff[TCP_MAXRXTSHIFT + 1] =
217115824Shsu    { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 };
2181541Srgrimes
219115824Shsustatic int tcp_totbackoff = 2559;	/* sum of tcp_backoff[] */
22011150Swollman
221172074Srwatson/*
222172074Srwatson * TCP timer processing.
223172074Srwatson */
224172074Srwatson
22550673Sjlemonvoid
226172074Srwatsontcp_timer_delack(void *xtp)
2271541Srgrimes{
228172074Srwatson	struct tcpcb *tp = xtp;
229172074Srwatson	struct inpcb *inp;
230183550Szec	CURVNET_SET(tp->t_vnet);
2311541Srgrimes
232172074Srwatson	inp = tp->t_inpcb;
233282964Sjch	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
234178285Srwatson	INP_WLOCK(inp);
235239075Strociny	if (callout_pending(&tp->t_timers->tt_delack) ||
236239075Strociny	    !callout_active(&tp->t_timers->tt_delack)) {
237178285Srwatson		INP_WUNLOCK(inp);
238183550Szec		CURVNET_RESTORE();
23950673Sjlemon		return;
24050673Sjlemon	}
241172309Ssilby	callout_deactivate(&tp->t_timers->tt_delack);
242239075Strociny	if ((inp->inp_flags & INP_DROPPED) != 0) {
243239075Strociny		INP_WUNLOCK(inp);
244239075Strociny		CURVNET_RESTORE();
245239075Strociny		return;
246239075Strociny	}
247282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0,
248282964Sjch		("%s: tp %p tcpcb can't be stopped here", __func__, tp));
249282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_DELACK) != 0,
250282964Sjch		("%s: tp %p delack callout should be running", __func__, tp));
2511541Srgrimes
25250673Sjlemon	tp->t_flags |= TF_ACKNOW;
253190948Srwatson	TCPSTAT_INC(tcps_delack);
25450673Sjlemon	(void) tcp_output(tp);
255178285Srwatson	INP_WUNLOCK(inp);
256183550Szec	CURVNET_RESTORE();
25750673Sjlemon}
25850673Sjlemon
259172074Srwatsonvoid
260172074Srwatsontcp_timer_2msl(void *xtp)
26150673Sjlemon{
262172074Srwatson	struct tcpcb *tp = xtp;
263172074Srwatson	struct inpcb *inp;
264183550Szec	CURVNET_SET(tp->t_vnet);
26550673Sjlemon#ifdef TCPDEBUG
26650673Sjlemon	int ostate;
26750673Sjlemon
26850673Sjlemon	ostate = tp->t_state;
26950673Sjlemon#endif
270309108Sjch	INP_INFO_RLOCK(&V_tcbinfo);
271172074Srwatson	inp = tp->t_inpcb;
272282964Sjch	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
273178285Srwatson	INP_WLOCK(inp);
274172074Srwatson	tcp_free_sackholes(tp);
275239075Strociny	if (callout_pending(&tp->t_timers->tt_2msl) ||
276172309Ssilby	    !callout_active(&tp->t_timers->tt_2msl)) {
277178285Srwatson		INP_WUNLOCK(tp->t_inpcb);
278309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
279183550Szec		CURVNET_RESTORE();
280172074Srwatson		return;
281172074Srwatson	}
282172309Ssilby	callout_deactivate(&tp->t_timers->tt_2msl);
283239075Strociny	if ((inp->inp_flags & INP_DROPPED) != 0) {
284239075Strociny		INP_WUNLOCK(inp);
285309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
286239075Strociny		CURVNET_RESTORE();
287239075Strociny		return;
288239075Strociny	}
289282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0,
290282964Sjch		("%s: tp %p tcpcb can't be stopped here", __func__, tp));
291282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_2MSL) != 0,
292282964Sjch		("%s: tp %p 2msl callout should be running", __func__, tp));
293172074Srwatson	/*
2941541Srgrimes	 * 2 MSL timeout in shutdown went off.  If we're closed but
2951541Srgrimes	 * still waiting for peer to close and connection has been idle
296303389Sjch	 * too long delete connection control block.  Otherwise, check
297303389Sjch	 * again in a bit.
298167036Smohans	 *
299303389Sjch	 * If in TIME_WAIT state just ignore as this timeout is handled in
300303389Sjch	 * tcp_tw_2msl_scan().
301303389Sjch	 *
302167036Smohans	 * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed,
303167036Smohans	 * there's no point in hanging onto FIN_WAIT_2 socket. Just close it.
304167036Smohans	 * Ignore fact that there were recent incoming segments.
3051541Srgrimes	 */
306303389Sjch	if ((inp->inp_flags & INP_TIMEWAIT) != 0) {
307303389Sjch		INP_WUNLOCK(inp);
308309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
309303389Sjch		CURVNET_RESTORE();
310303389Sjch		return;
311303389Sjch	}
312167036Smohans	if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 &&
313172074Srwatson	    tp->t_inpcb && tp->t_inpcb->inp_socket &&
314167036Smohans	    (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
315190948Srwatson		TCPSTAT_INC(tcps_finwait2_drops);
316172074Srwatson		tp = tcp_close(tp);
317167036Smohans	} else {
318303389Sjch		if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) {
319284261Sjch			if (!callout_reset(&tp->t_timers->tt_2msl,
320284261Sjch			   TP_KEEPINTVL(tp), tcp_timer_2msl, tp)) {
321284261Sjch				tp->t_timers->tt_flags &= ~TT_2MSL_RST;
322284261Sjch			}
323284261Sjch		} else
324172074Srwatson		       tp = tcp_close(tp);
325172074Srwatson       }
3261541Srgrimes
32750673Sjlemon#ifdef TCPDEBUG
328172312Skib	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
32997658Stanimura		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
33097658Stanimura			  PRU_SLOWTIMO);
33150673Sjlemon#endif
332172074Srwatson	if (tp != NULL)
333178285Srwatson		INP_WUNLOCK(inp);
334309108Sjch	INP_INFO_RUNLOCK(&V_tcbinfo);
335183550Szec	CURVNET_RESTORE();
33650673Sjlemon}
33750673Sjlemon
338172074Srwatsonvoid
339172074Srwatsontcp_timer_keep(void *xtp)
34050673Sjlemon{
341172074Srwatson	struct tcpcb *tp = xtp;
34278642Ssilby	struct tcptemp *t_template;
343172074Srwatson	struct inpcb *inp;
344183550Szec	CURVNET_SET(tp->t_vnet);
34550673Sjlemon#ifdef TCPDEBUG
34650673Sjlemon	int ostate;
34750673Sjlemon
34850673Sjlemon	ostate = tp->t_state;
34950673Sjlemon#endif
350309108Sjch	INP_INFO_RLOCK(&V_tcbinfo);
351172074Srwatson	inp = tp->t_inpcb;
352282964Sjch	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
353178285Srwatson	INP_WLOCK(inp);
354239075Strociny	if (callout_pending(&tp->t_timers->tt_keep) ||
355239075Strociny	    !callout_active(&tp->t_timers->tt_keep)) {
356178285Srwatson		INP_WUNLOCK(inp);
357309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
358183550Szec		CURVNET_RESTORE();
359172074Srwatson		return;
360172074Srwatson	}
361172309Ssilby	callout_deactivate(&tp->t_timers->tt_keep);
362239075Strociny	if ((inp->inp_flags & INP_DROPPED) != 0) {
363239075Strociny		INP_WUNLOCK(inp);
364309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
365239075Strociny		CURVNET_RESTORE();
366239075Strociny		return;
367239075Strociny	}
368282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0,
369282964Sjch		("%s: tp %p tcpcb can't be stopped here", __func__, tp));
370282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_KEEP) != 0,
371282964Sjch		("%s: tp %p keep callout should be running", __func__, tp));
372172074Srwatson	/*
37350673Sjlemon	 * Keep-alive timer went off; send something
37450673Sjlemon	 * or drop connection if idle for too long.
3751541Srgrimes	 */
376190948Srwatson	TCPSTAT_INC(tcps_keeptimeo);
37750673Sjlemon	if (tp->t_state < TCPS_ESTABLISHED)
37850673Sjlemon		goto dropit;
379330303Sjhb	if ((tcp_always_keepalive ||
380330303Sjhb	    inp->inp_socket->so_options & SO_KEEPALIVE) &&
38150673Sjlemon	    tp->t_state <= TCPS_CLOSING) {
382231025Sglebius		if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp))
38350673Sjlemon			goto dropit;
3841541Srgrimes		/*
38550673Sjlemon		 * Send a packet designed to force a response
38650673Sjlemon		 * if the peer is up and reachable:
38750673Sjlemon		 * either an ACK if the connection is still alive,
38850673Sjlemon		 * or an RST if the peer has closed the connection
38950673Sjlemon		 * due to timeout or reboot.
39050673Sjlemon		 * Using sequence number tp->snd_una-1
39150673Sjlemon		 * causes the transmitted zero-length segment
39250673Sjlemon		 * to lie outside the receive window;
39350673Sjlemon		 * by the protocol spec, this requires the
39450673Sjlemon		 * correspondent TCP to respond.
3951541Srgrimes		 */
396190948Srwatson		TCPSTAT_INC(tcps_keepprobe);
397111144Sjlemon		t_template = tcpip_maketemplate(inp);
39878642Ssilby		if (t_template) {
39978642Ssilby			tcp_respond(tp, t_template->tt_ipgen,
40078642Ssilby				    &t_template->tt_t, (struct mbuf *)NULL,
40178642Ssilby				    tp->rcv_nxt, tp->snd_una - 1, 0);
402179487Srwatson			free(t_template, M_TEMP);
40378642Ssilby		}
404284261Sjch		if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp),
405284261Sjch		    tcp_timer_keep, tp)) {
406284261Sjch			tp->t_timers->tt_flags &= ~TT_KEEP_RST;
407284261Sjch		}
408284261Sjch	} else if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp),
409284261Sjch		    tcp_timer_keep, tp)) {
410284261Sjch			tp->t_timers->tt_flags &= ~TT_KEEP_RST;
411284261Sjch		}
41250673Sjlemon
41350673Sjlemon#ifdef TCPDEBUG
414122326Ssam	if (inp->inp_socket->so_options & SO_DEBUG)
41555679Sshin		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
41650673Sjlemon			  PRU_SLOWTIMO);
41750673Sjlemon#endif
418178285Srwatson	INP_WUNLOCK(inp);
419309108Sjch	INP_INFO_RUNLOCK(&V_tcbinfo);
420183550Szec	CURVNET_RESTORE();
421172074Srwatson	return;
42250673Sjlemon
42350673Sjlemondropit:
424190948Srwatson	TCPSTAT_INC(tcps_keepdrops);
425172074Srwatson	tp = tcp_drop(tp, ETIMEDOUT);
426172074Srwatson
427172074Srwatson#ifdef TCPDEBUG
428172074Srwatson	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
429172074Srwatson		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
430172074Srwatson			  PRU_SLOWTIMO);
431172074Srwatson#endif
432172074Srwatson	if (tp != NULL)
433178285Srwatson		INP_WUNLOCK(tp->t_inpcb);
434309108Sjch	INP_INFO_RUNLOCK(&V_tcbinfo);
435183550Szec	CURVNET_RESTORE();
43650673Sjlemon}
43750673Sjlemon
438172074Srwatsonvoid
439172074Srwatsontcp_timer_persist(void *xtp)
44050673Sjlemon{
441172074Srwatson	struct tcpcb *tp = xtp;
442172074Srwatson	struct inpcb *inp;
443183550Szec	CURVNET_SET(tp->t_vnet);
44450673Sjlemon#ifdef TCPDEBUG
44550673Sjlemon	int ostate;
44650673Sjlemon
44750673Sjlemon	ostate = tp->t_state;
44850673Sjlemon#endif
449309108Sjch	INP_INFO_RLOCK(&V_tcbinfo);
450172074Srwatson	inp = tp->t_inpcb;
451282964Sjch	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
452178285Srwatson	INP_WLOCK(inp);
453239075Strociny	if (callout_pending(&tp->t_timers->tt_persist) ||
454239075Strociny	    !callout_active(&tp->t_timers->tt_persist)) {
455178285Srwatson		INP_WUNLOCK(inp);
456309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
457183550Szec		CURVNET_RESTORE();
458172074Srwatson		return;
459172074Srwatson	}
460172309Ssilby	callout_deactivate(&tp->t_timers->tt_persist);
461239075Strociny	if ((inp->inp_flags & INP_DROPPED) != 0) {
462239075Strociny		INP_WUNLOCK(inp);
463309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
464239075Strociny		CURVNET_RESTORE();
465239075Strociny		return;
466239075Strociny	}
467282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0,
468282964Sjch		("%s: tp %p tcpcb can't be stopped here", __func__, tp));
469282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_PERSIST) != 0,
470282964Sjch		("%s: tp %p persist callout should be running", __func__, tp));
471172074Srwatson	/*
47250673Sjlemon	 * Persistance timer into zero window.
47350673Sjlemon	 * Force a byte to be output, if possible.
47450673Sjlemon	 */
475190948Srwatson	TCPSTAT_INC(tcps_persisttimeo);
47650673Sjlemon	/*
47750673Sjlemon	 * Hack: if the peer is dead/unreachable, we do not
47850673Sjlemon	 * time out if the window is closed.  After a full
47950673Sjlemon	 * backoff, drop the connection if the idle time
48050673Sjlemon	 * (no responses to probes) reaches the maximum
48150673Sjlemon	 * backoff that we would use if retransmitting.
48250673Sjlemon	 */
48350673Sjlemon	if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
484194305Sjhb	    (ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
485194305Sjhb	     ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
486190948Srwatson		TCPSTAT_INC(tcps_persistdrop);
487172074Srwatson		tp = tcp_drop(tp, ETIMEDOUT);
488172074Srwatson		goto out;
48950673Sjlemon	}
490242267Sandre	/*
491242267Sandre	 * If the user has closed the socket then drop a persisting
492242267Sandre	 * connection after a much reduced timeout.
493242267Sandre	 */
494242267Sandre	if (tp->t_state > TCPS_CLOSE_WAIT &&
495242267Sandre	    (ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) {
496242267Sandre		TCPSTAT_INC(tcps_persistdrop);
497242267Sandre		tp = tcp_drop(tp, ETIMEDOUT);
498242267Sandre		goto out;
499242267Sandre	}
50050673Sjlemon	tcp_setpersist(tp);
501146463Sps	tp->t_flags |= TF_FORCEDATA;
50250673Sjlemon	(void) tcp_output(tp);
503146463Sps	tp->t_flags &= ~TF_FORCEDATA;
50450673Sjlemon
505172074Srwatsonout:
50650673Sjlemon#ifdef TCPDEBUG
507158644Sglebius	if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
508158644Sglebius		tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO);
50950673Sjlemon#endif
510172074Srwatson	if (tp != NULL)
511178285Srwatson		INP_WUNLOCK(inp);
512309108Sjch	INP_INFO_RUNLOCK(&V_tcbinfo);
513183550Szec	CURVNET_RESTORE();
51450673Sjlemon}
51550673Sjlemon
516172074Srwatsonvoid
517172074Srwatsontcp_timer_rexmt(void * xtp)
51850673Sjlemon{
519172074Srwatson	struct tcpcb *tp = xtp;
520183550Szec	CURVNET_SET(tp->t_vnet);
52150673Sjlemon	int rexmt;
522172074Srwatson	int headlocked;
523172074Srwatson	struct inpcb *inp;
52450673Sjlemon#ifdef TCPDEBUG
52550673Sjlemon	int ostate;
52650673Sjlemon
52750673Sjlemon	ostate = tp->t_state;
52850673Sjlemon#endif
529273838Ssbruno
530205391Skmacy	INP_INFO_RLOCK(&V_tcbinfo);
531172074Srwatson	inp = tp->t_inpcb;
532282964Sjch	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
533178285Srwatson	INP_WLOCK(inp);
534239075Strociny	if (callout_pending(&tp->t_timers->tt_rexmt) ||
535239075Strociny	    !callout_active(&tp->t_timers->tt_rexmt)) {
536178285Srwatson		INP_WUNLOCK(inp);
537205391Skmacy		INP_INFO_RUNLOCK(&V_tcbinfo);
538183550Szec		CURVNET_RESTORE();
539172074Srwatson		return;
540172074Srwatson	}
541172309Ssilby	callout_deactivate(&tp->t_timers->tt_rexmt);
542239075Strociny	if ((inp->inp_flags & INP_DROPPED) != 0) {
543239075Strociny		INP_WUNLOCK(inp);
544239075Strociny		INP_INFO_RUNLOCK(&V_tcbinfo);
545239075Strociny		CURVNET_RESTORE();
546239075Strociny		return;
547239075Strociny	}
548282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0,
549282964Sjch		("%s: tp %p tcpcb can't be stopped here", __func__, tp));
550282964Sjch	KASSERT((tp->t_timers->tt_flags & TT_REXMT) != 0,
551282964Sjch		("%s: tp %p rexmt callout should be running", __func__, tp));
552130989Sps	tcp_free_sackholes(tp);
55350673Sjlemon	/*
55450673Sjlemon	 * Retransmission timer went off.  Message has not
55550673Sjlemon	 * been acked within retransmit interval.  Back off
55650673Sjlemon	 * to a longer retransmit interval and retransmit one segment.
55750673Sjlemon	 */
55850673Sjlemon	if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
55950673Sjlemon		tp->t_rxtshift = TCP_MAXRXTSHIFT;
560190948Srwatson		TCPSTAT_INC(tcps_timeoutdrop);
561226318Snp
562172074Srwatson		tp = tcp_drop(tp, tp->t_softerror ?
563172074Srwatson			      tp->t_softerror : ETIMEDOUT);
564205391Skmacy		headlocked = 1;
565172074Srwatson		goto out;
56650673Sjlemon	}
567205391Skmacy	INP_INFO_RUNLOCK(&V_tcbinfo);
568172074Srwatson	headlocked = 0;
569242250Sandre	if (tp->t_state == TCPS_SYN_SENT) {
57013229Solah		/*
571242250Sandre		 * If the SYN was retransmitted, indicate CWND to be
572242250Sandre		 * limited to 1 segment in cc_conn_init().
573242250Sandre		 */
574242250Sandre		tp->snd_cwnd = 1;
575242250Sandre	} else if (tp->t_rxtshift == 1) {
576242250Sandre		/*
57750673Sjlemon		 * first retransmit; record ssthresh and cwnd so they can
578133874Srwatson		 * be recovered if this turns out to be a "bad" retransmit.
579133874Srwatson		 * A retransmit is considered "bad" if an ACK for this
58050673Sjlemon		 * segment is received within RTT/2 interval; the assumption
581133874Srwatson		 * here is that the ACK was already in flight.  See
58250673Sjlemon		 * "On Estimating End-to-End Network Path Properties" by
58350673Sjlemon		 * Allman and Paxson for more details.
5841541Srgrimes		 */
58550673Sjlemon		tp->snd_cwnd_prev = tp->snd_cwnd;
58650673Sjlemon		tp->snd_ssthresh_prev = tp->snd_ssthresh;
587117650Shsu		tp->snd_recover_prev = tp->snd_recover;
588215166Slstewart		if (IN_FASTRECOVERY(tp->t_flags))
589215166Slstewart			tp->t_flags |= TF_WASFRECOVERY;
590117650Shsu		else
591215166Slstewart			tp->t_flags &= ~TF_WASFRECOVERY;
592215166Slstewart		if (IN_CONGRECOVERY(tp->t_flags))
593215166Slstewart			tp->t_flags |= TF_WASCRECOVERY;
594215166Slstewart		else
595215166Slstewart			tp->t_flags &= ~TF_WASCRECOVERY;
59650673Sjlemon		tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
597221209Sjhb		tp->t_flags |= TF_PREVVALID;
598221209Sjhb	} else
599221209Sjhb		tp->t_flags &= ~TF_PREVVALID;
600190948Srwatson	TCPSTAT_INC(tcps_rexmttimeo);
601292823Spkelsey	if ((tp->t_state == TCPS_SYN_SENT) ||
602292823Spkelsey	    (tp->t_state == TCPS_SYN_RECEIVED))
603242260Sandre		rexmt = TCPTV_RTOBASE * tcp_syn_backoff[tp->t_rxtshift];
60473110Sjlemon	else
60573110Sjlemon		rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
60650673Sjlemon	TCPT_RANGESET(tp->t_rxtcur, rexmt,
60750673Sjlemon		      tp->t_rttmin, TCPTV_REXMTMAX);
608273838Ssbruno
60950673Sjlemon	/*
610273838Ssbruno	 * We enter the path for PLMTUD if connection is established or, if
611273838Ssbruno	 * connection is FIN_WAIT_1 status, reason for the last is that if
612273838Ssbruno	 * amount of data we send is very small, we could send it in couple of
613273838Ssbruno	 * packets and process straight to FIN. In that case we won't catch
614273838Ssbruno	 * ESTABLISHED state.
615273838Ssbruno	 */
616273838Ssbruno	if (V_tcp_pmtud_blackhole_detect && (((tp->t_state == TCPS_ESTABLISHED))
617273838Ssbruno	    || (tp->t_state == TCPS_FIN_WAIT_1))) {
618273838Ssbruno		int optlen;
619273838Ssbruno#ifdef INET6
620273838Ssbruno		int isipv6;
621273838Ssbruno#endif
622273838Ssbruno
623290125Shiren		/*
624290125Shiren		 * Idea here is that at each stage of mtu probe (usually, 1448
625290125Shiren		 * -> 1188 -> 524) should be given 2 chances to recover before
626290125Shiren		 *  further clamping down. 'tp->t_rxtshift % 2 == 0' should
627290125Shiren		 *  take care of that.
628290125Shiren		 */
629273838Ssbruno		if (((tp->t_flags2 & (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) ==
630273838Ssbruno		    (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) &&
631290125Shiren		    (tp->t_rxtshift >= 2 && tp->t_rxtshift % 2 == 0)) {
632273838Ssbruno			/*
633273838Ssbruno			 * Enter Path MTU Black-hole Detection mechanism:
634273838Ssbruno			 * - Disable Path MTU Discovery (IP "DF" bit).
635273838Ssbruno			 * - Reduce MTU to lower value than what we
636273838Ssbruno			 *   negotiated with peer.
637273838Ssbruno			 */
638273838Ssbruno			/* Record that we may have found a black hole. */
639273838Ssbruno			tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
640273838Ssbruno
641273838Ssbruno			/* Keep track of previous MSS. */
642273838Ssbruno			optlen = tp->t_maxopd - tp->t_maxseg;
643273838Ssbruno			tp->t_pmtud_saved_maxopd = tp->t_maxopd;
644273838Ssbruno
645273838Ssbruno			/*
646273838Ssbruno			 * Reduce the MSS to blackhole value or to the default
647273838Ssbruno			 * in an attempt to retransmit.
648273838Ssbruno			 */
649273838Ssbruno#ifdef INET6
650273838Ssbruno			isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? 1 : 0;
651273838Ssbruno			if (isipv6 &&
652273838Ssbruno			    tp->t_maxopd > V_tcp_v6pmtud_blackhole_mss) {
653273838Ssbruno				/* Use the sysctl tuneable blackhole MSS. */
654273838Ssbruno				tp->t_maxopd = V_tcp_v6pmtud_blackhole_mss;
655273838Ssbruno				V_tcp_pmtud_blackhole_activated++;
656273838Ssbruno			} else if (isipv6) {
657273838Ssbruno				/* Use the default MSS. */
658273838Ssbruno				tp->t_maxopd = V_tcp_v6mssdflt;
659273838Ssbruno				/*
660273838Ssbruno				 * Disable Path MTU Discovery when we switch to
661273838Ssbruno				 * minmss.
662273838Ssbruno				 */
663273838Ssbruno				tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
664273838Ssbruno				V_tcp_pmtud_blackhole_activated_min_mss++;
665273838Ssbruno			}
666273838Ssbruno#endif
667273838Ssbruno#if defined(INET6) && defined(INET)
668273838Ssbruno			else
669273838Ssbruno#endif
670273838Ssbruno#ifdef INET
671273838Ssbruno			if (tp->t_maxopd > V_tcp_pmtud_blackhole_mss) {
672273838Ssbruno				/* Use the sysctl tuneable blackhole MSS. */
673273838Ssbruno				tp->t_maxopd = V_tcp_pmtud_blackhole_mss;
674273838Ssbruno				V_tcp_pmtud_blackhole_activated++;
675273838Ssbruno			} else {
676273838Ssbruno				/* Use the default MSS. */
677273838Ssbruno				tp->t_maxopd = V_tcp_mssdflt;
678273838Ssbruno				/*
679273838Ssbruno				 * Disable Path MTU Discovery when we switch to
680273838Ssbruno				 * minmss.
681273838Ssbruno				 */
682273838Ssbruno				tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
683273838Ssbruno				V_tcp_pmtud_blackhole_activated_min_mss++;
684273838Ssbruno			}
685273838Ssbruno#endif
686273838Ssbruno			tp->t_maxseg = tp->t_maxopd - optlen;
687273838Ssbruno			/*
688273838Ssbruno			 * Reset the slow-start flight size
689273838Ssbruno			 * as it may depend on the new MSS.
690273838Ssbruno			 */
691273838Ssbruno			if (CC_ALGO(tp)->conn_init != NULL)
692273838Ssbruno				CC_ALGO(tp)->conn_init(tp->ccv);
693273838Ssbruno		} else {
694273838Ssbruno			/*
695273838Ssbruno			 * If further retransmissions are still unsuccessful
696273838Ssbruno			 * with a lowered MTU, maybe this isn't a blackhole and
697273838Ssbruno			 * we restore the previous MSS and blackhole detection
698273838Ssbruno			 * flags.
699290125Shiren			 * The limit '6' is determined by giving each probe
700290125Shiren			 * stage (1448, 1188, 524) 2 chances to recover.
701273838Ssbruno			 */
702273838Ssbruno			if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) &&
703290125Shiren			    (tp->t_rxtshift > 6)) {
704273838Ssbruno				tp->t_flags2 |= TF2_PLPMTU_PMTUD;
705273838Ssbruno				tp->t_flags2 &= ~TF2_PLPMTU_BLACKHOLE;
706273838Ssbruno				optlen = tp->t_maxopd - tp->t_maxseg;
707273838Ssbruno				tp->t_maxopd = tp->t_pmtud_saved_maxopd;
708273838Ssbruno				tp->t_maxseg = tp->t_maxopd - optlen;
709273838Ssbruno				V_tcp_pmtud_blackhole_failed++;
710273838Ssbruno				/*
711273838Ssbruno				 * Reset the slow-start flight size as it
712273838Ssbruno				 * may depend on the new MSS.
713273838Ssbruno				 */
714273838Ssbruno				if (CC_ALGO(tp)->conn_init != NULL)
715273838Ssbruno					CC_ALGO(tp)->conn_init(tp->ccv);
716273838Ssbruno			}
717273838Ssbruno		}
718273838Ssbruno	}
719273838Ssbruno
720273838Ssbruno	/*
721242264Sandre	 * Disable RFC1323 and SACK if we haven't got any response to
722133874Srwatson	 * our third SYN to work-around some broken terminal servers
723133874Srwatson	 * (most of which have hopefully been retired) that have bad VJ
724133874Srwatson	 * header compression code which trashes TCP segments containing
72577539Sjesper	 * unknown-to-them TCP options.
72677539Sjesper	 */
727245238Sjhb	if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
728245238Sjhb	    (tp->t_rxtshift == 3))
729242263Sandre		tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT);
73077539Sjesper	/*
731122922Sandre	 * If we backed off this far, our srtt estimate is probably bogus.
732122922Sandre	 * Clobber it so we'll take the next rtt measurement as our srtt;
73350673Sjlemon	 * move the current srtt into rttvar to keep the current
73450673Sjlemon	 * retransmit times until then.
73550673Sjlemon	 */
73650673Sjlemon	if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
73755679Sshin#ifdef INET6
73855679Sshin		if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
73955679Sshin			in6_losing(tp->t_inpcb);
74055679Sshin#endif
74150673Sjlemon		tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
74250673Sjlemon		tp->t_srtt = 0;
74350673Sjlemon	}
74450673Sjlemon	tp->snd_nxt = tp->snd_una;
745117650Shsu	tp->snd_recover = tp->snd_max;
74650673Sjlemon	/*
74750673Sjlemon	 * Force a segment to be sent.
74850673Sjlemon	 */
74950673Sjlemon	tp->t_flags |= TF_ACKNOW;
75050673Sjlemon	/*
75150673Sjlemon	 * If timing a segment in this window, stop the timer.
75250673Sjlemon	 */
75350673Sjlemon	tp->t_rtttime = 0;
754215166Slstewart
755216101Slstewart	cc_cong_signal(tp, NULL, CC_RTO);
756215166Slstewart
75750673Sjlemon	(void) tcp_output(tp);
7581541Srgrimes
759172074Srwatsonout:
76050673Sjlemon#ifdef TCPDEBUG
761157136Srwatson	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
76297658Stanimura		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
76397658Stanimura			  PRU_SLOWTIMO);
7641541Srgrimes#endif
765172074Srwatson	if (tp != NULL)
766178285Srwatson		INP_WUNLOCK(inp);
767172074Srwatson	if (headlocked)
768309108Sjch		INP_INFO_RUNLOCK(&V_tcbinfo);
769183550Szec	CURVNET_RESTORE();
7701541Srgrimes}
771172074Srwatson
772172074Srwatsonvoid
773282964Sjchtcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta)
774172074Srwatson{
775172074Srwatson	struct callout *t_callout;
776282964Sjch	timeout_t *f_callout;
777205391Skmacy	struct inpcb *inp = tp->t_inpcb;
778205391Skmacy	int cpu = INP_CPU(inp);
779284261Sjch	uint32_t f_reset;
780172074Srwatson
781237263Snp#ifdef TCP_OFFLOAD
782237263Snp	if (tp->t_flags & TF_TOE)
783237263Snp		return;
784237263Snp#endif
785237263Snp
786282964Sjch	if (tp->t_timers->tt_flags & TT_STOPPED)
787282964Sjch		return;
788282964Sjch
789172074Srwatson	switch (timer_type) {
790172074Srwatson		case TT_DELACK:
791172309Ssilby			t_callout = &tp->t_timers->tt_delack;
792172074Srwatson			f_callout = tcp_timer_delack;
793284261Sjch			f_reset = TT_DELACK_RST;
794172074Srwatson			break;
795172074Srwatson		case TT_REXMT:
796172309Ssilby			t_callout = &tp->t_timers->tt_rexmt;
797172074Srwatson			f_callout = tcp_timer_rexmt;
798284261Sjch			f_reset = TT_REXMT_RST;
799172074Srwatson			break;
800172074Srwatson		case TT_PERSIST:
801172309Ssilby			t_callout = &tp->t_timers->tt_persist;
802172074Srwatson			f_callout = tcp_timer_persist;
803284261Sjch			f_reset = TT_PERSIST_RST;
804172074Srwatson			break;
805172074Srwatson		case TT_KEEP:
806172309Ssilby			t_callout = &tp->t_timers->tt_keep;
807172074Srwatson			f_callout = tcp_timer_keep;
808284261Sjch			f_reset = TT_KEEP_RST;
809172074Srwatson			break;
810172074Srwatson		case TT_2MSL:
811172309Ssilby			t_callout = &tp->t_timers->tt_2msl;
812172074Srwatson			f_callout = tcp_timer_2msl;
813284261Sjch			f_reset = TT_2MSL_RST;
814172074Srwatson			break;
815172074Srwatson		default:
816282964Sjch			panic("tp %p bad timer_type %#x", tp, timer_type);
817172074Srwatson		}
818172074Srwatson	if (delta == 0) {
819282964Sjch		if ((tp->t_timers->tt_flags & timer_type) &&
820284261Sjch		    callout_stop(t_callout) &&
821284261Sjch		    (tp->t_timers->tt_flags & f_reset)) {
822284261Sjch			tp->t_timers->tt_flags &= ~(timer_type | f_reset);
823282964Sjch		}
824172074Srwatson	} else {
825282964Sjch		if ((tp->t_timers->tt_flags & timer_type) == 0) {
826284261Sjch			tp->t_timers->tt_flags |= (timer_type | f_reset);
827282964Sjch			callout_reset_on(t_callout, delta, f_callout, tp, cpu);
828282964Sjch		} else {
829282964Sjch			/* Reset already running callout on the same CPU. */
830284261Sjch			if (!callout_reset(t_callout, delta, f_callout, tp)) {
831284261Sjch				/*
832284261Sjch				 * Callout not cancelled, consider it as not
833284261Sjch				 * properly restarted. */
834284261Sjch				tp->t_timers->tt_flags &= ~f_reset;
835284261Sjch			}
836282964Sjch		}
837172074Srwatson	}
838172074Srwatson}
839172074Srwatson
840172074Srwatsonint
841282964Sjchtcp_timer_active(struct tcpcb *tp, uint32_t timer_type)
842172074Srwatson{
843172074Srwatson	struct callout *t_callout;
844172074Srwatson
845172074Srwatson	switch (timer_type) {
846172074Srwatson		case TT_DELACK:
847172309Ssilby			t_callout = &tp->t_timers->tt_delack;
848172074Srwatson			break;
849172074Srwatson		case TT_REXMT:
850172309Ssilby			t_callout = &tp->t_timers->tt_rexmt;
851172074Srwatson			break;
852172074Srwatson		case TT_PERSIST:
853172309Ssilby			t_callout = &tp->t_timers->tt_persist;
854172074Srwatson			break;
855172074Srwatson		case TT_KEEP:
856172309Ssilby			t_callout = &tp->t_timers->tt_keep;
857172074Srwatson			break;
858172074Srwatson		case TT_2MSL:
859172309Ssilby			t_callout = &tp->t_timers->tt_2msl;
860172074Srwatson			break;
861172074Srwatson		default:
862282964Sjch			panic("tp %p bad timer_type %#x", tp, timer_type);
863172074Srwatson		}
864172074Srwatson	return callout_active(t_callout);
865172074Srwatson}
866197244Ssilby
867282964Sjchvoid
868282964Sjchtcp_timer_stop(struct tcpcb *tp, uint32_t timer_type)
869282964Sjch{
870282964Sjch	struct callout *t_callout;
871282964Sjch	timeout_t *f_callout;
872284261Sjch	uint32_t f_reset;
873282964Sjch
874282964Sjch	tp->t_timers->tt_flags |= TT_STOPPED;
875282964Sjch
876282964Sjch	switch (timer_type) {
877282964Sjch		case TT_DELACK:
878282964Sjch			t_callout = &tp->t_timers->tt_delack;
879282964Sjch			f_callout = tcp_timer_delack_discard;
880284261Sjch			f_reset = TT_DELACK_RST;
881282964Sjch			break;
882282964Sjch		case TT_REXMT:
883282964Sjch			t_callout = &tp->t_timers->tt_rexmt;
884282964Sjch			f_callout = tcp_timer_rexmt_discard;
885284261Sjch			f_reset = TT_REXMT_RST;
886282964Sjch			break;
887282964Sjch		case TT_PERSIST:
888282964Sjch			t_callout = &tp->t_timers->tt_persist;
889282964Sjch			f_callout = tcp_timer_persist_discard;
890284261Sjch			f_reset = TT_PERSIST_RST;
891282964Sjch			break;
892282964Sjch		case TT_KEEP:
893282964Sjch			t_callout = &tp->t_timers->tt_keep;
894282964Sjch			f_callout = tcp_timer_keep_discard;
895284261Sjch			f_reset = TT_KEEP_RST;
896282964Sjch			break;
897282964Sjch		case TT_2MSL:
898282964Sjch			t_callout = &tp->t_timers->tt_2msl;
899282964Sjch			f_callout = tcp_timer_2msl_discard;
900284261Sjch			f_reset = TT_2MSL_RST;
901282964Sjch			break;
902282964Sjch		default:
903282964Sjch			panic("tp %p bad timer_type %#x", tp, timer_type);
904282964Sjch		}
905282964Sjch
906282964Sjch	if (tp->t_timers->tt_flags & timer_type) {
907284261Sjch		if (callout_stop(t_callout) &&
908284261Sjch		    (tp->t_timers->tt_flags & f_reset)) {
909284261Sjch			tp->t_timers->tt_flags &= ~(timer_type | f_reset);
910282964Sjch		} else {
911282964Sjch			/*
912282964Sjch			 * Can't stop the callout, defer tcpcb actual deletion
913282964Sjch			 * to the last tcp timer discard callout.
914282964Sjch			 * The TT_STOPPED flag will ensure that no tcp timer
915282964Sjch			 * callouts can be restarted on our behalf, and
916282964Sjch			 * past this point currently running callouts waiting
917282964Sjch			 * on inp lock will return right away after the
918282964Sjch			 * classical check for callout reset/stop events:
919282964Sjch			 * callout_pending() || !callout_active()
920282964Sjch			 */
921282964Sjch			callout_reset(t_callout, 1, f_callout, tp);
922282964Sjch		}
923282964Sjch	}
924282964Sjch}
925282964Sjch
926197244Ssilby#define	ticks_to_msecs(t)	(1000*(t) / hz)
927197244Ssilby
928197244Ssilbyvoid
929247777Sdavidetcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer,
930247777Sdavide    struct xtcp_timer *xtimer)
931197244Ssilby{
932247777Sdavide	sbintime_t now;
933247777Sdavide
934247777Sdavide	bzero(xtimer, sizeof(*xtimer));
935197244Ssilby	if (timer == NULL)
936197244Ssilby		return;
937247777Sdavide	now = getsbinuptime();
938197244Ssilby	if (callout_active(&timer->tt_delack))
939247777Sdavide		xtimer->tt_delack = (timer->tt_delack.c_time - now) / SBT_1MS;
940197244Ssilby	if (callout_active(&timer->tt_rexmt))
941247777Sdavide		xtimer->tt_rexmt = (timer->tt_rexmt.c_time - now) / SBT_1MS;
942197244Ssilby	if (callout_active(&timer->tt_persist))
943247777Sdavide		xtimer->tt_persist = (timer->tt_persist.c_time - now) / SBT_1MS;
944197244Ssilby	if (callout_active(&timer->tt_keep))
945247777Sdavide		xtimer->tt_keep = (timer->tt_keep.c_time - now) / SBT_1MS;
946197244Ssilby	if (callout_active(&timer->tt_2msl))
947247777Sdavide		xtimer->tt_2msl = (timer->tt_2msl.c_time - now) / SBT_1MS;
948197244Ssilby	xtimer->t_rcvtime = ticks_to_msecs(ticks - tp->t_rcvtime);
949197244Ssilby}
950