Removed all patch kit headers, sccsid and rcsid strings, put $Id$ in, some
[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 *
38 * @(#)hd_output.c 7.6 (Berkeley) 5/29/91
39 */
40
41#include "param.h"
42#include "systm.h"
43#include "mbuf.h"
44#include "domain.h"
45#include "socket.h"
46#include "syslog.h"
47#include "protosw.h"
48#include "errno.h"
49#include "time.h"
50#include "kernel.h"
51
52#include "../net/if.h"
53
54#include "hdlc.h"
55#include "hd_var.h"
56#include "x25.h"
57
58/*
59 * HDLC OUTPUT INTERFACE
60 *
61 * This routine is called when the X.25 packet layer output routine
62 * has a information frame (iframe) to write. It is also called
63 * by the input and control routines of the HDLC layer.
64 */
65
66hd_output (hdp, m0)
67register struct hdcb *hdp;
68struct mbuf *m0;
69{
70 struct x25config *xcp;
71 register struct mbuf *m = m0;
72 int len;
73
74 if (m == NULL)
75 panic ("hd_output");
76 if (m->m_flags & M_PKTHDR == 0)
77 panic ("hd_output 2");
78
79 if (hdp->hd_state != ABM) {
80 m_freem (m);
81 return;
82 }
83
84 /*
85 * Make room for the hdlc header either by prepending
86 * another mbuf, or by adjusting the offset and length
87 * of the first mbuf in the mbuf chain.
88 */
89
90 M_PREPEND(m, HDHEADERLN, M_DONTWAIT);
91 if (m == NULL)
92 return;
93 for (len = 0; m; m = m->m_next)
94 len += m->m_len;
95 m = m0;
96 m->m_pkthdr.len = len;
97
98 hd_append (&hdp->hd_txq, m);
99 hd_start (hdp);
100}
101
102hd_start (hdp)
103register struct hdcb *hdp;
104{
105 register struct mbuf *m;
106
107 /*
108 * The iframe is only transmitted if all these conditions are FALSE.
109 * The iframe remains queued (hdp->hd_txq) however and will be
110 * transmitted as soon as these conditions are cleared.
111 */
112
113 while (!(hdp->hd_condition & (TIMER_RECOVERY_CONDITION | REMOTE_RNR_CONDITION | REJ_CONDITION))) {
114 if (hdp->hd_vs == (hdp->hd_lastrxnr + hdp->hd_xcp->xc_lwsize) % MODULUS) {
115
116 /* We have now exceeded the maximum number of
117 outstanding iframes. Therefore, we must wait
118 until at least one is acknowledged if this
119 condition is not turned off before we are
120 requested to write another iframe. */
121 hdp->hd_window_condition++;
122 break;
123 }
124
125 /* hd_remove top iframe from transmit queue. */
126 if ((m = hd_remove (&hdp->hd_txq)) == NULL)
127 break;
128
129 hd_send_iframe (hdp, m, POLLOFF);
130 }
131}
132
133/*
134 * This procedure is passed a buffer descriptor for an iframe. It builds
135 * the rest of the control part of the frame and then writes it out. It
136 * also starts the acknowledgement timer and keeps the iframe in the
137 * Retransmit queue (Retxq) just in case we have to do this again.
138 *
139 * Note: This routine is also called from hd_input.c when retransmission
140 * of old frames is required.
141 */
142
143hd_send_iframe (hdp, buf, poll_bit)
144register struct hdcb *hdp;
145register struct mbuf *buf;
146int poll_bit;
147{
148 register struct Hdlc_iframe *iframe;
149 struct mbuf *m;
150
151 KILL_TIMER (hdp);
152
153 if (buf == 0) {
154 printf ("hd_send_iframe: zero arg\n");
155#ifdef HDLCDEBUG
156 hd_status (hdp);
157 hd_dumptrace (hdp);
158#endif
159 hdp->hd_vs = (hdp->hd_vs + 7) % MODULUS;
160 return;
161 }
162 iframe = mtod (buf, struct Hdlc_iframe *);
163
164 iframe -> hdlc_0 = 0;
165 iframe -> nr = hdp->hd_vr;
166 iframe -> pf = poll_bit;
167 iframe -> ns = hdp->hd_vs;
168 iframe -> address = ADDRESS_B;
169 hdp->hd_lasttxnr = hdp->hd_vr;
170 hdp->hd_rrtimer = 0;
171
172 if (hdp->hd_vs == hdp->hd_retxqi) {
173 /* Check for retransmissions. */
174 /* Put iframe only once in the Retransmission queue. */
175 hdp->hd_retxq[hdp->hd_retxqi] = buf;
176 hdp->hd_retxqi = (hdp->hd_retxqi + 1) % MODULUS;
177 hdp->hd_iframes_out++;
178 }
179
180 hdp->hd_vs = (hdp->hd_vs + 1) % MODULUS;
181
182 hd_trace (hdp, TX, (struct Hdlc_frame *)iframe);
183
184 /* Write buffer on device. */
185 m = hdp->hd_dontcopy ? buf : m_copy(buf, 0, (int)M_COPYALL);
186 if (m == 0) {
187 printf("hdlc: out of mbufs\n");
188 return;
189 }
190 (*hdp->hd_output)(hdp, m);
191 SET_TIMER (hdp);
192}
193
194hd_ifoutput(hdp, m)
195register struct mbuf *m;
196register struct hdcb *hdp;
197{
198 /*
199 * Queue message on interface, and start output if interface
200 * not yet active.
201 */
202 register struct ifnet *ifp = hdp->hd_ifp;
203 int s = splimp();
204
205 if (IF_QFULL(&ifp->if_snd)) {
206 IF_DROP(&ifp->if_snd);
207 /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
208 ifp->if_name, ifp->if_unit);*/
209 m_freem(m);
210 } else {
211 IF_ENQUEUE(&ifp->if_snd, m);
212 if ((ifp->if_flags & IFF_OACTIVE) == 0)
213 (*ifp->if_start)(ifp);
214 }
215 splx(s);
216}
217
218
219/*
220 * This routine gets control when the timer expires because we have not
221 * received an acknowledgement for a iframe.
222 */
223
224hd_resend_iframe (hdp)
225register struct hdcb *hdp;
226{
227
228 if (hdp->hd_retxcnt++ < hd_n2) {
229 if (!(hdp->hd_condition & TIMER_RECOVERY_CONDITION)) {
230 hdp->hd_xx = hdp->hd_vs;
231 hdp->hd_condition |= TIMER_RECOVERY_CONDITION;
232 }
233
234 hdp->hd_vs = hdp->hd_lastrxnr;
235 hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLON);
236 } else {
237 /* At this point we have not received a RR even after N2
238 retries - attempt to reset link. */
239
240 hd_initvars (hdp);
241 hd_writeinternal (hdp, SABM, POLLOFF);
242 hdp->hd_state = WAIT_UA;
243 SET_TIMER (hdp);
244 hd_message (hdp, "Timer recovery failed: link down");
245 (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
246 }
247}