xref: /csrg-svn/sys/netccitt/hd_subr.c (revision 41587)
1 /* Copyright (c) University of British Columbia, 1984 */
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/mbuf.h"
6 #include "../h/domain.h"
7 #include "../h/socket.h"
8 #include "../h/protosw.h"
9 #include "../h/errno.h"
10 #include "../h/time.h"
11 #include "../h/kernel.h"
12 
13 #include "../net/if.h"
14 
15 #include "../netccitt/hdlc.h"
16 #include "../netccitt/hd_var.h"
17 #include "../netccitt/x25.h"
18 
19 hd_init ()
20 {
21 
22 	hdintrq.ifq_maxlen = IFQ_MAXLEN;
23 }
24 
25 hd_ctlinput (prc, addr)
26 caddr_t addr;
27 {
28 	register struct x25config *xcp = (struct x25config *)addr;
29 	register struct ifnet *ifp;
30 	register struct hdcb *hdp;
31 	register struct ifaddr *ifa;
32 
33 	if (xcp->xc_family != AF_CCITT)
34 		return (EAFNOSUPPORT);
35 	if (xcp->xc_lptype != HDLCPROTO_LAPB)
36 		return (EPROTONOSUPPORT);
37 	for (ifa = ifa_ifwithaddr ((struct sockaddr *)xcp); ifa; ifa = ifa->ifa_next)
38 		if (ifa->ifa_addr.sa_family == AF_CCITT)
39 			break;
40 	if (ifa == 0 || (ifp = ifa->ifa_ifp) == 0)
41 		panic ("hd_ctlinput");
42 	for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
43 		if (hdp->hd_ifp == ifp)
44 			break;
45 
46 	if (hdp == 0) {		/* new interface */
47 		register int error;
48 		register struct mbuf *m;
49 
50 		m = m_getclr (M_DONTWAIT, MT_PCB);
51 		if (m == 0)
52 			return (ENOBUFS);
53 		if (error = pk_ctlinput (PRC_LINKDOWN, xcp)) {
54 			m_freem (m);
55 			return (error);
56 		}
57 
58 		hdp = mtod (m, struct hdcb *);
59 		hdp->hd_ifp = ifp;
60 		hdp->hd_xcp = xcp;
61 		hdp->hd_next = hdcbhead;
62 		hdcbhead = hdp;
63 		hdp->hd_state = INIT;
64 	}
65 
66 	switch (prc) {
67 	case PRC_IFUP:
68 		if (xcp->xc_lwsize == 0 ||
69 			xcp->xc_lwsize > MAX_WINDOW_SIZE)
70 				xcp->xc_lwsize = MAX_WINDOW_SIZE;
71 		if (hdp->hd_state == INIT)
72 			SET_TIMER (hdp);
73 		break;
74 
75 	case PRC_IFDOWN:
76 		if (hdp->hd_state == ABM)
77 			hd_message (hdp, "Operator shutdown: link closed");
78 		(void) pk_ctlinput (PRC_LINKDOWN, xcp);
79 		hd_writeinternal (hdp, DISC, POLLON);
80 		hdp->hd_state = DISC_SENT;
81 		SET_TIMER (hdp);
82 	}
83 	return (0);
84 }
85 
86 hd_initvars (hdp)
87 register struct hdcb *hdp;
88 {
89 	register struct mbuf *m;
90 	register int i;
91 
92 	/* Clear Transmit queue. */
93 	while ((m = hd_remove (&hdp->hd_txq)) != NULL)
94 		m_freem (m);
95 
96 	/* Clear Retransmit queue. */
97 	i = hdp->hd_lastrxnr;
98 	while (i != hdp->hd_retxqi) {
99 		m_freem (hdp->hd_retxq[i]);
100 		i = (i + 1) % MODULUS;
101 	}
102 	hdp->hd_retxqi = 0;
103 
104 	hdp->hd_vs = hdp->hd_vr = 0;
105 	hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0;
106 	hdp->hd_rrtimer = 0;
107 	KILL_TIMER(hdp);
108 	hdp->hd_retxcnt = 0;
109 	hdp->hd_condition = 0;
110 }
111 
112 hd_decode (hdp, frame)
113 register struct hdcb *hdp;
114 struct Hdlc_frame *frame;
115 {
116 	register int frametype = ILLEGAL;
117 	register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame;
118 	register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame;
119 	register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame;
120 
121 	if (iframe -> hdlc_0 == 0) {
122 		frametype = IFRAME;
123 		hdp->hd_iframes_in++;
124 	}
125 
126 	else if (sframe -> hdlc_01 == 1) {
127 		/* Supervisory format. */
128 		switch (sframe -> s2) {
129 		case 0:
130 			frametype = RR;
131 			hdp->hd_rrs_in++;
132 			break;
133 
134 		case 1:
135 			frametype = RNR;
136 			hdp->hd_rnrs_in++;
137 			break;
138 
139 		case 2:
140 			frametype = REJ;
141 			hdp->hd_rejs_in++;
142 		}
143 	}
144 	else if (uframe -> hdlc_11 == 3) {
145 		/* Unnumbered format. */
146 		switch (uframe -> m3) {
147 		case 0:
148 			frametype = DM;
149 			break;
150 
151 		case 1:
152 			frametype = SABM;
153 			break;
154 
155 		case 2:
156 			frametype = DISC;
157 			break;
158 
159 		case 3:
160 			frametype = UA;
161 			break;
162 
163 		case 4:
164 			frametype = FRMR;
165 			hdp->hd_frmrs_in++;
166 		}
167 	}
168 	return (frametype);
169 }
170 
171 /*
172  *  This routine is called when the HDLC layer internally  generates a
173  *  command or  response  for  the remote machine ( eg. RR, UA etc. ).
174  *  Only supervisory or unnumbered frames are processed.
175  */
176 
177 hd_writeinternal (hdp, frametype, pf)
178 register struct hdcb *hdp;
179 register int frametype, pf;
180 {
181 	register struct mbuf *buf;
182 	struct Hdlc_frame *frame;
183 	register struct Hdlc_sframe *sframe;
184 	register struct Hdlc_uframe *uframe;
185 
186 	MGET (buf, M_DONTWAIT, MT_HEADER);
187 	if (buf == 0)
188 		return;
189 	frame = mtod (buf, struct Hdlc_frame *);
190 	sframe = mtod (buf, struct Hdlc_sframe *);
191 	uframe = mtod (buf, struct Hdlc_uframe *);
192 
193 	/* Assume a response - address structure for DTE */
194 	frame -> address = ADDRESS_A;
195 	buf -> m_len = 2;
196 	buf -> m_act = buf -> m_next = NULL;
197 
198 	switch (frametype) {
199 	case RR:
200 		frame -> control = RR_CONTROL;
201 		hdp->hd_rrs_out++;
202 		break;
203 
204 	case RNR:
205 		frame -> control = RNR_CONTROL;
206 		hdp->hd_rnrs_out++;
207 		break;
208 
209 	case REJ:
210 		frame -> control = REJ_CONTROL;
211 		hdp->hd_rejs_out++;
212 		break;
213 
214 	case SABM:
215 		frame -> control = SABM_CONTROL;
216 		frame -> address = ADDRESS_B;
217 		break;
218 
219 	case DISC:
220 		frame -> control = DISC_CONTROL;
221 		frame -> address = ADDRESS_B;
222 		break;
223 
224 	case DM:
225 		frame -> control = DM_CONTROL;
226 		break;
227 
228 	case UA:
229 		frame -> control = UA_CONTROL;
230 		break;
231 
232 	case FRMR:
233 		frame -> control = FRMR_CONTROL;
234 		bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3);
235 		buf -> m_len = 5;
236 		hdp->hd_frmrs_out++;
237 
238 	}
239 
240 	if (sframe -> hdlc_01 == 1) {
241 		/* Supervisory format - RR, REJ, or RNR. */
242 		sframe -> nr = hdp->hd_vr;
243 		sframe -> pf = pf;
244 		hdp->hd_lasttxnr = hdp->hd_vr;
245 		hdp->hd_rrtimer = 0;
246 	}
247 	else
248 		uframe -> pf = pf;
249 
250 	hd_trace (hdp, TX, frame);
251 	(*hdp -> hd_ifp -> if_output) (hdp -> hd_ifp, buf,
252 		(struct sockaddr *)hdp->hd_xcp);
253 
254 }
255 
256 struct mbuf *
257 hd_remove (q)
258 struct hdtxq *q;
259 {
260 	register struct mbuf *m;
261 
262 	m = q -> head;
263 	if (m) {
264 		if ((q -> head = m -> m_act) == NULL)
265 			q -> tail = NULL;
266 		m -> m_act = 0;
267 	}
268 	return (m);
269 }
270 
271 hd_append (q, m)
272 register struct hdtxq *q;
273 register struct mbuf *m;
274 {
275 
276 	m -> m_act = NULL;
277 	if (q -> tail == NULL)
278 		q -> head = m;
279 	else
280 		q -> tail -> m_act = m;
281 	q -> tail = m;
282 }
283 
284 hd_flush (ifp)
285 struct ifnet *ifp;
286 {
287 	register struct mbuf *m;
288 	register int s;
289 
290 	while (1) {
291 		s = spl6 ();		/* XXX SHOULDN'T THIS BE splimp? */
292 		IF_DEQUEUE (&ifp->if_snd, m);
293 		splx (s);
294 		if (m == 0)
295 			break;
296 		m_freem (m);
297 	}
298 }
299 
300 hd_message (hdp, msg)
301 struct hdcb *hdp;
302 char *msg;
303 {
304 	char *format_ntn ();
305 
306 	if (hdcbhead -> hd_next)
307 		printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg);
308 	else
309 		printf ("HDLC: %s\n", msg);
310 }
311 
312 #ifdef HDLCDEBUG
313 hd_status (hdp)
314 struct hdcb *hdp;
315 {
316 	printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n",
317 		hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi);
318 
319 	printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n",
320 		hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx);
321 }
322 #endif
323