141703Ssklower /* 241703Ssklower * Copyright (c) University of British Columbia, 1984 341703Ssklower * Copyright (c) 1990 The Regents of the University of California. 441703Ssklower * All rights reserved. 541703Ssklower * 641703Ssklower * This code is derived from software contributed to Berkeley by 741703Ssklower * the Laboratory for Computation Vision and the Computer Science Department 841703Ssklower * of the University of British Columbia. 941703Ssklower * 1041703Ssklower * %sccs.include.redist.c% 1141703Ssklower * 12*45296Ssklower * @(#)hd_input.c 7.5 (Berkeley) 10/04/90 1341703Ssklower */ 1441586Ssklower 1545165Ssklower #include "param.h" 1645165Ssklower #include "systm.h" 1745165Ssklower #include "mbuf.h" 1845165Ssklower #include "domain.h" 1945165Ssklower #include "socket.h" 2045165Ssklower #include "protosw.h" 2145165Ssklower #include "errno.h" 2245165Ssklower #include "time.h" 2345165Ssklower #include "kernel.h" 2441586Ssklower 2541586Ssklower #include "../net/if.h" 2641586Ssklower 2745165Ssklower #include "hdlc.h" 2845165Ssklower #include "hd_var.h" 2945165Ssklower #include "x25.h" 3041586Ssklower 3141586Ssklower /* 3241586Ssklower * HDLC INPUT INTERFACE 3341586Ssklower * 3441586Ssklower * This routine is called when the HDLC physical device has 3541586Ssklower * completed reading a frame. 3641586Ssklower */ 3741586Ssklower 3841586Ssklower hdintr () 3941586Ssklower { 4041586Ssklower register struct mbuf *m; 4141586Ssklower register struct hdcb *hdp; 4241586Ssklower register struct ifnet *ifp; 4341586Ssklower register int s; 44*45296Ssklower extern struct ifqueue pkintrq; 4541586Ssklower static struct ifnet *lastifp; 4641586Ssklower static struct hdcb *lasthdp; 4741586Ssklower 4841586Ssklower for (;;) { 4941586Ssklower s = splimp (); 50*45296Ssklower IF_DEQUEUE (&hdintrq, m); 5141586Ssklower splx (s); 5241586Ssklower if (m == 0) 5341586Ssklower break; 5441586Ssklower if (m->m_len < HDHEADERLN) { 5541586Ssklower printf ("hdintr: packet too short (len=%d)\n", 5641586Ssklower m->m_len); 5741586Ssklower m_freem (m); 5841586Ssklower continue; 5941586Ssklower } 60*45296Ssklower if ((m->m_flags & M_PKTHDR) == 0) 61*45296Ssklower panic("hdintr"); 62*45296Ssklower ifp = m->m_pkthdr.rcvif; 6341586Ssklower 6441586Ssklower /* 6541586Ssklower * look up the appropriate hdlc control block 6641586Ssklower */ 6741586Ssklower 6841586Ssklower if (ifp == lastifp) 6941586Ssklower hdp = lasthdp; 7041586Ssklower else { 7141586Ssklower for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) 7241586Ssklower if (hdp->hd_ifp == ifp) 7341586Ssklower break; 7441586Ssklower if (hdp == 0) { 7541586Ssklower printf ("hdintr: unknown interface %x\n", ifp); 7641586Ssklower m_freem (m); 7741586Ssklower continue; 7841586Ssklower } 7941586Ssklower lastifp = ifp; 8041586Ssklower lasthdp = hdp; 8141586Ssklower } 8241586Ssklower 8341586Ssklower /* Process_rxframe returns FALSE if the frame was NOT queued 8441586Ssklower for the next higher layers. */ 8541586Ssklower if (process_rxframe (hdp, m) == FALSE) 8641586Ssklower m_freem (m); 8741586Ssklower } 88*45296Ssklower if (pkintrq.ifq_len) 89*45296Ssklower pkintr (); 9041586Ssklower } 9141586Ssklower 9241586Ssklower process_rxframe (hdp, fbuf) 9341586Ssklower register struct hdcb *hdp; 9441586Ssklower register struct mbuf *fbuf; 9541586Ssklower { 9641586Ssklower register int queued = FALSE, frametype, pf; 9741586Ssklower register struct Hdlc_frame *frame; 9841586Ssklower 9941586Ssklower frame = mtod (fbuf, struct Hdlc_frame *); 10041586Ssklower pf = ((struct Hdlc_iframe *) frame) -> pf; 10141586Ssklower 10241586Ssklower hd_trace (hdp, RX, frame); 10341586Ssklower if (frame -> address != ADDRESS_A && frame -> address != ADDRESS_B) 10441586Ssklower return (queued); 10541586Ssklower 10641586Ssklower switch ((frametype = hd_decode (hdp, frame)) + hdp->hd_state) { 10741586Ssklower case DM + DISC_SENT: 10841586Ssklower case UA + DISC_SENT: 10941586Ssklower /* 11041586Ssklower * Link now closed. Leave timer running 11141586Ssklower * so hd_timer() can periodically check the 11241586Ssklower * status of interface driver flag bit IFF_UP. 11341586Ssklower */ 11441586Ssklower hdp->hd_state = DISCONNECTED; 11541586Ssklower break; 11641586Ssklower 11741586Ssklower case DM + INIT: 11841586Ssklower case UA + INIT: 11941586Ssklower /* 12041586Ssklower * This is a non-standard state change needed for DCEs 12141586Ssklower * that do dynamic link selection. We can't go into the 12241586Ssklower * usual "SEND DM" state because a DM is a SARM in LAP. 12341586Ssklower */ 12441586Ssklower hd_writeinternal (hdp, SABM, POLLOFF); 12541586Ssklower hdp->hd_state = SABM_SENT; 12641586Ssklower SET_TIMER (hdp); 12741586Ssklower break; 12841586Ssklower 12941586Ssklower case SABM + DM_SENT: 13041586Ssklower case SABM + WAIT_SABM: 13141586Ssklower hd_writeinternal (hdp, UA, pf); 13241586Ssklower case UA + SABM_SENT: 13341586Ssklower case UA + WAIT_UA: 13441586Ssklower KILL_TIMER (hdp); 13541586Ssklower hd_initvars (hdp); 13641586Ssklower hdp->hd_state = ABM; 13741586Ssklower hd_message (hdp, "Link level operational"); 13841586Ssklower /* Notify the packet level - to send RESTART. */ 13941586Ssklower (void) pk_ctlinput (PRC_LINKUP, hdp->hd_xcp); 14041586Ssklower break; 14141586Ssklower 14241586Ssklower case SABM + SABM_SENT: 14341586Ssklower /* Got a SABM collision. Acknowledge the remote's SABM 14441586Ssklower via UA but still wait for UA. */ 14541586Ssklower hd_writeinternal (hdp, UA, pf); 14641586Ssklower break; 14741586Ssklower 14841586Ssklower case SABM + ABM: 14941586Ssklower /* Request to reset the link from the remote. */ 15041586Ssklower KILL_TIMER (hdp); 15141586Ssklower hd_message (hdp, "Link reset"); 15241586Ssklower #ifdef HDLCDEBUG 15341586Ssklower hd_dumptrace (hdp); 15441586Ssklower #endif 15541586Ssklower hd_flush (hdp->hd_ifp); 15641586Ssklower hd_writeinternal (hdp, UA, pf); 15741586Ssklower hd_initvars (hdp); 15841586Ssklower (void) pk_ctlinput (PRC_LINKRESET, hdp->hd_xcp); 15941586Ssklower hdp->hd_resets++; 16041586Ssklower break; 16141586Ssklower 16241586Ssklower case SABM + WAIT_UA: 16341586Ssklower hd_writeinternal (hdp, UA, pf); 16441586Ssklower break; 16541586Ssklower 16641586Ssklower case DM + ABM: 16741586Ssklower hd_message (hdp, "DM received: link down"); 16841586Ssklower #ifdef HDLCDEBUG 16941586Ssklower hd_dumptrace (hdp); 17041586Ssklower #endif 17141586Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_xcp); 17241586Ssklower hd_flush (hdp->hd_ifp); 17341586Ssklower case DM + DM_SENT: 17441586Ssklower case DM + WAIT_SABM: 17541586Ssklower case DM + WAIT_UA: 17641586Ssklower hd_writeinternal (hdp, SABM, pf); 17741586Ssklower hdp->hd_state = SABM_SENT; 17841586Ssklower SET_TIMER (hdp); 17941586Ssklower break; 18041586Ssklower 18141586Ssklower case DISC + INIT: 18241586Ssklower case DISC + DM_SENT: 18341586Ssklower case DISC + SABM_SENT: 18441586Ssklower /* Note: This is a non-standard state change. */ 18541586Ssklower hd_writeinternal (hdp, UA, pf); 18641586Ssklower hd_writeinternal (hdp, SABM, POLLOFF); 18741586Ssklower hdp->hd_state = SABM_SENT; 18841586Ssklower SET_TIMER (hdp); 18941586Ssklower break; 19041586Ssklower 19141586Ssklower case DISC + WAIT_UA: 19241586Ssklower hd_writeinternal (hdp, DM, pf); 19341586Ssklower SET_TIMER (hdp); 19441586Ssklower hdp->hd_state = DM_SENT; 19541586Ssklower break; 19641586Ssklower 19741586Ssklower case DISC + ABM: 19841586Ssklower hd_message (hdp, "DISC received: link down"); 19941586Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_xcp); 20041586Ssklower case DISC + WAIT_SABM: 20141586Ssklower hd_writeinternal (hdp, UA, pf); 20241586Ssklower hdp->hd_state = DM_SENT; 20341586Ssklower SET_TIMER (hdp); 20441586Ssklower break; 20541586Ssklower 20641586Ssklower case UA + ABM: 20741586Ssklower hd_message (hdp, "UA received: link down"); 20841586Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_xcp); 20941586Ssklower case UA + WAIT_SABM: 21041586Ssklower hd_writeinternal (hdp, DM, pf); 21141586Ssklower hdp->hd_state = DM_SENT; 21241586Ssklower SET_TIMER (hdp); 21341586Ssklower break; 21441586Ssklower 21541586Ssklower case FRMR + DM_SENT: 21641586Ssklower hd_writeinternal (hdp, SABM, pf); 21741586Ssklower hdp->hd_state = SABM_SENT; 21841586Ssklower SET_TIMER (hdp); 21941586Ssklower break; 22041586Ssklower 22141586Ssklower case FRMR + WAIT_SABM: 22241586Ssklower hd_writeinternal (hdp, DM, pf); 22341586Ssklower hdp->hd_state = DM_SENT; 22441586Ssklower SET_TIMER (hdp); 22541586Ssklower break; 22641586Ssklower 22741586Ssklower case FRMR + ABM: 22841586Ssklower hd_message (hdp, "FRMR received: link down"); 22941586Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_xcp); 23041586Ssklower #ifdef HDLCDEBUG 23141586Ssklower hd_dumptrace (hdp); 23241586Ssklower #endif 23341586Ssklower hd_flush (hdp->hd_ifp); 23441586Ssklower hd_writeinternal (hdp, SABM, pf); 23541586Ssklower hdp->hd_state = WAIT_UA; 23641586Ssklower SET_TIMER (hdp); 23741586Ssklower break; 23841586Ssklower 23941586Ssklower case RR + ABM: 24041586Ssklower case RNR + ABM: 24141586Ssklower case REJ + ABM: 24241586Ssklower process_sframe (hdp, (struct Hdlc_sframe *)frame, frametype); 24341586Ssklower break; 24441586Ssklower 24541586Ssklower case IFRAME + ABM: 24641586Ssklower queued = process_iframe (hdp, fbuf, (struct Hdlc_iframe *)frame); 24741586Ssklower break; 24841586Ssklower 24941586Ssklower case IFRAME + SABM_SENT: 25041586Ssklower case RR + SABM_SENT: 25141586Ssklower case RNR + SABM_SENT: 25241586Ssklower case REJ + SABM_SENT: 25341586Ssklower hd_writeinternal (hdp, DM, POLLON); 25441586Ssklower hdp->hd_state = DM_SENT; 25541586Ssklower SET_TIMER (hdp); 25641586Ssklower break; 25741586Ssklower 25841586Ssklower case IFRAME + WAIT_SABM: 25941586Ssklower case RR + WAIT_SABM: 26041586Ssklower case RNR + WAIT_SABM: 26141586Ssklower case REJ + WAIT_SABM: 26241586Ssklower hd_writeinternal (hdp, FRMR, POLLOFF); 26341586Ssklower SET_TIMER (hdp); 26441586Ssklower break; 26541586Ssklower 26641586Ssklower case ILLEGAL + SABM_SENT: 26741586Ssklower hdp->hd_unknown++; 26841586Ssklower hd_writeinternal (hdp, DM, POLLOFF); 26941586Ssklower hdp->hd_state = DM_SENT; 27041586Ssklower SET_TIMER (hdp); 27141586Ssklower break; 27241586Ssklower 27341586Ssklower case ILLEGAL + ABM: 27441586Ssklower hd_message (hdp, "Unknown frame received: link down"); 27541586Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_xcp); 27641586Ssklower case ILLEGAL + WAIT_SABM: 27741586Ssklower hdp->hd_unknown++; 27841586Ssklower #ifdef HDLCDEBUG 27941586Ssklower hd_dumptrace (hdp); 28041586Ssklower #endif 28141586Ssklower hd_writeinternal (hdp, FRMR, POLLOFF); 28241586Ssklower hdp->hd_state = WAIT_SABM; 28341586Ssklower SET_TIMER (hdp); 28441586Ssklower break; 28541586Ssklower } 28641586Ssklower 28741586Ssklower return (queued); 28841586Ssklower } 28941586Ssklower 29041586Ssklower process_iframe (hdp, fbuf, frame) 29141586Ssklower register struct hdcb *hdp; 29241586Ssklower struct mbuf *fbuf; 29341586Ssklower register struct Hdlc_iframe *frame; 29441586Ssklower { 29541586Ssklower register int nr = frame -> nr, 29641586Ssklower ns = frame -> ns, 29741586Ssklower pf = frame -> pf; 29841586Ssklower register int queued = FALSE; 29941586Ssklower 30041586Ssklower /* 30141586Ssklower * Validate the iframe's N(R) value. It's N(R) value must be in 30241586Ssklower * sync with our V(S) value and our "last received nr". 30341586Ssklower */ 30441586Ssklower 30541586Ssklower if (valid_nr (hdp, nr, FALSE) == FALSE) { 30641586Ssklower frame_reject (hdp, Z, frame); 30741586Ssklower return (queued); 30841586Ssklower } 30941586Ssklower 31041586Ssklower 31141586Ssklower /* 31241586Ssklower * This section tests the IFRAME for proper sequence. That is, it's 31341586Ssklower * sequence number N(S) MUST be equal to V(S). 31441586Ssklower */ 31541586Ssklower 31641586Ssklower if (ns != hdp->hd_vr) { 31741586Ssklower hdp->hd_invalid_ns++; 31841586Ssklower if (pf || (hdp->hd_condition & REJ_CONDITION) == 0) { 31941586Ssklower hdp->hd_condition |= REJ_CONDITION; 32041586Ssklower /* 32141586Ssklower * Flush the transmit queue. This is ugly but we 32241586Ssklower * have no choice. A reject response must be 32341586Ssklower * immediately sent to the DCE. Failure to do so 32441586Ssklower * may result in another out of sequence iframe 32541586Ssklower * arriving (and thus sending another reject) 32641586Ssklower * before the first reject is transmitted. This 32741586Ssklower * will cause the DCE to receive two or more 32841586Ssklower * rejects back to back, which must never happen. 32941586Ssklower */ 33041586Ssklower hd_flush (hdp->hd_ifp); 33141586Ssklower hd_writeinternal (hdp, REJ, pf); 33241586Ssklower } 33341586Ssklower return (queued); 33441586Ssklower } 33541586Ssklower hdp->hd_condition &= ~REJ_CONDITION; 33641586Ssklower 33741586Ssklower /* 33841586Ssklower * This section finally tests the IFRAME's sequence number against 33941586Ssklower * the window size (K) and the sequence number of the last frame 34041586Ssklower * we have acknowledged. If the IFRAME is completely correct then 34141586Ssklower * it is queued for the packet level. 34241586Ssklower */ 34341586Ssklower 34441586Ssklower if (ns != (hdp->hd_lasttxnr + hdp->hd_xcp->xc_lwsize) % MODULUS) { 34541586Ssklower hdp->hd_vr = (hdp->hd_vr + 1) % MODULUS; 34641586Ssklower if (pf == 1) { 34741586Ssklower /* Must generate a RR or RNR with final bit on. */ 34841586Ssklower hd_writeinternal (hdp, RR, POLLON); 34941586Ssklower } else 35041586Ssklower /* 35141586Ssklower * Hopefully we can piggyback the RR, if not we will generate 35241586Ssklower * a RR when T3 timer expires. 35341586Ssklower */ 35441586Ssklower if (hdp -> hd_rrtimer == 0) 35541586Ssklower hdp->hd_rrtimer = hd_t3; 35641586Ssklower 35741586Ssklower /* Forward iframe to packet level of X.25. */ 35843361Ssklower fbuf -> m_data += HDHEADERLN; 35941586Ssklower fbuf -> m_len -= HDHEADERLN; 36041586Ssklower #ifdef BSD4_3 36141586Ssklower fbuf->m_act = 0; /* probably not necessary */ 36241586Ssklower #else 36341586Ssklower { 36441586Ssklower register struct mbuf *m; 36541586Ssklower 36641586Ssklower for (m = fbuf; m -> m_next; m = m -> m_next) 36741586Ssklower m -> m_act = (struct mbuf *) 0; 36841586Ssklower m -> m_act = (struct mbuf *) 1; 36941586Ssklower } 37041586Ssklower #endif 37141586Ssklower pk_input (fbuf, hdp->hd_xcp); 37241586Ssklower queued = TRUE; 37341586Ssklower hd_start (hdp); 37441586Ssklower } else { 37541586Ssklower /* 37641586Ssklower * Here if the remote station has transmitted more iframes then 37741586Ssklower * the number which have been acknowledged plus K. 37841586Ssklower */ 37941586Ssklower hdp->hd_invalid_ns++; 38041586Ssklower frame_reject (hdp, W, frame); 38141586Ssklower } 38241586Ssklower return (queued); 38341586Ssklower } 38441586Ssklower 38541586Ssklower /* 38641586Ssklower * This routine is used to determine if a value (the middle parameter) 38741586Ssklower * is between two other values. The low value is the first parameter 38841586Ssklower * the high value is the last parameter. The routine checks the middle 38941586Ssklower * value to see if it is within the range of the first and last values. 39041586Ssklower * The reason we need this routine is the values are modulo some base 39141586Ssklower * hence a simple test for greater or less than is not sufficient. 39241586Ssklower */ 39341586Ssklower 39441586Ssklower bool 39541586Ssklower range_check (rear, value, front) 39641586Ssklower int rear, 39741586Ssklower value, 39841586Ssklower front; 39941586Ssklower { 40041586Ssklower register bool result = FALSE; 40141586Ssklower 40241586Ssklower if (front > rear) 40341586Ssklower result = (rear <= value) && (value <= front); 40441586Ssklower else 40541586Ssklower result = (rear <= value) || (value <= front); 40641586Ssklower 40741586Ssklower return (result); 40841586Ssklower } 40941586Ssklower 41041586Ssklower /* 41141586Ssklower * This routine handles all the frame reject conditions which can 41241586Ssklower * arise as a result of secondary processing. The frame reject 41341586Ssklower * condition Y (frame length error) are handled elsewhere. 41441586Ssklower */ 41541586Ssklower 41641586Ssklower static 41741586Ssklower frame_reject (hdp, rejectcode, frame) 41841586Ssklower struct hdcb *hdp; 41941586Ssklower struct Hdlc_iframe *frame; 42041586Ssklower { 42141586Ssklower register struct Frmr_frame *frmr = &hd_frmr; 42241586Ssklower 42341586Ssklower frmr -> frmr_control = ((struct Hdlc_frame *) frame) -> control; 42441586Ssklower 42541586Ssklower frmr -> frmr_ns = frame -> ns; 42641586Ssklower frmr -> frmr_f1_0 = 0; 42741586Ssklower frmr -> frmr_nr = frame -> nr; 42841586Ssklower frmr -> frmr_f2_0 = 0; 42941586Ssklower 43041586Ssklower frmr -> frmr_0000 = 0; 43141586Ssklower frmr -> frmr_w = frmr -> frmr_x = frmr -> frmr_y = 43241586Ssklower frmr -> frmr_z = 0; 43341586Ssklower switch (rejectcode) { 43441586Ssklower case Z: 43541586Ssklower frmr -> frmr_z = 1;/* invalid N(R). */ 43641586Ssklower break; 43741586Ssklower 43841586Ssklower case Y: 43941586Ssklower frmr -> frmr_y = 1;/* iframe length error. */ 44041586Ssklower break; 44141586Ssklower 44241586Ssklower case X: 44341586Ssklower frmr -> frmr_x = 1;/* invalid information field. */ 44441586Ssklower frmr -> frmr_w = 1; 44541586Ssklower break; 44641586Ssklower 44741586Ssklower case W: 44841586Ssklower frmr -> frmr_w = 1;/* invalid N(S). */ 44941586Ssklower } 45041586Ssklower 45141586Ssklower hd_writeinternal (hdp, FRMR, POLLOFF); 45241586Ssklower 45341586Ssklower hdp->hd_state = WAIT_SABM; 45441586Ssklower SET_TIMER (hdp); 45541586Ssklower } 45641586Ssklower 45741586Ssklower /* 45841586Ssklower * This procedure is invoked when ever we receive a supervisor 45941586Ssklower * frame such as RR, RNR and REJ. All processing for these 46041586Ssklower * frames is done here. 46141586Ssklower */ 46241586Ssklower 46341586Ssklower process_sframe (hdp, frame, frametype) 46441586Ssklower register struct hdcb *hdp; 46541586Ssklower register struct Hdlc_sframe *frame; 46641586Ssklower int frametype; 46741586Ssklower { 46841586Ssklower register int nr = frame -> nr, pf = frame -> pf, pollbit = 0; 46941586Ssklower 47041586Ssklower if (valid_nr (hdp, nr, pf) == TRUE) { 47141586Ssklower switch (frametype) { 47241586Ssklower case RR: 47341586Ssklower hdp->hd_condition &= ~REMOTE_RNR_CONDITION; 47441586Ssklower break; 47541586Ssklower 47641586Ssklower case RNR: 47741586Ssklower hdp->hd_condition |= REMOTE_RNR_CONDITION; 47841586Ssklower hdp->hd_retxcnt = 0; 47941586Ssklower break; 48041586Ssklower 48141586Ssklower case REJ: 48241586Ssklower hdp->hd_condition &= ~REMOTE_RNR_CONDITION; 48341586Ssklower rej_routine (hdp, nr); 48441586Ssklower } 48541586Ssklower 48641586Ssklower if (pf == 1) { 48741586Ssklower hdp->hd_retxcnt = 0; 48841586Ssklower hdp->hd_condition &= ~TIMER_RECOVERY_CONDITION; 48941586Ssklower 490*45296Ssklower if (frametype == RR && hdp->hd_lastrxnr == hdp->hd_vs 491*45296Ssklower && hdp->hd_timer == 0 && hdp->hd_txq.head == 0) 492*45296Ssklower hd_writeinternal(hdp, RR, pf); 493*45296Ssklower else 49441586Ssklower /* If any iframes have been queued because of the 49541586Ssklower timer condition, transmit then now. */ 49641586Ssklower if (hdp->hd_condition & REMOTE_RNR_CONDITION) { 49741586Ssklower /* Remote is busy or timer condition, so only 49841586Ssklower send one. */ 49941586Ssklower if (hdp->hd_vs != hdp->hd_retxqi) 50041586Ssklower hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], pollbit); 50141586Ssklower } 50241586Ssklower else /* Flush the retransmit list first. */ 50341586Ssklower while (hdp->hd_vs != hdp->hd_retxqi) 50441586Ssklower hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF); 50541586Ssklower } 50641586Ssklower 50741586Ssklower hd_start (hdp); 50841586Ssklower } else 50941586Ssklower frame_reject (hdp, Z, (struct Hdlc_iframe *)frame); /* Invalid N(R). */ 51041586Ssklower } 51141586Ssklower 51241586Ssklower /* 51341586Ssklower * This routine tests the validity of the N(R) which we have received. 51441586Ssklower * If it is ok, then all the iframes which it acknowledges (if any) 51541586Ssklower * will be freed. 51641586Ssklower */ 51741586Ssklower 51841586Ssklower bool 51941586Ssklower valid_nr (hdp, nr, finalbit) 52041586Ssklower register struct hdcb *hdp; 52141586Ssklower register int finalbit; 52241586Ssklower { 52341586Ssklower /* Make sure it really does acknowledge something. */ 52441586Ssklower if (hdp->hd_lastrxnr == nr) 52541586Ssklower return (TRUE); 52641586Ssklower 52741586Ssklower /* 52841586Ssklower * This section validates the frame's N(R) value. It's N(R) value 52941586Ssklower * must be in syncronization with our V(S) value and our "last 53041586Ssklower * received nr" variable. If it is correct then we are able to send 53141586Ssklower * more IFRAME's, else frame reject condition is entered. 53241586Ssklower */ 53341586Ssklower 53441586Ssklower if (range_check (hdp->hd_lastrxnr, nr, hdp->hd_vs) == FALSE) { 53541586Ssklower if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && 53641586Ssklower range_check (hdp->hd_vs, nr, hdp->hd_xx) == TRUE) 53741586Ssklower hdp->hd_vs = nr; 53841586Ssklower 53941586Ssklower else { 54041586Ssklower hdp->hd_invalid_nr++; 54141586Ssklower return (FALSE); 54241586Ssklower } 54341586Ssklower } 54441586Ssklower 54541586Ssklower /* 54641586Ssklower * If we get to here, we do have a valid frame but it might be out 54741586Ssklower * of sequence. However, we should still accept the receive state 54841586Ssklower * number N(R) since it has already passed our previous test and it 54941586Ssklower * does acknowledge frames which we are sending. 55041586Ssklower */ 55141586Ssklower 55241586Ssklower KILL_TIMER (hdp); 55341586Ssklower free_iframes (hdp, &nr, finalbit);/* Free all acknowledged iframes */ 55441586Ssklower if (nr != hdp->hd_vs) 55541586Ssklower SET_TIMER (hdp); 55641586Ssklower 55741586Ssklower return (TRUE); 55841586Ssklower } 55941586Ssklower 56041586Ssklower /* 56141586Ssklower * This routine determines how many iframes need to be retransmitted. 56241586Ssklower * It then resets the Send State Variable V(S) to accomplish this. 56341586Ssklower */ 56441586Ssklower 56541586Ssklower static 56641586Ssklower rej_routine (hdp, rejnr) 56741586Ssklower register struct hdcb *hdp; 56841586Ssklower register int rejnr; 56941586Ssklower { 57041586Ssklower register int anchor; 57141586Ssklower 57241586Ssklower /* 57341586Ssklower * Flush the output queue. Any iframes queued for 57441586Ssklower * transmission will be out of sequence. 57541586Ssklower */ 57641586Ssklower 57741586Ssklower hd_flush (hdp->hd_ifp); 57841586Ssklower 57941586Ssklower /* 58041586Ssklower * Determine how many frames should be re-transmitted. In the case 58141586Ssklower * of a normal REJ this should be 1 to K. In the case of a timer 58241586Ssklower * recovery REJ (ie. a REJ with the Final Bit on) this could be 0. 58341586Ssklower */ 58441586Ssklower 58541586Ssklower anchor = hdp->hd_vs; 58641586Ssklower if (hdp->hd_condition & TIMER_RECOVERY_CONDITION) 58741586Ssklower anchor = hdp->hd_xx; 58841586Ssklower 58941586Ssklower anchor = (anchor - rejnr + 8) % MODULUS; 59041586Ssklower 59141586Ssklower if (anchor > 0) { 59241586Ssklower 59341586Ssklower /* There is at least one iframe to retransmit. */ 59441586Ssklower KILL_TIMER (hdp); 59541586Ssklower hdp->hd_vs = rejnr; 59641586Ssklower 59741586Ssklower while (hdp->hd_vs != hdp->hd_retxqi) 59841586Ssklower hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF); 59941586Ssklower 60041586Ssklower } 60141586Ssklower hd_start (hdp); 60241586Ssklower } 60341586Ssklower 60441586Ssklower /* 60541586Ssklower * This routine frees iframes from the retransmit queue. It is called 60641586Ssklower * when a previously written iframe is acknowledged. 60741586Ssklower */ 60841586Ssklower 60941586Ssklower static 61041586Ssklower free_iframes (hdp, nr, finalbit) 61141586Ssklower register struct hdcb *hdp; 61241586Ssklower int *nr; 61341586Ssklower register int finalbit; 61441586Ssklower 61541586Ssklower { 61641586Ssklower register int i, k; 61741586Ssklower 61841586Ssklower /* 61941586Ssklower * We need to do the following because of a funny quirk in the 62041586Ssklower * protocol. This case occures when in Timer recovery condition 62141586Ssklower * we get a N(R) which acknowledges all the outstanding iframes 62241586Ssklower * but with the Final Bit off. In this case we need to save the last 62341586Ssklower * iframe for possible retransmission even though it has already been 62441586Ssklower * acknowledged! 62541586Ssklower */ 62641586Ssklower 62741586Ssklower if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && *nr == hdp->hd_xx && finalbit == 0) { 62841586Ssklower *nr = (*nr - 1 + 8) % MODULUS; 62941586Ssklower /* printf ("QUIRK\n"); */ 63041586Ssklower } 63141586Ssklower 63241586Ssklower k = (*nr - hdp->hd_lastrxnr + 8) % MODULUS; 63341586Ssklower 63441586Ssklower /* Loop here freeing all acknowledged iframes. */ 63541586Ssklower for (i = 0; i < k; ++i) { 63641586Ssklower m_freem (hdp->hd_retxq[hdp->hd_lastrxnr]); 63741586Ssklower hdp->hd_retxq[hdp->hd_lastrxnr] = 0; 63841586Ssklower hdp->hd_lastrxnr = (hdp->hd_lastrxnr + 1) % MODULUS; 63941586Ssklower } 64041586Ssklower 64141586Ssklower } 642