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