1 /* $NetBSD: tcp_timer.c,v 1.91 2016/07/25 00:10:38 knakahara Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 1997, 1998, 2001, 2005 The NetBSD Foundation, Inc.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Jason R. Thorpe and Kevin M. Lahey of the Numerical Aerospace Simulation
38 * Facility, NASA Ames Research Center.
39 * This code is derived from software contributed to The NetBSD Foundation
40 * by Charles M. Hannum.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
62 */
63
64 /*
65 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
66 * The Regents of the University of California. All rights reserved.
67 *
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
70 * are met:
71 * 1. Redistributions of source code must retain the above copyright
72 * notice, this list of conditions and the following disclaimer.
73 * 2. Redistributions in binary form must reproduce the above copyright
74 * notice, this list of conditions and the following disclaimer in the
75 * documentation and/or other materials provided with the distribution.
76 * 3. Neither the name of the University nor the names of its contributors
77 * may be used to endorse or promote products derived from this software
78 * without specific prior written permission.
79 *
80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90 * SUCH DAMAGE.
91 *
92 * @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
93 */
94
95 #include <sys/cdefs.h>
96 __KERNEL_RCSID(0, "$NetBSD: tcp_timer.c,v 1.91 2016/07/25 00:10:38 knakahara Exp $");
97
98 #ifdef _KERNEL_OPT
99 #include "opt_inet.h"
100 #include "opt_tcp_debug.h"
101 #endif
102
103 #include <sys/param.h>
104 #include <sys/systm.h>
105 #include <sys/mbuf.h>
106 #include <sys/socket.h>
107 #include <sys/socketvar.h>
108 #include <sys/protosw.h>
109 #include <sys/errno.h>
110 #include <sys/kernel.h>
111
112 #include <net/if.h>
113
114 #include <netinet/in.h>
115 #include <netinet/in_systm.h>
116 #include <netinet/ip.h>
117 #include <netinet/in_pcb.h>
118 #include <netinet/ip_var.h>
119 #include <netinet/ip_icmp.h>
120
121 #ifdef INET6
122 #ifndef INET
123 #include <netinet/in.h>
124 #endif
125 #include <netinet/ip6.h>
126 #include <netinet6/in6_pcb.h>
127 #endif
128
129 #include <netinet/tcp.h>
130 #include <netinet/tcp_fsm.h>
131 #include <netinet/tcp_seq.h>
132 #include <netinet/tcp_timer.h>
133 #include <netinet/tcp_var.h>
134 #include <netinet/tcp_private.h>
135 #include <netinet/tcp_congctl.h>
136 #include <netinet/tcpip.h>
137 #ifdef TCP_DEBUG
138 #include <netinet/tcp_debug.h>
139 #endif
140
141 /*
142 * Various tunable timer parameters. These are initialized in tcp_init(),
143 * unless they are patched.
144 */
145 u_int tcp_keepinit = 0;
146 u_int tcp_keepidle = 0;
147 u_int tcp_keepintvl = 0;
148 u_int tcp_keepcnt = 0; /* max idle probes */
149
150 int tcp_maxpersistidle = 0; /* max idle time in persist */
151
152 /*
153 * Time to delay the ACK. This is initialized in tcp_init(), unless
154 * its patched.
155 */
156 int tcp_delack_ticks = 0;
157
158 void tcp_timer_rexmt(void *);
159 void tcp_timer_persist(void *);
160 void tcp_timer_keep(void *);
161 void tcp_timer_2msl(void *);
162
163 const tcp_timer_func_t tcp_timer_funcs[TCPT_NTIMERS] = {
164 tcp_timer_rexmt,
165 tcp_timer_persist,
166 tcp_timer_keep,
167 tcp_timer_2msl,
168 };
169
170 /*
171 * Timer state initialization, called from tcp_init().
172 */
173 void
tcp_timer_init(void)174 tcp_timer_init(void)
175 {
176
177 if (tcp_keepinit == 0)
178 tcp_keepinit = TCPTV_KEEP_INIT;
179
180 if (tcp_keepidle == 0)
181 tcp_keepidle = TCPTV_KEEP_IDLE;
182
183 if (tcp_keepintvl == 0)
184 tcp_keepintvl = TCPTV_KEEPINTVL;
185
186 if (tcp_keepcnt == 0)
187 tcp_keepcnt = TCPTV_KEEPCNT;
188
189 if (tcp_maxpersistidle == 0)
190 tcp_maxpersistidle = TCPTV_KEEP_IDLE;
191
192 if (tcp_delack_ticks == 0)
193 tcp_delack_ticks = TCP_DELACK_TICKS;
194 }
195
196 /*
197 * Callout to process delayed ACKs for a TCPCB.
198 */
199 void
tcp_delack(void * arg)200 tcp_delack(void *arg)
201 {
202 struct tcpcb *tp = arg;
203
204 /*
205 * If tcp_output() wasn't able to transmit the ACK
206 * for whatever reason, it will restart the delayed
207 * ACK callout.
208 */
209
210 mutex_enter(softnet_lock);
211 if ((tp->t_flags & (TF_DEAD | TF_DELACK)) != TF_DELACK) {
212 mutex_exit(softnet_lock);
213 return;
214 }
215 if (!callout_expired(&tp->t_delack_ch)) {
216 mutex_exit(softnet_lock);
217 return;
218 }
219
220 tp->t_flags |= TF_ACKNOW;
221 KERNEL_LOCK(1, NULL);
222 (void) tcp_output(tp);
223 KERNEL_UNLOCK_ONE(NULL);
224 mutex_exit(softnet_lock);
225 }
226
227 /*
228 * Tcp protocol timeout routine called every 500 ms.
229 * Updates the timers in all active tcb's and
230 * causes finite state machine actions if timers expire.
231 */
232 void
tcp_slowtimo(void * arg)233 tcp_slowtimo(void *arg)
234 {
235
236 mutex_enter(softnet_lock);
237 tcp_iss_seq += TCP_ISSINCR; /* increment iss */
238 tcp_now++; /* for timestamps */
239 mutex_exit(softnet_lock);
240
241 callout_schedule(&tcp_slowtimo_ch, hz / PR_SLOWHZ);
242 }
243
244 /*
245 * Cancel all timers for TCP tp.
246 */
247 void
tcp_canceltimers(struct tcpcb * tp)248 tcp_canceltimers(struct tcpcb *tp)
249 {
250 int i;
251
252 for (i = 0; i < TCPT_NTIMERS; i++)
253 TCP_TIMER_DISARM(tp, i);
254 }
255
256 const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
257 { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
258
259 const int tcp_totbackoff = 511; /* sum of tcp_backoff[] */
260
261 /*
262 * TCP timer processing.
263 */
264
265 void
tcp_timer_rexmt(void * arg)266 tcp_timer_rexmt(void *arg)
267 {
268 struct tcpcb *tp = arg;
269 uint32_t rto;
270 #ifdef TCP_DEBUG
271 struct socket *so = NULL;
272 short ostate;
273 #endif
274
275 mutex_enter(softnet_lock);
276 if ((tp->t_flags & TF_DEAD) != 0) {
277 mutex_exit(softnet_lock);
278 return;
279 }
280 if (!callout_expired(&tp->t_timer[TCPT_REXMT])) {
281 mutex_exit(softnet_lock);
282 return;
283 }
284
285 KERNEL_LOCK(1, NULL);
286 if ((tp->t_flags & TF_PMTUD_PEND) && tp->t_inpcb &&
287 SEQ_GEQ(tp->t_pmtud_th_seq, tp->snd_una) &&
288 SEQ_LT(tp->t_pmtud_th_seq, (int)(tp->snd_una + tp->t_ourmss))) {
289 extern struct sockaddr_in icmpsrc;
290 struct icmp icmp;
291
292 tp->t_flags &= ~TF_PMTUD_PEND;
293
294 /* XXX create fake icmp message with relevant entries */
295 icmp.icmp_nextmtu = tp->t_pmtud_nextmtu;
296 icmp.icmp_ip.ip_len = tp->t_pmtud_ip_len;
297 icmp.icmp_ip.ip_hl = tp->t_pmtud_ip_hl;
298 icmpsrc.sin_addr = tp->t_inpcb->inp_faddr;
299 icmp_mtudisc(&icmp, icmpsrc.sin_addr);
300
301 /*
302 * Notify all connections to the same peer about
303 * new mss and trigger retransmit.
304 */
305 in_pcbnotifyall(&tcbtable, icmpsrc.sin_addr, EMSGSIZE,
306 tcp_mtudisc);
307 KERNEL_UNLOCK_ONE(NULL);
308 mutex_exit(softnet_lock);
309 return;
310 }
311 #ifdef TCP_DEBUG
312 #ifdef INET
313 if (tp->t_inpcb)
314 so = tp->t_inpcb->inp_socket;
315 #endif
316 #ifdef INET6
317 if (tp->t_in6pcb)
318 so = tp->t_in6pcb->in6p_socket;
319 #endif
320 ostate = tp->t_state;
321 #endif /* TCP_DEBUG */
322
323 /*
324 * Clear the SACK scoreboard, reset FACK estimate.
325 */
326 tcp_free_sackholes(tp);
327 tp->snd_fack = tp->snd_una;
328
329 /*
330 * Retransmission timer went off. Message has not
331 * been acked within retransmit interval. Back off
332 * to a longer retransmit interval and retransmit one segment.
333 */
334
335 if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
336 tp->t_rxtshift = TCP_MAXRXTSHIFT;
337 TCP_STATINC(TCP_STAT_TIMEOUTDROP);
338 tp = tcp_drop(tp, tp->t_softerror ?
339 tp->t_softerror : ETIMEDOUT);
340 goto out;
341 }
342 TCP_STATINC(TCP_STAT_REXMTTIMEO);
343 rto = TCP_REXMTVAL(tp);
344 if (rto < tp->t_rttmin)
345 rto = tp->t_rttmin;
346 TCPT_RANGESET(tp->t_rxtcur, rto * tcp_backoff[tp->t_rxtshift],
347 tp->t_rttmin, TCPTV_REXMTMAX);
348 TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur);
349
350 /*
351 * If we are losing and we are trying path MTU discovery,
352 * try turning it off. This will avoid black holes in
353 * the network which suppress or fail to send "packet
354 * too big" ICMP messages. We should ideally do
355 * lots more sophisticated searching to find the right
356 * value here...
357 */
358 if (tp->t_mtudisc && tp->t_rxtshift > TCP_MAXRXTSHIFT / 6) {
359 TCP_STATINC(TCP_STAT_PMTUBLACKHOLE);
360
361 #ifdef INET
362 /* try turning PMTUD off */
363 if (tp->t_inpcb)
364 tp->t_mtudisc = 0;
365 #endif
366 #ifdef INET6
367 /* try using IPv6 minimum MTU */
368 if (tp->t_in6pcb)
369 tp->t_mtudisc = 0;
370 #endif
371
372 /* XXX: more sophisticated Black hole recovery code? */
373 }
374
375 /*
376 * If losing, let the lower level know and try for
377 * a better route. Also, if we backed off this far,
378 * our srtt estimate is probably bogus. Clobber it
379 * so we'll take the next rtt measurement as our srtt;
380 * move the current srtt into rttvar to keep the current
381 * retransmit times until then.
382 */
383 if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
384 #ifdef INET
385 if (tp->t_inpcb)
386 in_losing(tp->t_inpcb);
387 #endif
388 #ifdef INET6
389 if (tp->t_in6pcb)
390 in6_losing(tp->t_in6pcb);
391 #endif
392 /*
393 * This operation is not described in RFC2988. The
394 * point is to keep srtt+4*rttvar constant, so we
395 * should shift right 2 bits to divide by 4, and then
396 * shift right one bit because the storage
397 * representation of rttvar is 1/16s vs 1/32s for
398 * srtt.
399 */
400 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
401 tp->t_srtt = 0;
402 }
403 tp->snd_nxt = tp->snd_una;
404 tp->snd_high = tp->snd_max;
405 /*
406 * If timing a segment in this window, stop the timer.
407 */
408 tp->t_rtttime = 0;
409 /*
410 * Remember if we are retransmitting a SYN, because if
411 * we do, set the initial congestion window must be set
412 * to 1 segment.
413 */
414 if (tp->t_state == TCPS_SYN_SENT)
415 tp->t_flags |= TF_SYN_REXMT;
416
417 /*
418 * Adjust congestion control parameters.
419 */
420 tp->t_congctl->slow_retransmit(tp);
421
422 (void) tcp_output(tp);
423
424 out:
425 #ifdef TCP_DEBUG
426 if (tp && so->so_options & SO_DEBUG)
427 tcp_trace(TA_USER, ostate, tp, NULL,
428 PRU_SLOWTIMO | (TCPT_REXMT << 8));
429 #endif
430 KERNEL_UNLOCK_ONE(NULL);
431 mutex_exit(softnet_lock);
432 }
433
434 void
tcp_timer_persist(void * arg)435 tcp_timer_persist(void *arg)
436 {
437 struct tcpcb *tp = arg;
438 uint32_t rto;
439 #ifdef TCP_DEBUG
440 struct socket *so = NULL;
441 short ostate;
442 #endif
443
444 mutex_enter(softnet_lock);
445 if ((tp->t_flags & TF_DEAD) != 0) {
446 mutex_exit(softnet_lock);
447 return;
448 }
449 if (!callout_expired(&tp->t_timer[TCPT_PERSIST])) {
450 mutex_exit(softnet_lock);
451 return;
452 }
453
454 KERNEL_LOCK(1, NULL);
455 #ifdef TCP_DEBUG
456 #ifdef INET
457 if (tp->t_inpcb)
458 so = tp->t_inpcb->inp_socket;
459 #endif
460 #ifdef INET6
461 if (tp->t_in6pcb)
462 so = tp->t_in6pcb->in6p_socket;
463 #endif
464
465 ostate = tp->t_state;
466 #endif /* TCP_DEBUG */
467
468 /*
469 * Persistance timer into zero window.
470 * Force a byte to be output, if possible.
471 */
472
473 /*
474 * Hack: if the peer is dead/unreachable, we do not
475 * time out if the window is closed. After a full
476 * backoff, drop the connection if the idle time
477 * (no responses to probes) reaches the maximum
478 * backoff that we would use if retransmitting.
479 */
480 rto = TCP_REXMTVAL(tp);
481 if (rto < tp->t_rttmin)
482 rto = tp->t_rttmin;
483 if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
484 ((tcp_now - tp->t_rcvtime) >= tcp_maxpersistidle ||
485 (tcp_now - tp->t_rcvtime) >= rto * tcp_totbackoff)) {
486 TCP_STATINC(TCP_STAT_PERSISTDROPS);
487 tp = tcp_drop(tp, ETIMEDOUT);
488 goto out;
489 }
490 TCP_STATINC(TCP_STAT_PERSISTTIMEO);
491 tcp_setpersist(tp);
492 tp->t_force = 1;
493 (void) tcp_output(tp);
494 tp->t_force = 0;
495
496 out:
497 #ifdef TCP_DEBUG
498 if (tp && so->so_options & SO_DEBUG)
499 tcp_trace(TA_USER, ostate, tp, NULL,
500 PRU_SLOWTIMO | (TCPT_PERSIST << 8));
501 #endif
502 KERNEL_UNLOCK_ONE(NULL);
503 mutex_exit(softnet_lock);
504 }
505
506 void
tcp_timer_keep(void * arg)507 tcp_timer_keep(void *arg)
508 {
509 struct tcpcb *tp = arg;
510 struct socket *so = NULL; /* Quell compiler warning */
511 #ifdef TCP_DEBUG
512 short ostate;
513 #endif
514
515 mutex_enter(softnet_lock);
516 if ((tp->t_flags & TF_DEAD) != 0) {
517 mutex_exit(softnet_lock);
518 return;
519 }
520 if (!callout_expired(&tp->t_timer[TCPT_KEEP])) {
521 mutex_exit(softnet_lock);
522 return;
523 }
524
525 KERNEL_LOCK(1, NULL);
526
527 #ifdef TCP_DEBUG
528 ostate = tp->t_state;
529 #endif /* TCP_DEBUG */
530
531 /*
532 * Keep-alive timer went off; send something
533 * or drop connection if idle for too long.
534 */
535
536 TCP_STATINC(TCP_STAT_KEEPTIMEO);
537 if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)
538 goto dropit;
539 #ifdef INET
540 if (tp->t_inpcb)
541 so = tp->t_inpcb->inp_socket;
542 #endif
543 #ifdef INET6
544 if (tp->t_in6pcb)
545 so = tp->t_in6pcb->in6p_socket;
546 #endif
547 KASSERT(so != NULL);
548 if (so->so_options & SO_KEEPALIVE &&
549 tp->t_state <= TCPS_CLOSE_WAIT) {
550 if ((tp->t_maxidle > 0) &&
551 ((tcp_now - tp->t_rcvtime) >=
552 tp->t_keepidle + tp->t_maxidle))
553 goto dropit;
554 /*
555 * Send a packet designed to force a response
556 * if the peer is up and reachable:
557 * either an ACK if the connection is still alive,
558 * or an RST if the peer has closed the connection
559 * due to timeout or reboot.
560 * Using sequence number tp->snd_una-1
561 * causes the transmitted zero-length segment
562 * to lie outside the receive window;
563 * by the protocol spec, this requires the
564 * correspondent TCP to respond.
565 */
566 TCP_STATINC(TCP_STAT_KEEPPROBE);
567 if (tcp_compat_42) {
568 /*
569 * The keepalive packet must have nonzero
570 * length to get a 4.2 host to respond.
571 */
572 (void)tcp_respond(tp, tp->t_template,
573 NULL, NULL, tp->rcv_nxt - 1,
574 tp->snd_una - 1, 0);
575 } else {
576 (void)tcp_respond(tp, tp->t_template,
577 NULL, NULL, tp->rcv_nxt,
578 tp->snd_una - 1, 0);
579 }
580 TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepintvl);
581 } else
582 TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepidle);
583
584 #ifdef TCP_DEBUG
585 if (tp && so->so_options & SO_DEBUG)
586 tcp_trace(TA_USER, ostate, tp, NULL,
587 PRU_SLOWTIMO | (TCPT_KEEP << 8));
588 #endif
589 KERNEL_UNLOCK_ONE(NULL);
590 mutex_exit(softnet_lock);
591 return;
592
593 dropit:
594 TCP_STATINC(TCP_STAT_KEEPDROPS);
595 (void) tcp_drop(tp, ETIMEDOUT);
596 KERNEL_UNLOCK_ONE(NULL);
597 mutex_exit(softnet_lock);
598 }
599
600 void
tcp_timer_2msl(void * arg)601 tcp_timer_2msl(void *arg)
602 {
603 struct tcpcb *tp = arg;
604 #ifdef TCP_DEBUG
605 struct socket *so = NULL;
606 short ostate;
607 #endif
608
609 mutex_enter(softnet_lock);
610 if ((tp->t_flags & TF_DEAD) != 0) {
611 mutex_exit(softnet_lock);
612 return;
613 }
614 if (!callout_expired(&tp->t_timer[TCPT_2MSL])) {
615 mutex_exit(softnet_lock);
616 return;
617 }
618
619 /*
620 * 2 MSL timeout went off, clear the SACK scoreboard, reset
621 * the FACK estimate.
622 */
623 KERNEL_LOCK(1, NULL);
624 tcp_free_sackholes(tp);
625 tp->snd_fack = tp->snd_una;
626
627 #ifdef TCP_DEBUG
628 #ifdef INET
629 if (tp->t_inpcb)
630 so = tp->t_inpcb->inp_socket;
631 #endif
632 #ifdef INET6
633 if (tp->t_in6pcb)
634 so = tp->t_in6pcb->in6p_socket;
635 #endif
636
637 ostate = tp->t_state;
638 #endif /* TCP_DEBUG */
639
640 /*
641 * 2 MSL timeout in shutdown went off. If we're closed but
642 * still waiting for peer to close and connection has been idle
643 * too long, or if 2MSL time is up from TIME_WAIT, delete connection
644 * control block. Otherwise, check again in a bit.
645 */
646 if (tp->t_state != TCPS_TIME_WAIT &&
647 ((tp->t_maxidle == 0) ||
648 ((tcp_now - tp->t_rcvtime) <= tp->t_maxidle)))
649 TCP_TIMER_ARM(tp, TCPT_2MSL, tp->t_keepintvl);
650 else
651 tp = tcp_close(tp);
652
653 #ifdef TCP_DEBUG
654 if (tp && so->so_options & SO_DEBUG)
655 tcp_trace(TA_USER, ostate, tp, NULL,
656 PRU_SLOWTIMO | (TCPT_2MSL << 8));
657 #endif
658 KERNEL_UNLOCK_ONE(NULL);
659 mutex_exit(softnet_lock);
660 }
661