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