|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)tcp_timer.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "systm.h" ! 11: #include "mbuf.h" ! 12: #include "socket.h" ! 13: #include "socketvar.h" ! 14: #include "protosw.h" ! 15: #include "errno.h" ! 16: ! 17: #include "../net/if.h" ! 18: #include "../net/route.h" ! 19: ! 20: #include "in.h" ! 21: #include "in_pcb.h" ! 22: #include "in_systm.h" ! 23: #include "ip.h" ! 24: #include "ip_var.h" ! 25: #include "tcp.h" ! 26: #include "tcp_fsm.h" ! 27: #include "tcp_seq.h" ! 28: #include "tcp_timer.h" ! 29: #include "tcp_var.h" ! 30: #include "tcpip.h" ! 31: ! 32: int tcpnodelack = 0; ! 33: /* ! 34: * Fast timeout routine for processing delayed acks ! 35: */ ! 36: tcp_fasttimo() ! 37: { ! 38: register struct inpcb *inp; ! 39: register struct tcpcb *tp; ! 40: int s = splnet(); ! 41: ! 42: inp = tcb.inp_next; ! 43: if (inp) ! 44: for (; inp != &tcb; inp = inp->inp_next) ! 45: if ((tp = (struct tcpcb *)inp->inp_ppcb) && ! 46: (tp->t_flags & TF_DELACK)) { ! 47: tp->t_flags &= ~TF_DELACK; ! 48: tp->t_flags |= TF_ACKNOW; ! 49: (void) tcp_output(tp); ! 50: } ! 51: splx(s); ! 52: } ! 53: ! 54: /* ! 55: * Tcp protocol timeout routine called every 500 ms. ! 56: * Updates the timers in all active tcb's and ! 57: * causes finite state machine actions if timers expire. ! 58: */ ! 59: tcp_slowtimo() ! 60: { ! 61: register struct inpcb *ip, *ipnxt; ! 62: register struct tcpcb *tp; ! 63: int s = splnet(); ! 64: register int i; ! 65: ! 66: /* ! 67: * Search through tcb's and update active timers. ! 68: */ ! 69: ip = tcb.inp_next; ! 70: if (ip == 0) { ! 71: splx(s); ! 72: return; ! 73: } ! 74: for (; ip != &tcb; ip = ipnxt) { ! 75: ipnxt = ip->inp_next; ! 76: tp = intotcpcb(ip); ! 77: if (tp == 0) ! 78: continue; ! 79: for (i = 0; i < TCPT_NTIMERS; i++) { ! 80: if (tp->t_timer[i] && --tp->t_timer[i] == 0) { ! 81: (void) tcp_usrreq(tp->t_inpcb->inp_socket, ! 82: PRU_SLOWTIMO, (struct mbuf *)0, ! 83: (struct mbuf *)i, (struct mbuf *)0); ! 84: if (ipnxt->inp_prev != ip) ! 85: goto tpgone; ! 86: } ! 87: } ! 88: tp->t_idle++; ! 89: if (tp->t_rtt) ! 90: tp->t_rtt++; ! 91: tpgone: ! 92: ; ! 93: } ! 94: tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ ! 95: #ifdef TCP_COMPAT_42 ! 96: if ((int)tcp_iss < 0) ! 97: tcp_iss = 0; /* XXX */ ! 98: #endif ! 99: splx(s); ! 100: } ! 101: ! 102: /* ! 103: * Cancel all timers for TCP tp. ! 104: */ ! 105: tcp_canceltimers(tp) ! 106: struct tcpcb *tp; ! 107: { ! 108: register int i; ! 109: ! 110: for (i = 0; i < TCPT_NTIMERS; i++) ! 111: tp->t_timer[i] = 0; ! 112: } ! 113: ! 114: int tcp_backoff[TCP_MAXRXTSHIFT+1] = ! 115: { 1, 2, 4, 6, 8, 10, 15, 20, 30, 30, 30, 30, 30 }; ! 116: /* ! 117: * TCP timer processing. ! 118: */ ! 119: struct tcpcb * ! 120: tcp_timers(tp, timer) ! 121: register struct tcpcb *tp; ! 122: int timer; ! 123: { ! 124: register int rexmt; ! 125: ! 126: switch (timer) { ! 127: ! 128: /* ! 129: * 2 MSL timeout in shutdown went off. If we're closed but ! 130: * still waiting for peer to close and connection has been idle ! 131: * too long, or if 2MSL time is up from TIME_WAIT, delete connection ! 132: * control block. Otherwise, check again in a bit. ! 133: */ ! 134: case TCPT_2MSL: ! 135: if (tp->t_state != TCPS_TIME_WAIT && ! 136: tp->t_idle <= TCPTV_MAXIDLE) ! 137: tp->t_timer[TCPT_2MSL] = TCPTV_KEEP; ! 138: else ! 139: tp = tcp_close(tp); ! 140: break; ! 141: ! 142: /* ! 143: * Retransmission timer went off. Message has not ! 144: * been acked within retransmit interval. Back off ! 145: * to a longer retransmit interval and retransmit one segment. ! 146: */ ! 147: case TCPT_REXMT: ! 148: tp->t_rxtshift++; ! 149: if (tp->t_rxtshift > TCP_MAXRXTSHIFT) { ! 150: tp = tcp_drop(tp, ETIMEDOUT); ! 151: break; ! 152: } ! 153: if (tp->t_srtt == 0) ! 154: rexmt = tcp_beta * TCPTV_SRTTDFLT; ! 155: else ! 156: rexmt = (int)(tcp_beta * tp->t_srtt); ! 157: rexmt *= tcp_backoff[tp->t_rxtshift - 1]; ! 158: TCPT_RANGESET(tp->t_timer[TCPT_REXMT], rexmt, ! 159: TCPTV_MIN, TCPTV_MAX); ! 160: /* ! 161: * If losing, let the lower level know ! 162: * and try for a better route. ! 163: */ ! 164: if (tp->t_rxtshift >= TCP_MAXRXTSHIFT / 4 || ! 165: rexmt >= 10 * PR_SLOWHZ) ! 166: in_losing(tp->t_inpcb); ! 167: tp->snd_nxt = tp->snd_una; ! 168: /* ! 169: * If timing a segment in this window, ! 170: * and we have already gotten some timing estimate, ! 171: * stop the timer. ! 172: */ ! 173: if (tp->t_rtt && tp->t_srtt) ! 174: tp->t_rtt = 0; ! 175: (void) tcp_output(tp); ! 176: break; ! 177: ! 178: /* ! 179: * Persistance timer into zero window. ! 180: * Force a byte to be output, if possible. ! 181: */ ! 182: case TCPT_PERSIST: ! 183: tcp_setpersist(tp); ! 184: tp->t_force = 1; ! 185: (void) tcp_output(tp); ! 186: tp->t_force = 0; ! 187: break; ! 188: ! 189: /* ! 190: * Keep-alive timer went off; send something ! 191: * or drop connection if idle for too long. ! 192: */ ! 193: case TCPT_KEEP: ! 194: if (tp->t_state < TCPS_ESTABLISHED) ! 195: goto dropit; ! 196: if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE && ! 197: tp->t_state <= TCPS_CLOSE_WAIT) { ! 198: if (tp->t_idle >= TCPTV_MAXIDLE) ! 199: goto dropit; ! 200: /* ! 201: * Saying tp->rcv_nxt-1 lies about what ! 202: * we have received, and by the protocol spec ! 203: * requires the correspondent TCP to respond. ! 204: * Saying tp->snd_una-1 causes the transmitted ! 205: * byte to lie outside the receive window; this ! 206: * is important because we don't necessarily ! 207: * have a byte in the window to send (consider ! 208: * a one-way stream!) ! 209: */ ! 210: tcp_respond(tp, ! 211: tp->t_template, tp->rcv_nxt-1, tp->snd_una-1, 0); ! 212: } ! 213: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; ! 214: break; ! 215: dropit: ! 216: tp = tcp_drop(tp, ETIMEDOUT); ! 217: break; ! 218: } ! 219: return (tp); ! 220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.