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