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