1 /* 2 * Copyright (C) Dirk Husemann, Computer Science Department IV, 3 * University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Dirk Husemann and the Computer Science Department (IV) of 9 * the University of Erlangen-Nuremberg, Germany. 10 * 11 * %sccs.include.redist.c% 12 * 13 * @(#)llc_timer.c 8.1 (Berkeley) 06/10/93 14 */ 15 16 #include <sys/param.h> 17 #include <sys/systm.h> 18 #include <sys/mbuf.h> 19 #include <sys/domain.h> 20 #include <sys/socket.h> 21 #include <sys/protosw.h> 22 #include <sys/errno.h> 23 #include <sys/time.h> 24 #include <sys/kernel.h> 25 26 #include <net/if.h> 27 #include <net/if_dl.h> 28 #include <net/if_llc.h> 29 30 #include <netccitt/dll.h> 31 #include <netccitt/llc_var.h> 32 33 34 /* 35 * Various timer values. They can be adjusted 36 * by patching the binary with adb if necessary. 37 */ 38 /* ISO 8802-2 timers */ 39 int llc_n2 = LLC_N2_VALUE; 40 int llc_ACK_timer = LLC_ACK_TIMER; 41 int llc_P_timer = LLC_P_TIMER; 42 int llc_BUSY_timer = LLC_BUSY_TIMER; 43 int llc_REJ_timer = LLC_REJ_TIMER; 44 /* Implementation specific timers */ 45 int llc_AGE_timer = LLC_AGE_TIMER; 46 int llc_DACTION_timer = LLC_DACTION_TIMER; 47 48 /* 49 * The timer routine. We are called every 500ms by the kernel. 50 * Handle the various virtual timers. 51 */ 52 53 void 54 llc_timer() 55 { 56 register struct llc_linkcb *linkp; 57 register struct llc_linkcb *nlinkp; 58 register int timer; 59 register int action; 60 register int s = splimp(); 61 62 /* 63 * All links are accessible over the doubly linked list llccb_q 64 */ 65 if (!LQEMPTY) { 66 /* 67 * A for-loop is not that great an idea as the linkp 68 * might get deleted if the age timer has expired ... 69 */ 70 linkp = LQFIRST; 71 while (LQVALID(linkp)) { 72 nlinkp = LQNEXT(linkp); 73 /* 74 * Check implementation specific timers first 75 */ 76 /* The delayed action/acknowledge idle timer */ 77 switch (LLC_TIMERXPIRED(linkp, DACTION)) { 78 case LLC_TIMER_RUNNING: 79 LLC_AGETIMER(linkp, DACTION); 80 break; 81 case LLC_TIMER_EXPIRED: { 82 register int cmdrsp; 83 register int pollfinal; 84 85 switch (LLC_GETFLAG(linkp, DACTION)) { 86 case LLC_DACKCMD: 87 cmdrsp = LLC_CMD, pollfinal = 0; 88 break; 89 case LLC_DACKCMDPOLL: 90 cmdrsp = LLC_CMD, pollfinal = 1; 91 break; 92 case LLC_DACKRSP: 93 cmdrsp = LLC_RSP, pollfinal = 0; 94 break; 95 case LLC_DACKRSPFINAL: 96 cmdrsp = LLC_RSP, pollfinal = 1; 97 break; 98 } 99 llc_send(linkp, LLCFT_RR, cmdrsp, pollfinal); 100 LLC_STOPTIMER(linkp, DACTION); 101 break; 102 } 103 } 104 /* The link idle timer */ 105 switch (LLC_TIMERXPIRED(linkp, AGE)) { 106 case LLC_TIMER_RUNNING: 107 LLC_AGETIMER(linkp, AGE); 108 break; 109 case LLC_TIMER_EXPIRED: 110 /* 111 * Only crunch the link when really no 112 * timers are running any more. 113 */ 114 if (llc_anytimersup(linkp) == 0) { 115 llc_dellink(linkp); 116 LLC_STOPTIMER(linkp, AGE); 117 goto gone; 118 } else { 119 LLC_STARTTIMER(linkp, AGE); 120 } 121 break; 122 } 123 /* 124 * Now, check all the ISO 8802-2 timers 125 */ 126 FOR_ALL_LLC_TIMERS(timer) { 127 action = 0; 128 if ((linkp->llcl_timerflags & (1<<timer)) && 129 (linkp->llcl_timers[timer] == 0)) { 130 switch (timer) { 131 case LLC_ACK_SHIFT: 132 action = LLC_ACK_TIMER_EXPIRED; 133 break; 134 case LLC_P_SHIFT: 135 action = LLC_P_TIMER_EXPIRED; 136 break; 137 case LLC_BUSY_SHIFT: 138 action = LLC_BUSY_TIMER_EXPIRED; 139 break; 140 case LLC_REJ_SHIFT: 141 action = LLC_REJ_TIMER_EXPIRED; 142 break; 143 } 144 linkp->llcl_timerflags &= ~(1<<timer); 145 (void)llc_statehandler(linkp, (struct llc *)0, action, 0, 1); 146 } else if (linkp->llcl_timers[timer] > 0) 147 linkp->llcl_timers[timer]--; 148 } 149 150 gone: linkp = nlinkp; 151 } 152 } 153 splx (s); 154 } 155