diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sys/netiso/tp_timer.c |
initial import of NetBSD tree
Diffstat (limited to 'sys/netiso/tp_timer.c')
-rw-r--r-- | sys/netiso/tp_timer.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/sys/netiso/tp_timer.c b/sys/netiso/tp_timer.c new file mode 100644 index 00000000000..1fa2be948db --- /dev/null +++ b/sys/netiso/tp_timer.c @@ -0,0 +1,371 @@ +/* $NetBSD: tp_timer.c,v 1.6 1995/08/12 23:59:51 mycroft Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tp_timer.c 8.1 (Berkeley) 6/10/93 + */ + +/*********************************************************** + Copyright IBM Corporation 1987 + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of IBM not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/malloc.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/kernel.h> + +#include <netiso/argo_debug.h> +#include <netiso/tp_param.h> +#include <netiso/tp_timer.h> +#include <netiso/tp_stat.h> +#include <netiso/tp_pcb.h> +#include <netiso/tp_tpdu.h> +#include <netiso/tp_trace.h> +#include <netiso/tp_seq.h> + +struct tp_ref *tp_ref; +int tp_rttdiv, tp_rttadd, N_TPREF = 127; +struct tp_refinfo tp_refinfo; +struct tp_pcb *tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist; + +/* + * CALLED FROM: + * at autoconfig time from tp_init() + * a combo of event, state, predicate + * FUNCTION and ARGUMENTS: + * initialize data structures for the timers + */ +void +tp_timerinit() +{ + register int s; + /* + * Initialize storage + */ + if (tp_refinfo.tpr_base) + return; + tp_refinfo.tpr_size = N_TPREF + 1; /* Need to start somewhere */ + s = sizeof(*tp_ref) * tp_refinfo.tpr_size; + if ((tp_ref = (struct tp_ref *) malloc(s, M_PCB, M_NOWAIT)) == 0) + panic("tp_timerinit"); + bzero((caddr_t)tp_ref, (unsigned) s); + tp_refinfo.tpr_base = tp_ref; + tp_rttdiv = hz / PR_SLOWHZ; + tp_rttadd = (2 * tp_rttdiv) - 1; +} +#ifdef TP_DEBUG_TIMERS +/********************** e timers *************************/ + +/* + * CALLED FROM: + * tp.trans all over + * FUNCTION and ARGUMENTS: + * Set an E type timer. + */ +void +tp_etimeout(tpcb, fun, ticks) + register struct tp_pcb *tpcb; + int fun; /* function to be called */ + int ticks; +{ + + register u_int *callp; + IFDEBUG(D_TIMER) + printf("etimeout pcb 0x%x state 0x%x\n", tpcb, tpcb->tp_state); + ENDDEBUG + IFTRACE(D_TIMER) + tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref, + tpcb->tp_state, ticks, tp_stat.ts_Eticks); + ENDTRACE + if (tpcb == 0) + return; + IncStat(ts_Eset); + if (ticks == 0) + ticks = 1; + callp = tpcb->tp_timer + fun; + if (*callp == 0 || *callp > ticks) + *callp = ticks; +} + +/* + * CALLED FROM: + * tp.trans all over + * FUNCTION and ARGUMENTS: + * Cancel all occurrences of E-timer function (fun) for reference (refp) + */ +void +tp_euntimeout(tpcb, fun) + register struct tp_pcb *tpcb; + int fun; +{ + IFTRACE(D_TIMER) + tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0); + ENDTRACE + + if (tpcb) + tpcb->tp_timer[fun] = 0; +} + +/**************** c timers ********************** + * + * These are not chained together; they sit + * in the tp_ref structure. they are the kind that + * are typically cancelled so it's faster not to + * mess with the chains + */ +#endif +/* + * CALLED FROM: + * the clock, every 500 ms + * FUNCTION and ARGUMENTS: + * Look for open references with active timers. + * If they exist, call the appropriate timer routines to update + * the timers and possibly generate events. + */ +void +tp_slowtimo() +{ + register u_int *cp; + register struct tp_ref *rp; + struct tp_pcb *tpcb; + struct tp_event E; + int s = splsoftnet(), t; + + /* check only open reference structures */ + IncStat(ts_Cticks); + /* tp_ref[0] is never used */ + for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) { + if ((tpcb = rp->tpr_pcb) == 0 || tpcb->tp_refstate < REF_OPEN) + continue; + /* check the timers */ + for (t = 0; t < TM_NTIMERS; t++) { + cp = tpcb->tp_timer + t; + if (*cp && --(*cp) <= 0 ) { + *cp = 0; + E.ev_number = t; + IFDEBUG(D_TIMER) + printf("tp_slowtimo: pcb 0x%x t %d\n", + tpcb, t); + ENDDEBUG + IncStat(ts_Cexpired); + tp_driver(tpcb, &E); + if (t == TM_reference && tpcb->tp_state == TP_CLOSED) { + if (tpcb->tp_notdetached) { + IFDEBUG(D_CONN) + printf("PRU_DETACH: not detached\n"); + ENDDEBUG + tp_detach(tpcb); + } + /* XXX wart; where else to do it? */ + free((caddr_t)tpcb, M_PCB); + } + } + } + } + splx(s); +} + +/* + * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off. + */ +tp_data_retrans(tpcb) +register struct tp_pcb *tpcb; +{ + int rexmt, win; + tpcb->tp_rttemit = 0; /* cancel current round trip time */ + tpcb->tp_dupacks = 0; + tpcb->tp_sndnxt = tpcb->tp_snduna; + if (tpcb->tp_fcredit == 0) { + /* + * We transmitted new data, started timing it and the window + * got shrunk under us. This can only happen if all data + * that they wanted us to send got acked, so don't + * bother shrinking the congestion windows, et. al. + * The retransmission timer should have been reset in goodack() + */ + IFDEBUG(D_ACKRECV) + printf("tp_data_retrans: 0 window tpcb 0x%x una 0x%x\n", + tpcb, tpcb->tp_snduna); + ENDDEBUG + tpcb->tp_rxtshift = 0; + tpcb->tp_timer[TM_data_retrans] = 0; + tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks; + return; + } + rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT); + win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2)); + win = max(win, 2); + tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* slow start again. */ + tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize; + /* We're losing; our srtt estimate is probably bogus. + * Clobber it so we'll take the next rtt measurement as our srtt; + * Maintain current rxt times until then. + */ + if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) { + /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */ + tpcb->tp_rtt = 0; + } + TP_RANGESET(tpcb->tp_rxtcur, rexmt, tpcb->tp_peer_acktime, 128); + tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur; + tp_send(tpcb); +} + +void +tp_fasttimo() +{ + register struct tp_pcb *t; + int s = splsoftnet(); + struct tp_event E; + + E.ev_number = TM_sendack; + while ((t = tp_ftimeolist) != (struct tp_pcb *)&tp_ftimeolist) { + if (t == 0) { + printf("tp_fasttimeo: should panic"); + tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist; + } else { + if (t->tp_flags & TPF_DELACK) { + IncStat(ts_Fdelack); + tp_driver(t, &E); + t->tp_flags &= ~TPF_DELACK; + } else + IncStat(ts_Fpruned); + tp_ftimeolist = t->tp_fasttimeo; + t->tp_fasttimeo = 0; + } + } + splx(s); +} + +#ifdef TP_DEBUG_TIMERS +/* + * CALLED FROM: + * tp.trans, tp_emit() + * FUNCTION and ARGUMENTS: + * Set a C type timer of type (which) to go off after (ticks) time. + */ +void +tp_ctimeout(tpcb, which, ticks) + register struct tp_pcb *tpcb; + int which, ticks; +{ + + IFTRACE(D_TIMER) + tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", + tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]); + ENDTRACE + if(tpcb->tp_timer[which]) + IncStat(ts_Ccan_act); + IncStat(ts_Cset); + if (ticks <= 0) + ticks = 1; + tpcb->tp_timer[which] = ticks; +} + +/* + * CALLED FROM: + * tp.trans + * FUNCTION and ARGUMENTS: + * Version of tp_ctimeout that resets the C-type time if the + * parameter (ticks) is > the current value of the timer. + */ +void +tp_ctimeout_MIN(tpcb, which, ticks) + register struct tp_pcb *tpcb; + int which, ticks; +{ + IFTRACE(D_TIMER) + tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", + tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]); + ENDTRACE + IncStat(ts_Cset); + if (tpcb->tp_timer[which]) { + tpcb->tp_timer[which] = min(ticks, tpcb->tp_timer[which]); + IncStat(ts_Ccan_act); + } else + tpcb->tp_timer[which] = ticks; +} + +/* + * CALLED FROM: + * tp.trans + * FUNCTION and ARGUMENTS: + * Cancel the (which) timer in the ref structure indicated by (refp). + */ +void +tp_cuntimeout(tpcb, which) + register struct tp_pcb *tpcb; + int which; +{ + IFDEBUG(D_TIMER) + printf("tp_cuntimeout(0x%x, %d) active %d\n", + tpcb, which, tpcb->tp_timer[which]); + ENDDEBUG + + IFTRACE(D_TIMER) + tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, + which, tpcb->tp_timer[which], 0); + ENDTRACE + + if (tpcb->tp_timer[which]) + IncStat(ts_Ccan_act); + else + IncStat(ts_Ccan_inact); + tpcb->tp_timer[which] = 0; +} +#endif |