]> git.saurik.com Git - apple/xnu.git/blob - bsd/netccitt/hd_output.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netccitt / hd_output.c
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) University of British Columbia, 1984
24 * Copyright (c) 1990, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * This code is derived from software contributed to Berkeley by
28 * the Laboratory for Computation Vision and the Computer Science Department
29 * of the University of British Columbia.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 *
59 * @(#)hd_output.c 8.1 (Berkeley) 6/10/93
60 */
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/mbuf.h>
65 #include <sys/domain.h>
66 #include <sys/socket.h>
67 #include <sys/syslog.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
75 #include <netccitt/hdlc.h>
76 #include <netccitt/hd_var.h>
77 #include <netccitt/x25.h>
78
79 /*
80 * HDLC OUTPUT INTERFACE
81 *
82 * This routine is called when the X.25 packet layer output routine
83 * has a information frame (iframe) to write. It is also called
84 * by the input and control routines of the HDLC layer.
85 */
86
87 hd_output (hdp, m0)
88 register struct hdcb *hdp;
89 struct mbuf *m0;
90 {
91 struct x25config *xcp;
92 register struct mbuf *m = m0;
93 int len;
94
95 if (m == NULL)
96 panic ("hd_output");
97 if ((m->m_flags & M_PKTHDR) == 0)
98 panic ("hd_output 2");
99
100 if (hdp->hd_state != ABM) {
101 m_freem (m);
102 return;
103 }
104
105 /*
106 * Make room for the hdlc header either by prepending
107 * another mbuf, or by adjusting the offset and length
108 * of the first mbuf in the mbuf chain.
109 */
110
111 M_PREPEND(m, HDHEADERLN, M_DONTWAIT);
112 if (m == NULL)
113 return;
114 for (len = 0; m; m = m->m_next)
115 len += m->m_len;
116 m = m0;
117 m->m_pkthdr.len = len;
118
119 hd_append (&hdp->hd_txq, m);
120 hd_start (hdp);
121 }
122
123 hd_start (hdp)
124 register struct hdcb *hdp;
125 {
126 register struct mbuf *m;
127
128 /*
129 * The iframe is only transmitted if all these conditions are FALSE.
130 * The iframe remains queued (hdp->hd_txq) however and will be
131 * transmitted as soon as these conditions are cleared.
132 */
133
134 while (!(hdp->hd_condition & (TIMER_RECOVERY_CONDITION | REMOTE_RNR_CONDITION | REJ_CONDITION))) {
135 if (hdp->hd_vs == (hdp->hd_lastrxnr + hdp->hd_xcp->xc_lwsize) % MODULUS) {
136
137 /* We have now exceeded the maximum number of
138 outstanding iframes. Therefore, we must wait
139 until at least one is acknowledged if this
140 condition is not turned off before we are
141 requested to write another iframe. */
142 hdp->hd_window_condition++;
143 break;
144 }
145
146 /* hd_remove top iframe from transmit queue. */
147 if ((m = hd_remove (&hdp->hd_txq)) == NULL)
148 break;
149
150 hd_send_iframe (hdp, m, POLLOFF);
151 }
152 }
153
154 /*
155 * This procedure is passed a buffer descriptor for an iframe. It builds
156 * the rest of the control part of the frame and then writes it out. It
157 * also starts the acknowledgement timer and keeps the iframe in the
158 * Retransmit queue (Retxq) just in case we have to do this again.
159 *
160 * Note: This routine is also called from hd_input.c when retransmission
161 * of old frames is required.
162 */
163
164 hd_send_iframe (hdp, buf, poll_bit)
165 register struct hdcb *hdp;
166 register struct mbuf *buf;
167 int poll_bit;
168 {
169 register struct Hdlc_iframe *iframe;
170 struct mbuf *m;
171
172 KILL_TIMER (hdp);
173
174 if (buf == 0) {
175 printf ("hd_send_iframe: zero arg\n");
176 #ifdef HDLCDEBUG
177 hd_status (hdp);
178 hd_dumptrace (hdp);
179 #endif
180 hdp->hd_vs = (hdp->hd_vs + 7) % MODULUS;
181 return;
182 }
183 iframe = mtod (buf, struct Hdlc_iframe *);
184
185 iframe -> hdlc_0 = 0;
186 iframe -> nr = hdp->hd_vr;
187 iframe -> pf = poll_bit;
188 iframe -> ns = hdp->hd_vs;
189 iframe -> address = ADDRESS_B;
190 hdp->hd_lasttxnr = hdp->hd_vr;
191 hdp->hd_rrtimer = 0;
192
193 if (hdp->hd_vs == hdp->hd_retxqi) {
194 /* Check for retransmissions. */
195 /* Put iframe only once in the Retransmission queue. */
196 hdp->hd_retxq[hdp->hd_retxqi] = buf;
197 hdp->hd_retxqi = (hdp->hd_retxqi + 1) % MODULUS;
198 hdp->hd_iframes_out++;
199 }
200
201 hdp->hd_vs = (hdp->hd_vs + 1) % MODULUS;
202
203 hd_trace (hdp, TX, (struct Hdlc_frame *)iframe);
204
205 /* Write buffer on device. */
206 m = hdp->hd_dontcopy ? buf : m_copy(buf, 0, (int)M_COPYALL);
207 if (m == 0) {
208 printf("hdlc: out of mbufs\n");
209 return;
210 }
211 (*hdp->hd_output)(hdp, m);
212 SET_TIMER (hdp);
213 }
214
215 hd_ifoutput(hdp, m)
216 register struct mbuf *m;
217 register struct hdcb *hdp;
218 {
219 /*
220 * Queue message on interface, and start output if interface
221 * not yet active.
222 */
223 register struct ifnet *ifp = hdp->hd_ifp;
224 int s = splimp();
225
226 if (IF_QFULL(&ifp->if_snd)) {
227 IF_DROP(&ifp->if_snd);
228 /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
229 ifp->if_name, ifp->if_unit);*/
230 m_freem(m);
231 } else {
232 IF_ENQUEUE(&ifp->if_snd, m);
233 if ((ifp->if_flags & IFF_OACTIVE) == 0)
234 (*ifp->if_start)(ifp);
235 }
236 splx(s);
237 }
238
239
240 /*
241 * This routine gets control when the timer expires because we have not
242 * received an acknowledgement for a iframe.
243 */
244
245 hd_resend_iframe (hdp)
246 register struct hdcb *hdp;
247 {
248
249 if (hdp->hd_retxcnt++ < hd_n2) {
250 if (!(hdp->hd_condition & TIMER_RECOVERY_CONDITION)) {
251 hdp->hd_xx = hdp->hd_vs;
252 hdp->hd_condition |= TIMER_RECOVERY_CONDITION;
253 }
254
255 hdp->hd_vs = hdp->hd_lastrxnr;
256 hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLON);
257 } else {
258 /* At this point we have not received a RR even after N2
259 retries - attempt to reset link. */
260
261 hd_initvars (hdp);
262 hd_writeinternal (hdp, SABM, POLLOFF);
263 hdp->hd_state = WAIT_UA;
264 SET_TIMER (hdp);
265 hd_message (hdp, "Timer recovery failed: link down");
266 (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
267 }
268 }