No empty .Rs/.Re
[netbsd-mini2440.git] / sys / netiso / tp_timer.c
bloba7ceb51a6d533c61121a6801e95b69063819c0ba
1 /* $NetBSD: tp_timer.c,v 1.18 2007/03/04 06:03:33 christos Exp $ */
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
31 * @(#)tp_timer.c 8.1 (Berkeley) 6/10/93
34 /***********************************************************
35 Copyright IBM Corporation 1987
37 All Rights Reserved
39 Permission to use, copy, modify, and distribute this software and its
40 documentation for any purpose and without fee is hereby granted,
41 provided that the above copyright notice appear in all copies and that
42 both that copyright notice and this permission notice appear in
43 supporting documentation, and that the name of IBM not be
44 used in advertising or publicity pertaining to distribution of the
45 software without specific, written prior permission.
47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 SOFTWARE.
55 ******************************************************************/
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: tp_timer.c,v 1.18 2007/03/04 06:03:33 christos Exp $");
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/time.h>
67 #include <sys/malloc.h>
68 #include <sys/protosw.h>
69 #include <sys/socket.h>
70 #include <sys/kernel.h>
72 #include <netiso/argo_debug.h>
73 #include <netiso/tp_param.h>
74 #include <netiso/tp_timer.h>
75 #include <netiso/tp_stat.h>
76 #include <netiso/tp_pcb.h>
77 #include <netiso/tp_tpdu.h>
78 #include <netiso/tp_trace.h>
79 #include <netiso/tp_seq.h>
80 #include <netiso/tp_var.h>
82 struct tp_ref *tp_ref;
83 int tp_rttdiv, tp_rttadd, N_TPREF = 127;
84 struct tp_refinfo tp_refinfo;
85 struct tp_pcb *tp_ftimeolist = (struct tp_pcb *) & tp_ftimeolist;
88 * CALLED FROM:
89 * at autoconfig time from tp_init()
90 * a combo of event, state, predicate
91 * FUNCTION and ARGUMENTS:
92 * initialize data structures for the timers
94 void
95 tp_timerinit(void)
97 int s;
99 * Initialize storage
101 if (tp_refinfo.tpr_base)
102 return;
103 tp_refinfo.tpr_size = N_TPREF + 1; /* Need to start somewhere */
104 s = sizeof(*tp_ref) * tp_refinfo.tpr_size;
105 if ((tp_ref = (struct tp_ref *) malloc(s, M_PCB, M_NOWAIT|M_ZERO)) == 0)
106 panic("tp_timerinit");
107 tp_refinfo.tpr_base = tp_ref;
108 tp_rttdiv = hz / PR_SLOWHZ;
109 tp_rttadd = (2 * tp_rttdiv) - 1;
111 #ifdef TP_DEBUG_TIMERS
112 /********************** e timers *************************/
115 * CALLED FROM:
116 * tp.trans all over
117 * FUNCTION and ARGUMENTS:
118 * Set an E type timer.
120 void
121 tp_etimeout(
122 struct tp_pcb *tpcb,
123 int fun, /* function to be called */
124 int ticks)
127 u_int *callp;
128 #ifdef ARGO_DEBUG
129 if (argo_debug[D_TIMER]) {
130 printf("etimeout pcb %p state 0x%x\n", tpcb, tpcb->tp_state);
132 #endif
133 #ifdef TPPT
134 if (tp_traceflags[D_TIMER]) {
135 tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref,
136 tpcb->tp_state, ticks, tp_stat.ts_Eticks);
138 #endif
139 if (tpcb == 0)
140 return;
141 IncStat(ts_Eset);
142 if (ticks == 0)
143 ticks = 1;
144 callp = tpcb->tp_timer + fun;
145 if (*callp == 0 || *callp > ticks)
146 *callp = ticks;
150 * CALLED FROM:
151 * tp.trans all over
152 * FUNCTION and ARGUMENTS:
153 * Cancel all occurrences of E-timer function (fun) for reference (refp)
155 void
156 tp_euntimeout(struct tp_pcb *tpcb, int fun)
158 #ifdef TPPT
159 if (tp_traceflags[D_TIMER]) {
160 tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0);
162 #endif
164 if (tpcb)
165 tpcb->tp_timer[fun] = 0;
168 /**************** c timers **********************
170 * These are not chained together; they sit
171 * in the tp_ref structure. they are the kind that
172 * are typically cancelled so it's faster not to
173 * mess with the chains
175 #endif
177 * CALLED FROM:
178 * the clock, every 500 ms
179 * FUNCTION and ARGUMENTS:
180 * Look for open references with active timers.
181 * If they exist, call the appropriate timer routines to update
182 * the timers and possibly generate events.
184 void
185 tp_slowtimo(void)
187 u_int *cp;
188 struct tp_ref *rp;
189 struct tp_pcb *tpcb;
190 struct tp_event E;
191 int t;
193 mutex_enter(softnet_lock);
194 KERNEL_LOCK(1, NULL);
195 /* check only open reference structures */
196 IncStat(ts_Cticks);
197 /* tp_ref[0] is never used */
198 for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) {
199 if ((tpcb = rp->tpr_pcb) == 0 || tpcb->tp_refstate < REF_OPEN)
200 continue;
201 /* check the timers */
202 for (t = 0; t < TM_NTIMERS; t++) {
203 cp = tpcb->tp_timer + t;
204 if (*cp && --(*cp) <= 0) {
205 *cp = 0;
206 E.ev_number = t;
207 #ifdef ARGO_DEBUG
208 if (argo_debug[D_TIMER]) {
209 printf("tp_slowtimo: pcb %p t %d\n",
210 tpcb, t);
212 #endif
213 IncStat(ts_Cexpired);
214 tp_driver(tpcb, &E);
215 if (t == TM_reference && tpcb->tp_state == TP_CLOSED) {
216 if (tpcb->tp_notdetached) {
217 #ifdef ARGO_DEBUG
218 if (argo_debug[D_CONN]) {
219 printf("PRU_DETACH: not detached\n");
221 #endif
222 tp_detach(tpcb);
224 /* XXX wart; where else to do it? */
225 free((void *) tpcb, M_PCB);
226 break;
231 KERNEL_UNLOCK_ONE(NULL);
232 mutex_exit(softnet_lock);
236 * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off.
238 void
239 tp_data_retrans(struct tp_pcb *tpcb)
241 int rexmt, win;
242 tpcb->tp_rttemit = 0; /* cancel current round trip time */
243 tpcb->tp_dupacks = 0;
244 tpcb->tp_sndnxt = tpcb->tp_snduna;
245 if (tpcb->tp_fcredit == 0) {
247 * We transmitted new data, started timing it and the window
248 * got shrunk under us. This can only happen if all data
249 * that they wanted us to send got acked, so don't
250 * bother shrinking the congestion windows, et. al.
251 * The retransmission timer should have been reset in goodack()
253 #ifdef ARGO_DEBUG
254 if (argo_debug[D_ACKRECV]) {
255 printf("tp_data_retrans: 0 window tpcb %p una 0x%x\n",
256 tpcb, tpcb->tp_snduna);
258 #endif
259 tpcb->tp_rxtshift = 0;
260 tpcb->tp_timer[TM_data_retrans] = 0;
261 tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks;
262 return;
264 rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT);
265 win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2));
266 win = max(win, 2);
267 tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* slow start again. */
268 tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize;
270 * We're losing; our srtt estimate is probably bogus. Clobber it so
271 * we'll take the next rtt measurement as our srtt; Maintain current
272 * rxt times until then.
274 if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) {
275 /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */
276 tpcb->tp_rtt = 0;
278 TP_RANGESET(tpcb->tp_rxtcur, rexmt, tpcb->tp_peer_acktime, 128);
279 tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur;
280 tp_send(tpcb);
283 void
284 tp_fasttimo(void)
286 struct tp_pcb *t;
287 struct tp_event E;
289 mutex_enter(softnet_lock);
290 KERNEL_LOCK(1, NULL);
291 E.ev_number = TM_sendack;
292 while ((t = tp_ftimeolist) != (struct tp_pcb *) & tp_ftimeolist) {
293 if (t == 0) {
294 printf("tp_fasttimeo: should panic");
295 tp_ftimeolist = (struct tp_pcb *) & tp_ftimeolist;
296 } else {
297 if (t->tp_flags & TPF_DELACK) {
298 IncStat(ts_Fdelack);
299 tp_driver(t, &E);
300 t->tp_flags &= ~TPF_DELACK;
301 } else
302 IncStat(ts_Fpruned);
303 tp_ftimeolist = t->tp_fasttimeo;
304 t->tp_fasttimeo = 0;
307 KERNEL_UNLOCK_ONE(NULL);
308 mutex_exit(softnet_lock);
311 #ifdef TP_DEBUG_TIMERS
313 * CALLED FROM:
314 * tp.trans, tp_emit()
315 * FUNCTION and ARGUMENTS:
316 * Set a C type timer of type (which) to go off after (ticks) time.
318 void
319 tp_ctimeout(struct tp_pcb *tpcb, int which, int ticks)
322 #ifdef TPPT
323 if (tp_traceflags[D_TIMER]) {
324 tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active",
325 tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
327 #endif
328 if (tpcb->tp_timer[which])
329 IncStat(ts_Ccan_act);
330 IncStat(ts_Cset);
331 if (ticks <= 0)
332 ticks = 1;
333 tpcb->tp_timer[which] = ticks;
337 * CALLED FROM:
338 * tp.trans
339 * FUNCTION and ARGUMENTS:
340 * Version of tp_ctimeout that resets the C-type time if the
341 * parameter (ticks) is > the current value of the timer.
343 void
344 tp_ctimeout_MIN(struct tp_pcb *tpcb, int which, int ticks)
346 #ifdef TPPT
347 if (tp_traceflags[D_TIMER]) {
348 tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active",
349 tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
351 #endif
352 IncStat(ts_Cset);
353 if (tpcb->tp_timer[which]) {
354 tpcb->tp_timer[which] = min(ticks, tpcb->tp_timer[which]);
355 IncStat(ts_Ccan_act);
356 } else
357 tpcb->tp_timer[which] = ticks;
361 * CALLED FROM:
362 * tp.trans
363 * FUNCTION and ARGUMENTS:
364 * Cancel the (which) timer in the ref structure indicated by (refp).
366 void
367 tp_cuntimeout(struct tp_pcb *tpcb, int which)
369 #ifdef ARGO_DEBUG
370 if (argo_debug[D_TIMER]) {
371 printf("tp_cuntimeout(%p, %d) active %d\n",
372 tpcb, which, tpcb->tp_timer[which]);
374 #endif
376 #ifdef TPPT
377 if (tp_traceflags[D_TIMER]) {
378 tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp - tp_ref,
379 which, tpcb->tp_timer[which], 0);
381 #endif
383 if (tpcb->tp_timer[which])
384 IncStat(ts_Ccan_act);
385 else
386 IncStat(ts_Ccan_inact);
387 tpcb->tp_timer[which] = 0;
389 #endif