Commit | Line | Data |
---|---|---|
8ae0e4b4 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
8ae0e4b4 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
35f3fc10 | 6 | * @(#)tcp_timer.c 7.2 (Berkeley) %G% |
8ae0e4b4 | 7 | */ |
f03530e6 | 8 | |
20666ad3 JB |
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" | |
6e7edb25 BJ |
16 | |
17 | #include "../net/if.h" | |
c124e997 | 18 | #include "../net/route.h" |
f4d55810 | 19 | |
20666ad3 JB |
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" | |
f03530e6 | 31 | |
8b5a83bb | 32 | int tcpnodelack = 0; |
f03530e6 BJ |
33 | /* |
34 | * Fast timeout routine for processing delayed acks | |
35 | */ | |
36 | tcp_fasttimo() | |
37 | { | |
b8b9174f BJ |
38 | register struct inpcb *inp; |
39 | register struct tcpcb *tp; | |
40 | int s = splnet(); | |
b8b9174f | 41 | |
fd5dc5f0 BJ |
42 | inp = tcb.inp_next; |
43 | if (inp) | |
44 | for (; inp != &tcb; inp = inp->inp_next) | |
b8b9174f BJ |
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; | |
35f3fc10 | 49 | tcpstat.tcps_delack++; |
b8b9174f BJ |
50 | (void) tcp_output(tp); |
51 | } | |
52 | splx(s); | |
f03530e6 BJ |
53 | } |
54 | ||
55 | /* | |
56 | * Tcp protocol timeout routine called every 500 ms. | |
57 | * Updates the timers in all active tcb's and | |
58 | * causes finite state machine actions if timers expire. | |
59 | */ | |
60 | tcp_slowtimo() | |
61 | { | |
1e977657 | 62 | register struct inpcb *ip, *ipnxt; |
f03530e6 BJ |
63 | register struct tcpcb *tp; |
64 | int s = splnet(); | |
f03530e6 | 65 | register int i; |
f03530e6 BJ |
66 | |
67 | /* | |
68 | * Search through tcb's and update active timers. | |
69 | */ | |
4aed14e3 BJ |
70 | ip = tcb.inp_next; |
71 | if (ip == 0) { | |
72 | splx(s); | |
73 | return; | |
74 | } | |
039b88d5 MK |
75 | for (; ip != &tcb; ip = ipnxt) { |
76 | ipnxt = ip->inp_next; | |
f03530e6 | 77 | tp = intotcpcb(ip); |
37de812c BJ |
78 | if (tp == 0) |
79 | continue; | |
a6503abf | 80 | for (i = 0; i < TCPT_NTIMERS; i++) { |
1e977657 | 81 | if (tp->t_timer[i] && --tp->t_timer[i] == 0) { |
f03530e6 BJ |
82 | (void) tcp_usrreq(tp->t_inpcb->inp_socket, |
83 | PRU_SLOWTIMO, (struct mbuf *)0, | |
755d8841 | 84 | (struct mbuf *)i, (struct mbuf *)0); |
1e977657 BJ |
85 | if (ipnxt->inp_prev != ip) |
86 | goto tpgone; | |
87 | } | |
f03530e6 | 88 | } |
405c9168 BJ |
89 | tp->t_idle++; |
90 | if (tp->t_rtt) | |
91 | tp->t_rtt++; | |
1e977657 | 92 | tpgone: |
039b88d5 | 93 | ; |
f03530e6 | 94 | } |
a6503abf | 95 | tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ |
367bed15 | 96 | #ifdef TCP_COMPAT_42 |
c50542f3 MK |
97 | if ((int)tcp_iss < 0) |
98 | tcp_iss = 0; /* XXX */ | |
99 | #endif | |
f03530e6 BJ |
100 | splx(s); |
101 | } | |
102 | ||
103 | /* | |
a6503abf | 104 | * Cancel all timers for TCP tp. |
f03530e6 | 105 | */ |
0974b45c | 106 | tcp_canceltimers(tp) |
f03530e6 BJ |
107 | struct tcpcb *tp; |
108 | { | |
f03530e6 BJ |
109 | register int i; |
110 | ||
a6503abf BJ |
111 | for (i = 0; i < TCPT_NTIMERS; i++) |
112 | tp->t_timer[i] = 0; | |
f03530e6 BJ |
113 | } |
114 | ||
2a89e5a6 MK |
115 | int tcp_backoff[TCP_MAXRXTSHIFT+1] = |
116 | { 1, 2, 4, 6, 8, 10, 15, 20, 30, 30, 30, 30, 30 }; | |
f03530e6 | 117 | /* |
405c9168 | 118 | * TCP timer processing. |
f03530e6 | 119 | */ |
0e3936fa | 120 | struct tcpcb * |
a6503abf | 121 | tcp_timers(tp, timer) |
f03530e6 | 122 | register struct tcpcb *tp; |
a6503abf | 123 | int timer; |
f03530e6 | 124 | { |
2a89e5a6 | 125 | register int rexmt; |
f03530e6 | 126 | |
0974b45c | 127 | switch (timer) { |
f03530e6 | 128 | |
405c9168 | 129 | /* |
6209c5c4 MK |
130 | * 2 MSL timeout in shutdown went off. If we're closed but |
131 | * still waiting for peer to close and connection has been idle | |
132 | * too long, or if 2MSL time is up from TIME_WAIT, delete connection | |
133 | * control block. Otherwise, check again in a bit. | |
405c9168 | 134 | */ |
a6503abf | 135 | case TCPT_2MSL: |
6209c5c4 MK |
136 | if (tp->t_state != TCPS_TIME_WAIT && |
137 | tp->t_idle <= TCPTV_MAXIDLE) | |
138 | tp->t_timer[TCPT_2MSL] = TCPTV_KEEP; | |
139 | else | |
140 | tp = tcp_close(tp); | |
0e3936fa | 141 | break; |
f03530e6 | 142 | |
405c9168 BJ |
143 | /* |
144 | * Retransmission timer went off. Message has not | |
145 | * been acked within retransmit interval. Back off | |
eeaf00e3 | 146 | * to a longer retransmit interval and retransmit one segment. |
405c9168 | 147 | */ |
a6503abf | 148 | case TCPT_REXMT: |
405c9168 | 149 | tp->t_rxtshift++; |
fd5dc5f0 | 150 | if (tp->t_rxtshift > TCP_MAXRXTSHIFT) { |
35f3fc10 | 151 | tcpstat.tcps_timeoutdrop++; |
0e3936fa SL |
152 | tp = tcp_drop(tp, ETIMEDOUT); |
153 | break; | |
fd5dc5f0 | 154 | } |
35f3fc10 | 155 | tcpstat.tcps_rexmttimeo++; |
2a89e5a6 MK |
156 | if (tp->t_srtt == 0) |
157 | rexmt = tcp_beta * TCPTV_SRTTDFLT; | |
158 | else | |
159 | rexmt = (int)(tcp_beta * tp->t_srtt); | |
160 | rexmt *= tcp_backoff[tp->t_rxtshift - 1]; | |
161 | TCPT_RANGESET(tp->t_timer[TCPT_REXMT], rexmt, | |
7380f986 | 162 | TCPTV_MIN, TCPTV_MAX); |
6a4fd140 MK |
163 | /* |
164 | * If losing, let the lower level know | |
165 | * and try for a better route. | |
166 | */ | |
167 | if (tp->t_rxtshift >= TCP_MAXRXTSHIFT / 4 || | |
168 | rexmt >= 10 * PR_SLOWHZ) | |
169 | in_losing(tp->t_inpcb); | |
405c9168 | 170 | tp->snd_nxt = tp->snd_una; |
7872cc0a | 171 | /* |
f2da4d39 MK |
172 | * If timing a segment in this window, |
173 | * and we have already gotten some timing estimate, | |
174 | * stop the timer. | |
7872cc0a | 175 | */ |
f2da4d39 | 176 | if (tp->t_rtt && tp->t_srtt) |
7872cc0a | 177 | tp->t_rtt = 0; |
405c9168 | 178 | (void) tcp_output(tp); |
0e3936fa | 179 | break; |
f03530e6 | 180 | |
405c9168 BJ |
181 | /* |
182 | * Persistance timer into zero window. | |
183 | * Force a byte to be output, if possible. | |
184 | */ | |
a6503abf | 185 | case TCPT_PERSIST: |
35f3fc10 | 186 | tcpstat.tcps_persisttimeo++; |
a13c006d | 187 | tcp_setpersist(tp); |
405c9168 BJ |
188 | tp->t_force = 1; |
189 | (void) tcp_output(tp); | |
190 | tp->t_force = 0; | |
0e3936fa | 191 | break; |
f03530e6 | 192 | |
405c9168 BJ |
193 | /* |
194 | * Keep-alive timer went off; send something | |
195 | * or drop connection if idle for too long. | |
196 | */ | |
a6503abf | 197 | case TCPT_KEEP: |
35f3fc10 | 198 | tcpstat.tcps_keeptimeo++; |
f3cdd721 BJ |
199 | if (tp->t_state < TCPS_ESTABLISHED) |
200 | goto dropit; | |
c0200c65 MK |
201 | if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE && |
202 | tp->t_state <= TCPS_CLOSE_WAIT) { | |
f3cdd721 BJ |
203 | if (tp->t_idle >= TCPTV_MAXIDLE) |
204 | goto dropit; | |
3bd14c98 | 205 | /* |
35f3fc10 MK |
206 | * Send a packet designed to force a response |
207 | * if the peer is up and reachable: | |
208 | * either an ACK if the connection is still alive, | |
209 | * or an RST if the peer has closed the connection | |
210 | * due to timeout or reboot. | |
211 | * Using sequence number tp->snd_una-1 | |
212 | * causes the transmitted zero-length segment | |
213 | * to lie outside the receive window; | |
214 | * by the protocol spec, this requires the | |
215 | * correspondent TCP to respond. | |
3bd14c98 | 216 | */ |
35f3fc10 | 217 | tcpstat.tcps_keepprobe++; |
8e65fd66 | 218 | tcp_respond(tp, |
35f3fc10 | 219 | tp->t_template, tp->rcv_nxt, tp->snd_una-1, 0); |
c0200c65 | 220 | } |
405c9168 | 221 | tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; |
0e3936fa | 222 | break; |
f3cdd721 | 223 | dropit: |
35f3fc10 | 224 | tcpstat.tcps_keepdrops++; |
0e3936fa SL |
225 | tp = tcp_drop(tp, ETIMEDOUT); |
226 | break; | |
f03530e6 | 227 | } |
0e3936fa | 228 | return (tp); |
f03530e6 | 229 | } |