1 /* $NetBSD: tcp_timer.c,v 1.96 2021/03/08 17:54:43 christos 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.96 2021/03/08 17:54:43 christos Exp $"); 97 98 #ifdef _KERNEL_OPT 99 #include "opt_inet.h" 100 #include "opt_tcp_debug.h" 101 #include "opt_net_mpsafe.h" 102 #endif 103 104 #include <sys/param.h> 105 #include <sys/systm.h> 106 #include <sys/mbuf.h> 107 #include <sys/socket.h> 108 #include <sys/socketvar.h> 109 #include <sys/protosw.h> 110 #include <sys/errno.h> 111 #include <sys/kernel.h> 112 #include <sys/callout.h> 113 #include <sys/workqueue.h> 114 #include <sys/cprng.h> 115 116 #include <net/if.h> 117 118 #include <netinet/in.h> 119 #include <netinet/in_systm.h> 120 #include <netinet/ip.h> 121 #include <netinet/in_pcb.h> 122 #include <netinet/ip_var.h> 123 #include <netinet/ip_icmp.h> 124 125 #ifdef INET6 126 #include <netinet/ip6.h> 127 #include <netinet6/in6_pcb.h> 128 #endif 129 130 #include <netinet/tcp.h> 131 #include <netinet/tcp_fsm.h> 132 #include <netinet/tcp_seq.h> 133 #include <netinet/tcp_timer.h> 134 #include <netinet/tcp_var.h> 135 #include <netinet/tcp_private.h> 136 #include <netinet/tcp_congctl.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 static callout_t tcp_slowtimo_ch; 153 #ifdef NET_MPSAFE 154 static struct workqueue *tcp_slowtimo_wq; 155 static struct work tcp_slowtimo_wk; 156 #endif 157 158 static void tcp_slowtimo_work(struct work *, void *); 159 static void tcp_slowtimo(void *); 160 161 /* 162 * Time to delay the ACK. This is initialized in tcp_init(), unless 163 * its patched. 164 */ 165 int tcp_delack_ticks = 0; 166 167 void tcp_timer_rexmt(void *); 168 void tcp_timer_persist(void *); 169 void tcp_timer_keep(void *); 170 void tcp_timer_2msl(void *); 171 172 const tcp_timer_func_t tcp_timer_funcs[TCPT_NTIMERS] = { 173 tcp_timer_rexmt, 174 tcp_timer_persist, 175 tcp_timer_keep, 176 tcp_timer_2msl, 177 }; 178 179 /* 180 * Timer state initialization, called from tcp_init(). 181 */ 182 void 183 tcp_timer_init(void) 184 { 185 186 if (tcp_keepinit == 0) 187 tcp_keepinit = TCPTV_KEEP_INIT; 188 189 if (tcp_keepidle == 0) 190 tcp_keepidle = TCPTV_KEEP_IDLE; 191 192 if (tcp_keepintvl == 0) 193 tcp_keepintvl = TCPTV_KEEPINTVL; 194 195 if (tcp_keepcnt == 0) 196 tcp_keepcnt = TCPTV_KEEPCNT; 197 198 if (tcp_maxpersistidle == 0) 199 tcp_maxpersistidle = TCPTV_KEEP_IDLE; 200 201 if (tcp_delack_ticks == 0) 202 tcp_delack_ticks = TCP_DELACK_TICKS; 203 } 204 205 void 206 tcp_slowtimo_init(void) 207 { 208 #ifdef NET_MPSAFE 209 int error; 210 211 error = workqueue_create(&tcp_slowtimo_wq, "tcp_slowtimo", 212 tcp_slowtimo_work, NULL, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE); 213 if (error != 0) 214 panic("%s: workqueue_create failed (%d)\n", __func__, error); 215 #endif 216 callout_init(&tcp_slowtimo_ch, CALLOUT_MPSAFE); 217 callout_reset(&tcp_slowtimo_ch, 1, tcp_slowtimo, NULL); 218 } 219 220 /* 221 * Callout to process delayed ACKs for a TCPCB. 222 */ 223 void 224 tcp_delack(void *arg) 225 { 226 struct tcpcb *tp = arg; 227 228 /* 229 * If tcp_output() wasn't able to transmit the ACK 230 * for whatever reason, it will restart the delayed 231 * ACK callout. 232 */ 233 234 mutex_enter(softnet_lock); 235 if ((tp->t_flags & (TF_DEAD | TF_DELACK)) != TF_DELACK) { 236 mutex_exit(softnet_lock); 237 return; 238 } 239 if (!callout_expired(&tp->t_delack_ch)) { 240 mutex_exit(softnet_lock); 241 return; 242 } 243 244 tp->t_flags |= TF_ACKNOW; 245 KERNEL_LOCK(1, NULL); 246 (void) tcp_output(tp); 247 KERNEL_UNLOCK_ONE(NULL); 248 mutex_exit(softnet_lock); 249 } 250 251 /* 252 * Tcp protocol timeout routine called every 500 ms. 253 * Updates the timers in all active tcb's and 254 * causes finite state machine actions if timers expire. 255 */ 256 static void 257 tcp_slowtimo_work(struct work *wk, void *arg) 258 { 259 260 mutex_enter(softnet_lock); 261 tcp_iss_seq += TCP_ISSINCR + (TCP_ISS_RANDOM_MASK & cprng_fast32()); 262 tcp_now++; /* for timestamps */ 263 mutex_exit(softnet_lock); 264 265 callout_schedule(&tcp_slowtimo_ch, hz / PR_SLOWHZ); 266 } 267 268 static void 269 tcp_slowtimo(void *arg) 270 { 271 272 #ifdef NET_MPSAFE 273 workqueue_enqueue(tcp_slowtimo_wq, &tcp_slowtimo_wk, NULL); 274 #else 275 tcp_slowtimo_work(NULL, NULL); 276 #endif 277 } 278 279 /* 280 * Cancel all timers for TCP tp. 281 */ 282 void 283 tcp_canceltimers(struct tcpcb *tp) 284 { 285 int i; 286 287 for (i = 0; i < TCPT_NTIMERS; i++) 288 TCP_TIMER_DISARM(tp, i); 289 } 290 291 const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = 292 { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; 293 294 const int tcp_totbackoff = 511; /* sum of tcp_backoff[] */ 295 296 /* 297 * TCP timer processing. 298 */ 299 300 void 301 tcp_timer_rexmt(void *arg) 302 { 303 struct tcpcb *tp = arg; 304 uint32_t rto; 305 #ifdef TCP_DEBUG 306 struct socket *so = NULL; 307 short ostate; 308 #endif 309 310 mutex_enter(softnet_lock); 311 if ((tp->t_flags & TF_DEAD) != 0) { 312 mutex_exit(softnet_lock); 313 return; 314 } 315 if (!callout_expired(&tp->t_timer[TCPT_REXMT])) { 316 mutex_exit(softnet_lock); 317 return; 318 } 319 320 KERNEL_LOCK(1, NULL); 321 if ((tp->t_flags & TF_PMTUD_PEND) && tp->t_inpcb && 322 SEQ_GEQ(tp->t_pmtud_th_seq, tp->snd_una) && 323 SEQ_LT(tp->t_pmtud_th_seq, (int)(tp->snd_una + tp->t_ourmss))) { 324 extern struct sockaddr_in icmpsrc; 325 struct icmp icmp; 326 327 tp->t_flags &= ~TF_PMTUD_PEND; 328 329 /* XXX create fake icmp message with relevant entries */ 330 icmp.icmp_nextmtu = tp->t_pmtud_nextmtu; 331 icmp.icmp_ip.ip_len = tp->t_pmtud_ip_len; 332 icmp.icmp_ip.ip_hl = tp->t_pmtud_ip_hl; 333 icmpsrc.sin_addr = tp->t_inpcb->inp_faddr; 334 icmp_mtudisc(&icmp, icmpsrc.sin_addr); 335 336 /* 337 * Notify all connections to the same peer about 338 * new mss and trigger retransmit. 339 */ 340 in_pcbnotifyall(&tcbtable, icmpsrc.sin_addr, EMSGSIZE, 341 tcp_mtudisc); 342 KERNEL_UNLOCK_ONE(NULL); 343 mutex_exit(softnet_lock); 344 return; 345 } 346 #ifdef TCP_DEBUG 347 if (tp->t_inpcb) 348 so = tp->t_inpcb->inp_socket; 349 #ifdef INET6 350 if (tp->t_in6pcb) 351 so = tp->t_in6pcb->in6p_socket; 352 #endif 353 ostate = tp->t_state; 354 #endif /* TCP_DEBUG */ 355 356 /* 357 * Clear the SACK scoreboard, reset FACK estimate. 358 */ 359 tcp_free_sackholes(tp); 360 tp->snd_fack = tp->snd_una; 361 362 /* 363 * Retransmission timer went off. Message has not 364 * been acked within retransmit interval. Back off 365 * to a longer retransmit interval and retransmit one segment. 366 */ 367 368 if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { 369 tp->t_rxtshift = TCP_MAXRXTSHIFT; 370 TCP_STATINC(TCP_STAT_TIMEOUTDROP); 371 tp = tcp_drop(tp, tp->t_softerror ? 372 tp->t_softerror : ETIMEDOUT); 373 goto out; 374 } 375 TCP_STATINC(TCP_STAT_REXMTTIMEO); 376 rto = TCP_REXMTVAL(tp); 377 if (rto < tp->t_rttmin) 378 rto = tp->t_rttmin; 379 TCPT_RANGESET(tp->t_rxtcur, rto * tcp_backoff[tp->t_rxtshift], 380 tp->t_rttmin, TCPTV_REXMTMAX); 381 TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); 382 383 /* 384 * If we are losing and we are trying path MTU discovery, 385 * try turning it off. This will avoid black holes in 386 * the network which suppress or fail to send "packet 387 * too big" ICMP messages. We should ideally do 388 * lots more sophisticated searching to find the right 389 * value here... 390 */ 391 if (tp->t_mtudisc && tp->t_rxtshift > TCP_MAXRXTSHIFT / 6) { 392 TCP_STATINC(TCP_STAT_PMTUBLACKHOLE); 393 394 /* try turning PMTUD off */ 395 if (tp->t_inpcb) 396 tp->t_mtudisc = 0; 397 #ifdef INET6 398 /* try using IPv6 minimum MTU */ 399 if (tp->t_in6pcb) 400 tp->t_mtudisc = 0; 401 #endif 402 403 /* XXX: more sophisticated Black hole recovery code? */ 404 } 405 406 /* 407 * If losing, let the lower level know and try for 408 * a better route. Also, if we backed off this far, 409 * our srtt estimate is probably bogus. Clobber it 410 * so we'll take the next rtt measurement as our srtt; 411 * move the current srtt into rttvar to keep the current 412 * retransmit times until then. 413 */ 414 if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { 415 if (tp->t_inpcb) 416 in_losing(tp->t_inpcb); 417 #ifdef INET6 418 if (tp->t_in6pcb) 419 in6_losing(tp->t_in6pcb); 420 #endif 421 /* 422 * This operation is not described in RFC2988. The 423 * point is to keep srtt+4*rttvar constant, so we 424 * should shift right 2 bits to divide by 4, and then 425 * shift right one bit because the storage 426 * representation of rttvar is 1/16s vs 1/32s for 427 * srtt. 428 */ 429 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); 430 tp->t_srtt = 0; 431 } 432 tp->snd_nxt = tp->snd_una; 433 tp->snd_high = tp->snd_max; 434 /* 435 * If timing a segment in this window, stop the timer. 436 */ 437 tp->t_rtttime = 0; 438 /* 439 * Remember if we are retransmitting a SYN, because if 440 * we do, set the initial congestion window must be set 441 * to 1 segment. 442 */ 443 if (tp->t_state == TCPS_SYN_SENT) 444 tp->t_flags |= TF_SYN_REXMT; 445 446 /* 447 * Adjust congestion control parameters. 448 */ 449 tp->t_congctl->slow_retransmit(tp); 450 451 (void) tcp_output(tp); 452 453 out: 454 #ifdef TCP_DEBUG 455 if (tp && so->so_options & SO_DEBUG) 456 tcp_trace(TA_USER, ostate, tp, NULL, 457 PRU_SLOWTIMO | (TCPT_REXMT << 8)); 458 #endif 459 KERNEL_UNLOCK_ONE(NULL); 460 mutex_exit(softnet_lock); 461 } 462 463 void 464 tcp_timer_persist(void *arg) 465 { 466 struct tcpcb *tp = arg; 467 uint32_t rto; 468 #ifdef TCP_DEBUG 469 struct socket *so = NULL; 470 short ostate; 471 #endif 472 473 mutex_enter(softnet_lock); 474 if ((tp->t_flags & TF_DEAD) != 0) { 475 mutex_exit(softnet_lock); 476 return; 477 } 478 if (!callout_expired(&tp->t_timer[TCPT_PERSIST])) { 479 mutex_exit(softnet_lock); 480 return; 481 } 482 483 KERNEL_LOCK(1, NULL); 484 #ifdef TCP_DEBUG 485 if (tp->t_inpcb) 486 so = tp->t_inpcb->inp_socket; 487 #ifdef INET6 488 if (tp->t_in6pcb) 489 so = tp->t_in6pcb->in6p_socket; 490 #endif 491 492 ostate = tp->t_state; 493 #endif /* TCP_DEBUG */ 494 495 /* 496 * Persistance timer into zero window. 497 * Force a byte to be output, if possible. 498 */ 499 500 /* 501 * Hack: if the peer is dead/unreachable, we do not 502 * time out if the window is closed. After a full 503 * backoff, drop the connection if the idle time 504 * (no responses to probes) reaches the maximum 505 * backoff that we would use if retransmitting. 506 */ 507 rto = TCP_REXMTVAL(tp); 508 if (rto < tp->t_rttmin) 509 rto = tp->t_rttmin; 510 if (tp->t_rxtshift == TCP_MAXRXTSHIFT && 511 ((tcp_now - tp->t_rcvtime) >= tcp_maxpersistidle || 512 (tcp_now - tp->t_rcvtime) >= rto * tcp_totbackoff)) { 513 TCP_STATINC(TCP_STAT_PERSISTDROPS); 514 tp = tcp_drop(tp, ETIMEDOUT); 515 goto out; 516 } 517 TCP_STATINC(TCP_STAT_PERSISTTIMEO); 518 tcp_setpersist(tp); 519 tp->t_force = 1; 520 (void) tcp_output(tp); 521 tp->t_force = 0; 522 523 out: 524 #ifdef TCP_DEBUG 525 if (tp && so->so_options & SO_DEBUG) 526 tcp_trace(TA_USER, ostate, tp, NULL, 527 PRU_SLOWTIMO | (TCPT_PERSIST << 8)); 528 #endif 529 KERNEL_UNLOCK_ONE(NULL); 530 mutex_exit(softnet_lock); 531 } 532 533 void 534 tcp_timer_keep(void *arg) 535 { 536 struct tcpcb *tp = arg; 537 struct socket *so = NULL; /* Quell compiler warning */ 538 #ifdef TCP_DEBUG 539 short ostate; 540 #endif 541 542 mutex_enter(softnet_lock); 543 if ((tp->t_flags & TF_DEAD) != 0) { 544 mutex_exit(softnet_lock); 545 return; 546 } 547 if (!callout_expired(&tp->t_timer[TCPT_KEEP])) { 548 mutex_exit(softnet_lock); 549 return; 550 } 551 552 KERNEL_LOCK(1, NULL); 553 554 #ifdef TCP_DEBUG 555 ostate = tp->t_state; 556 #endif /* TCP_DEBUG */ 557 558 /* 559 * Keep-alive timer went off; send something 560 * or drop connection if idle for too long. 561 */ 562 563 TCP_STATINC(TCP_STAT_KEEPTIMEO); 564 if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) 565 goto dropit; 566 if (tp->t_inpcb) 567 so = tp->t_inpcb->inp_socket; 568 #ifdef INET6 569 if (tp->t_in6pcb) 570 so = tp->t_in6pcb->in6p_socket; 571 #endif 572 KASSERT(so != NULL); 573 if (so->so_options & SO_KEEPALIVE && 574 tp->t_state <= TCPS_CLOSE_WAIT) { 575 if ((tp->t_maxidle > 0) && 576 ((tcp_now - tp->t_rcvtime) >= 577 tp->t_keepidle + tp->t_maxidle)) 578 goto dropit; 579 /* 580 * Send a packet designed to force a response 581 * if the peer is up and reachable: 582 * either an ACK if the connection is still alive, 583 * or an RST if the peer has closed the connection 584 * due to timeout or reboot. 585 * Using sequence number tp->snd_una-1 586 * causes the transmitted zero-length segment 587 * to lie outside the receive window; 588 * by the protocol spec, this requires the 589 * correspondent TCP to respond. 590 */ 591 TCP_STATINC(TCP_STAT_KEEPPROBE); 592 593 (void)tcp_respond(tp, tp->t_template, 594 NULL, NULL, tp->rcv_nxt, 595 tp->snd_una - 1, 0); 596 597 TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepintvl); 598 } else 599 TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepidle); 600 601 #ifdef TCP_DEBUG 602 if (tp && so->so_options & SO_DEBUG) 603 tcp_trace(TA_USER, ostate, tp, NULL, 604 PRU_SLOWTIMO | (TCPT_KEEP << 8)); 605 #endif 606 KERNEL_UNLOCK_ONE(NULL); 607 mutex_exit(softnet_lock); 608 return; 609 610 dropit: 611 TCP_STATINC(TCP_STAT_KEEPDROPS); 612 (void) tcp_drop(tp, ETIMEDOUT); 613 KERNEL_UNLOCK_ONE(NULL); 614 mutex_exit(softnet_lock); 615 } 616 617 void 618 tcp_timer_2msl(void *arg) 619 { 620 struct tcpcb *tp = arg; 621 #ifdef TCP_DEBUG 622 struct socket *so = NULL; 623 short ostate; 624 #endif 625 626 mutex_enter(softnet_lock); 627 if ((tp->t_flags & TF_DEAD) != 0) { 628 mutex_exit(softnet_lock); 629 return; 630 } 631 if (!callout_expired(&tp->t_timer[TCPT_2MSL])) { 632 mutex_exit(softnet_lock); 633 return; 634 } 635 636 /* 637 * 2 MSL timeout went off, clear the SACK scoreboard, reset 638 * the FACK estimate. 639 */ 640 KERNEL_LOCK(1, NULL); 641 tcp_free_sackholes(tp); 642 tp->snd_fack = tp->snd_una; 643 644 #ifdef TCP_DEBUG 645 if (tp->t_inpcb) 646 so = tp->t_inpcb->inp_socket; 647 #ifdef INET6 648 if (tp->t_in6pcb) 649 so = tp->t_in6pcb->in6p_socket; 650 #endif 651 652 ostate = tp->t_state; 653 #endif /* TCP_DEBUG */ 654 655 /* 656 * 2 MSL timeout in shutdown went off. If we're closed but 657 * still waiting for peer to close and connection has been idle 658 * too long, or if 2MSL time is up from TIME_WAIT, delete connection 659 * control block. Otherwise, check again in a bit. 660 */ 661 if (tp->t_state != TCPS_TIME_WAIT && 662 ((tp->t_maxidle == 0) || 663 ((tcp_now - tp->t_rcvtime) <= tp->t_maxidle))) 664 TCP_TIMER_ARM(tp, TCPT_2MSL, tp->t_keepintvl); 665 else 666 tp = tcp_close(tp); 667 668 #ifdef TCP_DEBUG 669 if (tp && so->so_options & SO_DEBUG) 670 tcp_trace(TA_USER, ostate, tp, NULL, 671 PRU_SLOWTIMO | (TCPT_2MSL << 8)); 672 #endif 673 KERNEL_UNLOCK_ONE(NULL); 674 mutex_exit(softnet_lock); 675 } 676