1 /* $NetBSD: llc_output.c,v 1.12 2005/02/26 22:45:10 perry 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.12 2005/02/26 22:45:10 perry 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 llc_output(struct mbuf *m, ...)
109 {
110 struct llc_linkcb *linkp;
111 int i = splnet();
112 va_list ap;
113
114 va_start(ap, m);
115 linkp = va_arg(ap, struct llc_linkcb *);
116 va_end(ap);
117
118 LLC_ENQUEUE(linkp, m);
119 llc_start(linkp);
120 splx(i);
121 return 0;
122 }
123
124
125 /*
126 * llc_start() --- We try to subsequently dequeue all the frames available and
127 * send them out.
128 */
129 void
130 llc_start(linkp)
131 struct llc_linkcb *linkp;
132 {
133 struct mbuf *m;
134
135 while ((LLC_STATEEQ(linkp,NORMAL) || LLC_STATEEQ(linkp,BUSY) ||
136 LLC_STATEEQ(linkp,REJECT)) &&
137 (linkp->llcl_slotsfree > 0) &&
138 (LLC_GETFLAG(linkp,REMOTE_BUSY) == 0)) {
139 LLC_DEQUEUE(linkp,m);
140 if (m == NULL)
141 break;
142 LLC_SETFRAME(linkp, m);
143 (void) llc_statehandler(linkp, NULL, NL_DATA_REQUEST, 0, 0);
144 }
145 }
146
147
148 /*
149 * llc_send() --- Handles single frames. If dealing with INFO frames we need to
150 * prepend the LLC header, otherwise we just allocate an mbuf.
151 * In both cases the actual send is done by llc_rawsend().
152 */
153 void
154 llc_send(linkp, frame_kind, cmdrsp, pollfinal)
155 struct llc_linkcb *linkp;
156 int frame_kind;
157 int cmdrsp;
158 int pollfinal;
159 {
160 struct mbuf *m = (struct mbuf *) 0;
161 struct llc *frame;
162
163 if (frame_kind == LLCFT_INFO)
164 m = linkp->llcl_output_buffers[llc_seq2slot(linkp,
165 linkp->llcl_vs)];
166 LLC_GETHDR(frame, m);
167
168 /* pass it on to llc_rawsend() */
169 llc_rawsend(linkp, m, frame, frame_kind, linkp->llcl_vs, cmdrsp, pollfinal);
170
171 if (frame_kind == LLCFT_INFO)
172 LLC_INC(linkp->llcl_vs);
173 }
174
175 /*
176 * llc_resend() --- llc_resend() retransmits all unacknowledged INFO frames.
177 */
178 void
179 llc_resend(linkp, cmdrsp, pollfinal)
180 struct llc_linkcb *linkp;
181 int cmdrsp;
182 int pollfinal;
183 {
184 struct llc *frame;
185 struct mbuf *m;
186 int slot;
187
188 if (linkp->llcl_slotsfree < linkp->llcl_window)
189 /* assert lock between nr_received & V(S) */
190 if (linkp->llcl_nr_received != linkp->llcl_vs)
191 panic("llc: V(S) != N(R) received");
192
193 for (slot = llc_seq2slot(linkp, linkp->llcl_vs);
194 slot != linkp->llcl_freeslot;
195 LLC_INC(linkp->llcl_vs),
196 slot = llc_seq2slot(linkp, linkp->llcl_vs)) {
197 m = linkp->llcl_output_buffers[slot];
198 LLC_GETHDR(frame, m);
199 llc_rawsend(linkp, m, frame, LLCFT_INFO, linkp->llcl_vs,
200 cmdrsp, pollfinal);
201 pollfinal = 0;
202 }
203 }
204
205 /*
206 * llc_rawsend() --- constructs an LLC frame and sends it out via the
207 * associated interface of the link control block.
208 *
209 * We need to make sure that outgoing frames have the correct length,
210 * in particular the 4 byte ones (RR, RNR, REJ) as LLC_GETHDR() will
211 * set the mbuf len to 3 as default len for non INFO frames ...
212 *
213 * Frame kind Length (w/o MAC header, {D,S}SAP incl.)
214 * --------------------------------------------------------------
215 * DISC, SABME, UA, DM 3 bytes ({D,S}SAP + CONTROL)
216 * RR, RNR, REJ 4 bytes ({D,S}SAP + CONTROL0 + CONTROL1)
217 * XID 6 bytes ({D,S}SAP + CONTROL0 + FI,CLASS,WINDOW)
218 * FRMR 7 bytes ({D,S}SAP + CONTROL0 + REJ CONTROL,V(S),V(R),CAUSE)
219 * INFO 4 -- MTU
220 * UI, TEST 3 -- MTU
221 *
222 */
223 #define LLC_SETLEN(m, l) (m)->m_pkthdr.len = (m)->m_len = (l)
224
225 void
226 llc_rawsend(linkp, m, frame, frame_kind, vs, cmdrsp, pollfinal)
227 struct llc_linkcb *linkp;
228 struct mbuf *m;
229 struct llc *frame;
230 int frame_kind;
231 int vs;
232 int cmdrsp;
233 int pollfinal;
234 {
235 short adjust = LLC_UFRAMELEN;
236 struct ifnet *ifp;
237
238 switch (frame_kind) {
239 /* supervisory and information frames */
240 case LLCFT_INFO:
241 frame->llc_control = LLC_INFO;
242 LLCSBITS(frame->llc_control, i_ns, vs);
243 LLCSBITS(frame->llc_control_ext, i_nr, linkp->llcl_vr);
244 adjust = LLC_ISFRAMELEN;
245 break;
246 case LLCFT_RR:
247 frame->llc_control = LLC_RR;
248 LLC_SETLEN(m, LLC_ISFRAMELEN);
249 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
250 adjust = LLC_ISFRAMELEN;
251 break;
252 case LLCFT_RNR:
253 frame->llc_control = LLC_RNR;
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_REJ:
259 frame->llc_control = LLC_REJ;
260 LLC_SETLEN(m, LLC_ISFRAMELEN);
261 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
262 adjust = LLC_ISFRAMELEN;
263 break;
264 /* unnumbered frames */
265 case LLCFT_DM:
266 frame->llc_control = LLC_DM;
267 break;
268 case LLCFT_SABME:
269 frame->llc_control = LLC_SABME;
270 break;
271 case LLCFT_DISC:
272 frame->llc_control = LLC_DISC;
273 break;
274 case LLCFT_UA:
275 frame->llc_control = LLC_UA;
276 break;
277 case LLCFT_UI:
278 frame->llc_control = LLC_UI;
279 break;
280 case LLCFT_FRMR:
281 frame->llc_control = LLC_FRMR;
282 /* get more space --- FRMR frame are longer than usual */
283 LLC_SETLEN(m, LLC_FRMRLEN);
284 bcopy((caddr_t) & linkp->llcl_frmrinfo,
285 (caddr_t) & frame->llc_frmrinfo,
286 sizeof(struct frmrinfo));
287 break;
288 default:
289 /*
290 * We don't send {XID, TEST} frames
291 */
292 if (m)
293 m_freem(m);
294 return;
295 }
296
297 /*
298 * Fill in DSAP/SSAP
299 */
300 frame->llc_dsap = frame->llc_ssap = LLSAPADDR(&linkp->llcl_addr);
301 frame->llc_ssap |= cmdrsp;
302
303 /*
304 * Check for delayed action pending. ISO 8802-2, 7.9.2 (5)
305 * and ISO 8802-2, 7.9.2.3 (32), (34), (36) pertain to this
306 * piece of code --- hopefully we got it right here (i.e.
307 * in the spirit of (32), (34), and (36) ...
308 */
309 switch (frame_kind) {
310 case LLCFT_RR:
311 case LLCFT_RNR:
312 case LLCFT_REJ:
313 case LLCFT_INFO:
314 switch (LLC_GETFLAG(linkp,DACTION)) {
315 case LLC_DACKCMD:
316 case LLC_DACKRSP:
317 LLC_STOPTIMER(linkp,DACTION);
318 break;
319 case LLC_DACKCMDPOLL:
320 if (cmdrsp == LLC_CMD) {
321 pollfinal = 1;
322 LLC_STOPTIMER(linkp,DACTION);
323 }
324 break;
325 case LLC_DACKRSPFINAL:
326 if (cmdrsp == LLC_RSP) {
327 pollfinal = 1;
328 LLC_STOPTIMER(linkp,DACTION);
329 }
330 break;
331 }
332 break;
333 }
334
335 if (adjust == LLC_UFRAMELEN)
336 LLCSBITS(frame->llc_control,u_pf,pollfinal);
337 else
338 LLCSBITS(frame->llc_control_ext,s_pf,pollfinal);
339
340 /*
341 * Get interface to send frame onto
342 */
343 ifp = linkp->llcl_if;
344 if (frame_kind == LLCFT_INFO) {
345 /*
346 * send out a copy of the frame, retain the original
347 */
348 (*ifp->if_output) (ifp, m_copy(m, 0, (int) M_COPYALL),
349 rt_key(linkp->llcl_nlrt),
350 linkp->llcl_nlrt);
351 /*
352 * Account for the LLC header and let it ``disappear''
353 * as the raw info frame payload is what we hold in
354 * the output_buffers of the link.
355 */
356 m_adj(m, LLC_ISFRAMELEN);
357 } else
358 (*ifp->if_output) (ifp, m,
359 rt_key(linkp->llcl_nlrt),
360 linkp->llcl_nlrt);
361 }
Cache object: bdba7ae81dd0e102147ab0eb67304b0e
|