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