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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
   34  * $FreeBSD: releng/5.0/sys/netinet/tcp_timer.c 108612 2003-01-03 20:35:59Z hsu $
   35  */
   36 
   37 #include "opt_inet6.h"
   38 #include "opt_tcpdebug.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/lock.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/mutex.h>
   45 #include <sys/protosw.h>
   46 #include <sys/socket.h>
   47 #include <sys/socketvar.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/systm.h>
   50 
   51 #include <net/route.h>
   52 
   53 #include <netinet/in.h>
   54 #include <netinet/in_pcb.h>
   55 #include <netinet/in_systm.h>
   56 #ifdef INET6
   57 #include <netinet6/in6_pcb.h>
   58 #endif
   59 #include <netinet/ip_var.h>
   60 #include <netinet/tcp.h>
   61 #include <netinet/tcp_fsm.h>
   62 #include <netinet/tcp_timer.h>
   63 #include <netinet/tcp_var.h>
   64 #include <netinet/tcpip.h>
   65 #ifdef TCPDEBUG
   66 #include <netinet/tcp_debug.h>
   67 #endif
   68 
   69 static int
   70 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
   71 {
   72         int error, s, tt;
   73 
   74         tt = *(int *)oidp->oid_arg1;
   75         s = (int)((int64_t)tt * 1000 / hz);
   76 
   77         error = sysctl_handle_int(oidp, &s, 0, req);
   78         if (error || !req->newptr)
   79                 return (error);
   80 
   81         tt = (int)((int64_t)s * hz / 1000);
   82         if (tt < 1)
   83                 return (EINVAL);
   84 
   85         *(int *)oidp->oid_arg1 = tt;
   86         return (0);
   87 }
   88 
   89 int     tcp_keepinit;
   90 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit, CTLTYPE_INT|CTLFLAG_RW,
   91     &tcp_keepinit, 0, sysctl_msec_to_ticks, "I", "");
   92 
   93 int     tcp_keepidle;
   94 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle, CTLTYPE_INT|CTLFLAG_RW,
   95     &tcp_keepidle, 0, sysctl_msec_to_ticks, "I", "");
   96 
   97 int     tcp_keepintvl;
   98 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl, CTLTYPE_INT|CTLFLAG_RW,
   99     &tcp_keepintvl, 0, sysctl_msec_to_ticks, "I", "");
  100 
  101 int     tcp_delacktime;
  102 SYSCTL_PROC(_net_inet_tcp, TCPCTL_DELACKTIME, delacktime,
  103     CTLTYPE_INT|CTLFLAG_RW, &tcp_delacktime, 0, sysctl_msec_to_ticks, "I",
  104     "Time before a delayed ACK is sent");
  105  
  106 int     tcp_msl;
  107 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW,
  108     &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime");
  109 
  110 int     tcp_rexmit_min;
  111 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW,
  112     &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I", "Minimum Retransmission Timeout");
  113 
  114 int     tcp_rexmit_slop;
  115 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_slop, CTLTYPE_INT|CTLFLAG_RW,
  116     &tcp_rexmit_slop, 0, sysctl_msec_to_ticks, "I", "Retransmission Timer Slop");
  117 
  118 static int      always_keepalive = 1;
  119 SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW, 
  120     &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections");
  121 
  122 static int      tcp_keepcnt = TCPTV_KEEPCNT;
  123         /* max idle probes */
  124 int     tcp_maxpersistidle;
  125         /* max idle time in persist */
  126 int     tcp_maxidle;
  127 
  128 /*
  129  * Tcp protocol timeout routine called every 500 ms.
  130  * Updates timestamps used for TCP
  131  * causes finite state machine actions if timers expire.
  132  */
  133 void
  134 tcp_slowtimo()
  135 {
  136         int s;
  137 
  138         s = splnet();
  139 
  140         tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
  141 
  142         splx(s);
  143 }
  144 
  145 /*
  146  * Cancel all timers for TCP tp.
  147  */
  148 void
  149 tcp_canceltimers(tp)
  150         struct tcpcb *tp;
  151 {
  152         callout_stop(tp->tt_2msl);
  153         callout_stop(tp->tt_persist);
  154         callout_stop(tp->tt_keep);
  155         callout_stop(tp->tt_rexmt);
  156 }
  157 
  158 int     tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
  159     { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 };
  160 
  161 int     tcp_backoff[TCP_MAXRXTSHIFT + 1] =
  162     { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
  163 
  164 static int tcp_totbackoff = 511;        /* sum of tcp_backoff[] */
  165 
  166 /*
  167  * TCP timer processing.
  168  */
  169 
  170 void
  171 tcp_timer_delack(xtp)
  172         void *xtp;
  173 {
  174         struct tcpcb *tp = xtp;
  175         int s;
  176         struct inpcb *inp;
  177 
  178         s = splnet();
  179         INP_INFO_RLOCK(&tcbinfo);
  180         inp = tp->t_inpcb;
  181         if (!inp) {
  182                 INP_INFO_RUNLOCK(&tcbinfo);
  183                 splx(s);
  184                 return;
  185         }
  186         INP_LOCK(inp);
  187         INP_INFO_RUNLOCK(&tcbinfo);
  188         if (callout_pending(tp->tt_delack) || !callout_active(tp->tt_delack)) {
  189                 INP_UNLOCK(inp);
  190                 splx(s);
  191                 return;
  192         }
  193         callout_deactivate(tp->tt_delack);
  194 
  195         tp->t_flags |= TF_ACKNOW;
  196         tcpstat.tcps_delack++;
  197         (void) tcp_output(tp);
  198         INP_UNLOCK(inp);
  199         splx(s);
  200 }
  201 
  202 void
  203 tcp_timer_2msl(xtp)
  204         void *xtp;
  205 {
  206         struct tcpcb *tp = xtp;
  207         int s;
  208         struct inpcb *inp;
  209 #ifdef TCPDEBUG
  210         int ostate;
  211 
  212         ostate = tp->t_state;
  213 #endif
  214         s = splnet();
  215         INP_INFO_WLOCK(&tcbinfo);
  216         inp = tp->t_inpcb;
  217         if (!inp) {
  218                 INP_INFO_WUNLOCK(&tcbinfo);
  219                 splx(s);
  220                 return;
  221         }
  222         INP_LOCK(inp);
  223         if (callout_pending(tp->tt_2msl) || !callout_active(tp->tt_2msl)) {
  224                 INP_UNLOCK(tp->t_inpcb);
  225                 INP_INFO_WUNLOCK(&tcbinfo);
  226                 splx(s);
  227                 return;
  228         }
  229         callout_deactivate(tp->tt_2msl);
  230         /*
  231          * 2 MSL timeout in shutdown went off.  If we're closed but
  232          * still waiting for peer to close and connection has been idle
  233          * too long, or if 2MSL time is up from TIME_WAIT, delete connection
  234          * control block.  Otherwise, check again in a bit.
  235          */
  236         if (tp->t_state != TCPS_TIME_WAIT &&
  237             (ticks - tp->t_rcvtime) <= tcp_maxidle)
  238                 callout_reset(tp->tt_2msl, tcp_keepintvl,
  239                               tcp_timer_2msl, tp);
  240         else
  241                 tp = tcp_close(tp);
  242 
  243 #ifdef TCPDEBUG
  244         if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
  245                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
  246                           PRU_SLOWTIMO);
  247 #endif
  248         if (tp)
  249                 INP_UNLOCK(inp);
  250         INP_INFO_WUNLOCK(&tcbinfo);
  251         splx(s);
  252 }
  253 
  254 void
  255 tcp_timer_keep(xtp)
  256         void *xtp;
  257 {
  258         struct tcpcb *tp = xtp;
  259         struct tcptemp *t_template;
  260         int s;
  261         struct inpcb *inp;
  262 #ifdef TCPDEBUG
  263         int ostate;
  264 
  265         ostate = tp->t_state;
  266 #endif
  267         s = splnet();
  268         INP_INFO_WLOCK(&tcbinfo);
  269         inp = tp->t_inpcb;
  270         if (!inp) {
  271                 INP_INFO_WUNLOCK(&tcbinfo);
  272                 splx(s);
  273                 return;
  274         }
  275         INP_LOCK(inp);
  276         if (callout_pending(tp->tt_keep) || !callout_active(tp->tt_keep)) {
  277                 INP_UNLOCK(inp);
  278                 INP_INFO_WUNLOCK(&tcbinfo);
  279                 splx(s);
  280                 return;
  281         }
  282         callout_deactivate(tp->tt_keep);
  283         /*
  284          * Keep-alive timer went off; send something
  285          * or drop connection if idle for too long.
  286          */
  287         tcpstat.tcps_keeptimeo++;
  288         if (tp->t_state < TCPS_ESTABLISHED)
  289                 goto dropit;
  290         if ((always_keepalive ||
  291              tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
  292             tp->t_state <= TCPS_CLOSING) {
  293                 if ((ticks - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle)
  294                         goto dropit;
  295                 /*
  296                  * Send a packet designed to force a response
  297                  * if the peer is up and reachable:
  298                  * either an ACK if the connection is still alive,
  299                  * or an RST if the peer has closed the connection
  300                  * due to timeout or reboot.
  301                  * Using sequence number tp->snd_una-1
  302                  * causes the transmitted zero-length segment
  303                  * to lie outside the receive window;
  304                  * by the protocol spec, this requires the
  305                  * correspondent TCP to respond.
  306                  */
  307                 tcpstat.tcps_keepprobe++;
  308                 t_template = tcp_maketemplate(tp);
  309                 if (t_template) {
  310                         tcp_respond(tp, t_template->tt_ipgen,
  311                                     &t_template->tt_t, (struct mbuf *)NULL,
  312                                     tp->rcv_nxt, tp->snd_una - 1, 0);
  313                         (void) m_free(dtom(t_template));
  314                 }
  315                 callout_reset(tp->tt_keep, tcp_keepintvl, tcp_timer_keep, tp);
  316         } else
  317                 callout_reset(tp->tt_keep, tcp_keepidle, tcp_timer_keep, tp);
  318 
  319 #ifdef TCPDEBUG
  320         if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
  321                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
  322                           PRU_SLOWTIMO);
  323 #endif
  324         INP_UNLOCK(inp);
  325         INP_INFO_WUNLOCK(&tcbinfo);
  326         splx(s);
  327         return;
  328 
  329 dropit:
  330         tcpstat.tcps_keepdrops++;
  331         tp = tcp_drop(tp, ETIMEDOUT);
  332 
  333 #ifdef TCPDEBUG
  334         if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
  335                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
  336                           PRU_SLOWTIMO);
  337 #endif
  338         if (tp)
  339                 INP_UNLOCK(tp->t_inpcb);
  340         INP_INFO_WUNLOCK(&tcbinfo);
  341         splx(s);
  342 }
  343 
  344 void
  345 tcp_timer_persist(xtp)
  346         void *xtp;
  347 {
  348         struct tcpcb *tp = xtp;
  349         int s;
  350         struct inpcb *inp;
  351 #ifdef TCPDEBUG
  352         int ostate;
  353 
  354         ostate = tp->t_state;
  355 #endif
  356         s = splnet();
  357         INP_INFO_WLOCK(&tcbinfo);
  358         inp = tp->t_inpcb;
  359         if (!inp) {
  360                 INP_INFO_WUNLOCK(&tcbinfo);
  361                 splx(s);
  362                 return;
  363         }
  364         INP_LOCK(inp);
  365         if (callout_pending(tp->tt_persist) || !callout_active(tp->tt_persist)){
  366                 INP_UNLOCK(inp);
  367                 INP_INFO_WUNLOCK(&tcbinfo);
  368                 splx(s);
  369                 return;
  370         }
  371         callout_deactivate(tp->tt_persist);
  372         /*
  373          * Persistance timer into zero window.
  374          * Force a byte to be output, if possible.
  375          */
  376         tcpstat.tcps_persisttimeo++;
  377         /*
  378          * Hack: if the peer is dead/unreachable, we do not
  379          * time out if the window is closed.  After a full
  380          * backoff, drop the connection if the idle time
  381          * (no responses to probes) reaches the maximum
  382          * backoff that we would use if retransmitting.
  383          */
  384         if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
  385             ((ticks - tp->t_rcvtime) >= tcp_maxpersistidle ||
  386              (ticks - tp->t_rcvtime) >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
  387                 tcpstat.tcps_persistdrop++;
  388                 tp = tcp_drop(tp, ETIMEDOUT);
  389                 goto out;
  390         }
  391         tcp_setpersist(tp);
  392         tp->t_force = 1;
  393         (void) tcp_output(tp);
  394         tp->t_force = 0;
  395 
  396 out:
  397 #ifdef TCPDEBUG
  398         if (tp && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
  399                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
  400                           PRU_SLOWTIMO);
  401 #endif
  402         if (tp)
  403                 INP_UNLOCK(inp);
  404         INP_INFO_WUNLOCK(&tcbinfo);
  405         splx(s);
  406 }
  407 
  408 void
  409 tcp_timer_rexmt(xtp)
  410         void *xtp;
  411 {
  412         struct tcpcb *tp = xtp;
  413         int s;
  414         int rexmt;
  415         int headlocked;
  416         struct inpcb *inp;
  417 #ifdef TCPDEBUG
  418         int ostate;
  419 
  420         ostate = tp->t_state;
  421 #endif
  422         s = splnet();
  423         INP_INFO_WLOCK(&tcbinfo);
  424         headlocked = 1;
  425         inp = tp->t_inpcb;
  426         if (!inp) {
  427                 INP_INFO_WUNLOCK(&tcbinfo);
  428                 splx(s);
  429                 return;
  430         }
  431         INP_LOCK(inp);
  432         if (callout_pending(tp->tt_rexmt) || !callout_active(tp->tt_rexmt)) {
  433                 INP_UNLOCK(inp);
  434                 INP_INFO_WUNLOCK(&tcbinfo);
  435                 splx(s);
  436                 return;
  437         }
  438         callout_deactivate(tp->tt_rexmt);
  439         /*
  440          * Retransmission timer went off.  Message has not
  441          * been acked within retransmit interval.  Back off
  442          * to a longer retransmit interval and retransmit one segment.
  443          */
  444         if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
  445                 tp->t_rxtshift = TCP_MAXRXTSHIFT;
  446                 tcpstat.tcps_timeoutdrop++;
  447                 tp = tcp_drop(tp, tp->t_softerror ?
  448                               tp->t_softerror : ETIMEDOUT);
  449                 goto out;
  450         }
  451         INP_INFO_WUNLOCK(&tcbinfo);
  452         headlocked = 0;
  453         if (tp->t_rxtshift == 1) {
  454                 /*
  455                  * first retransmit; record ssthresh and cwnd so they can
  456                  * be recovered if this turns out to be a "bad" retransmit.
  457                  * A retransmit is considered "bad" if an ACK for this 
  458                  * segment is received within RTT/2 interval; the assumption
  459                  * here is that the ACK was already in flight.  See 
  460                  * "On Estimating End-to-End Network Path Properties" by
  461                  * Allman and Paxson for more details.
  462                  */
  463                 tp->snd_cwnd_prev = tp->snd_cwnd;
  464                 tp->snd_ssthresh_prev = tp->snd_ssthresh;
  465                 tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
  466         }
  467         tcpstat.tcps_rexmttimeo++;
  468         if (tp->t_state == TCPS_SYN_SENT)
  469                 rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
  470         else
  471                 rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
  472         TCPT_RANGESET(tp->t_rxtcur, rexmt,
  473                       tp->t_rttmin, TCPTV_REXMTMAX);
  474         /*
  475          * Disable rfc1323 and rfc1644 if we havn't got any response to
  476          * our third SYN to work-around some broken terminal servers 
  477          * (most of which have hopefully been retired) that have bad VJ 
  478          * header compression code which trashes TCP segments containing 
  479          * unknown-to-them TCP options.
  480          */
  481         if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3))
  482                 tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_REQ_CC);
  483         /*
  484          * If losing, let the lower level know and try for
  485          * a better route.  Also, if we backed off this far,
  486          * our srtt estimate is probably bogus.  Clobber it
  487          * so we'll take the next rtt measurement as our srtt;
  488          * move the current srtt into rttvar to keep the current
  489          * retransmit times until then.
  490          */
  491         if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
  492 #ifdef INET6
  493                 if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
  494                         in6_losing(tp->t_inpcb);
  495                 else
  496 #endif
  497                 in_losing(tp->t_inpcb);
  498                 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
  499                 tp->t_srtt = 0;
  500         }
  501         tp->snd_nxt = tp->snd_una;
  502         /*
  503          * Note:  We overload snd_recover to function also as the
  504          * snd_last variable described in RFC 2582
  505          */
  506         tp->snd_recover = tp->snd_max;
  507         /*
  508          * Force a segment to be sent.
  509          */
  510         tp->t_flags |= TF_ACKNOW;
  511         /*
  512          * If timing a segment in this window, stop the timer.
  513          */
  514         tp->t_rtttime = 0;
  515         /*
  516          * Close the congestion window down to one segment
  517          * (we'll open it by one segment for each ack we get).
  518          * Since we probably have a window's worth of unacked
  519          * data accumulated, this "slow start" keeps us from
  520          * dumping all that data as back-to-back packets (which
  521          * might overwhelm an intermediate gateway).
  522          *
  523          * There are two phases to the opening: Initially we
  524          * open by one mss on each ack.  This makes the window
  525          * size increase exponentially with time.  If the
  526          * window is larger than the path can handle, this
  527          * exponential growth results in dropped packet(s)
  528          * almost immediately.  To get more time between
  529          * drops but still "push" the network to take advantage
  530          * of improving conditions, we switch from exponential
  531          * to linear window opening at some threshhold size.
  532          * For a threshhold, we use half the current window
  533          * size, truncated to a multiple of the mss.
  534          *
  535          * (the minimum cwnd that will give us exponential
  536          * growth is 2 mss.  We don't allow the threshhold
  537          * to go below this.)
  538          */
  539         {
  540                 u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
  541                 if (win < 2)
  542                         win = 2;
  543                 tp->snd_cwnd = tp->t_maxseg;
  544                 tp->snd_ssthresh = win * tp->t_maxseg;
  545                 tp->t_dupacks = 0;
  546         }
  547         (void) tcp_output(tp);
  548 
  549 out:
  550 #ifdef TCPDEBUG
  551         if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
  552                 tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
  553                           PRU_SLOWTIMO);
  554 #endif
  555         if (tp)
  556                 INP_UNLOCK(inp);
  557         if (headlocked)
  558                 INP_INFO_WUNLOCK(&tcbinfo);
  559         splx(s);
  560 }

Cache object: 1c3dce0228f899bdd30d279bfb4c1a21


[ 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.