]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netccitt/llc_output.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
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.
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.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
60 * @(#)llc_output.c 8.1 (Berkeley) 6/10/93
63 #include <sys/param.h>
64 #include <sys/systm.h>
66 #include <sys/domain.h>
67 #include <sys/socket.h>
68 #include <sys/protosw.h>
69 #include <sys/errno.h>
71 #include <sys/kernel.h>
74 #include <net/if_dl.h>
75 #include <net/if_llc.h>
76 #include <net/route.h>
78 #include <netccitt/dll.h>
79 #include <netccitt/llc_var.h>
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.
87 llc_output(struct llc_linkcb
*linkp
, struct mbuf
*m
)
92 LLC_ENQUEUE(linkp
, m
);
100 * llc_start() --- We try to subsequently dequeue all the frames available and
104 llc_start(struct llc_linkcb
*linkp
)
107 register struct mbuf
*m
;
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
);
117 LLC_SETFRAME(linkp
, m
);
118 (void)llc_statehandler(linkp
, (struct llc
*) 0, NL_DATA_REQUEST
,
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().
129 llc_send(struct llc_linkcb
*linkp
, int frame_kind
, int cmdrsp
, int pollfinal
)
131 register struct mbuf
*m
= (struct mbuf
*)0;
132 register struct llc
*frame
;
134 if (frame_kind
== LLCFT_INFO
)
135 m
= linkp
->llcl_output_buffers
[llc_seq2slot(linkp
,
137 LLC_GETHDR(frame
, m
);
139 /* pass it on to llc_rawsend() */
140 llc_rawsend(linkp
, m
, frame
, frame_kind
, linkp
->llcl_vs
, cmdrsp
, pollfinal
);
142 if (frame_kind
== LLCFT_INFO
)
143 LLC_INC(linkp
->llcl_vs
);
149 * llc_resend() --- llc_resend() retransmits all unacknowledged INFO frames.
151 llc_resend(struct llc_linkcb
*linkp
, int cmdrsp
, int pollfinal
)
153 register struct llc
*frame
;
154 register struct mbuf
*m
;
155 register int seq
, slot
;
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");
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
,
177 * llc_rawsend() --- constructs an LLC frame and sends it out via the
178 * associated interface of the link control block.
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 ...
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)
194 #define LLC_SETLEN(m, l) (m)->m_pkthdr.len = (m)->m_len = (l)
196 llc_rawsend(struct llc_linkcb
*linkp
, struct mbuf
*m
, struct llc
*frame
,
197 int frame_kind
, int vs
, int cmdrsp
, int pollfinal
)
199 register short adjust
= LLC_UFRAMELEN
;
202 switch (frame_kind
) {
203 /* supervisory and information frames */
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
;
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
;
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
;
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
;
228 /* unnumbered frames */
230 frame
->llc_control
= LLC_DM
;
233 frame
->llc_control
= LLC_SABME
;
236 frame
->llc_control
= LLC_DISC
;
239 frame
->llc_control
= LLC_UA
;
242 frame
->llc_control
= LLC_UI
;
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
));
254 * We don't send {XID, TEST} frames
264 frame
->llc_dsap
= frame
->llc_ssap
= LLSAPADDR(&linkp
->llcl_addr
);
265 frame
->llc_ssap
|= cmdrsp
;
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) ...
273 switch (frame_kind
) {
278 switch (LLC_GETFLAG(linkp
, DACTION
)) {
281 LLC_STOPTIMER(linkp
, DACTION
);
283 case LLC_DACKCMDPOLL
:
284 if (cmdrsp
== LLC_CMD
) {
286 LLC_STOPTIMER(linkp
, DACTION
);
289 case LLC_DACKRSPFINAL
:
290 if (cmdrsp
== LLC_RSP
) {
292 LLC_STOPTIMER(linkp
, DACTION
);
299 if (adjust
== LLC_UFRAMELEN
)
300 LLCSBITS(frame
->llc_control
, u_pf
, pollfinal
);
301 else LLCSBITS(frame
->llc_control_ext
, s_pf
, pollfinal
);
304 * Get interface to send frame onto
306 ifp
= linkp
->llcl_if
;
307 if (frame_kind
== LLCFT_INFO
) {
309 * send out a copy of the frame, retain the
312 (*ifp
->if_output
)(ifp
, m_copy(m
, 0, (int)M_COPYALL
),
313 rt_key(linkp
->llcl_nlrt
),
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.
320 m_adj(m
, LLC_ISFRAMELEN
);
321 } else (*ifp
->if_output
)(ifp
, m
,
322 rt_key(linkp
->llcl_nlrt
),