|
|
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.