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