149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*51254Ssklower * @(#)tp_timer.c 7.11 (Berkeley) 10/02/91 849268Sbostic */ 949268Sbostic 1036415Ssklower /*********************************************************** 1136415Ssklower Copyright IBM Corporation 1987 1236415Ssklower 1336415Ssklower All Rights Reserved 1436415Ssklower 1536415Ssklower Permission to use, copy, modify, and distribute this software and its 1636415Ssklower documentation for any purpose and without fee is hereby granted, 1736415Ssklower provided that the above copyright notice appear in all copies and that 1836415Ssklower both that copyright notice and this permission notice appear in 1936415Ssklower supporting documentation, and that the name of IBM not be 2036415Ssklower used in advertising or publicity pertaining to distribution of the 2136415Ssklower software without specific, written prior permission. 2236415Ssklower 2336415Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436415Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536415Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636415Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736415Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836415Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936415Ssklower SOFTWARE. 3036415Ssklower 3136415Ssklower ******************************************************************/ 3236415Ssklower 3336415Ssklower /* 3436415Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536415Ssklower */ 3636415Ssklower /* 3736415Ssklower * ARGO TP 3836415Ssklower * 3936415Ssklower * $Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $ 4036415Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_timer.c,v $ 4136415Ssklower * 4236415Ssklower */ 4336415Ssklower 4436415Ssklower #include "param.h" 45*51254Ssklower #include "systm.h" 4636415Ssklower #include "time.h" 4737469Ssklower #include "malloc.h" 48*51254Ssklower #include "protosw.h" 4948752Ssklower #include "socket.h" 50*51254Ssklower #include "kernel.h" 5136415Ssklower 5237469Ssklower #include "tp_param.h" 5337469Ssklower #include "tp_timer.h" 5437469Ssklower #include "tp_stat.h" 5537469Ssklower #include "tp_pcb.h" 5637469Ssklower #include "tp_tpdu.h" 5737469Ssklower #include "argo_debug.h" 5837469Ssklower #include "tp_trace.h" 5937469Ssklower #include "tp_seq.h" 6036415Ssklower 6148752Ssklower struct tp_ref *tp_ref; 62*51254Ssklower int tp_rttdiv, tp_rttadd, N_TPREF = 127; 6351006Ssklower struct tp_refinfo tp_refinfo; 6451024Ssklower struct tp_pcb *tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist; 6536415Ssklower 6636415Ssklower /* 6736415Ssklower * CALLED FROM: 6836415Ssklower * at autoconfig time from tp_init() 6936415Ssklower * a combo of event, state, predicate 7036415Ssklower * FUNCTION and ARGUMENTS: 7136415Ssklower * initialize data structures for the timers 7236415Ssklower */ 7336415Ssklower void 7436415Ssklower tp_timerinit() 7536415Ssklower { 7648752Ssklower register int s; 7736415Ssklower /* 7848752Ssklower * Initialize storage 7936415Ssklower */ 80*51254Ssklower if (tp_refinfo.tpr_base) 81*51254Ssklower return; 8251204Ssklower tp_refinfo.tpr_size = N_TPREF + 1; /* Need to start somewhere */ 83*51254Ssklower s = sizeof(*tp_ref) * tp_refinfo.tpr_size; 84*51254Ssklower if ((tp_ref = (struct tp_ref *) malloc(s, M_PCB, M_NOWAIT)) == 0) 85*51254Ssklower panic("tp_timerinit"); 8651006Ssklower tp_refinfo.tpr_base = tp_ref; 87*51254Ssklower tp_rttdiv = hz / PR_SLOWHZ; 88*51254Ssklower tp_rttadd = (2 * tp_rttdiv) - 1; 8936415Ssklower } 90*51254Ssklower #ifdef TP_DEBUG_TIMERS 9136415Ssklower /********************** e timers *************************/ 9236415Ssklower 9336415Ssklower /* 9436415Ssklower * CALLED FROM: 9536415Ssklower * tp.trans all over 9636415Ssklower * FUNCTION and ARGUMENTS: 9751204Ssklower * Set an E type timer. 9836415Ssklower */ 9936415Ssklower void 10051204Ssklower tp_etimeout(tpcb, fun, ticks) 10151204Ssklower register struct tp_pcb *tpcb; 10251204Ssklower int fun; /* function to be called */ 10351204Ssklower int ticks; 10436415Ssklower { 10536415Ssklower 10651204Ssklower register u_int *callp; 10736415Ssklower IFDEBUG(D_TIMER) 10851204Ssklower printf("etimeout pcb 0x%x state 0x%x\n", tpcb, tpcb->tp_state); 10936415Ssklower ENDDEBUG 11036415Ssklower IFTRACE(D_TIMER) 11151204Ssklower tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref, 11251204Ssklower tpcb->tp_state, ticks, tp_stat.ts_Eticks); 11336415Ssklower ENDTRACE 11451007Ssklower if (tpcb == 0) 11551007Ssklower return; 11636415Ssklower IncStat(ts_Eset); 11736415Ssklower if (ticks == 0) 11836415Ssklower ticks = 1; 11951204Ssklower callp = tpcb->tp_timer + fun; 12051204Ssklower if (*callp == 0 || *callp > ticks) 12151204Ssklower *callp = ticks; 12236415Ssklower } 12336415Ssklower 12436415Ssklower /* 12536415Ssklower * CALLED FROM: 12636415Ssklower * tp.trans all over 12736415Ssklower * FUNCTION and ARGUMENTS: 12836415Ssklower * Cancel all occurrences of E-timer function (fun) for reference (refp) 12936415Ssklower */ 13036415Ssklower void 13151204Ssklower tp_euntimeout(tpcb, fun) 13251204Ssklower register struct tp_pcb *tpcb; 13336415Ssklower int fun; 13436415Ssklower { 13536415Ssklower IFTRACE(D_TIMER) 13651204Ssklower tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0); 13736415Ssklower ENDTRACE 13836415Ssklower 13951007Ssklower if (tpcb) 14051204Ssklower tpcb->tp_timer[fun] = 0; 14136415Ssklower } 14236415Ssklower 14336415Ssklower /**************** c timers ********************** 14436415Ssklower * 14536415Ssklower * These are not chained together; they sit 14636415Ssklower * in the tp_ref structure. they are the kind that 14736415Ssklower * are typically cancelled so it's faster not to 14836415Ssklower * mess with the chains 14936415Ssklower */ 150*51254Ssklower #endif 15136415Ssklower /* 15236415Ssklower * CALLED FROM: 15336415Ssklower * the clock, every 500 ms 15436415Ssklower * FUNCTION and ARGUMENTS: 15536415Ssklower * Look for open references with active timers. 15636415Ssklower * If they exist, call the appropriate timer routines to update 15736415Ssklower * the timers and possibly generate events. 15836415Ssklower * (The E timers are done in other procedures; the C timers are 15936415Ssklower * updated here, and events for them are generated here.) 16036415Ssklower */ 16136415Ssklower ProtoHook 16236415Ssklower tp_slowtimo() 16336415Ssklower { 16451204Ssklower register u_int *cp, *cpbase; 16551007Ssklower register struct tp_ref *rp; 16651007Ssklower struct tp_pcb *tpcb; 16736415Ssklower struct tp_event E; 16851007Ssklower int s = splnet(), t; 16936415Ssklower 17036415Ssklower /* check only open reference structures */ 17136415Ssklower IncStat(ts_Cticks); 17251007Ssklower /* tp_ref[0] is never used */ 17351007Ssklower for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) { 174*51254Ssklower if ((tpcb = rp->tpr_pcb) == 0 || tpcb->tp_refstate < REF_OPEN) 17536415Ssklower continue; 17651204Ssklower cpbase = tpcb->tp_timer; 17751204Ssklower t = TM_NTIMERS; 17851204Ssklower /* check the timers */ 17951007Ssklower for (cp = cpbase + t; (--t, --cp) >= cpbase; ) { 18051204Ssklower if (*cp && --(*cp) <= 0 ) { 18151204Ssklower *cp = 0; 18251007Ssklower E.ev_number = t; 18351007Ssklower IFDEBUG(D_TIMER) 18451007Ssklower printf("C expired! type 0x%x\n", t); 18551007Ssklower ENDDEBUG 18651007Ssklower IncStat(ts_Cexpired); 18751007Ssklower tp_driver( rp->tpr_pcb, &E); 18851007Ssklower if (t == TM_reference && tpcb->tp_state == TP_CLOSED) { 18951007Ssklower if (tpcb->tp_notdetached) { 19051007Ssklower IFDEBUG(D_CONN) 19151007Ssklower printf("PRU_DETACH: not detached\n"); 19251007Ssklower ENDDEBUG 19351007Ssklower tp_detach(tpcb); 19451007Ssklower } 19551007Ssklower /* XXX wart; where else to do it? */ 19651007Ssklower free((caddr_t)tpcb, M_PCB); 19751007Ssklower } 19836415Ssklower } 19936415Ssklower } 20036415Ssklower } 20136415Ssklower splx(s); 20236415Ssklower return 0; 20336415Ssklower } 20436415Ssklower 20551204Ssklower /* 20651204Ssklower * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off. 20751204Ssklower */ 20851204Ssklower tp_data_retrans(tpcb) 20951204Ssklower register struct tp_pcb *tpcb; 21051204Ssklower { 21151204Ssklower int rexmt, win; 21251204Ssklower tpcb->tp_rttemit = 0; /* cancel current round trip time */ 21351204Ssklower tpcb->tp_dupacks = 0; 21451204Ssklower tpcb->tp_sndnxt = tpcb->tp_snduna; 21551204Ssklower if (tpcb->tp_fcredit == 0) { 21651204Ssklower /* 21751204Ssklower * We transmitted new data, started timing it and the window 21851204Ssklower * got shrunk under us. This can only happen if all data 21951204Ssklower * that they wanted us to send got acked, so don't 22051204Ssklower * bother shrinking the congestion windows, et. al. 22151204Ssklower * The retransmission timer should have been reset in goodack() 22251204Ssklower */ 22351204Ssklower tpcb->tp_rxtshift = 0; 22451204Ssklower tpcb->tp_timer[TM_data_retrans] = 0; 22551204Ssklower tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks; 22651204Ssklower } 22751204Ssklower rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT); 22851204Ssklower win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2)); 22951204Ssklower win = max(win, 2); 23051204Ssklower tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* slow start again. */ 23151204Ssklower tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize; 23251204Ssklower /* We're losing; our srtt estimate is probably bogus. 23351204Ssklower * Clobber it so we'll take the next rtt measurement as our srtt; 23451204Ssklower * Maintain current rxt times until then. 23551204Ssklower */ 23651204Ssklower if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) { 23751204Ssklower /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */ 23851204Ssklower tpcb->tp_rtt = 0; 23951204Ssklower } 240*51254Ssklower TP_RANGESET(tpcb->tp_rxtcur, rexmt, tpcb->tp_peer_acktime, 128); 241*51254Ssklower tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur; 24251204Ssklower tp_send(tpcb); 24351204Ssklower } 24451204Ssklower 24551024Ssklower int 24651024Ssklower tp_fasttimo() 24751024Ssklower { 24851024Ssklower register struct tp_pcb *t; 24951024Ssklower int s = splnet(); 25051024Ssklower struct tp_event E; 25151024Ssklower 25251024Ssklower E.ev_number = TM_sendack; 25351024Ssklower while ((t = tp_ftimeolist) != (struct tp_pcb *)&tp_ftimeolist) { 25451024Ssklower if (t == 0) { 25551024Ssklower printf("tp_fasttimeo: should panic"); 25651024Ssklower tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist; 25751024Ssklower } else { 25851024Ssklower if (t->tp_flags & TPF_DELACK) { 25951024Ssklower t->tp_flags &= ~TPF_DELACK; 26051024Ssklower IncStat(ts_Fdelack); 26151024Ssklower tp_driver(t, &E); 26251204Ssklower t->tp_timer[TM_sendack] = t->tp_keepalive_ticks; 26351024Ssklower } else 26451024Ssklower IncStat(ts_Fpruned); 26551024Ssklower tp_ftimeolist = t->tp_fasttimeo; 26651024Ssklower t->tp_fasttimeo = 0; 26751024Ssklower } 26851024Ssklower } 26951024Ssklower splx(s); 27051024Ssklower } 27151024Ssklower 272*51254Ssklower #ifdef TP_DEBUG_TIMERS 27336415Ssklower /* 27436415Ssklower * CALLED FROM: 27536415Ssklower * tp.trans, tp_emit() 27636415Ssklower * FUNCTION and ARGUMENTS: 27736415Ssklower * Set a C type timer of type (which) to go off after (ticks) time. 27836415Ssklower */ 27936415Ssklower void 28051204Ssklower tp_ctimeout(tpcb, which, ticks) 28151204Ssklower register struct tp_pcb *tpcb; 28236415Ssklower int which, ticks; 28336415Ssklower { 28436415Ssklower 28536415Ssklower IFTRACE(D_TIMER) 28636415Ssklower tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", 28751204Ssklower tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]); 28836415Ssklower ENDTRACE 28951204Ssklower if(tpcb->tp_timer[which]) 29036415Ssklower IncStat(ts_Ccan_act); 29136415Ssklower IncStat(ts_Cset); 29251007Ssklower if (ticks <= 0) 29351007Ssklower ticks = 1; 29451204Ssklower tpcb->tp_timer[which] = ticks; 29536415Ssklower } 29636415Ssklower 29736415Ssklower /* 29836415Ssklower * CALLED FROM: 29936415Ssklower * tp.trans 30036415Ssklower * FUNCTION and ARGUMENTS: 30136415Ssklower * Version of tp_ctimeout that resets the C-type time if the 30236415Ssklower * parameter (ticks) is > the current value of the timer. 30336415Ssklower */ 30436415Ssklower void 30551204Ssklower tp_ctimeout_MIN(tpcb, which, ticks) 30651204Ssklower register struct tp_pcb *tpcb; 30736415Ssklower int which, ticks; 30836415Ssklower { 30936415Ssklower IFTRACE(D_TIMER) 31036415Ssklower tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", 31151204Ssklower tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]); 31236415Ssklower ENDTRACE 31336415Ssklower IncStat(ts_Cset); 31451204Ssklower if (tpcb->tp_timer[which]) { 31551204Ssklower tpcb->tp_timer[which] = MIN(ticks, tpcb->tp_timer[which]); 31651007Ssklower IncStat(ts_Ccan_act); 31751007Ssklower } else 31851204Ssklower tpcb->tp_timer[which] = ticks; 31936415Ssklower } 32036415Ssklower 32136415Ssklower /* 32236415Ssklower * CALLED FROM: 32336415Ssklower * tp.trans 32436415Ssklower * FUNCTION and ARGUMENTS: 32536415Ssklower * Cancel the (which) timer in the ref structure indicated by (refp). 32636415Ssklower */ 32736415Ssklower void 32851204Ssklower tp_cuntimeout(tpcb, which) 32951204Ssklower register struct tp_pcb *tpcb; 33036415Ssklower int which; 33136415Ssklower { 33236415Ssklower IFDEBUG(D_TIMER) 33351204Ssklower printf("tp_cuntimeout(0x%x, %d) active %d\n", 33451204Ssklower tpcb, which, tpcb->tp_timer[which]); 33536415Ssklower ENDDEBUG 33636415Ssklower 33736415Ssklower IFTRACE(D_TIMER) 33836415Ssklower tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, 33951204Ssklower which, tpcb->tp_timer[which], 0); 34036415Ssklower ENDTRACE 34136415Ssklower 34251204Ssklower if (tpcb->tp_timer[which]) 34336415Ssklower IncStat(ts_Ccan_act); 34436415Ssklower else 34536415Ssklower IncStat(ts_Ccan_inact); 34651204Ssklower tpcb->tp_timer[which] = 0; 34736415Ssklower } 348*51254Ssklower #endif 349