Commit | Line | Data |
---|---|---|
7bcd1bb8 KB |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | * | |
0593296a | 7 | * @(#)tp_timer.c 7.13 (Berkeley) %G% |
7bcd1bb8 KB |
8 | */ |
9 | ||
b65ddd42 KS |
10 | /*********************************************************** |
11 | Copyright IBM Corporation 1987 | |
12 | ||
13 | All Rights Reserved | |
14 | ||
15 | Permission to use, copy, modify, and distribute this software and its | |
16 | documentation for any purpose and without fee is hereby granted, | |
17 | provided that the above copyright notice appear in all copies and that | |
18 | both that copyright notice and this permission notice appear in | |
19 | supporting documentation, and that the name of IBM not be | |
20 | used in advertising or publicity pertaining to distribution of the | |
21 | software without specific, written prior permission. | |
22 | ||
23 | IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
25 | IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
26 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
27 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
28 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
29 | SOFTWARE. | |
30 | ||
31 | ******************************************************************/ | |
32 | ||
33 | /* | |
34 | * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison | |
35 | */ | |
36 | /* | |
37 | * ARGO TP | |
38 | * | |
39 | * $Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $ | |
40 | * $Source: /usr/argo/sys/netiso/RCS/tp_timer.c,v $ | |
41 | * | |
b65ddd42 KS |
42 | */ |
43 | ||
b65ddd42 | 44 | #include "param.h" |
f46d96dc | 45 | #include "systm.h" |
b65ddd42 | 46 | #include "time.h" |
a50e2bc0 | 47 | #include "malloc.h" |
f46d96dc | 48 | #include "protosw.h" |
e64561c1 | 49 | #include "socket.h" |
f46d96dc | 50 | #include "kernel.h" |
b65ddd42 | 51 | |
e8e39cc0 | 52 | #include "argo_debug.h" |
a50e2bc0 KS |
53 | #include "tp_param.h" |
54 | #include "tp_timer.h" | |
55 | #include "tp_stat.h" | |
56 | #include "tp_pcb.h" | |
57 | #include "tp_tpdu.h" | |
a50e2bc0 KS |
58 | #include "tp_trace.h" |
59 | #include "tp_seq.h" | |
b65ddd42 | 60 | |
e64561c1 | 61 | struct tp_ref *tp_ref; |
f46d96dc | 62 | int tp_rttdiv, tp_rttadd, N_TPREF = 127; |
aade66bc | 63 | struct tp_refinfo tp_refinfo; |
13cdf5ec | 64 | struct tp_pcb *tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist; |
b65ddd42 | 65 | |
b65ddd42 KS |
66 | /* |
67 | * CALLED FROM: | |
68 | * at autoconfig time from tp_init() | |
69 | * a combo of event, state, predicate | |
70 | * FUNCTION and ARGUMENTS: | |
71 | * initialize data structures for the timers | |
72 | */ | |
73 | void | |
74 | tp_timerinit() | |
75 | { | |
e64561c1 | 76 | register int s; |
b65ddd42 | 77 | /* |
e64561c1 | 78 | * Initialize storage |
b65ddd42 | 79 | */ |
f46d96dc KS |
80 | if (tp_refinfo.tpr_base) |
81 | return; | |
3a2fbed9 | 82 | tp_refinfo.tpr_size = N_TPREF + 1; /* Need to start somewhere */ |
f46d96dc KS |
83 | s = sizeof(*tp_ref) * tp_refinfo.tpr_size; |
84 | if ((tp_ref = (struct tp_ref *) malloc(s, M_PCB, M_NOWAIT)) == 0) | |
85 | panic("tp_timerinit"); | |
0593296a | 86 | bzero((caddr_t)tp_ref, (unsigned) s); |
bdf41b09 | 87 | tp_refinfo.tpr_base = tp_ref; |
f46d96dc KS |
88 | tp_rttdiv = hz / PR_SLOWHZ; |
89 | tp_rttadd = (2 * tp_rttdiv) - 1; | |
b65ddd42 | 90 | } |
f46d96dc | 91 | #ifdef TP_DEBUG_TIMERS |
b65ddd42 KS |
92 | /********************** e timers *************************/ |
93 | ||
b65ddd42 KS |
94 | /* |
95 | * CALLED FROM: | |
96 | * tp.trans all over | |
97 | * FUNCTION and ARGUMENTS: | |
bdf41b09 | 98 | * Set an E type timer. |
b65ddd42 KS |
99 | */ |
100 | void | |
bdf41b09 KS |
101 | tp_etimeout(tpcb, fun, ticks) |
102 | register struct tp_pcb *tpcb; | |
103 | int fun; /* function to be called */ | |
104 | int ticks; | |
b65ddd42 | 105 | { |
b65ddd42 | 106 | |
bdf41b09 | 107 | register u_int *callp; |
b65ddd42 | 108 | IFDEBUG(D_TIMER) |
bdf41b09 | 109 | printf("etimeout pcb 0x%x state 0x%x\n", tpcb, tpcb->tp_state); |
b65ddd42 KS |
110 | ENDDEBUG |
111 | IFTRACE(D_TIMER) | |
bdf41b09 KS |
112 | tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref, |
113 | tpcb->tp_state, ticks, tp_stat.ts_Eticks); | |
b65ddd42 | 114 | ENDTRACE |
3a2fbed9 KS |
115 | if (tpcb == 0) |
116 | return; | |
b65ddd42 KS |
117 | IncStat(ts_Eset); |
118 | if (ticks == 0) | |
119 | ticks = 1; | |
bdf41b09 KS |
120 | callp = tpcb->tp_timer + fun; |
121 | if (*callp == 0 || *callp > ticks) | |
122 | *callp = ticks; | |
b65ddd42 KS |
123 | } |
124 | ||
125 | /* | |
126 | * CALLED FROM: | |
127 | * tp.trans all over | |
128 | * FUNCTION and ARGUMENTS: | |
129 | * Cancel all occurrences of E-timer function (fun) for reference (refp) | |
130 | */ | |
131 | void | |
bdf41b09 KS |
132 | tp_euntimeout(tpcb, fun) |
133 | register struct tp_pcb *tpcb; | |
b65ddd42 KS |
134 | int fun; |
135 | { | |
b65ddd42 | 136 | IFTRACE(D_TIMER) |
bdf41b09 | 137 | tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0); |
b65ddd42 KS |
138 | ENDTRACE |
139 | ||
3a2fbed9 | 140 | if (tpcb) |
bdf41b09 | 141 | tpcb->tp_timer[fun] = 0; |
b65ddd42 KS |
142 | } |
143 | ||
144 | /**************** c timers ********************** | |
145 | * | |
146 | * These are not chained together; they sit | |
147 | * in the tp_ref structure. they are the kind that | |
148 | * are typically cancelled so it's faster not to | |
149 | * mess with the chains | |
150 | */ | |
f46d96dc | 151 | #endif |
b65ddd42 KS |
152 | /* |
153 | * CALLED FROM: | |
154 | * the clock, every 500 ms | |
155 | * FUNCTION and ARGUMENTS: | |
156 | * Look for open references with active timers. | |
157 | * If they exist, call the appropriate timer routines to update | |
158 | * the timers and possibly generate events. | |
b65ddd42 KS |
159 | */ |
160 | ProtoHook | |
161 | tp_slowtimo() | |
162 | { | |
0593296a | 163 | register u_int *cp; |
3a2fbed9 KS |
164 | register struct tp_ref *rp; |
165 | struct tp_pcb *tpcb; | |
b65ddd42 | 166 | struct tp_event E; |
3a2fbed9 | 167 | int s = splnet(), t; |
b65ddd42 KS |
168 | |
169 | /* check only open reference structures */ | |
170 | IncStat(ts_Cticks); | |
3a2fbed9 KS |
171 | /* tp_ref[0] is never used */ |
172 | for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) { | |
f46d96dc | 173 | if ((tpcb = rp->tpr_pcb) == 0 || tpcb->tp_refstate < REF_OPEN) |
b65ddd42 | 174 | continue; |
bdf41b09 KS |
175 | t = TM_NTIMERS; |
176 | /* check the timers */ | |
0593296a KS |
177 | for (t = 0; t < TM_NTIMERS; t++) { |
178 | cp = tpcb->tp_timer + t; | |
bdf41b09 KS |
179 | if (*cp && --(*cp) <= 0 ) { |
180 | *cp = 0; | |
3a2fbed9 | 181 | E.ev_number = t; |
3a2fbed9 KS |
182 | IFDEBUG(D_TIMER) |
183 | printf("C expired! type 0x%x\n", t); | |
184 | ENDDEBUG | |
185 | IncStat(ts_Cexpired); | |
0593296a | 186 | tp_driver(tpcb, &E); |
3a2fbed9 KS |
187 | if (t == TM_reference && tpcb->tp_state == TP_CLOSED) { |
188 | if (tpcb->tp_notdetached) { | |
189 | IFDEBUG(D_CONN) | |
190 | printf("PRU_DETACH: not detached\n"); | |
191 | ENDDEBUG | |
192 | tp_detach(tpcb); | |
193 | } | |
194 | /* XXX wart; where else to do it? */ | |
195 | free((caddr_t)tpcb, M_PCB); | |
b65ddd42 KS |
196 | } |
197 | } | |
198 | } | |
b65ddd42 KS |
199 | } |
200 | splx(s); | |
201 | return 0; | |
202 | } | |
203 | ||
bdf41b09 KS |
204 | /* |
205 | * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off. | |
206 | */ | |
207 | tp_data_retrans(tpcb) | |
208 | register struct tp_pcb *tpcb; | |
209 | { | |
210 | int rexmt, win; | |
211 | tpcb->tp_rttemit = 0; /* cancel current round trip time */ | |
212 | tpcb->tp_dupacks = 0; | |
213 | tpcb->tp_sndnxt = tpcb->tp_snduna; | |
214 | if (tpcb->tp_fcredit == 0) { | |
215 | /* | |
216 | * We transmitted new data, started timing it and the window | |
217 | * got shrunk under us. This can only happen if all data | |
218 | * that they wanted us to send got acked, so don't | |
219 | * bother shrinking the congestion windows, et. al. | |
220 | * The retransmission timer should have been reset in goodack() | |
221 | */ | |
0593296a KS |
222 | IFDEBUG(D_ACKRECV) |
223 | printf("tp_data_retrans: 0 window tpcb 0x%x una 0x%x\n", | |
224 | tpcb, tpcb->tp_snduna); | |
225 | ENDDEBUG | |
bdf41b09 KS |
226 | tpcb->tp_rxtshift = 0; |
227 | tpcb->tp_timer[TM_data_retrans] = 0; | |
228 | tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks; | |
0593296a | 229 | return; |
bdf41b09 KS |
230 | } |
231 | rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT); | |
232 | win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2)); | |
233 | win = max(win, 2); | |
234 | tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* slow start again. */ | |
235 | tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize; | |
236 | /* We're losing; our srtt estimate is probably bogus. | |
237 | * Clobber it so we'll take the next rtt measurement as our srtt; | |
238 | * Maintain current rxt times until then. | |
239 | */ | |
240 | if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) { | |
241 | /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */ | |
242 | tpcb->tp_rtt = 0; | |
243 | } | |
f46d96dc KS |
244 | TP_RANGESET(tpcb->tp_rxtcur, rexmt, tpcb->tp_peer_acktime, 128); |
245 | tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur; | |
bdf41b09 KS |
246 | tp_send(tpcb); |
247 | } | |
248 | ||
13cdf5ec KS |
249 | int |
250 | tp_fasttimo() | |
251 | { | |
252 | register struct tp_pcb *t; | |
253 | int s = splnet(); | |
254 | struct tp_event E; | |
255 | ||
256 | E.ev_number = TM_sendack; | |
257 | while ((t = tp_ftimeolist) != (struct tp_pcb *)&tp_ftimeolist) { | |
258 | if (t == 0) { | |
259 | printf("tp_fasttimeo: should panic"); | |
260 | tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist; | |
261 | } else { | |
262 | if (t->tp_flags & TPF_DELACK) { | |
13cdf5ec KS |
263 | IncStat(ts_Fdelack); |
264 | tp_driver(t, &E); | |
0593296a | 265 | t->tp_flags &= ~TPF_DELACK; |
13cdf5ec KS |
266 | } else |
267 | IncStat(ts_Fpruned); | |
268 | tp_ftimeolist = t->tp_fasttimeo; | |
269 | t->tp_fasttimeo = 0; | |
270 | } | |
271 | } | |
272 | splx(s); | |
273 | } | |
274 | ||
f46d96dc | 275 | #ifdef TP_DEBUG_TIMERS |
b65ddd42 KS |
276 | /* |
277 | * CALLED FROM: | |
278 | * tp.trans, tp_emit() | |
279 | * FUNCTION and ARGUMENTS: | |
280 | * Set a C type timer of type (which) to go off after (ticks) time. | |
281 | */ | |
282 | void | |
bdf41b09 KS |
283 | tp_ctimeout(tpcb, which, ticks) |
284 | register struct tp_pcb *tpcb; | |
b65ddd42 KS |
285 | int which, ticks; |
286 | { | |
b65ddd42 KS |
287 | |
288 | IFTRACE(D_TIMER) | |
289 | tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", | |
bdf41b09 | 290 | tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]); |
b65ddd42 | 291 | ENDTRACE |
bdf41b09 | 292 | if(tpcb->tp_timer[which]) |
b65ddd42 KS |
293 | IncStat(ts_Ccan_act); |
294 | IncStat(ts_Cset); | |
3a2fbed9 KS |
295 | if (ticks <= 0) |
296 | ticks = 1; | |
bdf41b09 | 297 | tpcb->tp_timer[which] = ticks; |
b65ddd42 KS |
298 | } |
299 | ||
300 | /* | |
301 | * CALLED FROM: | |
302 | * tp.trans | |
303 | * FUNCTION and ARGUMENTS: | |
304 | * Version of tp_ctimeout that resets the C-type time if the | |
305 | * parameter (ticks) is > the current value of the timer. | |
306 | */ | |
307 | void | |
bdf41b09 KS |
308 | tp_ctimeout_MIN(tpcb, which, ticks) |
309 | register struct tp_pcb *tpcb; | |
b65ddd42 KS |
310 | int which, ticks; |
311 | { | |
b65ddd42 KS |
312 | IFTRACE(D_TIMER) |
313 | tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", | |
bdf41b09 | 314 | tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]); |
b65ddd42 | 315 | ENDTRACE |
b65ddd42 | 316 | IncStat(ts_Cset); |
bdf41b09 KS |
317 | if (tpcb->tp_timer[which]) { |
318 | tpcb->tp_timer[which] = MIN(ticks, tpcb->tp_timer[which]); | |
3a2fbed9 KS |
319 | IncStat(ts_Ccan_act); |
320 | } else | |
bdf41b09 | 321 | tpcb->tp_timer[which] = ticks; |
b65ddd42 KS |
322 | } |
323 | ||
324 | /* | |
325 | * CALLED FROM: | |
326 | * tp.trans | |
327 | * FUNCTION and ARGUMENTS: | |
328 | * Cancel the (which) timer in the ref structure indicated by (refp). | |
329 | */ | |
330 | void | |
bdf41b09 KS |
331 | tp_cuntimeout(tpcb, which) |
332 | register struct tp_pcb *tpcb; | |
b65ddd42 | 333 | int which; |
b65ddd42 | 334 | { |
b65ddd42 | 335 | IFDEBUG(D_TIMER) |
bdf41b09 KS |
336 | printf("tp_cuntimeout(0x%x, %d) active %d\n", |
337 | tpcb, which, tpcb->tp_timer[which]); | |
b65ddd42 KS |
338 | ENDDEBUG |
339 | ||
340 | IFTRACE(D_TIMER) | |
341 | tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, | |
bdf41b09 | 342 | which, tpcb->tp_timer[which], 0); |
b65ddd42 KS |
343 | ENDTRACE |
344 | ||
bdf41b09 | 345 | if (tpcb->tp_timer[which]) |
b65ddd42 KS |
346 | IncStat(ts_Ccan_act); |
347 | else | |
348 | IncStat(ts_Ccan_inact); | |
bdf41b09 | 349 | tpcb->tp_timer[which] = 0; |
b65ddd42 | 350 | } |
f46d96dc | 351 | #endif |