# 2.11BSD#431 - /usr/src/sys/netinet/tcp_timer.c

##### Functions

    tcp_canceltimers  X
    tcp_fasttimo      X
    tcp_slowtimo      X
    tcp_timers        X

##### Variables

    tcp_backoff       X
    tcp_keepidle      X
    tcp_keepintvl     X
    tcp_maxidle       X
    tcpnodelack       X

       1: /*
       2:  * Copyright (c) 1982, 1986 Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms are permitted
       6:  * provided that this notice is preserved and that due credit is given
       7:  * to the University of California at Berkeley. The name of the University
       8:  * may not be used to endorse or promote products derived from this
       9:  * software without specific prior written permission. This software
      10:  * is provided ``as is'' without express or implied warranty.
      11:  *
      12:  *	@(#)tcp_timer.c	7.11.1.2 (Berkeley) 3/16/88
      13:  */
      14:
      15: #include "param.h"
      16: #include "systm.h"
      17: #include "mbuf.h"
      18: #include "socket.h"
      19: #include "socketvar.h"
      20: #include "protosw.h"
      21: #include "errno.h"
      22:
      23: #include "../net/if.h"
      24: #include "../net/route.h"
      25:
      26: #include "domain.h"
      27: #include "in.h"
      28: #include "in_pcb.h"
      29: #include "in_systm.h"
      30: #include "ip.h"
      31: #include "ip_var.h"
      32: #include "tcp.h"
      33: #include "tcp_fsm.h"
      34: #include "tcp_seq.h"
      35: #include "tcp_timer.h"
      36: #include "tcp_var.h"
      37: #include "tcpip.h"
      38:
      39: int tcpnodelack = 0;
      40: int tcp_keepidle = TCPTV_KEEP_IDLE;
      41: int tcp_keepintvl = TCPTV_KEEPINTVL;
      42: int tcp_maxidle;
      43: /*
      44:  * Fast timeout routine for processing delayed acks
      45:  */
      46: tcp_fasttimo()
      47: {
      48:     register struct inpcb *inp;
      49:     register struct tcpcb *tp;
      50:     int s = splnet();
      51:
      52:     inp = tcb.inp_next;
      53:     if (inp)
      54:     for (; inp != &tcb; inp = inp->inp_next)
      55:         if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
      56:             (tp->t_flags & TF_DELACK)) {
      57:             tp->t_flags &= ~TF_DELACK;
      58:             tp->t_flags |= TF_ACKNOW;
      59:             tcpstat.tcps_delack++;
      60:             (void) tcp_output(tp);
      61:         }
      62:     splx(s);
      63: }
      64:
      65: /*
      66:  * Tcp protocol timeout routine called every 500 ms.
      67:  * Updates the timers in all active tcb's and
      68:  * causes finite state machine actions if timers expire.
      69:  */
      70: tcp_slowtimo()
      71: {
      72:     register struct inpcb *ip, *ipnxt;
      73:     register struct tcpcb *tp;
      74:     int s = splnet();
      75:     register int i;
      76:
      77:     tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
      78:     /*
      79: 	 * Search through tcb's and update active timers.
      80: 	 */
      81:     ip = tcb.inp_next;
      82:     if (ip == 0) {
      83:         splx(s);
      84:         return;
      85:     }
      86:     for (; ip != &tcb; ip = ipnxt) {
      87:         ipnxt = ip->inp_next;
      88:         tp = intotcpcb(ip);
      89:         if (tp == 0)
      90:             continue;
      91:         for (i = 0; i < TCPT_NTIMERS; i++) {
      92:             if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
      93:                 (void) tcp_usrreq(tp->t_inpcb->inp_socket,
      94:                     PRU_SLOWTIMO, (struct mbuf *)0,
      95:                     (struct mbuf *)i, (struct mbuf *)0);
      96:                 if (ipnxt->inp_prev != ip)
      97:                     goto tpgone;
      98:             }
      99:         }
     100:         tp->t_idle++;
     101:         if (tp->t_rtt)
     102:             tp->t_rtt++;
     103: tpgone:
     104:         ;
     105:     }
     106:     tcp_iss += TCP_ISSINCR/PR_SLOWHZ;       /* increment iss */
     107: #ifdef TCP_COMPAT_42
     108:     if ((long)tcp_iss < 0)
     109:         tcp_iss = 0;                /* XXX */
     110: #endif
     111:     splx(s);
     112: }
     113:
     114: /*
     115:  * Cancel all timers for TCP tp.
     116:  */
     117: tcp_canceltimers(tp)
     118:     struct tcpcb *tp;
     119: {
     120:     register int i;
     121:
     122:     for (i = 0; i < TCPT_NTIMERS; i++)
     123:         tp->t_timer[i] = 0;
     124: }
     125:
     126: int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
     127:     { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
     128:
     129: /*
     130:  * TCP timer processing.
     131:  */
     132: struct tcpcb *
     133: tcp_timers(tp, timer)
     134:     register struct tcpcb *tp;
     135:     int timer;
     136: {
     137:     register int rexmt;
     138:
     139:     switch (timer) {
     140:
     141:     /*
     142: 	 * 2 MSL timeout in shutdown went off.  If we're closed but
     143: 	 * still waiting for peer to close and connection has been idle
     144: 	 * too long, or if 2MSL time is up from TIME_WAIT, delete connection
     145: 	 * control block.  Otherwise, check again in a bit.
     146: 	 */
     147:     case TCPT_2MSL:
     148:         if (tp->t_state != TCPS_TIME_WAIT &&
     149:             tp->t_idle <= tcp_maxidle)
     150:             tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
     151:         else
     152:             tp = tcp_close(tp);
     153:         break;
     154:
     155:     /*
     156: 	 * Retransmission timer went off.  Message has not
     157: 	 * been acked within retransmit interval.  Back off
     158: 	 * to a longer retransmit interval and retransmit one segment.
     159: 	 */
     160:     case TCPT_REXMT:
     161:         if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
     162:             tp->t_rxtshift = TCP_MAXRXTSHIFT;
     163:             tcpstat.tcps_timeoutdrop++;
     164:             tp = tcp_drop(tp, ETIMEDOUT);
     165:             break;
     166:         }
     167:         tcpstat.tcps_rexmttimeo++;
     168:         rexmt = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
     169:         rexmt *= tcp_backoff[tp->t_rxtshift];
     170:         TCPT_RANGESET(tp->t_rxtcur, rexmt, TCPTV_MIN, TCPTV_REXMTMAX);
     171:         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
     172:         /*
     173: 		 * If losing, let the lower level know and try for
     174: 		 * a better route.  Also, if we backed off this far,
     175: 		 * our srtt estimate is probably bogus.  Clobber it
     176: 		 * so we'll take the next rtt measurement as our srtt;
     177: 		 * move the current srtt into rttvar to keep the current
     178: 		 * retransmit times until then.
     179: 		 */
     180:         if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
     181: #if BSD>=43
     182:             in_losing(tp->t_inpcb);
     183: #endif
     184:             tp->t_rttvar += (tp->t_srtt >> 2);
     185:             tp->t_srtt = 0;
     186:         }
     187:         tp->snd_nxt = tp->snd_una;
     188:         /*
     189: 		 * If timing a segment in this window, stop the timer.
     190: 		 */
     191:         tp->t_rtt = 0;
     192:         /*
     193: 		 * Close the congestion window down to one segment
     194: 		 * (we'll open it by one segment for each ack we get).
     195: 		 * Since we probably have a window's worth of unacked
     196: 		 * data accumulated, this "slow start" keeps us from
     197: 		 * dumping all that data as back-to-back packets (which
     198: 		 * might overwhelm an intermediate gateway).
     199: 		 *
     200: 		 * There are two phases to the opening: Initially we
     201: 		 * open by one mss on each ack.  This makes the window
     202: 		 * size increase exponentially with time.  If the
     203: 		 * window is larger than the path can handle, this
     204: 		 * exponential growth results in dropped packet(s)
     205: 		 * almost immediately.  To get more time between
     206: 		 * drops but still "push" the network to take advantage
     207: 		 * of improving conditions, we switch from exponential
     208: 		 * to linear window opening at some threshhold size.
     209: 		 * For a threshhold, we use half the current window
     210: 		 * size, truncated to a multiple of the mss.
     211: 		 *
     212: 		 * (the minimum cwnd that will give us exponential
     213: 		 * growth is 2 mss.  We don't allow the threshhold
     214: 		 * to go below this.)
     215: 		 */
     216:         {
     217:         u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
     218:         if (win < 2)
     219:             win = 2;
     220:         tp->snd_cwnd = tp->t_maxseg;
     221:         tp->snd_ssthresh = win * tp->t_maxseg;
     222:         }
     223:         (void) tcp_output(tp);
     224:         break;
     225:
     226:     /*
     227: 	 * Persistance timer into zero window.
     228: 	 * Force a byte to be output, if possible.
     229: 	 */
     230:     case TCPT_PERSIST:
     231:         tcpstat.tcps_persisttimeo++;
     232:         tcp_setpersist(tp);
     233:         tp->t_force = 1;
     234:         (void) tcp_output(tp);
     235:         tp->t_force = 0;
     236:         break;
     237:
     238:     /*
     239: 	 * Keep-alive timer went off; send something
     240: 	 * or drop connection if idle for too long.
     241: 	 */
     242:     case TCPT_KEEP:
     243:         tcpstat.tcps_keeptimeo++;
     244:         if (tp->t_state < TCPS_ESTABLISHED)
     245:             goto dropit;
     246:         if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
     247:             tp->t_state <= TCPS_CLOSE_WAIT) {
     248:                 if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
     249:                 goto dropit;
     250:             /*
     251: 			 * Send a packet designed to force a response
     252: 			 * if the peer is up and reachable:
     253: 			 * either an ACK if the connection is still alive,
     254: 			 * or an RST if the peer has closed the connection
     255: 			 * due to timeout or reboot.
     256: 			 * Using sequence number tp->snd_una-1
     257: 			 * causes the transmitted zero-length segment
     258: 			 * to lie outside the receive window;
     259: 			 * by the protocol spec, this requires the
     260: 			 * correspondent TCP to respond.
     261: 			 */
     262:             tcpstat.tcps_keepprobe++;
     263: #ifdef TCP_COMPAT_42
     264:             /*
     265: 			 * The keepalive packet must have nonzero length
     266: 			 * to get a 4.2 host to respond.
     267: 			 */
     268:             tcp_respond(tp, tp->t_template,
     269:                 tp->rcv_nxt - 1, tp->snd_una - 1, 0);
     270: #else
     271:             tcp_respond(tp, tp->t_template,
     272:                 tp->rcv_nxt, tp->snd_una - 1, 0);
     273: #endif
     274:             tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
     275:         } else
     276:             tp->t_timer[TCPT_KEEP] = tcp_keepidle;
     277:         break;
     278:     dropit:
     279:         tcpstat.tcps_keepdrops++;
     280:         tp = tcp_drop(tp, ETIMEDOUT);
     281:         break;
     282:     }
     283:     return (tp);
     284: }

#### Defined functions

tcp_canceltimers defined in line 117; never used
tcp_fasttimo defined in line 46; never used
tcp_slowtimo defined in line 70; never used
tcp_timers defined in line 132; never used

#### Defined variables

tcp_backoff defined in line 126; used 1 times

- in line 169

tcp_keepidle defined in line 40; never used
tcp_keepintvl defined in line 41; never used
tcp_maxidle defined in line 42; used 3 times

- in line 77, 149, 248

tcpnodelack defined in line 39; never used

Last modified: 1988-04-29 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1748 |