xref: /csrg-svn/sys/netinet/tcp_timer.c (revision 5069)
1 /* tcp_timer.c 4.1 81/11/24 */
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/mbuf.h"
6 #include "../h/socket.h"
7 #include "../h/socketvar.h"
8 #include "../h/protosw.h"
9 #include "../net/inet.h"
10 #include "../net/inet_pcb.h"
11 #include "../net/inet_systm.h"
12 #include "../net/if.h"
13 #include "../net/imp.h"
14 #include "../net/ip.h"
15 #include "../net/ip_var.h"
16 #include "../net/tcp.h"
17 #include "../net/tcp_fsm.h"
18 #include "../net/tcp_var.h"
19 #include "/usr/include/errno.h"
20 
21 /*
22  * Fast timeout routine for processing delayed acks
23  */
24 tcp_fasttimo()
25 {
26 
27 }
28 
29 /*
30  * Tcp protocol timeout routine called every 500 ms.
31  * Updates the timers in all active tcb's and
32  * causes finite state machine actions if timers expire.
33  */
34 tcp_slowtimo()
35 {
36 	register struct inpcb *ip;
37 	register struct tcpcb *tp;
38 	int s = splnet();
39 	register short *tmp;
40 	register int i;
41 COUNT(TCP_TIMEO);
42 
43 	/*
44 	 * Search through tcb's and update active timers.
45 	 */
46 	for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) {
47 		tp = intotcpcb(ip);
48 		tmp = &tp->t_init;
49 		for (i = 0; i < TNTIMERS; i++) {
50 			if (*tmp && --*tmp == 0)
51 				(void) tcp_usrreq(tp->t_inpcb->inp_socket,
52 				    PRU_SLOWTIMO, (struct mbuf *)0,
53 				    (caddr_t)i);
54 			tmp++;
55 		}
56 		tp->t_xmt++;
57 	}
58 	tcp_iss += ISSINCR/2;		/* increment iss */
59 	splx(s);
60 }
61 
62 /*
63  * Cancel all timers for tcp tp.
64  */
65 tcp_tcancel(tp)
66 	struct tcpcb *tp;
67 {
68 	register short *tmp = &tp->t_init;
69 	register int i;
70 
71 	for (i = 0; i < TNTIMERS; i++)
72 		*tmp++ = 0;
73 }
74 
75 /*
76  * TCP timer went off processing.
77  */
78 tcp_timers(tp, timertype)
79 	register struct tcpcb *tp;
80 	int timertype;
81 {
82 
83 COUNT(TCP_TIMERS);
84 	switch (timertype) {
85 
86 	case TFINACK:		/* fin-ack timer */
87 		switch (tp->t_state) {
88 
89 		case TIME_WAIT:
90 			/*
91 			 * We can be sure our ACK of foreign FIN was rcvd,
92 			 * and can close if no data left for user.
93 			 */
94 			if (rcv_empty(tp)) {
95 				tcp_disconnect(tp);
96 				return (CLOSED);
97 			}
98 			return (RCV_WAIT);			/* 17 */
99 
100 		case CLOSING:
101 			tp->tc_flags |= TC_WAITED_2_ML;
102 			return (SAME);
103 
104 		default:
105 			return (SAME);
106 		}
107 
108 	case TREXMT:		/* retransmission timer */
109 		if (tp->t_rexmt_val > tp->snd_una) {	 	/* 34 */
110 			/*
111 			 * Set so for a retransmission, increase rexmt time
112 			 * in case of multiple retransmissions.
113 			 */
114 			tp->snd_nxt = tp->snd_una;
115 			tp->tc_flags |= TC_REXMT;
116 			tp->t_xmtime = tp->t_xmtime << 1;
117 			if (tp->t_xmtime > T_REMAX)
118 				tp->t_xmtime = T_REMAX;
119 			(void) tcp_send(tp);
120 		}
121 		return (SAME);
122 
123 	case TREXMTTL:		/* retransmit too long */
124 		if (tp->t_rtl_val > tp->snd_una) {		/* 36 */
125 			tcp_error(tp, ETIMEDOUT);
126 			return (CLOSED);
127 		}
128 		return (SAME);
129 
130 	case TPERSIST:		/* persist timer */
131 		/*
132 		 * Force a byte send through closed window.
133 		 */
134 		tp->tc_flags |= TC_FORCE_ONE;
135 		(void) tcp_send(tp);
136 		return (SAME);
137 	}
138 	panic("tcp_timers");
139 	/*NOTREACHED*/
140 }
141