|
|
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) Dirk Husemann, Computer Science Department IV, ! 24: * University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992 ! 25: * Copyright (c) 1992, 1993 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * This code is derived from software contributed to Berkeley by ! 29: * Dirk Husemann and the Computer Science Department (IV) of ! 30: * the University of Erlangen-Nuremberg, Germany. ! 31: * ! 32: * Redistribution and use in source and binary forms, with or without ! 33: * modification, are permitted provided that the following conditions ! 34: * are met: ! 35: * 1. Redistributions of source code must retain the above copyright ! 36: * notice, this list of conditions and the following disclaimer. ! 37: * 2. Redistributions in binary form must reproduce the above copyright ! 38: * notice, this list of conditions and the following disclaimer in the ! 39: * documentation and/or other materials provided with the distribution. ! 40: * 3. All advertising materials mentioning features or use of this software ! 41: * must display the following acknowledgement: ! 42: * This product includes software developed by the University of ! 43: * California, Berkeley and its contributors. ! 44: * 4. Neither the name of the University nor the names of its contributors ! 45: * may be used to endorse or promote products derived from this software ! 46: * without specific prior written permission. ! 47: * ! 48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 58: * SUCH DAMAGE. ! 59: * ! 60: * @(#)llc_output.c 8.1 (Berkeley) 6/10/93 ! 61: */ ! 62: ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/mbuf.h> ! 66: #include <sys/domain.h> ! 67: #include <sys/socket.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: #include <net/if_dl.h> ! 75: #include <net/if_llc.h> ! 76: #include <net/route.h> ! 77: ! 78: #include <netccitt/dll.h> ! 79: #include <netccitt/llc_var.h> ! 80: ! 81: /* ! 82: * llc_output() --- called by an upper layer (network layer) entity whenever ! 83: * there is an INFO frame to be transmitted. We enqueue the ! 84: * info frame and call llc_start() to do the actual sending. ! 85: */ ! 86: ! 87: llc_output(struct llc_linkcb *linkp, struct mbuf *m) ! 88: { ! 89: register int i; ! 90: ! 91: i = splimp(); ! 92: LLC_ENQUEUE(linkp, m); ! 93: llc_start(linkp); ! 94: splx(i); ! 95: ! 96: } ! 97: ! 98: ! 99: /* ! 100: * llc_start() --- We try to subsequently dequeue all the frames available and ! 101: * send them out. ! 102: */ ! 103: void ! 104: llc_start(struct llc_linkcb *linkp) ! 105: { ! 106: register int i; ! 107: register struct mbuf *m; ! 108: int action; ! 109: ! 110: while ((LLC_STATEEQ(linkp, NORMAL) || LLC_STATEEQ(linkp, BUSY) || ! 111: LLC_STATEEQ(linkp, REJECT)) && ! 112: (linkp->llcl_slotsfree > 0) && ! 113: (LLC_GETFLAG(linkp, REMOTE_BUSY) == 0)) { ! 114: LLC_DEQUEUE(linkp, m); ! 115: if (m == NULL) ! 116: break; ! 117: LLC_SETFRAME(linkp, m); ! 118: (void)llc_statehandler(linkp, (struct llc *) 0, NL_DATA_REQUEST, ! 119: 0, 0); ! 120: } ! 121: } ! 122: ! 123: ! 124: /* ! 125: * llc_send() --- Handles single frames. If dealing with INFO frames we need to ! 126: * prepend the LLC header, otherwise we just allocate an mbuf. ! 127: * In both cases the actual send is done by llc_rawsend(). ! 128: */ ! 129: llc_send(struct llc_linkcb *linkp, int frame_kind, int cmdrsp, int pollfinal) ! 130: { ! 131: register struct mbuf *m = (struct mbuf *)0; ! 132: register struct llc *frame; ! 133: ! 134: if (frame_kind == LLCFT_INFO) ! 135: m = linkp->llcl_output_buffers[llc_seq2slot(linkp, ! 136: linkp->llcl_vs)]; ! 137: LLC_GETHDR(frame, m); ! 138: ! 139: /* pass it on to llc_rawsend() */ ! 140: llc_rawsend(linkp, m, frame, frame_kind, linkp->llcl_vs, cmdrsp, pollfinal); ! 141: ! 142: if (frame_kind == LLCFT_INFO) ! 143: LLC_INC(linkp->llcl_vs); ! 144: ! 145: return 0; ! 146: } ! 147: ! 148: /* ! 149: * llc_resend() --- llc_resend() retransmits all unacknowledged INFO frames. ! 150: */ ! 151: llc_resend(struct llc_linkcb *linkp, int cmdrsp, int pollfinal) ! 152: { ! 153: register struct llc *frame; ! 154: register struct mbuf *m; ! 155: register int seq, slot; ! 156: ! 157: if (linkp->llcl_slotsfree < linkp->llcl_window) ! 158: /* assert lock between nr_received & V(S) */ ! 159: if (linkp->llcl_nr_received != linkp->llcl_vs) ! 160: panic("llc: V(S) != N(R) received\n"); ! 161: ! 162: for (slot = llc_seq2slot(linkp, linkp->llcl_vs); ! 163: slot != linkp->llcl_freeslot; ! 164: LLC_INC(linkp->llcl_vs), ! 165: slot = llc_seq2slot(linkp, linkp->llcl_vs)) { ! 166: m = linkp->llcl_output_buffers[slot]; ! 167: LLC_GETHDR(frame, m); ! 168: llc_rawsend(linkp, m, frame, LLCFT_INFO, linkp->llcl_vs, ! 169: cmdrsp, pollfinal); ! 170: pollfinal = 0; ! 171: } ! 172: ! 173: return 0; ! 174: } ! 175: ! 176: /* ! 177: * llc_rawsend() --- constructs an LLC frame and sends it out via the ! 178: * associated interface of the link control block. ! 179: * ! 180: * We need to make sure that outgoing frames have the correct length, ! 181: * in particular the 4 byte ones (RR, RNR, REJ) as LLC_GETHDR() will ! 182: * set the mbuf len to 3 as default len for non INFO frames ... ! 183: * ! 184: * Frame kind Length (w/o MAC header, {D,S}SAP incl.) ! 185: * -------------------------------------------------------------- ! 186: * DISC, SABME, UA, DM 3 bytes ({D,S}SAP + CONTROL) ! 187: * RR, RNR, REJ 4 bytes ({D,S}SAP + CONTROL0 + CONTROL1) ! 188: * XID 6 bytes ({D,S}SAP + CONTROL0 + FI,CLASS,WINDOW) ! 189: * FRMR 7 bytes ({D,S}SAP + CONTROL0 + REJ CONTROL,V(S),V(R),CAUSE) ! 190: * INFO 4 -- MTU ! 191: * UI, TEST 3 -- MTU ! 192: * ! 193: */ ! 194: #define LLC_SETLEN(m, l) (m)->m_pkthdr.len = (m)->m_len = (l) ! 195: ! 196: llc_rawsend(struct llc_linkcb *linkp, struct mbuf *m, struct llc *frame, ! 197: int frame_kind, int vs, int cmdrsp, int pollfinal) ! 198: { ! 199: register short adjust = LLC_UFRAMELEN; ! 200: struct ifnet *ifp; ! 201: ! 202: switch (frame_kind) { ! 203: /* supervisory and information frames */ ! 204: case LLCFT_INFO: ! 205: frame->llc_control = LLC_INFO; ! 206: LLCSBITS(frame->llc_control, i_ns, vs); ! 207: LLCSBITS(frame->llc_control_ext, i_nr, linkp->llcl_vr); ! 208: adjust = LLC_ISFRAMELEN; ! 209: break; ! 210: case LLCFT_RR: ! 211: frame->llc_control = LLC_RR; ! 212: LLC_SETLEN(m, LLC_ISFRAMELEN); ! 213: LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr); ! 214: adjust = LLC_ISFRAMELEN; ! 215: break; ! 216: case LLCFT_RNR: ! 217: frame->llc_control = LLC_RNR; ! 218: LLC_SETLEN(m, LLC_ISFRAMELEN); ! 219: LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr); ! 220: adjust = LLC_ISFRAMELEN; ! 221: break; ! 222: case LLCFT_REJ: ! 223: frame->llc_control = LLC_REJ; ! 224: LLC_SETLEN(m, LLC_ISFRAMELEN); ! 225: LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr); ! 226: adjust = LLC_ISFRAMELEN; ! 227: break; ! 228: /* unnumbered frames */ ! 229: case LLCFT_DM: ! 230: frame->llc_control = LLC_DM; ! 231: break; ! 232: case LLCFT_SABME: ! 233: frame->llc_control = LLC_SABME; ! 234: break; ! 235: case LLCFT_DISC: ! 236: frame->llc_control = LLC_DISC; ! 237: break; ! 238: case LLCFT_UA: ! 239: frame->llc_control = LLC_UA; ! 240: break; ! 241: case LLCFT_UI: ! 242: frame->llc_control = LLC_UI; ! 243: break; ! 244: case LLCFT_FRMR: ! 245: frame->llc_control = LLC_FRMR; ! 246: /* get more space --- FRMR frame are longer then usual */ ! 247: LLC_SETLEN(m, LLC_FRMRLEN); ! 248: bcopy((caddr_t) &linkp->llcl_frmrinfo, ! 249: (caddr_t) &frame->llc_frmrinfo, ! 250: sizeof(struct frmrinfo)); ! 251: break; ! 252: default: ! 253: /* ! 254: * We don't send {XID, TEST} frames ! 255: */ ! 256: if (m) ! 257: m_freem(m); ! 258: return; ! 259: } ! 260: ! 261: /* ! 262: * Fill in DSAP/SSAP ! 263: */ ! 264: frame->llc_dsap = frame->llc_ssap = LLSAPADDR(&linkp->llcl_addr); ! 265: frame->llc_ssap |= cmdrsp; ! 266: ! 267: /* ! 268: * Check for delayed action pending. ISO 8802-2, 7.9.2 (5) ! 269: * and ISO 8802-2, 7.9.2.3 (32), (34), (36) pertain to this ! 270: * piece of code --- hopefully we got it right here (i.e. ! 271: * in the spirit of (32), (34), and (36) ... ! 272: */ ! 273: switch (frame_kind) { ! 274: case LLCFT_RR: ! 275: case LLCFT_RNR: ! 276: case LLCFT_REJ: ! 277: case LLCFT_INFO: ! 278: switch (LLC_GETFLAG(linkp, DACTION)) { ! 279: case LLC_DACKCMD: ! 280: case LLC_DACKRSP: ! 281: LLC_STOPTIMER(linkp, DACTION); ! 282: break; ! 283: case LLC_DACKCMDPOLL: ! 284: if (cmdrsp == LLC_CMD) { ! 285: pollfinal = 1; ! 286: LLC_STOPTIMER(linkp, DACTION); ! 287: } ! 288: break; ! 289: case LLC_DACKRSPFINAL: ! 290: if (cmdrsp == LLC_RSP) { ! 291: pollfinal = 1; ! 292: LLC_STOPTIMER(linkp, DACTION); ! 293: } ! 294: break; ! 295: } ! 296: break; ! 297: } ! 298: ! 299: if (adjust == LLC_UFRAMELEN) ! 300: LLCSBITS(frame->llc_control, u_pf, pollfinal); ! 301: else LLCSBITS(frame->llc_control_ext, s_pf, pollfinal); ! 302: ! 303: /* ! 304: * Get interface to send frame onto ! 305: */ ! 306: ifp = linkp->llcl_if; ! 307: if (frame_kind == LLCFT_INFO) { ! 308: /* ! 309: * send out a copy of the frame, retain the ! 310: * original ! 311: */ ! 312: (*ifp->if_output)(ifp, m_copy(m, 0, (int)M_COPYALL), ! 313: rt_key(linkp->llcl_nlrt), ! 314: linkp->llcl_nlrt); ! 315: /* ! 316: * Account for the LLC header and let it ``disappear'' ! 317: * as the raw info frame payload is what we hold in ! 318: * the output_buffers of the link. ! 319: */ ! 320: m_adj(m, LLC_ISFRAMELEN); ! 321: } else (*ifp->if_output)(ifp, m, ! 322: rt_key(linkp->llcl_nlrt), ! 323: linkp->llcl_nlrt); ! 324: } ! 325:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.