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