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