must have directory vnode as first op
[unix-history] / usr / src / sys / netiso / tp_timer.c
CommitLineData
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
15Permission to use, copy, modify, and distribute this software and its
16documentation for any purpose and without fee is hereby granted,
17provided that the above copyright notice appear in all copies and that
18both that copyright notice and this permission notice appear in
19supporting documentation, and that the name of IBM not be
20used in advertising or publicity pertaining to distribution of the
21software without specific, written prior permission.
22
23IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29SOFTWARE.
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 61struct tp_ref *tp_ref;
f46d96dc 62int tp_rttdiv, tp_rttadd, N_TPREF = 127;
aade66bc 63struct tp_refinfo tp_refinfo;
13cdf5ec 64struct 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 */
73void
74tp_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 */
100void
bdf41b09
KS
101tp_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 */
131void
bdf41b09
KS
132tp_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 */
160ProtoHook
161tp_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 */
207tp_data_retrans(tpcb)
208register 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
249int
250tp_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 */
282void
bdf41b09
KS
283tp_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 */
307void
bdf41b09
KS
308tp_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 */
330void
bdf41b09
KS
331tp_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