Commit | Line | Data |
---|---|---|
f4d55810 | 1 | /* tcp_timer.c 4.31 83/02/10 */ |
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" | |
f4d55810 | 9 | #include "../h/errno.h" |
6e7edb25 BJ |
10 | |
11 | #include "../net/if.h" | |
c124e997 | 12 | #include "../net/route.h" |
f4d55810 | 13 | |
6e7edb25 | 14 | #include "../netinet/in.h" |
fcfe450e BJ |
15 | #include "../netinet/in_pcb.h" |
16 | #include "../netinet/in_systm.h" | |
fcfe450e BJ |
17 | #include "../netinet/ip.h" |
18 | #include "../netinet/ip_var.h" | |
19 | #include "../netinet/tcp.h" | |
20 | #include "../netinet/tcp_fsm.h" | |
21 | #include "../netinet/tcp_seq.h" | |
22 | #include "../netinet/tcp_timer.h" | |
23 | #include "../netinet/tcp_var.h" | |
24 | #include "../netinet/tcpip.h" | |
f03530e6 | 25 | |
8b5a83bb | 26 | int tcpnodelack = 0; |
f03530e6 BJ |
27 | /* |
28 | * Fast timeout routine for processing delayed acks | |
29 | */ | |
30 | tcp_fasttimo() | |
31 | { | |
b8b9174f BJ |
32 | register struct inpcb *inp; |
33 | register struct tcpcb *tp; | |
34 | int s = splnet(); | |
b8b9174f | 35 | |
fd5dc5f0 BJ |
36 | inp = tcb.inp_next; |
37 | if (inp) | |
38 | for (; inp != &tcb; inp = inp->inp_next) | |
b8b9174f BJ |
39 | if ((tp = (struct tcpcb *)inp->inp_ppcb) && |
40 | (tp->t_flags & TF_DELACK)) { | |
41 | tp->t_flags &= ~TF_DELACK; | |
42 | tp->t_flags |= TF_ACKNOW; | |
43 | (void) tcp_output(tp); | |
44 | } | |
45 | splx(s); | |
f03530e6 BJ |
46 | } |
47 | ||
48 | /* | |
49 | * Tcp protocol timeout routine called every 500 ms. | |
50 | * Updates the timers in all active tcb's and | |
51 | * causes finite state machine actions if timers expire. | |
52 | */ | |
53 | tcp_slowtimo() | |
54 | { | |
1e977657 | 55 | register struct inpcb *ip, *ipnxt; |
f03530e6 BJ |
56 | register struct tcpcb *tp; |
57 | int s = splnet(); | |
f03530e6 | 58 | register int i; |
f03530e6 BJ |
59 | |
60 | /* | |
61 | * Search through tcb's and update active timers. | |
62 | */ | |
4aed14e3 BJ |
63 | ip = tcb.inp_next; |
64 | if (ip == 0) { | |
65 | splx(s); | |
66 | return; | |
67 | } | |
1e977657 | 68 | while (ip != &tcb) { |
f03530e6 | 69 | tp = intotcpcb(ip); |
37de812c BJ |
70 | if (tp == 0) |
71 | continue; | |
1e977657 | 72 | ipnxt = ip->inp_next; |
a6503abf | 73 | for (i = 0; i < TCPT_NTIMERS; i++) { |
1e977657 | 74 | if (tp->t_timer[i] && --tp->t_timer[i] == 0) { |
f03530e6 BJ |
75 | (void) tcp_usrreq(tp->t_inpcb->inp_socket, |
76 | PRU_SLOWTIMO, (struct mbuf *)0, | |
a1edc12b | 77 | (struct mbuf *)i, |
6e7edb25 | 78 | (struct socketopt *)0); |
1e977657 BJ |
79 | if (ipnxt->inp_prev != ip) |
80 | goto tpgone; | |
81 | } | |
f03530e6 | 82 | } |
405c9168 BJ |
83 | tp->t_idle++; |
84 | if (tp->t_rtt) | |
85 | tp->t_rtt++; | |
1e977657 BJ |
86 | tpgone: |
87 | ip = ipnxt; | |
f03530e6 | 88 | } |
a6503abf | 89 | tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ |
f03530e6 BJ |
90 | splx(s); |
91 | } | |
92 | ||
93 | /* | |
a6503abf | 94 | * Cancel all timers for TCP tp. |
f03530e6 | 95 | */ |
0974b45c | 96 | tcp_canceltimers(tp) |
f03530e6 BJ |
97 | struct tcpcb *tp; |
98 | { | |
f03530e6 BJ |
99 | register int i; |
100 | ||
a6503abf BJ |
101 | for (i = 0; i < TCPT_NTIMERS; i++) |
102 | tp->t_timer[i] = 0; | |
f03530e6 BJ |
103 | } |
104 | ||
7380f986 BJ |
105 | float tcp_backoff[TCP_MAXRXTSHIFT] = |
106 | { 1.0, 1.2, 1.4, 1.7, 2.0, 3.0, 5.0, 8.0, 16.0, 32.0 }; | |
7380f986 | 107 | int tcpexprexmtbackoff = 0; |
f03530e6 | 108 | /* |
405c9168 | 109 | * TCP timer processing. |
f03530e6 | 110 | */ |
0e3936fa | 111 | struct tcpcb * |
a6503abf | 112 | tcp_timers(tp, timer) |
f03530e6 | 113 | register struct tcpcb *tp; |
a6503abf | 114 | int timer; |
f03530e6 BJ |
115 | { |
116 | ||
0974b45c | 117 | switch (timer) { |
f03530e6 | 118 | |
405c9168 BJ |
119 | /* |
120 | * 2 MSL timeout in shutdown went off. Delete connection | |
121 | * control block. | |
122 | */ | |
a6503abf | 123 | case TCPT_2MSL: |
0e3936fa SL |
124 | tp = tcp_close(tp); |
125 | break; | |
f03530e6 | 126 | |
405c9168 BJ |
127 | /* |
128 | * Retransmission timer went off. Message has not | |
129 | * been acked within retransmit interval. Back off | |
130 | * to a longer retransmit interval and retransmit all | |
131 | * unacknowledged messages in the window. | |
132 | */ | |
a6503abf | 133 | case TCPT_REXMT: |
405c9168 | 134 | tp->t_rxtshift++; |
fd5dc5f0 | 135 | if (tp->t_rxtshift > TCP_MAXRXTSHIFT) { |
0e3936fa SL |
136 | tp = tcp_drop(tp, ETIMEDOUT); |
137 | break; | |
fd5dc5f0 | 138 | } |
405c9168 | 139 | TCPT_RANGESET(tp->t_timer[TCPT_REXMT], |
d977a479 | 140 | (int)tp->t_srtt, TCPTV_MIN, TCPTV_MAX); |
7380f986 BJ |
141 | if (tcpexprexmtbackoff) { |
142 | TCPT_RANGESET(tp->t_timer[TCPT_REXMT], | |
143 | tp->t_timer[TCPT_REXMT] << tp->t_rxtshift, | |
144 | TCPTV_MIN, TCPTV_MAX); | |
145 | } else { | |
146 | TCPT_RANGESET(tp->t_timer[TCPT_REXMT], | |
147 | tp->t_timer[TCPT_REXMT] * | |
148 | tcp_backoff[tp->t_rxtshift - 1], | |
149 | TCPTV_MIN, TCPTV_MAX); | |
150 | } | |
405c9168 BJ |
151 | tp->snd_nxt = tp->snd_una; |
152 | /* this only transmits one segment! */ | |
153 | (void) tcp_output(tp); | |
0e3936fa | 154 | break; |
f03530e6 | 155 | |
405c9168 BJ |
156 | /* |
157 | * Persistance timer into zero window. | |
158 | * Force a byte to be output, if possible. | |
159 | */ | |
a6503abf | 160 | case TCPT_PERSIST: |
a13c006d | 161 | tcp_setpersist(tp); |
405c9168 BJ |
162 | tp->t_force = 1; |
163 | (void) tcp_output(tp); | |
164 | tp->t_force = 0; | |
0e3936fa | 165 | break; |
f03530e6 | 166 | |
405c9168 BJ |
167 | /* |
168 | * Keep-alive timer went off; send something | |
169 | * or drop connection if idle for too long. | |
170 | */ | |
a6503abf | 171 | case TCPT_KEEP: |
f3cdd721 BJ |
172 | if (tp->t_state < TCPS_ESTABLISHED) |
173 | goto dropit; | |
3bd14c98 | 174 | if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) { |
f3cdd721 BJ |
175 | if (tp->t_idle >= TCPTV_MAXIDLE) |
176 | goto dropit; | |
3bd14c98 BJ |
177 | /* |
178 | * Saying tp->rcv_nxt-1 lies about what | |
179 | * we have received, and by the protocol spec | |
180 | * requires the correspondent TCP to respond. | |
181 | * Saying tp->snd_una-1 causes the transmitted | |
182 | * byte to lie outside the receive window; this | |
183 | * is important because we don't necessarily | |
184 | * have a byte in the window to send (consider | |
185 | * a one-way stream!) | |
186 | */ | |
8e65fd66 | 187 | tcp_respond(tp, |
3bd14c98 BJ |
188 | tp->t_template, tp->rcv_nxt-1, tp->snd_una-1, 0); |
189 | } else | |
1e977657 | 190 | tp->t_idle = 0; |
405c9168 | 191 | tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; |
0e3936fa | 192 | break; |
f3cdd721 | 193 | dropit: |
0e3936fa SL |
194 | tp = tcp_drop(tp, ETIMEDOUT); |
195 | break; | |
f03530e6 | 196 | } |
0e3936fa | 197 | return (tp); |
f03530e6 | 198 | } |