Annotation of XNU/bsd/netiso/tp_timer.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.