|
|
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.