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