|
|
1.1 root 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: *
1.1.1.2 ! root 38: * from: @(#)hd_output.c 7.6 (Berkeley) 5/29/91
! 39: * hd_output.c,v 1.2 1993/05/20 04:12:07 cgd Exp
1.1 root 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:
67: hd_output (hdp, m0)
68: register struct hdcb *hdp;
69: struct 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:
103: hd_start (hdp)
104: register 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:
144: hd_send_iframe (hdp, buf, poll_bit)
145: register struct hdcb *hdp;
146: register struct mbuf *buf;
147: int 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:
195: hd_ifoutput(hdp, m)
196: register struct mbuf *m;
197: register 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:
225: hd_resend_iframe (hdp)
226: register 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.