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