|
|
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_input.c 7.7 (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 "protosw.h"
47: #include "errno.h"
48: #include "time.h"
49: #include "kernel.h"
50:
51: #include "../net/if.h"
52:
53: #include "hdlc.h"
54: #include "hd_var.h"
55: #include "x25.h"
56:
1.1.1.2 ! root 57: int frame_reject(), rej_routine(), free_iframes();
! 58:
1.1 root 59: /*
60: * HDLC INPUT INTERFACE
61: *
62: * This routine is called when the HDLC physical device has
63: * completed reading a frame.
64: */
65:
66: hdintr ()
67: {
68: register struct mbuf *m;
69: register struct hdcb *hdp;
70: register struct ifnet *ifp;
71: register int s;
72: extern struct ifqueue pkintrq;
73: static struct ifnet *lastifp;
74: static struct hdcb *lasthdp;
75:
76: for (;;) {
77: s = splimp ();
78: IF_DEQUEUE (&hdintrq, m);
79: splx (s);
80: if (m == 0)
81: break;
82: if (m->m_len < HDHEADERLN) {
83: printf ("hdintr: packet too short (len=%d)\n",
84: m->m_len);
85: m_freem (m);
86: continue;
87: }
88: if ((m->m_flags & M_PKTHDR) == 0)
89: panic("hdintr");
90: ifp = m->m_pkthdr.rcvif;
91:
92: /*
93: * look up the appropriate hdlc control block
94: */
95:
96: if (ifp == lastifp)
97: hdp = lasthdp;
98: else {
99: for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
100: if (hdp->hd_ifp == ifp)
101: break;
102: if (hdp == 0) {
103: printf ("hdintr: unknown interface %x\n", ifp);
104: m_freem (m);
105: continue;
106: }
107: lastifp = ifp;
108: lasthdp = hdp;
109: }
110:
111: /* Process_rxframe returns FALSE if the frame was NOT queued
112: for the next higher layers. */
113: if (process_rxframe (hdp, m) == FALSE)
114: m_freem (m);
115: }
116: if (pkintrq.ifq_len)
117: pkintr ();
118: }
119:
120: process_rxframe (hdp, fbuf)
121: register struct hdcb *hdp;
122: register struct mbuf *fbuf;
123: {
124: register int queued = FALSE, frametype, pf;
125: register struct Hdlc_frame *frame;
126:
127: frame = mtod (fbuf, struct Hdlc_frame *);
128: pf = ((struct Hdlc_iframe *) frame) -> pf;
129:
130: hd_trace (hdp, RX, frame);
131: if (frame -> address != ADDRESS_A && frame -> address != ADDRESS_B)
132: return (queued);
133:
134: switch ((frametype = hd_decode (hdp, frame)) + hdp->hd_state) {
135: case DM + DISC_SENT:
136: case UA + DISC_SENT:
137: /*
138: * Link now closed. Leave timer running
139: * so hd_timer() can periodically check the
140: * status of interface driver flag bit IFF_UP.
141: */
142: hdp->hd_state = DISCONNECTED;
143: break;
144:
145: case DM + INIT:
146: case UA + INIT:
147: /*
148: * This is a non-standard state change needed for DCEs
149: * that do dynamic link selection. We can't go into the
150: * usual "SEND DM" state because a DM is a SARM in LAP.
151: */
152: hd_writeinternal (hdp, SABM, POLLOFF);
153: hdp->hd_state = SABM_SENT;
154: SET_TIMER (hdp);
155: break;
156:
157: case SABM + DM_SENT:
158: case SABM + WAIT_SABM:
159: hd_writeinternal (hdp, UA, pf);
160: case UA + SABM_SENT:
161: case UA + WAIT_UA:
162: KILL_TIMER (hdp);
163: hd_initvars (hdp);
164: hdp->hd_state = ABM;
165: hd_message (hdp, "Link level operational");
166: /* Notify the packet level - to send RESTART. */
167: (void) pk_ctlinput (PRC_LINKUP, hdp->hd_pkp);
168: break;
169:
170: case SABM + SABM_SENT:
171: /* Got a SABM collision. Acknowledge the remote's SABM
172: via UA but still wait for UA. */
173: hd_writeinternal (hdp, UA, pf);
174: break;
175:
176: case SABM + ABM:
177: /* Request to reset the link from the remote. */
178: KILL_TIMER (hdp);
179: hd_message (hdp, "Link reset");
180: #ifdef HDLCDEBUG
181: hd_dumptrace (hdp);
182: #endif
183: hd_flush (hdp->hd_ifp);
184: hd_writeinternal (hdp, UA, pf);
185: hd_initvars (hdp);
186: (void) pk_ctlinput (PRC_LINKRESET, hdp->hd_pkp);
187: hdp->hd_resets++;
188: break;
189:
190: case SABM + WAIT_UA:
191: hd_writeinternal (hdp, UA, pf);
192: break;
193:
194: case DM + ABM:
195: hd_message (hdp, "DM received: link down");
196: #ifdef HDLCDEBUG
197: hd_dumptrace (hdp);
198: #endif
199: (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
200: hd_flush (hdp->hd_ifp);
201: case DM + DM_SENT:
202: case DM + WAIT_SABM:
203: case DM + WAIT_UA:
204: hd_writeinternal (hdp, SABM, pf);
205: hdp->hd_state = SABM_SENT;
206: SET_TIMER (hdp);
207: break;
208:
209: case DISC + INIT:
210: case DISC + DM_SENT:
211: case DISC + SABM_SENT:
212: /* Note: This is a non-standard state change. */
213: hd_writeinternal (hdp, UA, pf);
214: hd_writeinternal (hdp, SABM, POLLOFF);
215: hdp->hd_state = SABM_SENT;
216: SET_TIMER (hdp);
217: break;
218:
219: case DISC + WAIT_UA:
220: hd_writeinternal (hdp, DM, pf);
221: SET_TIMER (hdp);
222: hdp->hd_state = DM_SENT;
223: break;
224:
225: case DISC + ABM:
226: hd_message (hdp, "DISC received: link down");
227: (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
228: case DISC + WAIT_SABM:
229: hd_writeinternal (hdp, UA, pf);
230: hdp->hd_state = DM_SENT;
231: SET_TIMER (hdp);
232: break;
233:
234: case UA + ABM:
235: hd_message (hdp, "UA received: link down");
236: (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
237: case UA + WAIT_SABM:
238: hd_writeinternal (hdp, DM, pf);
239: hdp->hd_state = DM_SENT;
240: SET_TIMER (hdp);
241: break;
242:
243: case FRMR + DM_SENT:
244: hd_writeinternal (hdp, SABM, pf);
245: hdp->hd_state = SABM_SENT;
246: SET_TIMER (hdp);
247: break;
248:
249: case FRMR + WAIT_SABM:
250: hd_writeinternal (hdp, DM, pf);
251: hdp->hd_state = DM_SENT;
252: SET_TIMER (hdp);
253: break;
254:
255: case FRMR + ABM:
256: hd_message (hdp, "FRMR received: link down");
257: (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
258: #ifdef HDLCDEBUG
259: hd_dumptrace (hdp);
260: #endif
261: hd_flush (hdp->hd_ifp);
262: hd_writeinternal (hdp, SABM, pf);
263: hdp->hd_state = WAIT_UA;
264: SET_TIMER (hdp);
265: break;
266:
267: case RR + ABM:
268: case RNR + ABM:
269: case REJ + ABM:
270: process_sframe (hdp, (struct Hdlc_sframe *)frame, frametype);
271: break;
272:
273: case IFRAME + ABM:
274: queued = process_iframe (hdp, fbuf, (struct Hdlc_iframe *)frame);
275: break;
276:
277: case IFRAME + SABM_SENT:
278: case RR + SABM_SENT:
279: case RNR + SABM_SENT:
280: case REJ + SABM_SENT:
281: hd_writeinternal (hdp, DM, POLLON);
282: hdp->hd_state = DM_SENT;
283: SET_TIMER (hdp);
284: break;
285:
286: case IFRAME + WAIT_SABM:
287: case RR + WAIT_SABM:
288: case RNR + WAIT_SABM:
289: case REJ + WAIT_SABM:
290: hd_writeinternal (hdp, FRMR, POLLOFF);
291: SET_TIMER (hdp);
292: break;
293:
294: case ILLEGAL + SABM_SENT:
295: hdp->hd_unknown++;
296: hd_writeinternal (hdp, DM, POLLOFF);
297: hdp->hd_state = DM_SENT;
298: SET_TIMER (hdp);
299: break;
300:
301: case ILLEGAL + ABM:
302: hd_message (hdp, "Unknown frame received: link down");
303: (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
304: case ILLEGAL + WAIT_SABM:
305: hdp->hd_unknown++;
306: #ifdef HDLCDEBUG
307: hd_dumptrace (hdp);
308: #endif
309: hd_writeinternal (hdp, FRMR, POLLOFF);
310: hdp->hd_state = WAIT_SABM;
311: SET_TIMER (hdp);
312: break;
313: }
314:
315: return (queued);
316: }
317:
318: process_iframe (hdp, fbuf, frame)
319: register struct hdcb *hdp;
320: struct mbuf *fbuf;
321: register struct Hdlc_iframe *frame;
322: {
323: register int nr = frame -> nr,
324: ns = frame -> ns,
325: pf = frame -> pf;
326: register int queued = FALSE;
327:
328: /*
329: * Validate the iframe's N(R) value. It's N(R) value must be in
330: * sync with our V(S) value and our "last received nr".
331: */
332:
333: if (valid_nr (hdp, nr, FALSE) == FALSE) {
334: frame_reject (hdp, Z, frame);
335: return (queued);
336: }
337:
338:
339: /*
340: * This section tests the IFRAME for proper sequence. That is, it's
341: * sequence number N(S) MUST be equal to V(S).
342: */
343:
344: if (ns != hdp->hd_vr) {
345: hdp->hd_invalid_ns++;
346: if (pf || (hdp->hd_condition & REJ_CONDITION) == 0) {
347: hdp->hd_condition |= REJ_CONDITION;
348: /*
349: * Flush the transmit queue. This is ugly but we
350: * have no choice. A reject response must be
351: * immediately sent to the DCE. Failure to do so
352: * may result in another out of sequence iframe
353: * arriving (and thus sending another reject)
354: * before the first reject is transmitted. This
355: * will cause the DCE to receive two or more
356: * rejects back to back, which must never happen.
357: */
358: hd_flush (hdp->hd_ifp);
359: hd_writeinternal (hdp, REJ, pf);
360: }
361: return (queued);
362: }
363: hdp->hd_condition &= ~REJ_CONDITION;
364:
365: /*
366: * This section finally tests the IFRAME's sequence number against
367: * the window size (K) and the sequence number of the last frame
368: * we have acknowledged. If the IFRAME is completely correct then
369: * it is queued for the packet level.
370: */
371:
372: if (ns != (hdp -> hd_lasttxnr + hdp -> hd_xcp -> xc_lwsize) % MODULUS) {
373: hdp -> hd_vr = (hdp -> hd_vr + 1) % MODULUS;
374: if (pf == 1) {
375: /* Must generate a RR or RNR with final bit on. */
376: hd_writeinternal (hdp, RR, POLLON);
377: } else
378: /*
379: * Hopefully we can piggyback the RR, if not we will generate
380: * a RR when T3 timer expires.
381: */
382: if (hdp -> hd_rrtimer == 0)
383: hdp->hd_rrtimer = hd_t3;
384:
385: /* Forward iframe to packet level of X.25. */
386: fbuf -> m_data += HDHEADERLN;
387: fbuf -> m_len -= HDHEADERLN;
388: fbuf -> m_pkthdr.len -= HDHEADERLN;
389: fbuf -> m_pkthdr.rcvif = (struct ifnet *)hdp -> hd_pkp;
390: #ifdef BSD4_3
391: fbuf->m_act = 0; /* probably not necessary */
392: #else
393: {
394: register struct mbuf *m;
395:
396: for (m = fbuf; m -> m_next; m = m -> m_next)
397: m -> m_act = (struct mbuf *) 0;
398: m -> m_act = (struct mbuf *) 1;
399: }
400: #endif
401: pk_input (fbuf);
402: queued = TRUE;
403: hd_start (hdp);
404: } else {
405: /*
406: * Here if the remote station has transmitted more iframes then
407: * the number which have been acknowledged plus K.
408: */
409: hdp->hd_invalid_ns++;
410: frame_reject (hdp, W, frame);
411: }
412: return (queued);
413: }
414:
415: /*
416: * This routine is used to determine if a value (the middle parameter)
417: * is between two other values. The low value is the first parameter
418: * the high value is the last parameter. The routine checks the middle
419: * value to see if it is within the range of the first and last values.
420: * The reason we need this routine is the values are modulo some base
421: * hence a simple test for greater or less than is not sufficient.
422: */
423:
424: bool
425: range_check (rear, value, front)
426: int rear,
427: value,
428: front;
429: {
430: register bool result = FALSE;
431:
432: if (front > rear)
433: result = (rear <= value) && (value <= front);
434: else
435: result = (rear <= value) || (value <= front);
436:
437: return (result);
438: }
439:
440: /*
441: * This routine handles all the frame reject conditions which can
442: * arise as a result of secondary processing. The frame reject
443: * condition Y (frame length error) are handled elsewhere.
444: */
445:
446: static
447: frame_reject (hdp, rejectcode, frame)
448: struct hdcb *hdp;
449: struct Hdlc_iframe *frame;
450: {
451: register struct Frmr_frame *frmr = &hd_frmr;
452:
1.1.1.2 ! root 453:
1.1 root 454: frmr -> frmr_control = ((struct Hdlc_frame *) frame) -> control;
455:
456: frmr -> frmr_ns = frame -> ns;
457: frmr -> frmr_f1_0 = 0;
458: frmr -> frmr_nr = frame -> nr;
459: frmr -> frmr_f2_0 = 0;
460:
461: frmr -> frmr_0000 = 0;
462: frmr -> frmr_w = frmr -> frmr_x = frmr -> frmr_y =
463: frmr -> frmr_z = 0;
464: switch (rejectcode) {
465: case Z:
466: frmr -> frmr_z = 1;/* invalid N(R). */
467: break;
468:
469: case Y:
470: frmr -> frmr_y = 1;/* iframe length error. */
471: break;
472:
473: case X:
474: frmr -> frmr_x = 1;/* invalid information field. */
475: frmr -> frmr_w = 1;
476: break;
477:
478: case W:
479: frmr -> frmr_w = 1;/* invalid N(S). */
480: }
481:
482: hd_writeinternal (hdp, FRMR, POLLOFF);
483:
484: hdp->hd_state = WAIT_SABM;
485: SET_TIMER (hdp);
486: }
487:
488: /*
489: * This procedure is invoked when ever we receive a supervisor
490: * frame such as RR, RNR and REJ. All processing for these
491: * frames is done here.
492: */
493:
494: process_sframe (hdp, frame, frametype)
495: register struct hdcb *hdp;
496: register struct Hdlc_sframe *frame;
497: int frametype;
498: {
499: register int nr = frame -> nr, pf = frame -> pf, pollbit = 0;
1.1.1.2 ! root 500: int rej_routine();
1.1 root 501:
502: if (valid_nr (hdp, nr, pf) == TRUE) {
503: switch (frametype) {
504: case RR:
505: hdp->hd_condition &= ~REMOTE_RNR_CONDITION;
506: break;
507:
508: case RNR:
509: hdp->hd_condition |= REMOTE_RNR_CONDITION;
510: hdp->hd_retxcnt = 0;
511: break;
512:
513: case REJ:
514: hdp->hd_condition &= ~REMOTE_RNR_CONDITION;
515: rej_routine (hdp, nr);
516: }
517:
518: if (pf == 1) {
519: hdp->hd_retxcnt = 0;
520: hdp->hd_condition &= ~TIMER_RECOVERY_CONDITION;
521:
522: if (frametype == RR && hdp->hd_lastrxnr == hdp->hd_vs
523: && hdp->hd_timer == 0 && hdp->hd_txq.head == 0)
524: hd_writeinternal(hdp, RR, pf);
525: else
526: /* If any iframes have been queued because of the
527: timer condition, transmit then now. */
528: if (hdp->hd_condition & REMOTE_RNR_CONDITION) {
529: /* Remote is busy or timer condition, so only
530: send one. */
531: if (hdp->hd_vs != hdp->hd_retxqi)
532: hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], pollbit);
533: }
534: else /* Flush the retransmit list first. */
535: while (hdp->hd_vs != hdp->hd_retxqi)
536: hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF);
537: }
538:
539: hd_start (hdp);
540: } else
541: frame_reject (hdp, Z, (struct Hdlc_iframe *)frame); /* Invalid N(R). */
542: }
543:
544: /*
545: * This routine tests the validity of the N(R) which we have received.
546: * If it is ok, then all the iframes which it acknowledges (if any)
547: * will be freed.
548: */
549:
550: bool
551: valid_nr (hdp, nr, finalbit)
552: register struct hdcb *hdp;
553: register int finalbit;
554: {
1.1.1.2 ! root 555: int free_iframes();
! 556:
1.1 root 557: /* Make sure it really does acknowledge something. */
558: if (hdp->hd_lastrxnr == nr)
559: return (TRUE);
560:
561: /*
562: * This section validates the frame's N(R) value. It's N(R) value
563: * must be in syncronization with our V(S) value and our "last
564: * received nr" variable. If it is correct then we are able to send
565: * more IFRAME's, else frame reject condition is entered.
566: */
567:
568: if (range_check (hdp->hd_lastrxnr, nr, hdp->hd_vs) == FALSE) {
569: if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) &&
570: range_check (hdp->hd_vs, nr, hdp->hd_xx) == TRUE)
571: hdp->hd_vs = nr;
572:
573: else {
574: hdp->hd_invalid_nr++;
575: return (FALSE);
576: }
577: }
578:
579: /*
580: * If we get to here, we do have a valid frame but it might be out
581: * of sequence. However, we should still accept the receive state
582: * number N(R) since it has already passed our previous test and it
583: * does acknowledge frames which we are sending.
584: */
585:
586: KILL_TIMER (hdp);
587: free_iframes (hdp, &nr, finalbit);/* Free all acknowledged iframes */
588: if (nr != hdp->hd_vs)
589: SET_TIMER (hdp);
590:
591: return (TRUE);
592: }
593:
594: /*
595: * This routine determines how many iframes need to be retransmitted.
596: * It then resets the Send State Variable V(S) to accomplish this.
597: */
598:
599: static
600: rej_routine (hdp, rejnr)
601: register struct hdcb *hdp;
602: register int rejnr;
603: {
604: register int anchor;
605:
606: /*
607: * Flush the output queue. Any iframes queued for
608: * transmission will be out of sequence.
609: */
610:
611: hd_flush (hdp->hd_ifp);
612:
613: /*
614: * Determine how many frames should be re-transmitted. In the case
615: * of a normal REJ this should be 1 to K. In the case of a timer
616: * recovery REJ (ie. a REJ with the Final Bit on) this could be 0.
617: */
618:
619: anchor = hdp->hd_vs;
620: if (hdp->hd_condition & TIMER_RECOVERY_CONDITION)
621: anchor = hdp->hd_xx;
622:
623: anchor = (anchor - rejnr + 8) % MODULUS;
624:
625: if (anchor > 0) {
626:
627: /* There is at least one iframe to retransmit. */
628: KILL_TIMER (hdp);
629: hdp->hd_vs = rejnr;
630:
631: while (hdp->hd_vs != hdp->hd_retxqi)
632: hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF);
633:
634: }
635: hd_start (hdp);
636: }
637:
638: /*
639: * This routine frees iframes from the retransmit queue. It is called
640: * when a previously written iframe is acknowledged.
641: */
642:
643: static
644: free_iframes (hdp, nr, finalbit)
645: register struct hdcb *hdp;
646: int *nr;
647: register int finalbit;
648:
649: {
650: register int i, k;
651:
652: /*
653: * We need to do the following because of a funny quirk in the
654: * protocol. This case occures when in Timer recovery condition
655: * we get a N(R) which acknowledges all the outstanding iframes
656: * but with the Final Bit off. In this case we need to save the last
657: * iframe for possible retransmission even though it has already been
658: * acknowledged!
659: */
660:
661: if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && *nr == hdp->hd_xx && finalbit == 0) {
662: *nr = (*nr - 1 + 8) % MODULUS;
663: /* printf ("QUIRK\n"); */
664: }
665:
666: k = (*nr - hdp->hd_lastrxnr + 8) % MODULUS;
667:
668: /* Loop here freeing all acknowledged iframes. */
669: for (i = 0; i < k; ++i) {
670: m_freem (hdp->hd_retxq[hdp->hd_lastrxnr]);
671: hdp->hd_retxq[hdp->hd_lastrxnr] = 0;
672: hdp->hd_lastrxnr = (hdp->hd_lastrxnr + 1) % MODULUS;
673: }
674:
675: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.