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