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