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