Annotation of XNU/bsd/netiso/tp_timer.c, revision 1.1.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.