|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*-
26: * Copyright (c) 1991, 1993
27: * The Regents of the University of California. All rights reserved.
28: *
29: * Redistribution and use in source and binary forms, with or without
30: * modification, are permitted provided that the following conditions
31: * are met:
32: * 1. Redistributions of source code must retain the above copyright
33: * notice, this list of conditions and the following disclaimer.
34: * 2. Redistributions in binary form must reproduce the above copyright
35: * notice, this list of conditions and the following disclaimer in the
36: * documentation and/or other materials provided with the distribution.
37: * 3. All advertising materials mentioning features or use of this software
38: * must display the following acknowledgement:
39: * This product includes software developed by the University of
40: * California, Berkeley and its contributors.
41: * 4. Neither the name of the University nor the names of its contributors
42: * may be used to endorse or promote products derived from this software
43: * without specific prior written permission.
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55: * SUCH DAMAGE.
56: *
57: * @(#)tp_timer.c 8.1 (Berkeley) 6/10/93
58: */
59:
60: /***********************************************************
61: Copyright IBM Corporation 1987
62:
63: All Rights Reserved
64:
65: Permission to use, copy, modify, and distribute this software and its
66: documentation for any purpose and without fee is hereby granted,
67: provided that the above copyright notice appear in all copies and that
68: both that copyright notice and this permission notice appear in
69: supporting documentation, and that the name of IBM not be
70: used in advertising or publicity pertaining to distribution of the
71: software without specific, written prior permission.
72:
73: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
74: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
75: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
76: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
77: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
78: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
79: SOFTWARE.
80:
81: ******************************************************************/
82:
83: /*
84: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
85: */
86: /*
87: * ARGO TP
88: */
89:
90: #include <sys/param.h>
91: #include <sys/systm.h>
92: #include <sys/time.h>
93: #include <sys/malloc.h>
94: #include <sys/protosw.h>
95: #include <sys/socket.h>
96: #include <sys/kernel.h>
97:
98: #include <netiso/argo_debug.h>
99: #include <netiso/tp_param.h>
100: #include <netiso/tp_timer.h>
101: #include <netiso/tp_stat.h>
102: #include <netiso/tp_pcb.h>
103: #include <netiso/tp_tpdu.h>
104: #include <netiso/tp_trace.h>
105: #include <netiso/tp_seq.h>
106:
107: struct tp_ref *tp_ref;
108: int tp_rttdiv, tp_rttadd, N_TPREF = 127;
109: struct tp_refinfo tp_refinfo;
110: struct tp_pcb *tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist;
111:
112: /*
113: * CALLED FROM:
114: * at autoconfig time from tp_init()
115: * a combo of event, state, predicate
116: * FUNCTION and ARGUMENTS:
117: * initialize data structures for the timers
118: */
119: void
120: tp_timerinit()
121: {
122: register int s;
123: /*
124: * Initialize storage
125: */
126: if (tp_refinfo.tpr_base)
127: return;
128: tp_refinfo.tpr_size = N_TPREF + 1; /* Need to start somewhere */
129: s = sizeof(*tp_ref) * tp_refinfo.tpr_size;
130: // if ((tp_ref = (struct tp_ref *) malloc(s, M_PCB, M_NOWAIT)) == 0)
131: MALLOC(tp_ref, struct tp_ref *, s, M_PCB, M_NOWAIT);
132: if (tp_ref == 0)
133: panic("tp_timerinit");
134: bzero((caddr_t)tp_ref, (unsigned) s);
135: tp_refinfo.tpr_base = tp_ref;
136: tp_rttdiv = hz / PR_SLOWHZ;
137: tp_rttadd = (2 * tp_rttdiv) - 1;
138: }
139: #ifdef TP_DEBUG_TIMERS
140: /********************** e timers *************************/
141:
142: /*
143: * CALLED FROM:
144: * tp.trans all over
145: * FUNCTION and ARGUMENTS:
146: * Set an E type timer.
147: */
148: void
149: tp_etimeout(tpcb, fun, ticks)
150: register struct tp_pcb *tpcb;
151: int fun; /* function to be called */
152: int ticks;
153: {
154:
155: register u_int *callp;
156: IFDEBUG(D_TIMER)
157: printf("etimeout pcb 0x%x state 0x%x\n", tpcb, tpcb->tp_state);
158: ENDDEBUG
159: IFTRACE(D_TIMER)
160: tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref,
161: tpcb->tp_state, ticks, tp_stat.ts_Eticks);
162: ENDTRACE
163: if (tpcb == 0)
164: return;
165: IncStat(ts_Eset);
166: if (ticks == 0)
167: ticks = 1;
168: callp = tpcb->tp_timer + fun;
169: if (*callp == 0 || *callp > ticks)
170: *callp = ticks;
171: }
172:
173: /*
174: * CALLED FROM:
175: * tp.trans all over
176: * FUNCTION and ARGUMENTS:
177: * Cancel all occurrences of E-timer function (fun) for reference (refp)
178: */
179: void
180: tp_euntimeout(tpcb, fun)
181: register struct tp_pcb *tpcb;
182: int fun;
183: {
184: IFTRACE(D_TIMER)
185: tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0);
186: ENDTRACE
187:
188: if (tpcb)
189: tpcb->tp_timer[fun] = 0;
190: }
191:
192: /**************** c timers **********************
193: *
194: * These are not chained together; they sit
195: * in the tp_ref structure. they are the kind that
196: * are typically cancelled so it's faster not to
197: * mess with the chains
198: */
199: #endif
200: /*
201: * CALLED FROM:
202: * the clock, every 500 ms
203: * FUNCTION and ARGUMENTS:
204: * Look for open references with active timers.
205: * If they exist, call the appropriate timer routines to update
206: * the timers and possibly generate events.
207: */
208: ProtoHook
209: tp_slowtimo()
210: {
211: register u_int *cp;
212: register struct tp_ref *rp;
213: struct tp_pcb *tpcb;
214: struct tp_event E;
215: int s = splnet(), t;
216:
217: /* check only open reference structures */
218: IncStat(ts_Cticks);
219: /* tp_ref[0] is never used */
220: for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) {
221: if ((tpcb = rp->tpr_pcb) == 0 || tpcb->tp_refstate < REF_OPEN)
222: continue;
223: /* check the timers */
224: for (t = 0; t < TM_NTIMERS; t++) {
225: cp = tpcb->tp_timer + t;
226: if (*cp && --(*cp) <= 0 ) {
227: *cp = 0;
228: E.ev_number = t;
229: IFDEBUG(D_TIMER)
230: printf("tp_slowtimo: pcb 0x%x t %d\n",
231: tpcb, t);
232: ENDDEBUG
233: IncStat(ts_Cexpired);
234: tp_driver(tpcb, &E);
235: if (t == TM_reference && tpcb->tp_state == TP_CLOSED) {
236: if (tpcb->tp_notdetached) {
237: IFDEBUG(D_CONN)
238: printf("PRU_DETACH: not detached\n");
239: ENDDEBUG
240: tp_detach(tpcb);
241: }
242: /* XXX wart; where else to do it? */
243: free((caddr_t)tpcb, M_PCB);
244: }
245: }
246: }
247: }
248: splx(s);
249: return 0;
250: }
251:
252: /*
253: * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off.
254: */
255: tp_data_retrans(tpcb)
256: register struct tp_pcb *tpcb;
257: {
258: int rexmt, win;
259: tpcb->tp_rttemit = 0; /* cancel current round trip time */
260: tpcb->tp_dupacks = 0;
261: tpcb->tp_sndnxt = tpcb->tp_snduna;
262: if (tpcb->tp_fcredit == 0) {
263: /*
264: * We transmitted new data, started timing it and the window
265: * got shrunk under us. This can only happen if all data
266: * that they wanted us to send got acked, so don't
267: * bother shrinking the congestion windows, et. al.
268: * The retransmission timer should have been reset in goodack()
269: */
270: IFDEBUG(D_ACKRECV)
271: printf("tp_data_retrans: 0 window tpcb 0x%x una 0x%x\n",
272: tpcb, tpcb->tp_snduna);
273: ENDDEBUG
274: tpcb->tp_rxtshift = 0;
275: tpcb->tp_timer[TM_data_retrans] = 0;
276: tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks;
277: return;
278: }
279: rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT);
280: win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2));
281: win = max(win, 2);
282: tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* slow start again. */
283: tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize;
284: /* We're losing; our srtt estimate is probably bogus.
285: * Clobber it so we'll take the next rtt measurement as our srtt;
286: * Maintain current rxt times until then.
287: */
288: if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) {
289: /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */
290: tpcb->tp_rtt = 0;
291: }
292: TP_RANGESET(tpcb->tp_rxtcur, rexmt, tpcb->tp_peer_acktime, 128);
293: tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur;
294: tp_send(tpcb);
295: }
296:
297: int
298: tp_fasttimo()
299: {
300: register struct tp_pcb *t;
301: int s = splnet();
302: struct tp_event E;
303:
304: E.ev_number = TM_sendack;
305: while ((t = tp_ftimeolist) != (struct tp_pcb *)&tp_ftimeolist) {
306: if (t == 0) {
307: printf("tp_fasttimeo: should panic");
308: tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist;
309: } else {
310: if (t->tp_flags & TPF_DELACK) {
311: IncStat(ts_Fdelack);
312: tp_driver(t, &E);
313: t->tp_flags &= ~TPF_DELACK;
314: } else
315: IncStat(ts_Fpruned);
316: tp_ftimeolist = t->tp_fasttimeo;
317: t->tp_fasttimeo = 0;
318: }
319: }
320: splx(s);
321: }
322:
323: #ifdef TP_DEBUG_TIMERS
324: /*
325: * CALLED FROM:
326: * tp.trans, tp_emit()
327: * FUNCTION and ARGUMENTS:
328: * Set a C type timer of type (which) to go off after (ticks) time.
329: */
330: void
331: tp_ctimeout(tpcb, which, ticks)
332: register struct tp_pcb *tpcb;
333: int which, ticks;
334: {
335:
336: IFTRACE(D_TIMER)
337: tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active",
338: tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
339: ENDTRACE
340: if(tpcb->tp_timer[which])
341: IncStat(ts_Ccan_act);
342: IncStat(ts_Cset);
343: if (ticks <= 0)
344: ticks = 1;
345: tpcb->tp_timer[which] = ticks;
346: }
347:
348: /*
349: * CALLED FROM:
350: * tp.trans
351: * FUNCTION and ARGUMENTS:
352: * Version of tp_ctimeout that resets the C-type time if the
353: * parameter (ticks) is > the current value of the timer.
354: */
355: void
356: tp_ctimeout_MIN(tpcb, which, ticks)
357: register struct tp_pcb *tpcb;
358: int which, ticks;
359: {
360: IFTRACE(D_TIMER)
361: tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active",
362: tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
363: ENDTRACE
364: IncStat(ts_Cset);
365: if (tpcb->tp_timer[which]) {
366: tpcb->tp_timer[which] = min(ticks, tpcb->tp_timer[which]);
367: IncStat(ts_Ccan_act);
368: } else
369: tpcb->tp_timer[which] = ticks;
370: }
371:
372: /*
373: * CALLED FROM:
374: * tp.trans
375: * FUNCTION and ARGUMENTS:
376: * Cancel the (which) timer in the ref structure indicated by (refp).
377: */
378: void
379: tp_cuntimeout(tpcb, which)
380: register struct tp_pcb *tpcb;
381: int which;
382: {
383: IFDEBUG(D_TIMER)
384: printf("tp_cuntimeout(0x%x, %d) active %d\n",
385: tpcb, which, tpcb->tp_timer[which]);
386: ENDDEBUG
387:
388: IFTRACE(D_TIMER)
389: tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref,
390: which, tpcb->tp_timer[which], 0);
391: ENDTRACE
392:
393: if (tpcb->tp_timer[which])
394: IncStat(ts_Ccan_act);
395: else
396: IncStat(ts_Ccan_inact);
397: tpcb->tp_timer[which] = 0;
398: }
399: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.