|
|
1.1 ! root 1: /* ! 2: * Copyright (c) University of British Columbia, 1984 ! 3: * Copyright (c) 1990 The Regents of the University of California. ! 4: * All rights reserved. ! 5: * ! 6: * This code is derived from software contributed to Berkeley by ! 7: * the Laboratory for Computation Vision and the Computer Science Department ! 8: * of the University of British Columbia. ! 9: * ! 10: * Redistribution and use in source and binary forms, with or without ! 11: * modification, are permitted provided that the following conditions ! 12: * are met: ! 13: * 1. Redistributions of source code must retain the above copyright ! 14: * notice, this list of conditions and the following disclaimer. ! 15: * 2. Redistributions in binary form must reproduce the above copyright ! 16: * notice, this list of conditions and the following disclaimer in the ! 17: * documentation and/or other materials provided with the distribution. ! 18: * 3. All advertising materials mentioning features or use of this software ! 19: * must display the following acknowledgement: ! 20: * This product includes software developed by the University of ! 21: * California, Berkeley and its contributors. ! 22: * 4. Neither the name of the University nor the names of its contributors ! 23: * may be used to endorse or promote products derived from this software ! 24: * without specific prior written permission. ! 25: * ! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 36: * SUCH DAMAGE. ! 37: * ! 38: * @(#)hd_output.c 7.6 (Berkeley) 5/29/91 ! 39: */ ! 40: ! 41: #include "param.h" ! 42: #include "systm.h" ! 43: #include "mbuf.h" ! 44: #include "domain.h" ! 45: #include "socket.h" ! 46: #include "syslog.h" ! 47: #include "protosw.h" ! 48: #include "errno.h" ! 49: #include "time.h" ! 50: #include "kernel.h" ! 51: ! 52: #include "../net/if.h" ! 53: ! 54: #include "hdlc.h" ! 55: #include "hd_var.h" ! 56: #include "x25.h" ! 57: ! 58: /* ! 59: * HDLC OUTPUT INTERFACE ! 60: * ! 61: * This routine is called when the X.25 packet layer output routine ! 62: * has a information frame (iframe) to write. It is also called ! 63: * by the input and control routines of the HDLC layer. ! 64: */ ! 65: ! 66: hd_output (hdp, m0) ! 67: register struct hdcb *hdp; ! 68: struct mbuf *m0; ! 69: { ! 70: struct x25config *xcp; ! 71: register struct mbuf *m = m0; ! 72: int len; ! 73: ! 74: if (m == NULL) ! 75: panic ("hd_output"); ! 76: if (m->m_flags & M_PKTHDR == 0) ! 77: panic ("hd_output 2"); ! 78: ! 79: if (hdp->hd_state != ABM) { ! 80: m_freem (m); ! 81: return; ! 82: } ! 83: ! 84: /* ! 85: * Make room for the hdlc header either by prepending ! 86: * another mbuf, or by adjusting the offset and length ! 87: * of the first mbuf in the mbuf chain. ! 88: */ ! 89: ! 90: M_PREPEND(m, HDHEADERLN, M_DONTWAIT); ! 91: if (m == NULL) ! 92: return; ! 93: for (len = 0; m; m = m->m_next) ! 94: len += m->m_len; ! 95: m = m0; ! 96: m->m_pkthdr.len = len; ! 97: ! 98: hd_append (&hdp->hd_txq, m); ! 99: hd_start (hdp); ! 100: } ! 101: ! 102: hd_start (hdp) ! 103: register struct hdcb *hdp; ! 104: { ! 105: register struct mbuf *m; ! 106: ! 107: /* ! 108: * The iframe is only transmitted if all these conditions are FALSE. ! 109: * The iframe remains queued (hdp->hd_txq) however and will be ! 110: * transmitted as soon as these conditions are cleared. ! 111: */ ! 112: ! 113: while (!(hdp->hd_condition & (TIMER_RECOVERY_CONDITION | REMOTE_RNR_CONDITION | REJ_CONDITION))) { ! 114: if (hdp->hd_vs == (hdp->hd_lastrxnr + hdp->hd_xcp->xc_lwsize) % MODULUS) { ! 115: ! 116: /* We have now exceeded the maximum number of ! 117: outstanding iframes. Therefore, we must wait ! 118: until at least one is acknowledged if this ! 119: condition is not turned off before we are ! 120: requested to write another iframe. */ ! 121: hdp->hd_window_condition++; ! 122: break; ! 123: } ! 124: ! 125: /* hd_remove top iframe from transmit queue. */ ! 126: if ((m = hd_remove (&hdp->hd_txq)) == NULL) ! 127: break; ! 128: ! 129: hd_send_iframe (hdp, m, POLLOFF); ! 130: } ! 131: } ! 132: ! 133: /* ! 134: * This procedure is passed a buffer descriptor for an iframe. It builds ! 135: * the rest of the control part of the frame and then writes it out. It ! 136: * also starts the acknowledgement timer and keeps the iframe in the ! 137: * Retransmit queue (Retxq) just in case we have to do this again. ! 138: * ! 139: * Note: This routine is also called from hd_input.c when retransmission ! 140: * of old frames is required. ! 141: */ ! 142: ! 143: hd_send_iframe (hdp, buf, poll_bit) ! 144: register struct hdcb *hdp; ! 145: register struct mbuf *buf; ! 146: int poll_bit; ! 147: { ! 148: register struct Hdlc_iframe *iframe; ! 149: struct mbuf *m; ! 150: ! 151: KILL_TIMER (hdp); ! 152: ! 153: if (buf == 0) { ! 154: printf ("hd_send_iframe: zero arg\n"); ! 155: #ifdef HDLCDEBUG ! 156: hd_status (hdp); ! 157: hd_dumptrace (hdp); ! 158: #endif ! 159: hdp->hd_vs = (hdp->hd_vs + 7) % MODULUS; ! 160: return; ! 161: } ! 162: iframe = mtod (buf, struct Hdlc_iframe *); ! 163: ! 164: iframe -> hdlc_0 = 0; ! 165: iframe -> nr = hdp->hd_vr; ! 166: iframe -> pf = poll_bit; ! 167: iframe -> ns = hdp->hd_vs; ! 168: iframe -> address = ADDRESS_B; ! 169: hdp->hd_lasttxnr = hdp->hd_vr; ! 170: hdp->hd_rrtimer = 0; ! 171: ! 172: if (hdp->hd_vs == hdp->hd_retxqi) { ! 173: /* Check for retransmissions. */ ! 174: /* Put iframe only once in the Retransmission queue. */ ! 175: hdp->hd_retxq[hdp->hd_retxqi] = buf; ! 176: hdp->hd_retxqi = (hdp->hd_retxqi + 1) % MODULUS; ! 177: hdp->hd_iframes_out++; ! 178: } ! 179: ! 180: hdp->hd_vs = (hdp->hd_vs + 1) % MODULUS; ! 181: ! 182: hd_trace (hdp, TX, (struct Hdlc_frame *)iframe); ! 183: ! 184: /* Write buffer on device. */ ! 185: m = hdp->hd_dontcopy ? buf : m_copy(buf, 0, (int)M_COPYALL); ! 186: if (m == 0) { ! 187: printf("hdlc: out of mbufs\n"); ! 188: return; ! 189: } ! 190: (*hdp->hd_output)(hdp, m); ! 191: SET_TIMER (hdp); ! 192: } ! 193: ! 194: hd_ifoutput(hdp, m) ! 195: register struct mbuf *m; ! 196: register struct hdcb *hdp; ! 197: { ! 198: /* ! 199: * Queue message on interface, and start output if interface ! 200: * not yet active. ! 201: */ ! 202: register struct ifnet *ifp = hdp->hd_ifp; ! 203: int s = splimp(); ! 204: ! 205: if (IF_QFULL(&ifp->if_snd)) { ! 206: IF_DROP(&ifp->if_snd); ! 207: /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", ! 208: ifp->if_name, ifp->if_unit);*/ ! 209: m_freem(m); ! 210: } else { ! 211: IF_ENQUEUE(&ifp->if_snd, m); ! 212: if ((ifp->if_flags & IFF_OACTIVE) == 0) ! 213: (*ifp->if_start)(ifp); ! 214: } ! 215: splx(s); ! 216: } ! 217: ! 218: ! 219: /* ! 220: * This routine gets control when the timer expires because we have not ! 221: * received an acknowledgement for a iframe. ! 222: */ ! 223: ! 224: hd_resend_iframe (hdp) ! 225: register struct hdcb *hdp; ! 226: { ! 227: ! 228: if (hdp->hd_retxcnt++ < hd_n2) { ! 229: if (!(hdp->hd_condition & TIMER_RECOVERY_CONDITION)) { ! 230: hdp->hd_xx = hdp->hd_vs; ! 231: hdp->hd_condition |= TIMER_RECOVERY_CONDITION; ! 232: } ! 233: ! 234: hdp->hd_vs = hdp->hd_lastrxnr; ! 235: hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLON); ! 236: } else { ! 237: /* At this point we have not received a RR even after N2 ! 238: retries - attempt to reset link. */ ! 239: ! 240: hd_initvars (hdp); ! 241: hd_writeinternal (hdp, SABM, POLLOFF); ! 242: hdp->hd_state = WAIT_UA; ! 243: SET_TIMER (hdp); ! 244: hd_message (hdp, "Timer recovery failed: link down"); ! 245: (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); ! 246: } ! 247: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.