The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/tcp_timer.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 16b843b10dcc2d08beead0632a4ea079


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.