]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/netinet/tcp_timer.c
MFC r297873
[FreeBSD/stable/8.git] / sys / netinet / tcp_timer.c
1 /*-
2  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *      @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include "opt_inet6.h"
36 #include "opt_tcpdebug.h"
37
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/lock.h>
41 #include <sys/mbuf.h>
42 #include <sys/mutex.h>
43 #include <sys/protosw.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/sysctl.h>
47 #include <sys/systm.h>
48
49 #include <net/if.h>
50 #include <net/route.h>
51 #include <net/vnet.h>
52
53 #include <netinet/cc.h>
54 #include <netinet/in.h>
55 #include <netinet/in_pcb.h>
56 #include <netinet/in_systm.h>
57 #ifdef INET6
58 #include <netinet6/in6_pcb.h>
59 #endif
60 #include <netinet/ip_var.h>
61 #include <netinet/tcp_fsm.h>
62 #include <netinet/tcp_timer.h>
63 #include <netinet/tcp_var.h>
64 #include <netinet/tcpip.h>
65 #ifdef TCPDEBUG
66 #include <netinet/tcp_debug.h>
67 #endif
68
69 int     tcp_keepinit;
70 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit, CTLTYPE_INT|CTLFLAG_RW,
71     &tcp_keepinit, 0, sysctl_msec_to_ticks, "I", "time to establish connection");
72
73 int     tcp_keepidle;
74 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle, CTLTYPE_INT|CTLFLAG_RW,
75     &tcp_keepidle, 0, sysctl_msec_to_ticks, "I", "time before keepalive probes begin");
76
77 int     tcp_keepintvl;
78 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl, CTLTYPE_INT|CTLFLAG_RW,
79     &tcp_keepintvl, 0, sysctl_msec_to_ticks, "I", "time between keepalive probes");
80
81 int     tcp_delacktime;
82 SYSCTL_PROC(_net_inet_tcp, TCPCTL_DELACKTIME, delacktime, CTLTYPE_INT|CTLFLAG_RW,
83     &tcp_delacktime, 0, sysctl_msec_to_ticks, "I",
84     "Time before a delayed ACK is sent");
85
86 int     tcp_msl;
87 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW,
88     &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime");
89
90 int     tcp_rexmit_min;
91 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW,
92     &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I",
93     "Minimum Retransmission Timeout");
94
95 int     tcp_rexmit_slop;
96 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_slop, CTLTYPE_INT|CTLFLAG_RW,
97     &tcp_rexmit_slop, 0, sysctl_msec_to_ticks, "I",
98     "Retransmission Timer Slop");
99
100 static int      always_keepalive = 1;
101 SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW,
102     &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections");
103
104 int    tcp_fast_finwait2_recycle = 0;
105 SYSCTL_INT(_net_inet_tcp, OID_AUTO, fast_finwait2_recycle, CTLFLAG_RW, 
106     &tcp_fast_finwait2_recycle, 0,
107     "Recycle closed FIN_WAIT_2 connections faster");
108
109 int    tcp_finwait2_timeout;
110 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout, CTLTYPE_INT|CTLFLAG_RW,
111     &tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I", "FIN-WAIT2 timeout");
112
113
114 static int      tcp_keepcnt = TCPTV_KEEPCNT;
115         /* max idle probes */
116 int     tcp_maxpersistidle;
117         /* max idle time in persist */
118 int     tcp_maxidle;
119
120 static int      tcp_rexmit_drop_options = 1;
121 SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
122     &tcp_rexmit_drop_options, 0,
123     "Drop TCP options from 3rd and later retransmitted SYN");
124
125 /*
126  * Tcp protocol timeout routine called every 500 ms.
127  * Updates timestamps used for TCP
128  * causes finite state machine actions if timers expire.
129  */
130 void
131 tcp_slowtimo(void)
132 {
133         VNET_ITERATOR_DECL(vnet_iter);
134
135         VNET_LIST_RLOCK_NOSLEEP();
136         VNET_FOREACH(vnet_iter) {
137                 CURVNET_SET(vnet_iter);
138                 tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
139                 INP_INFO_WLOCK(&V_tcbinfo);
140                 (void) tcp_tw_2msl_scan(0);
141                 INP_INFO_WUNLOCK(&V_tcbinfo);
142                 CURVNET_RESTORE();
143         }
144         VNET_LIST_RUNLOCK_NOSLEEP();
145 }
146
147 int     tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
148     { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 };
149
150 int     tcp_backoff[TCP_MAXRXTSHIFT + 1] =
151     { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 };
152
153 static int tcp_totbackoff = 2559;       /* sum of tcp_backoff[] */
154
155 static int tcp_timer_race;
156 SYSCTL_INT(_net_inet_tcp, OID_AUTO, timer_race, CTLFLAG_RD, &tcp_timer_race,
157     0, "Count of t_inpcb races on tcp_discardcb");
158
159 /*
160  * TCP timer processing.
161  */
162
163 void
164 tcp_timer_delack(void *xtp)
165 {
166         struct tcpcb *tp = xtp;
167         struct inpcb *inp;
168         CURVNET_SET(tp->t_vnet);
169
170         inp = tp->t_inpcb;
171         /*
172          * XXXRW: While this assert is in fact correct, bugs in the tcpcb
173          * tear-down mean we need it as a work-around for races between
174          * timers and tcp_discardcb().
175          *
176          * KASSERT(inp != NULL, ("tcp_timer_delack: inp == NULL"));
177          */
178         if (inp == NULL) {
179                 tcp_timer_race++;
180                 CURVNET_RESTORE();
181                 return;
182         }
183         INP_WLOCK(inp);
184         if (callout_pending(&tp->t_timers->tt_delack) ||
185             !callout_active(&tp->t_timers->tt_delack)) {
186                 INP_WUNLOCK(inp);
187                 CURVNET_RESTORE();
188                 return;
189         }
190         callout_deactivate(&tp->t_timers->tt_delack);
191         if ((inp->inp_flags & INP_DROPPED) != 0) {
192                 INP_WUNLOCK(inp);
193                 CURVNET_RESTORE();
194                 return;
195         }
196
197         tp->t_flags |= TF_ACKNOW;
198         TCPSTAT_INC(tcps_delack);
199         (void) tcp_output(tp);
200         INP_WUNLOCK(inp);
201         CURVNET_RESTORE();
202 }
203
204 void
205 tcp_timer_2msl(void *xtp)
206 {
207         struct tcpcb *tp = xtp;
208         struct inpcb *inp;
209         CURVNET_SET(tp->t_vnet);
210 #ifdef TCPDEBUG
211         int ostate;
212
213         ostate = tp->t_state;
214 #endif
215         /*
216          * XXXRW: Does this actually happen?
217          */
218         INP_INFO_WLOCK(&V_tcbinfo);
219         inp = tp->t_inpcb;
220         /*
221          * XXXRW: While this assert is in fact correct, bugs in the tcpcb
222          * tear-down mean we need it as a work-around for races between
223          * timers and tcp_discardcb().
224          *
225          * KASSERT(inp != NULL, ("tcp_timer_2msl: inp == NULL"));
226          */
227         if (inp == NULL) {
228                 tcp_timer_race++;
229                 INP_INFO_WUNLOCK(&V_tcbinfo);
230                 CURVNET_RESTORE();
231                 return;
232         }
233         INP_WLOCK(inp);
234         tcp_free_sackholes(tp);
235         if (callout_pending(&tp->t_timers->tt_2msl) ||
236             !callout_active(&tp->t_timers->tt_2msl)) {
237                 INP_WUNLOCK(tp->t_inpcb);
238                 INP_INFO_WUNLOCK(&V_tcbinfo);
239                 CURVNET_RESTORE();
240                 return;
241         }
242         callout_deactivate(&tp->t_timers->tt_2msl);
243         if ((inp->inp_flags & INP_DROPPED) != 0) {
244                 INP_WUNLOCK(inp);
245                 INP_INFO_WUNLOCK(&V_tcbinfo);
246                 CURVNET_RESTORE();
247                 return;
248         }
249         /*
250          * 2 MSL timeout in shutdown went off.  If we're closed but
251          * still waiting for peer to close and connection has been idle
252          * too long, or if 2MSL time is up from TIME_WAIT, delete connection
253          * control block.  Otherwise, check again in a bit.
254          *
255          * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed, 
256          * there's no point in hanging onto FIN_WAIT_2 socket. Just close it. 
257          * Ignore fact that there were recent incoming segments.
258          */
259         if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 &&
260             tp->t_inpcb && tp->t_inpcb->inp_socket && 
261             (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
262                 TCPSTAT_INC(tcps_finwait2_drops);
263                 tp = tcp_close(tp);             
264         } else {
265                 if (tp->t_state != TCPS_TIME_WAIT &&
266                    ticks - tp->t_rcvtime <= tcp_maxidle)
267                        callout_reset(&tp->t_timers->tt_2msl, tcp_keepintvl,
268                                      tcp_timer_2msl, tp);
269                else
270                        tp = tcp_close(tp);
271        }
272
273 #ifdef TCPDEBUG
274         if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
275                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
276                           PRU_SLOWTIMO);
277 #endif
278         if (tp != NULL)
279                 INP_WUNLOCK(inp);
280         INP_INFO_WUNLOCK(&V_tcbinfo);
281         CURVNET_RESTORE();
282 }
283
284 void
285 tcp_timer_keep(void *xtp)
286 {
287         struct tcpcb *tp = xtp;
288         struct tcptemp *t_template;
289         struct inpcb *inp;
290         CURVNET_SET(tp->t_vnet);
291 #ifdef TCPDEBUG
292         int ostate;
293
294         ostate = tp->t_state;
295 #endif
296         INP_INFO_WLOCK(&V_tcbinfo);
297         inp = tp->t_inpcb;
298         /*
299          * XXXRW: While this assert is in fact correct, bugs in the tcpcb
300          * tear-down mean we need it as a work-around for races between
301          * timers and tcp_discardcb().
302          *
303          * KASSERT(inp != NULL, ("tcp_timer_keep: inp == NULL"));
304          */
305         if (inp == NULL) {
306                 tcp_timer_race++;
307                 INP_INFO_WUNLOCK(&V_tcbinfo);
308                 CURVNET_RESTORE();
309                 return;
310         }
311         INP_WLOCK(inp);
312         if (callout_pending(&tp->t_timers->tt_keep) ||
313             !callout_active(&tp->t_timers->tt_keep)) {
314                 INP_WUNLOCK(inp);
315                 INP_INFO_WUNLOCK(&V_tcbinfo);
316                 CURVNET_RESTORE();
317                 return;
318         }
319         callout_deactivate(&tp->t_timers->tt_keep);
320         if ((inp->inp_flags & INP_DROPPED) != 0) {
321                 INP_WUNLOCK(inp);
322                 INP_INFO_WUNLOCK(&V_tcbinfo);
323                 CURVNET_RESTORE();
324                 return;
325         }
326         /*
327          * Keep-alive timer went off; send something
328          * or drop connection if idle for too long.
329          */
330         TCPSTAT_INC(tcps_keeptimeo);
331         if (tp->t_state < TCPS_ESTABLISHED)
332                 goto dropit;
333         if ((always_keepalive || inp->inp_socket->so_options & SO_KEEPALIVE) &&
334             tp->t_state <= TCPS_CLOSING) {
335                 if (ticks - tp->t_rcvtime >= tcp_keepidle + tcp_maxidle)
336                         goto dropit;
337                 /*
338                  * Send a packet designed to force a response
339                  * if the peer is up and reachable:
340                  * either an ACK if the connection is still alive,
341                  * or an RST if the peer has closed the connection
342                  * due to timeout or reboot.
343                  * Using sequence number tp->snd_una-1
344                  * causes the transmitted zero-length segment
345                  * to lie outside the receive window;
346                  * by the protocol spec, this requires the
347                  * correspondent TCP to respond.
348                  */
349                 TCPSTAT_INC(tcps_keepprobe);
350                 t_template = tcpip_maketemplate(inp);
351                 if (t_template) {
352                         tcp_respond(tp, t_template->tt_ipgen,
353                                     &t_template->tt_t, (struct mbuf *)NULL,
354                                     tp->rcv_nxt, tp->snd_una - 1, 0);
355                         free(t_template, M_TEMP);
356                 }
357                 callout_reset(&tp->t_timers->tt_keep, tcp_keepintvl, tcp_timer_keep, tp);
358         } else
359                 callout_reset(&tp->t_timers->tt_keep, tcp_keepidle, tcp_timer_keep, tp);
360
361 #ifdef TCPDEBUG
362         if (inp->inp_socket->so_options & SO_DEBUG)
363                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
364                           PRU_SLOWTIMO);
365 #endif
366         INP_WUNLOCK(inp);
367         INP_INFO_WUNLOCK(&V_tcbinfo);
368         CURVNET_RESTORE();
369         return;
370
371 dropit:
372         TCPSTAT_INC(tcps_keepdrops);
373         tp = tcp_drop(tp, ETIMEDOUT);
374
375 #ifdef TCPDEBUG
376         if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
377                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
378                           PRU_SLOWTIMO);
379 #endif
380         if (tp != NULL)
381                 INP_WUNLOCK(tp->t_inpcb);
382         INP_INFO_WUNLOCK(&V_tcbinfo);
383         CURVNET_RESTORE();
384 }
385
386 void
387 tcp_timer_persist(void *xtp)
388 {
389         struct tcpcb *tp = xtp;
390         struct inpcb *inp;
391         CURVNET_SET(tp->t_vnet);
392 #ifdef TCPDEBUG
393         int ostate;
394
395         ostate = tp->t_state;
396 #endif
397         INP_INFO_WLOCK(&V_tcbinfo);
398         inp = tp->t_inpcb;
399         /*
400          * XXXRW: While this assert is in fact correct, bugs in the tcpcb
401          * tear-down mean we need it as a work-around for races between
402          * timers and tcp_discardcb().
403          *
404          * KASSERT(inp != NULL, ("tcp_timer_persist: inp == NULL"));
405          */
406         if (inp == NULL) {
407                 tcp_timer_race++;
408                 INP_INFO_WUNLOCK(&V_tcbinfo);
409                 CURVNET_RESTORE();
410                 return;
411         }
412         INP_WLOCK(inp);
413         if (callout_pending(&tp->t_timers->tt_persist) ||
414             !callout_active(&tp->t_timers->tt_persist)) {
415                 INP_WUNLOCK(inp);
416                 INP_INFO_WUNLOCK(&V_tcbinfo);
417                 CURVNET_RESTORE();
418                 return;
419         }
420         callout_deactivate(&tp->t_timers->tt_persist);
421         if ((inp->inp_flags & INP_DROPPED) != 0) {
422                 INP_WUNLOCK(inp);
423                 INP_INFO_WUNLOCK(&V_tcbinfo);
424                 CURVNET_RESTORE();
425                 return;
426         }
427         /*
428          * Persistance timer into zero window.
429          * Force a byte to be output, if possible.
430          */
431         TCPSTAT_INC(tcps_persisttimeo);
432         /*
433          * Hack: if the peer is dead/unreachable, we do not
434          * time out if the window is closed.  After a full
435          * backoff, drop the connection if the idle time
436          * (no responses to probes) reaches the maximum
437          * backoff that we would use if retransmitting.
438          */
439         if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
440             (ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
441              ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
442                 TCPSTAT_INC(tcps_persistdrop);
443                 tp = tcp_drop(tp, ETIMEDOUT);
444                 goto out;
445         }
446         tcp_setpersist(tp);
447         tp->t_flags |= TF_FORCEDATA;
448         (void) tcp_output(tp);
449         tp->t_flags &= ~TF_FORCEDATA;
450
451 out:
452 #ifdef TCPDEBUG
453         if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
454                 tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO);
455 #endif
456         if (tp != NULL)
457                 INP_WUNLOCK(inp);
458         INP_INFO_WUNLOCK(&V_tcbinfo);
459         CURVNET_RESTORE();
460 }
461
462 void
463 tcp_timer_rexmt(void * xtp)
464 {
465         struct tcpcb *tp = xtp;
466         CURVNET_SET(tp->t_vnet);
467         int rexmt;
468         int headlocked;
469         struct inpcb *inp;
470 #ifdef TCPDEBUG
471         int ostate;
472
473         ostate = tp->t_state;
474 #endif
475         INP_INFO_WLOCK(&V_tcbinfo);
476         headlocked = 1;
477         inp = tp->t_inpcb;
478         /*
479          * XXXRW: While this assert is in fact correct, bugs in the tcpcb
480          * tear-down mean we need it as a work-around for races between
481          * timers and tcp_discardcb().
482          *
483          * KASSERT(inp != NULL, ("tcp_timer_rexmt: inp == NULL"));
484          */
485         if (inp == NULL) {
486                 tcp_timer_race++;
487                 INP_INFO_WUNLOCK(&V_tcbinfo);
488                 CURVNET_RESTORE();
489                 return;
490         }
491         INP_WLOCK(inp);
492         if (callout_pending(&tp->t_timers->tt_rexmt) ||
493             !callout_active(&tp->t_timers->tt_rexmt)) {
494                 INP_WUNLOCK(inp);
495                 INP_INFO_WUNLOCK(&V_tcbinfo);
496                 CURVNET_RESTORE();
497                 return;
498         }
499         callout_deactivate(&tp->t_timers->tt_rexmt);
500         if ((inp->inp_flags & INP_DROPPED) != 0) {
501                 INP_WUNLOCK(inp);
502                 INP_INFO_WUNLOCK(&V_tcbinfo);
503                 CURVNET_RESTORE();
504                 return;
505         }
506         tcp_free_sackholes(tp);
507         /*
508          * Retransmission timer went off.  Message has not
509          * been acked within retransmit interval.  Back off
510          * to a longer retransmit interval and retransmit one segment.
511          */
512         if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
513                 tp->t_rxtshift = TCP_MAXRXTSHIFT;
514                 TCPSTAT_INC(tcps_timeoutdrop);
515                 tp = tcp_drop(tp, tp->t_softerror ?
516                               tp->t_softerror : ETIMEDOUT);
517                 goto out;
518         }
519         INP_INFO_WUNLOCK(&V_tcbinfo);
520         headlocked = 0;
521         if (tp->t_rxtshift == 1) {
522                 /*
523                  * first retransmit; record ssthresh and cwnd so they can
524                  * be recovered if this turns out to be a "bad" retransmit.
525                  * A retransmit is considered "bad" if an ACK for this
526                  * segment is received within RTT/2 interval; the assumption
527                  * here is that the ACK was already in flight.  See
528                  * "On Estimating End-to-End Network Path Properties" by
529                  * Allman and Paxson for more details.
530                  */
531                 tp->snd_cwnd_prev = tp->snd_cwnd;
532                 tp->snd_ssthresh_prev = tp->snd_ssthresh;
533                 tp->snd_recover_prev = tp->snd_recover;
534                 if (IN_FASTRECOVERY(tp->t_flags))
535                         tp->t_flags |= TF_WASFRECOVERY;
536                 else
537                         tp->t_flags &= ~TF_WASFRECOVERY;
538                 if (IN_CONGRECOVERY(tp->t_flags))
539                         tp->t_flags |= TF_WASCRECOVERY;
540                 else
541                         tp->t_flags &= ~TF_WASCRECOVERY;
542                 tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
543                 tp->t_flags |= TF_PREVVALID;
544         } else
545                 tp->t_flags &= ~TF_PREVVALID;
546         TCPSTAT_INC(tcps_rexmttimeo);
547         if (tp->t_state == TCPS_SYN_SENT)
548                 rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
549         else
550                 rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
551         TCPT_RANGESET(tp->t_rxtcur, rexmt,
552                       tp->t_rttmin, TCPTV_REXMTMAX);
553         /*
554          * Disable rfc1323 if we haven't got any response to
555          * our third SYN to work-around some broken terminal servers
556          * (most of which have hopefully been retired) that have bad VJ
557          * header compression code which trashes TCP segments containing
558          * unknown-to-them TCP options.
559          */
560         if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
561             (tp->t_rxtshift == 3))
562                 tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP);
563         /*
564          * If we backed off this far, our srtt estimate is probably bogus.
565          * Clobber it so we'll take the next rtt measurement as our srtt;
566          * move the current srtt into rttvar to keep the current
567          * retransmit times until then.
568          */
569         if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
570 #ifdef INET6
571                 if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
572                         in6_losing(tp->t_inpcb);
573                 else
574 #endif
575                 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
576                 tp->t_srtt = 0;
577         }
578         tp->snd_nxt = tp->snd_una;
579         tp->snd_recover = tp->snd_max;
580         /*
581          * Force a segment to be sent.
582          */
583         tp->t_flags |= TF_ACKNOW;
584         /*
585          * If timing a segment in this window, stop the timer.
586          */
587         tp->t_rtttime = 0;
588
589         cc_cong_signal(tp, NULL, CC_RTO);
590
591         (void) tcp_output(tp);
592
593 out:
594 #ifdef TCPDEBUG
595         if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
596                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
597                           PRU_SLOWTIMO);
598 #endif
599         if (tp != NULL)
600                 INP_WUNLOCK(inp);
601         if (headlocked)
602                 INP_INFO_WUNLOCK(&V_tcbinfo);
603         CURVNET_RESTORE();
604 }
605
606 void
607 tcp_timer_activate(struct tcpcb *tp, int timer_type, u_int delta)
608 {
609         struct callout *t_callout;
610         void *f_callout;
611
612         switch (timer_type) {
613                 case TT_DELACK:
614                         t_callout = &tp->t_timers->tt_delack;
615                         f_callout = tcp_timer_delack;
616                         break;
617                 case TT_REXMT:
618                         t_callout = &tp->t_timers->tt_rexmt;
619                         f_callout = tcp_timer_rexmt;
620                         break;
621                 case TT_PERSIST:
622                         t_callout = &tp->t_timers->tt_persist;
623                         f_callout = tcp_timer_persist;
624                         break;
625                 case TT_KEEP:
626                         t_callout = &tp->t_timers->tt_keep;
627                         f_callout = tcp_timer_keep;
628                         break;
629                 case TT_2MSL:
630                         t_callout = &tp->t_timers->tt_2msl;
631                         f_callout = tcp_timer_2msl;
632                         break;
633                 default:
634                         panic("bad timer_type");
635                 }
636         if (delta == 0) {
637                 callout_stop(t_callout);
638         } else {
639                 callout_reset(t_callout, delta, f_callout, tp);
640         }
641 }
642
643 int
644 tcp_timer_active(struct tcpcb *tp, int timer_type)
645 {
646         struct callout *t_callout;
647
648         switch (timer_type) {
649                 case TT_DELACK:
650                         t_callout = &tp->t_timers->tt_delack;
651                         break;
652                 case TT_REXMT:
653                         t_callout = &tp->t_timers->tt_rexmt;
654                         break;
655                 case TT_PERSIST:
656                         t_callout = &tp->t_timers->tt_persist;
657                         break;
658                 case TT_KEEP:
659                         t_callout = &tp->t_timers->tt_keep;
660                         break;
661                 case TT_2MSL:
662                         t_callout = &tp->t_timers->tt_2msl;
663                         break;
664                 default:
665                         panic("bad timer_type");
666                 }
667         return callout_active(t_callout);
668 }