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*57018Ssklower * @(#)hd_input.c 7.9 (Berkeley) 12/08/92 1341703Ssklower */ 1441586Ssklower 1556530Sbostic #include <sys/param.h> 1656530Sbostic #include <sys/systm.h> 1756530Sbostic #include <sys/mbuf.h> 1856530Sbostic #include <sys/domain.h> 1956530Sbostic #include <sys/socket.h> 2056530Sbostic #include <sys/protosw.h> 2156530Sbostic #include <sys/errno.h> 2256530Sbostic #include <sys/time.h> 2356530Sbostic #include <sys/kernel.h> 2441586Ssklower 2556530Sbostic #include <net/if.h> 2641586Ssklower 2756530Sbostic #include <netccitt/hdlc.h> 2856530Sbostic #include <netccitt/hd_var.h> 2956530Sbostic #include <netccitt/x25.h> 3041586Ssklower 31*57018Ssklower static frame_reject(); 32*57018Ssklower static rej_routine(); 33*57018Ssklower static free_iframes(); 3441586Ssklower /* 3541586Ssklower * HDLC INPUT INTERFACE 3641586Ssklower * 3741586Ssklower * This routine is called when the HDLC physical device has 3841586Ssklower * completed reading a frame. 3941586Ssklower */ 4041586Ssklower 4141586Ssklower hdintr () 4241586Ssklower { 4341586Ssklower register struct mbuf *m; 4441586Ssklower register struct hdcb *hdp; 4541586Ssklower register struct ifnet *ifp; 4641586Ssklower register int s; 4741586Ssklower static struct ifnet *lastifp; 4841586Ssklower static struct hdcb *lasthdp; 4941586Ssklower 5041586Ssklower for (;;) { 5141586Ssklower s = splimp (); 5245296Ssklower IF_DEQUEUE (&hdintrq, m); 5341586Ssklower splx (s); 5441586Ssklower if (m == 0) 5541586Ssklower break; 5641586Ssklower if (m->m_len < HDHEADERLN) { 5741586Ssklower printf ("hdintr: packet too short (len=%d)\n", 5841586Ssklower m->m_len); 5941586Ssklower m_freem (m); 6041586Ssklower continue; 6141586Ssklower } 6245296Ssklower if ((m->m_flags & M_PKTHDR) == 0) 6345296Ssklower panic("hdintr"); 6445296Ssklower ifp = m->m_pkthdr.rcvif; 6541586Ssklower 6641586Ssklower /* 6741586Ssklower * look up the appropriate hdlc control block 6841586Ssklower */ 6941586Ssklower 7041586Ssklower if (ifp == lastifp) 7141586Ssklower hdp = lasthdp; 7241586Ssklower else { 7341586Ssklower for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) 7441586Ssklower if (hdp->hd_ifp == ifp) 7541586Ssklower break; 7641586Ssklower if (hdp == 0) { 7741586Ssklower printf ("hdintr: unknown interface %x\n", ifp); 7841586Ssklower m_freem (m); 7941586Ssklower continue; 8041586Ssklower } 8141586Ssklower lastifp = ifp; 8241586Ssklower lasthdp = hdp; 8341586Ssklower } 8441586Ssklower 8541586Ssklower /* Process_rxframe returns FALSE if the frame was NOT queued 8641586Ssklower for the next higher layers. */ 8741586Ssklower if (process_rxframe (hdp, m) == FALSE) 8841586Ssklower m_freem (m); 8941586Ssklower } 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. */ 13949927Ssklower (void) pk_ctlinput (PRC_LINKUP, hdp->hd_pkp); 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); 15849927Ssklower (void) pk_ctlinput (PRC_LINKRESET, hdp->hd_pkp); 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 17149927Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); 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"); 19949927Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); 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"); 20849927Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); 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"); 22949927Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); 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"); 27549927Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); 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 34449927Ssklower if (ns != (hdp -> hd_lasttxnr + hdp -> hd_xcp -> xc_lwsize) % MODULUS) { 34549927Ssklower 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; 36045890Ssklower fbuf -> m_pkthdr.len -= HDHEADERLN; 36149927Ssklower fbuf -> m_pkthdr.rcvif = (struct ifnet *)hdp -> hd_pkp; 36241586Ssklower #ifdef BSD4_3 36341586Ssklower fbuf->m_act = 0; /* probably not necessary */ 36441586Ssklower #else 36541586Ssklower { 36641586Ssklower register struct mbuf *m; 36741586Ssklower 36841586Ssklower for (m = fbuf; m -> m_next; m = m -> m_next) 36941586Ssklower m -> m_act = (struct mbuf *) 0; 37041586Ssklower m -> m_act = (struct mbuf *) 1; 37141586Ssklower } 37241586Ssklower #endif 37349927Ssklower pk_input (fbuf); 37441586Ssklower queued = TRUE; 37541586Ssklower hd_start (hdp); 37641586Ssklower } else { 37741586Ssklower /* 37841586Ssklower * Here if the remote station has transmitted more iframes then 37941586Ssklower * the number which have been acknowledged plus K. 38041586Ssklower */ 38141586Ssklower hdp->hd_invalid_ns++; 38241586Ssklower frame_reject (hdp, W, frame); 38341586Ssklower } 38441586Ssklower return (queued); 38541586Ssklower } 38641586Ssklower 38741586Ssklower /* 38841586Ssklower * This routine is used to determine if a value (the middle parameter) 38941586Ssklower * is between two other values. The low value is the first parameter 39041586Ssklower * the high value is the last parameter. The routine checks the middle 39141586Ssklower * value to see if it is within the range of the first and last values. 39241586Ssklower * The reason we need this routine is the values are modulo some base 39341586Ssklower * hence a simple test for greater or less than is not sufficient. 39441586Ssklower */ 39541586Ssklower 39641586Ssklower bool 39741586Ssklower range_check (rear, value, front) 39841586Ssklower int rear, 39941586Ssklower value, 40041586Ssklower front; 40141586Ssklower { 40241586Ssklower register bool result = FALSE; 40341586Ssklower 40441586Ssklower if (front > rear) 40541586Ssklower result = (rear <= value) && (value <= front); 40641586Ssklower else 40741586Ssklower result = (rear <= value) || (value <= front); 40841586Ssklower 40941586Ssklower return (result); 41041586Ssklower } 41141586Ssklower 41241586Ssklower /* 41341586Ssklower * This routine handles all the frame reject conditions which can 41441586Ssklower * arise as a result of secondary processing. The frame reject 41541586Ssklower * condition Y (frame length error) are handled elsewhere. 41641586Ssklower */ 41741586Ssklower 41841586Ssklower static 41941586Ssklower frame_reject (hdp, rejectcode, frame) 42041586Ssklower struct hdcb *hdp; 42141586Ssklower struct Hdlc_iframe *frame; 42241586Ssklower { 42341586Ssklower register struct Frmr_frame *frmr = &hd_frmr; 42441586Ssklower 42541586Ssklower frmr -> frmr_control = ((struct Hdlc_frame *) frame) -> control; 42641586Ssklower 42741586Ssklower frmr -> frmr_ns = frame -> ns; 42841586Ssklower frmr -> frmr_f1_0 = 0; 42941586Ssklower frmr -> frmr_nr = frame -> nr; 43041586Ssklower frmr -> frmr_f2_0 = 0; 43141586Ssklower 43241586Ssklower frmr -> frmr_0000 = 0; 43341586Ssklower frmr -> frmr_w = frmr -> frmr_x = frmr -> frmr_y = 43441586Ssklower frmr -> frmr_z = 0; 43541586Ssklower switch (rejectcode) { 43641586Ssklower case Z: 43741586Ssklower frmr -> frmr_z = 1;/* invalid N(R). */ 43841586Ssklower break; 43941586Ssklower 44041586Ssklower case Y: 44141586Ssklower frmr -> frmr_y = 1;/* iframe length error. */ 44241586Ssklower break; 44341586Ssklower 44441586Ssklower case X: 44541586Ssklower frmr -> frmr_x = 1;/* invalid information field. */ 44641586Ssklower frmr -> frmr_w = 1; 44741586Ssklower break; 44841586Ssklower 44941586Ssklower case W: 45041586Ssklower frmr -> frmr_w = 1;/* invalid N(S). */ 45141586Ssklower } 45241586Ssklower 45341586Ssklower hd_writeinternal (hdp, FRMR, POLLOFF); 45441586Ssklower 45541586Ssklower hdp->hd_state = WAIT_SABM; 45641586Ssklower SET_TIMER (hdp); 45741586Ssklower } 45841586Ssklower 45941586Ssklower /* 46041586Ssklower * This procedure is invoked when ever we receive a supervisor 46141586Ssklower * frame such as RR, RNR and REJ. All processing for these 46241586Ssklower * frames is done here. 46341586Ssklower */ 46441586Ssklower 46541586Ssklower process_sframe (hdp, frame, frametype) 46641586Ssklower register struct hdcb *hdp; 46741586Ssklower register struct Hdlc_sframe *frame; 46841586Ssklower int frametype; 46941586Ssklower { 47041586Ssklower register int nr = frame -> nr, pf = frame -> pf, pollbit = 0; 47141586Ssklower 47241586Ssklower if (valid_nr (hdp, nr, pf) == TRUE) { 47341586Ssklower switch (frametype) { 47441586Ssklower case RR: 47541586Ssklower hdp->hd_condition &= ~REMOTE_RNR_CONDITION; 47641586Ssklower break; 47741586Ssklower 47841586Ssklower case RNR: 47941586Ssklower hdp->hd_condition |= REMOTE_RNR_CONDITION; 48041586Ssklower hdp->hd_retxcnt = 0; 48141586Ssklower break; 48241586Ssklower 48341586Ssklower case REJ: 48441586Ssklower hdp->hd_condition &= ~REMOTE_RNR_CONDITION; 48541586Ssklower rej_routine (hdp, nr); 48641586Ssklower } 48741586Ssklower 48841586Ssklower if (pf == 1) { 48941586Ssklower hdp->hd_retxcnt = 0; 49041586Ssklower hdp->hd_condition &= ~TIMER_RECOVERY_CONDITION; 49141586Ssklower 49245296Ssklower if (frametype == RR && hdp->hd_lastrxnr == hdp->hd_vs 49345296Ssklower && hdp->hd_timer == 0 && hdp->hd_txq.head == 0) 49445296Ssklower hd_writeinternal(hdp, RR, pf); 49545296Ssklower else 49641586Ssklower /* If any iframes have been queued because of the 49741586Ssklower timer condition, transmit then now. */ 49841586Ssklower if (hdp->hd_condition & REMOTE_RNR_CONDITION) { 49941586Ssklower /* Remote is busy or timer condition, so only 50041586Ssklower send one. */ 50141586Ssklower if (hdp->hd_vs != hdp->hd_retxqi) 50241586Ssklower hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], pollbit); 50341586Ssklower } 50441586Ssklower else /* Flush the retransmit list first. */ 50541586Ssklower while (hdp->hd_vs != hdp->hd_retxqi) 50641586Ssklower hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF); 50741586Ssklower } 50841586Ssklower 50941586Ssklower hd_start (hdp); 51041586Ssklower } else 51141586Ssklower frame_reject (hdp, Z, (struct Hdlc_iframe *)frame); /* Invalid N(R). */ 51241586Ssklower } 51341586Ssklower 51441586Ssklower /* 51541586Ssklower * This routine tests the validity of the N(R) which we have received. 51641586Ssklower * If it is ok, then all the iframes which it acknowledges (if any) 51741586Ssklower * will be freed. 51841586Ssklower */ 51941586Ssklower 52041586Ssklower bool 52141586Ssklower valid_nr (hdp, nr, finalbit) 52241586Ssklower register struct hdcb *hdp; 52341586Ssklower register int finalbit; 52441586Ssklower { 52541586Ssklower /* Make sure it really does acknowledge something. */ 52641586Ssklower if (hdp->hd_lastrxnr == nr) 52741586Ssklower return (TRUE); 52841586Ssklower 52941586Ssklower /* 53041586Ssklower * This section validates the frame's N(R) value. It's N(R) value 53141586Ssklower * must be in syncronization with our V(S) value and our "last 53241586Ssklower * received nr" variable. If it is correct then we are able to send 53341586Ssklower * more IFRAME's, else frame reject condition is entered. 53441586Ssklower */ 53541586Ssklower 53641586Ssklower if (range_check (hdp->hd_lastrxnr, nr, hdp->hd_vs) == FALSE) { 53741586Ssklower if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && 53841586Ssklower range_check (hdp->hd_vs, nr, hdp->hd_xx) == TRUE) 53941586Ssklower hdp->hd_vs = nr; 54041586Ssklower 54141586Ssklower else { 54241586Ssklower hdp->hd_invalid_nr++; 54341586Ssklower return (FALSE); 54441586Ssklower } 54541586Ssklower } 54641586Ssklower 54741586Ssklower /* 54841586Ssklower * If we get to here, we do have a valid frame but it might be out 54941586Ssklower * of sequence. However, we should still accept the receive state 55041586Ssklower * number N(R) since it has already passed our previous test and it 55141586Ssklower * does acknowledge frames which we are sending. 55241586Ssklower */ 55341586Ssklower 55441586Ssklower KILL_TIMER (hdp); 55541586Ssklower free_iframes (hdp, &nr, finalbit);/* Free all acknowledged iframes */ 55641586Ssklower if (nr != hdp->hd_vs) 55741586Ssklower SET_TIMER (hdp); 55841586Ssklower 55941586Ssklower return (TRUE); 56041586Ssklower } 56141586Ssklower 56241586Ssklower /* 56341586Ssklower * This routine determines how many iframes need to be retransmitted. 56441586Ssklower * It then resets the Send State Variable V(S) to accomplish this. 56541586Ssklower */ 56641586Ssklower 56741586Ssklower static 56841586Ssklower rej_routine (hdp, rejnr) 56941586Ssklower register struct hdcb *hdp; 57041586Ssklower register int rejnr; 57141586Ssklower { 57241586Ssklower register int anchor; 57341586Ssklower 57441586Ssklower /* 57541586Ssklower * Flush the output queue. Any iframes queued for 57641586Ssklower * transmission will be out of sequence. 57741586Ssklower */ 57841586Ssklower 57941586Ssklower hd_flush (hdp->hd_ifp); 58041586Ssklower 58141586Ssklower /* 58241586Ssklower * Determine how many frames should be re-transmitted. In the case 58341586Ssklower * of a normal REJ this should be 1 to K. In the case of a timer 58441586Ssklower * recovery REJ (ie. a REJ with the Final Bit on) this could be 0. 58541586Ssklower */ 58641586Ssklower 58741586Ssklower anchor = hdp->hd_vs; 58841586Ssklower if (hdp->hd_condition & TIMER_RECOVERY_CONDITION) 58941586Ssklower anchor = hdp->hd_xx; 59041586Ssklower 59141586Ssklower anchor = (anchor - rejnr + 8) % MODULUS; 59241586Ssklower 59341586Ssklower if (anchor > 0) { 59441586Ssklower 59541586Ssklower /* There is at least one iframe to retransmit. */ 59641586Ssklower KILL_TIMER (hdp); 59741586Ssklower hdp->hd_vs = rejnr; 59841586Ssklower 59941586Ssklower while (hdp->hd_vs != hdp->hd_retxqi) 60041586Ssklower hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF); 60141586Ssklower 60241586Ssklower } 60341586Ssklower hd_start (hdp); 60441586Ssklower } 60541586Ssklower 60641586Ssklower /* 60741586Ssklower * This routine frees iframes from the retransmit queue. It is called 60841586Ssklower * when a previously written iframe is acknowledged. 60941586Ssklower */ 61041586Ssklower 61141586Ssklower static 61241586Ssklower free_iframes (hdp, nr, finalbit) 61341586Ssklower register struct hdcb *hdp; 61441586Ssklower int *nr; 61541586Ssklower register int finalbit; 61641586Ssklower 61741586Ssklower { 61841586Ssklower register int i, k; 61941586Ssklower 62041586Ssklower /* 62141586Ssklower * We need to do the following because of a funny quirk in the 62241586Ssklower * protocol. This case occures when in Timer recovery condition 62341586Ssklower * we get a N(R) which acknowledges all the outstanding iframes 62441586Ssklower * but with the Final Bit off. In this case we need to save the last 62541586Ssklower * iframe for possible retransmission even though it has already been 62641586Ssklower * acknowledged! 62741586Ssklower */ 62841586Ssklower 62941586Ssklower if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && *nr == hdp->hd_xx && finalbit == 0) { 63041586Ssklower *nr = (*nr - 1 + 8) % MODULUS; 63141586Ssklower /* printf ("QUIRK\n"); */ 63241586Ssklower } 63341586Ssklower 63441586Ssklower k = (*nr - hdp->hd_lastrxnr + 8) % MODULUS; 63541586Ssklower 63641586Ssklower /* Loop here freeing all acknowledged iframes. */ 63741586Ssklower for (i = 0; i < k; ++i) { 63841586Ssklower m_freem (hdp->hd_retxq[hdp->hd_lastrxnr]); 63941586Ssklower hdp->hd_retxq[hdp->hd_lastrxnr] = 0; 64041586Ssklower hdp->hd_lastrxnr = (hdp->hd_lastrxnr + 1) % MODULUS; 64141586Ssklower } 64241586Ssklower 64341586Ssklower } 644