|
|
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: *
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:
66: hd_output (hdp, m0)
67: register struct hdcb *hdp;
68: struct 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:
102: hd_start (hdp)
103: register 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:
143: hd_send_iframe (hdp, buf, poll_bit)
144: register struct hdcb *hdp;
145: register struct mbuf *buf;
146: int 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:
194: hd_ifoutput(hdp, m)
195: register struct mbuf *m;
196: register 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:
224: hd_resend_iframe (hdp)
225: register 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.