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