machine independent
[unix-history] / usr / src / sys / netinet / tcp_timer.c
CommitLineData
d977a479 1/* tcp_timer.c 4.15 82/02/25 */
f03530e6
BJ
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"
0974b45c
BJ
9#include "../net/in.h"
10#include "../net/in_pcb.h"
11#include "../net/in_systm.h"
f03530e6 12#include "../net/if.h"
f03530e6
BJ
13#include "../net/ip.h"
14#include "../net/ip_var.h"
15#include "../net/tcp.h"
16#include "../net/tcp_fsm.h"
0974b45c
BJ
17#include "../net/tcp_seq.h"
18#include "../net/tcp_timer.h"
f03530e6 19#include "../net/tcp_var.h"
0974b45c 20#include "../net/tcpip.h"
f1b2fa5b 21#include "../errno.h"
f03530e6 22
8b5a83bb 23int tcpnodelack = 0;
f03530e6
BJ
24/*
25 * Fast timeout routine for processing delayed acks
26 */
27tcp_fasttimo()
28{
b8b9174f
BJ
29 register struct inpcb *inp;
30 register struct tcpcb *tp;
31 int s = splnet();
0974b45c 32COUNT(TCP_FASTTIMO);
b8b9174f 33
fd5dc5f0
BJ
34 inp = tcb.inp_next;
35 if (inp)
36 for (; inp != &tcb; inp = inp->inp_next)
b8b9174f
BJ
37 if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
38 (tp->t_flags & TF_DELACK)) {
39 tp->t_flags &= ~TF_DELACK;
40 tp->t_flags |= TF_ACKNOW;
41 (void) tcp_output(tp);
42 }
43 splx(s);
f03530e6
BJ
44}
45
46/*
47 * Tcp protocol timeout routine called every 500 ms.
48 * Updates the timers in all active tcb's and
49 * causes finite state machine actions if timers expire.
50 */
51tcp_slowtimo()
52{
53 register struct inpcb *ip;
54 register struct tcpcb *tp;
55 int s = splnet();
f03530e6 56 register int i;
0974b45c 57COUNT(TCP_SLOWTIMO);
f03530e6
BJ
58
59 /*
60 * Search through tcb's and update active timers.
61 */
4aed14e3
BJ
62 ip = tcb.inp_next;
63 if (ip == 0) {
64 splx(s);
65 return;
66 }
67 for (; ip != &tcb; ip = ip->inp_next) {
f03530e6 68 tp = intotcpcb(ip);
37de812c
BJ
69 if (tp == 0)
70 continue;
a6503abf 71 for (i = 0; i < TCPT_NTIMERS; i++) {
0974b45c 72 if (tp->t_timer[i] && --tp->t_timer[i] == 0)
f03530e6
BJ
73 (void) tcp_usrreq(tp->t_inpcb->inp_socket,
74 PRU_SLOWTIMO, (struct mbuf *)0,
75 (caddr_t)i);
f03530e6 76 }
405c9168
BJ
77 tp->t_idle++;
78 if (tp->t_rtt)
79 tp->t_rtt++;
f03530e6 80 }
a6503abf 81 tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
f03530e6
BJ
82 splx(s);
83}
84
85/*
a6503abf 86 * Cancel all timers for TCP tp.
f03530e6 87 */
0974b45c 88tcp_canceltimers(tp)
f03530e6
BJ
89 struct tcpcb *tp;
90{
f03530e6
BJ
91 register int i;
92
0974b45c 93COUNT(TCP_CANCELTIMERS);
a6503abf
BJ
94 for (i = 0; i < TCPT_NTIMERS; i++)
95 tp->t_timer[i] = 0;
f03530e6
BJ
96}
97
d977a479 98int tcprexmtprint;
f03530e6 99/*
405c9168 100 * TCP timer processing.
f03530e6 101 */
a6503abf 102tcp_timers(tp, timer)
f03530e6 103 register struct tcpcb *tp;
a6503abf 104 int timer;
f03530e6
BJ
105{
106
107COUNT(TCP_TIMERS);
0974b45c 108 switch (timer) {
f03530e6 109
405c9168
BJ
110 /*
111 * 2 MSL timeout in shutdown went off. Delete connection
112 * control block.
113 */
a6503abf
BJ
114 case TCPT_2MSL:
115 tcp_close(tp);
116 return;
f03530e6 117
405c9168
BJ
118 /*
119 * Retransmission timer went off. Message has not
120 * been acked within retransmit interval. Back off
121 * to a longer retransmit interval and retransmit all
122 * unacknowledged messages in the window.
123 */
a6503abf 124 case TCPT_REXMT:
405c9168 125 tp->t_rxtshift++;
fd5dc5f0
BJ
126 if (tp->t_rxtshift > TCP_MAXRXTSHIFT) {
127 tcp_drop(tp, ETIMEDOUT);
128 return;
129 }
405c9168 130 TCPT_RANGESET(tp->t_timer[TCPT_REXMT],
d977a479 131 (int)tp->t_srtt, TCPTV_MIN, TCPTV_MAX);
b8b9174f
BJ
132 TCPT_RANGESET(tp->t_timer[TCPT_REXMT],
133 tp->t_timer[TCPT_REXMT] << tp->t_rxtshift,
134 TCPTV_MIN, TCPTV_MAX);
d977a479
BJ
135if (tcprexmtprint)
136printf("rexmt set to %d\n", tp->t_timer[TCPT_REXMT]);
405c9168
BJ
137 tp->snd_nxt = tp->snd_una;
138 /* this only transmits one segment! */
139 (void) tcp_output(tp);
a6503abf 140 return;
f03530e6 141
405c9168
BJ
142 /*
143 * Persistance timer into zero window.
144 * Force a byte to be output, if possible.
145 */
a6503abf 146 case TCPT_PERSIST:
405c9168
BJ
147 tp->t_force = 1;
148 (void) tcp_output(tp);
149 tp->t_force = 0;
150 TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
d977a479 151 tcp_beta * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX);
0974b45c 152 return;
f03530e6 153
405c9168
BJ
154 /*
155 * Keep-alive timer went off; send something
156 * or drop connection if idle for too long.
157 */
a6503abf 158 case TCPT_KEEP:
405c9168
BJ
159 if (tp->t_state < TCPS_ESTABLISHED ||
160 tp->t_idle >= TCPTV_MAXIDLE) {
161 tcp_drop(tp, ETIMEDOUT);
162 return;
163 }
8e65fd66
BJ
164 if (tp->t_inpcb->inp_socket->so_options & SO_NOKEEPALIVE)
165 tp->t_idle = 0;
166 else
167 tcp_respond(tp,
168 tp->t_template, tp->rcv_nxt, tp->snd_una-1, 0);
405c9168 169 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
a6503abf 170 return;
8b5a83bb
BJ
171
172#ifdef TCPTRUEOOB
173 /*
174 * Out-of-band data retransmit timer.
175 */
176 case TCPT_OOBREXMT:
177 if (tp->t_flags & TF_NOOPT)
178 return;
179 (void) tcp_output(tp);
180 TCPT_RANGESET(tp->t_timer[TCPT_OOBREXMT],
181 2 * tp->t_srtt, TCPTV_MIN, TCPTV_MAX);
182 return;
183#endif
f03530e6 184 }
f03530e6 185}