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