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