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