1/* 2 * Copyright (c) 1996-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 * 29 * $Begemot: libunimsg/netnatm/saal/saal_sscop.c,v 1.11 2004/07/08 08:22:13 brandt Exp $ 30 * 31 * Core SSCOP code (ITU-T Q.2110) 32 */ 33 34#include <netnatm/saal/sscop.h> 35#include <netnatm/saal/sscoppriv.h> 36 37#ifndef FAILURE 38#define FAILURE(S) 39#endif 40 41#define MKSTR(S) #S 42 43static const char *const sscop_sigs[] = { 44 MKSTR(SSCOP_ESTABLISH_request), 45 MKSTR(SSCOP_ESTABLISH_indication), 46 MKSTR(SSCOP_ESTABLISH_response), 47 MKSTR(SSCOP_ESTABLISH_confirm), 48 MKSTR(SSCOP_RELEASE_request), 49 MKSTR(SSCOP_RELEASE_indication), 50 MKSTR(SSCOP_RELEASE_confirm), 51 MKSTR(SSCOP_DATA_request), 52 MKSTR(SSCOP_DATA_indication), 53 MKSTR(SSCOP_UDATA_request), 54 MKSTR(SSCOP_UDATA_indication), 55 MKSTR(SSCOP_RECOVER_indication), 56 MKSTR(SSCOP_RECOVER_response), 57 MKSTR(SSCOP_RESYNC_request), 58 MKSTR(SSCOP_RESYNC_indication), 59 MKSTR(SSCOP_RESYNC_response), 60 MKSTR(SSCOP_RESYNC_confirm), 61 MKSTR(SSCOP_RETRIEVE_request), 62 MKSTR(SSCOP_RETRIEVE_indication), 63 MKSTR(SSCOP_RETRIEVE_COMPL_indication), 64}; 65 66static const char *const sscop_msigs[] = { 67 MKSTR(SSCOP_MDATA_request), 68 MKSTR(SSCOP_MDATA_indication), 69 MKSTR(SSCOP_MERROR_indication), 70}; 71 72static const char *const states[] = { 73 MKSTR(SSCOP_IDLE), 74 MKSTR(SSCOP_OUT_PEND), 75 MKSTR(SSCOP_IN_PEND), 76 MKSTR(SSCOP_OUT_DIS_PEND), 77 MKSTR(SSCOP_OUT_RESYNC_PEND), 78 MKSTR(SSCOP_IN_RESYNC_PEND), 79 MKSTR(SSCOP_OUT_REC_PEND), 80 MKSTR(SSCOP_REC_PEND), 81 MKSTR(SSCOP_IN_REC_PEND), 82 MKSTR(SSCOP_READY), 83}; 84 85#ifdef SSCOP_DEBUG 86static const char *const events[] = { 87 MKSTR(SIG_BGN), 88 MKSTR(SIG_BGAK), 89 MKSTR(SIG_END), 90 MKSTR(SIG_ENDAK), 91 MKSTR(SIG_RS), 92 MKSTR(SIG_RSAK), 93 MKSTR(SIG_BGREJ), 94 MKSTR(SIG_SD), 95 MKSTR(SIG_ER), 96 MKSTR(SIG_POLL), 97 MKSTR(SIG_STAT), 98 MKSTR(SIG_USTAT), 99 MKSTR(SIG_UD), 100 MKSTR(SIG_MD), 101 MKSTR(SIG_ERAK), 102 103 MKSTR(SIG_T_CC), 104 MKSTR(SIG_T_POLL), 105 MKSTR(SIG_T_KA), 106 MKSTR(SIG_T_NR), 107 MKSTR(SIG_T_IDLE), 108 109 MKSTR(SIG_PDU_Q), 110 MKSTR(SIG_USER_DATA), 111 MKSTR(SIG_ESTAB_REQ), 112 MKSTR(SIG_ESTAB_RESP), 113 MKSTR(SIG_RELEASE_REQ), 114 MKSTR(SIG_RECOVER), 115 MKSTR(SIG_SYNC_REQ), 116 MKSTR(SIG_SYNC_RESP), 117 MKSTR(SIG_UDATA), 118 MKSTR(SIG_MDATA), 119 MKSTR(SIG_UPDU_Q), 120 MKSTR(SIG_MPDU_Q), 121 MKSTR(SIG_RETRIEVE), 122}; 123 124static const char *const pdus[] = { 125 "illegale PDU type 0", /* no PDU type 0 */ 126 MKSTR(PDU_BGN), 127 MKSTR(PDU_BGAK), 128 MKSTR(PDU_END), 129 MKSTR(PDU_ENDAK), 130 MKSTR(PDU_RS), 131 MKSTR(PDU_RSAK), 132 MKSTR(PDU_BGREJ), 133 MKSTR(PDU_SD), 134 MKSTR(PDU_ER), 135 MKSTR(PDU_POLL), 136 MKSTR(PDU_STAT), 137 MKSTR(PDU_USTAT), 138 MKSTR(PDU_UD), 139 MKSTR(PDU_MD), 140 MKSTR(PDU_ERAK), 141}; 142#endif 143 144MEMINIT(); 145 146static void sscop_signal(struct sscop *, u_int, struct sscop_msg *); 147static void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *); 148static void handle_sigs(struct sscop *); 149static void sscop_set_state(struct sscop *, u_int); 150 151/************************************************************/ 152 153 154/************************************************************/ 155/* 156 * Queue macros 157 */ 158#define SSCOP_MSG_FREE(MSG) \ 159 do { \ 160 if(MSG) { \ 161 MBUF_FREE((MSG)->m); \ 162 MSG_FREE((MSG)); \ 163 } \ 164 } while(0) 165 166static inline struct sscop_msg *QFIND(sscop_msgq_head_t *q, u_int rn) 167{ 168 struct sscop_msg *msg = NULL, *m; 169 MSGQ_FOREACH(m, q) { 170 if(m->seqno == rn) { 171 msg = m; 172 break; 173 } 174 } 175 return msg; 176} 177 178#define QINSERT(Q,M) \ 179 do { \ 180 struct sscop_msg *_msg = NULL, *_m; \ 181 MSGQ_FOREACH(_m, (Q)) { \ 182 if (_m->seqno > (M)->seqno) { \ 183 _msg = _m; \ 184 break; \ 185 } \ 186 } \ 187 if (_msg != NULL) \ 188 MSGQ_INSERT_BEFORE(_msg, (M)); \ 189 else \ 190 MSGQ_APPEND((Q), (M)); \ 191 } while (0) 192 193 194/* 195 * Send an error indication to the management plane. 196 */ 197#define MAAL_ERROR(S,E,C) \ 198 do { \ 199 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 200 "MAA-Signal %s in state %s", \ 201 sscop_msigs[SSCOP_MERROR_indication], states[(S)->state])); \ 202 (S)->funcs->send_manage((S), (S)->aarg, \ 203 SSCOP_MERROR_indication, NULL, (E), (C)); \ 204 } while(0) 205 206#define MAAL_DATA(S,M) \ 207 do { \ 208 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 209 "MAA-Signal %s in state %s", \ 210 sscop_msigs[SSCOP_MDATA_indication], states[(S)->state])); \ 211 (S)->funcs->send_manage((S), (S)->aarg, \ 212 SSCOP_MDATA_indication, (M), 0, 0); \ 213 } while(0) 214 215#define AAL_DATA(S,D,M,N) \ 216 do { \ 217 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 218 "AA-Signal %s in state %s", \ 219 sscop_sigs[D], states[(S)->state])); \ 220 (S)->funcs->send_upper((S), (S)->aarg, (D), (M), (N)); \ 221 } while(0) 222 223#define AAL_SIG(S,D) \ 224 do { \ 225 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 226 "AA-Signal %s in state %s", \ 227 sscop_sigs[D], states[(S)->state])); \ 228 (S)->funcs->send_upper((S), (S)->aarg, (D), NULL, 0); \ 229 } while(0) 230 231#ifdef SSCOP_DEBUG 232#define AAL_SEND(S,M) do { \ 233 if (ISVERBOSE(S, SSCOP_DBG_PDU)) \ 234 sscop_dump_pdu(S, "tx", (M)); \ 235 (S)->funcs->send_lower((S), (S)->aarg, (M)); \ 236 } while(0) 237#else 238#define AAL_SEND(S,M) (S)->funcs->send_lower((S), (S)->aarg, (M)) 239#endif 240 241 242/* 243 * Free a save user-to-user data buffer and set the pointer to zero 244 * to signal, that it is free. 245 */ 246#define FREE_UU(F) \ 247 do { \ 248 if(sscop->F) { \ 249 MBUF_FREE(sscop->F); \ 250 sscop->F = NULL; \ 251 } \ 252 } while(0) 253 254#define SET_UU(F,U) \ 255 do { \ 256 FREE_UU(F); \ 257 sscop->F = U->m; \ 258 U->m = NULL; \ 259 SSCOP_MSG_FREE(U); \ 260 } while(0) 261 262#define AAL_UU_SIGNAL(S, SIG, M, PL, SN) \ 263 do { \ 264 if(MBUF_LEN((M)->m) > 0) { \ 265 MBUF_UNPAD((M)->m,(PL)); \ 266 AAL_DATA((S), (SIG), (M)->m, (SN)); \ 267 (M)->m = NULL; \ 268 } else { \ 269 AAL_DATA((S), (SIG), NULL, (SN)); \ 270 } \ 271 SSCOP_MSG_FREE((M)); \ 272 } while(0) 273 274 275 276TIMER_FUNC(cc, CC) 277TIMER_FUNC(nr, NR) 278TIMER_FUNC(ka, KA) 279TIMER_FUNC(poll, POLL) 280TIMER_FUNC(idle, IDLE) 281 282/************************************************************/ 283/* 284 * INSTANCE AND TYPE HANDLING. 285 */ 286#ifdef SSCOP_DEBUG 287static void 288sscop_dump_pdu(struct sscop *sscop, const char *dir, 289 const struct SSCOP_MBUF_T *m) 290{ 291 u_int32_t v1, v2, v3, v4; 292 u_int size = MBUF_LEN(m); 293 u_int n, i; 294 295 if (size < 8) 296 return; 297 298 v1 = MBUF_TRAIL32(m, -1); 299 v2 = MBUF_TRAIL32(m, -2); 300 301 switch ((v1 >> 24) & 0xf) { 302 303 case 0: 304 return; 305 306 case PDU_BGN: 307 sscop->funcs->verbose(sscop, sscop->aarg, 308 "%s BGN n(mr)=%u n(sq)=%u pl=%u", 309 dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3); 310 return; 311 312 case PDU_BGAK: 313 sscop->funcs->verbose(sscop, sscop->aarg, 314 "%s BGAK n(mr)=%u pl=%u", 315 dir, v1 & 0xffffff, (v1 >> 30) & 0x3); 316 return; 317 318 case PDU_END: 319 sscop->funcs->verbose(sscop, sscop->aarg, 320 "%s END r=%u s=%u pl=%u", 321 dir, (v1 >> 29) & 1, (v1 >> 28) & 1, (v1 >> 30) & 0x3); 322 return; 323 324 case PDU_ENDAK: 325 sscop->funcs->verbose(sscop, sscop->aarg, "%s ENDAK", dir); 326 return; 327 328 case PDU_RS: 329 sscop->funcs->verbose(sscop, sscop->aarg, 330 "%s RS n(mr)=%u n(sq)=%u pl=%u", 331 dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3); 332 return; 333 334 case PDU_RSAK: 335 sscop->funcs->verbose(sscop, sscop->aarg, "%s RSAK n(mr)=%u", 336 dir, v1 & 0xffffff); 337 return; 338 339 case PDU_BGREJ: 340 sscop->funcs->verbose(sscop, sscop->aarg, "%s BGREJ pl=%u", 341 dir, (v1 >> 30) & 0x3); 342 return; 343 344 case PDU_SD: 345 sscop->funcs->verbose(sscop, sscop->aarg, "%s SD n(s)=%u pl=%u", 346 dir, v1 & 0xffffff, (v1 >> 30) & 0x3); 347 return; 348 349 case PDU_ER: 350 sscop->funcs->verbose(sscop, sscop->aarg, "%s ER n(mr)=%u n(sq)=%u", 351 dir, v1 & 0xffffff, v2 & 0xff); 352 return; 353 354 case PDU_POLL: 355 sscop->funcs->verbose(sscop, sscop->aarg, "%s POLL n(s)=%u n(ps)=%u", 356 dir, v1 & 0xffffff, v2 & 0xffffff); 357 return; 358 359 case PDU_STAT: 360 if (size < 12) 361 return; 362 v3 = MBUF_TRAIL32(m, -3); 363 sscop->funcs->verbose(sscop, sscop->aarg, 364 "%s STAT n(r)=%u n(mr)=%u n(ps)=%u", 365 dir, v1 & 0xffffff, v2 & 0xffffff, v3 & 0xffffff); 366 n = (size - 12) / 4; 367 for (i = 0; i < (size - 12) / 4; i++, n--) { 368 v4 = MBUF_TRAIL32(m, -4 - (int)i); 369 sscop->funcs->verbose(sscop, sscop->aarg, 370 " LE(%u)=%u", n, v4 & 0xffffff); 371 } 372 return; 373 374 case PDU_USTAT: 375 if (size < 16) 376 return; 377 sscop->funcs->verbose(sscop, sscop->aarg, 378 "%s STAT n(r)=%u n(mr)=%u LE1=%u LE2=%u", 379 dir, v1 & 0xffffff, v2 & 0xffffff, 380 MBUF_TRAIL32(m, -4) & 0xffffff, 381 MBUF_TRAIL32(m, -3) & 0xffffff); 382 return; 383 384 case PDU_UD: 385 sscop->funcs->verbose(sscop, sscop->aarg, 386 "%s UD pl=%u", dir, (v1 >> 30) & 0x3); 387 return; 388 389 case PDU_MD: 390 sscop->funcs->verbose(sscop, sscop->aarg, 391 "%s MD pl=%u", dir, (v1 >> 30) & 0x3); 392 return; 393 394 case PDU_ERAK: 395 sscop->funcs->verbose(sscop, sscop->aarg, 396 "%s ERAK n(mr)=%u", dir, v1 & 0xffffff); 397 return; 398 } 399} 400#endif 401 402 403/* 404 * Initialize state of variables 405 */ 406static void 407sscop_init(struct sscop *sscop) 408{ 409 sscop->state = SSCOP_IDLE; 410 411 sscop->vt_sq = 0; 412 sscop->vr_sq = 0; 413 sscop->clear_buffers = 1; 414 415 sscop->ll_busy = 0; 416 417 sscop->rxq = 0; 418} 419 420static void 421sscop_clear(struct sscop *sscop) 422{ 423 TIMER_STOP(sscop, cc); 424 TIMER_STOP(sscop, ka); 425 TIMER_STOP(sscop, nr); 426 TIMER_STOP(sscop, idle); 427 TIMER_STOP(sscop, poll); 428 429 FREE_UU(uu_bgn); 430 FREE_UU(uu_bgak); 431 FREE_UU(uu_bgrej); 432 FREE_UU(uu_end); 433 FREE_UU(uu_rs); 434 435 MSGQ_CLEAR(&sscop->xq); 436 MSGQ_CLEAR(&sscop->uxq); 437 MSGQ_CLEAR(&sscop->mxq); 438 MSGQ_CLEAR(&sscop->xbuf); 439 MSGQ_CLEAR(&sscop->rbuf); 440 441 SIGQ_CLEAR(&sscop->sigs); 442 SIGQ_CLEAR(&sscop->saved_sigs); 443} 444 445 446/* 447 * Allocate instance memory, initialize the state of all variables. 448 */ 449struct sscop * 450sscop_create(void *a, const struct sscop_funcs *funcs) 451{ 452 struct sscop *sscop; 453 454 MEMZALLOC(sscop, struct sscop *, sizeof(struct sscop)); 455 if (sscop == NULL) 456 return (NULL); 457 458 if (a == NULL) 459 sscop->aarg = sscop; 460 else 461 sscop->aarg = a; 462 sscop->funcs = funcs; 463 464 sscop->maxk = MAXK; 465 sscop->maxj = MAXJ; 466 sscop->maxcc = MAXCC; 467 sscop->maxpd = MAXPD; 468 sscop->maxstat = MAXSTAT; 469 sscop->timercc = TIMERCC; 470 sscop->timerka = TIMERKA; 471 sscop->timernr = TIMERNR; 472 sscop->timerpoll = TIMERPOLL; 473 sscop->timeridle = TIMERIDLE; 474 sscop->robustness = 0; 475 sscop->poll_after_rex = 0; 476 sscop->mr = MAXMR; 477 478 TIMER_INIT(sscop, cc); 479 TIMER_INIT(sscop, nr); 480 TIMER_INIT(sscop, ka); 481 TIMER_INIT(sscop, poll); 482 TIMER_INIT(sscop, idle); 483 484 MSGQ_INIT(&sscop->xq); 485 MSGQ_INIT(&sscop->uxq); 486 MSGQ_INIT(&sscop->mxq); 487 MSGQ_INIT(&sscop->rbuf); 488 MSGQ_INIT(&sscop->xbuf); 489 490 SIGQ_INIT(&sscop->sigs); 491 SIGQ_INIT(&sscop->saved_sigs); 492 493 sscop_init(sscop); 494 495 return (sscop); 496} 497 498/* 499 * Free all resources in a sscop instance 500 */ 501void 502sscop_destroy(struct sscop *sscop) 503{ 504 sscop_reset(sscop); 505 506 MEMFREE(sscop); 507} 508 509/* 510 * Reset the SSCOP instance. 511 */ 512void 513sscop_reset(struct sscop *sscop) 514{ 515 sscop_clear(sscop); 516 sscop_init(sscop); 517} 518 519void 520sscop_getparam(const struct sscop *sscop, struct sscop_param *p) 521{ 522 p->timer_cc = sscop->timercc; 523 p->timer_poll = sscop->timerpoll; 524 p->timer_keep_alive = sscop->timerka; 525 p->timer_no_response = sscop->timernr; 526 p->timer_idle = sscop->timeridle; 527 p->maxk = sscop->maxk; 528 p->maxj = sscop->maxj; 529 p->maxcc = sscop->maxcc; 530 p->maxpd = sscop->maxpd; 531 p->maxstat = sscop->maxstat; 532 p->mr = sscop->mr; 533 p->flags = 0; 534 if(sscop->robustness) 535 p->flags |= SSCOP_ROBUST; 536 if(sscop->poll_after_rex) 537 p->flags |= SSCOP_POLLREX; 538} 539 540int 541sscop_setparam(struct sscop *sscop, struct sscop_param *p, u_int *pmask) 542{ 543 u_int mask = *pmask; 544 545 /* can change only in idle state */ 546 if (sscop->state != SSCOP_IDLE) 547 return (EISCONN); 548 549 *pmask = 0; 550 551 /* 552 * first check all parameters 553 */ 554 if ((mask & SSCOP_SET_TCC) && p->timer_cc == 0) 555 *pmask |= SSCOP_SET_TCC; 556 if ((mask & SSCOP_SET_TPOLL) && p->timer_poll == 0) 557 *pmask |= SSCOP_SET_TPOLL; 558 if ((mask & SSCOP_SET_TKA) && p->timer_keep_alive == 0) 559 *pmask |= SSCOP_SET_TKA; 560 if ((mask & SSCOP_SET_TNR) && p->timer_no_response == 0) 561 *pmask |= SSCOP_SET_TNR; 562 if ((mask & SSCOP_SET_TIDLE) && p->timer_idle == 0) 563 *pmask |= SSCOP_SET_TIDLE; 564 if ((mask & SSCOP_SET_MAXK) && p->maxk > MAXMAXK) 565 *pmask |= SSCOP_SET_MAXK; 566 if ((mask & SSCOP_SET_MAXJ) && p->maxj > MAXMAXJ) 567 *pmask |= SSCOP_SET_MAXJ; 568 if ((mask & SSCOP_SET_MAXCC) && p->maxcc > 255) 569 *pmask |= SSCOP_SET_MAXCC; 570 if ((mask & SSCOP_SET_MAXPD) && p->maxpd >= (1 << 24)) 571 *pmask |= SSCOP_SET_MAXPD; 572 if ((mask & SSCOP_SET_MAXSTAT) && 573 ((p->maxstat & 1) == 0 || p->maxstat == 1 || p->maxstat == 2 || 574 p->maxstat * 4 > MAXMAXK - 8)) 575 *pmask |= SSCOP_SET_MAXSTAT; 576 if ((mask & SSCOP_SET_MR) && p->mr >= (1 << 24) - 1) 577 *pmask |= SSCOP_SET_MR; 578 579 if (*pmask) 580 return (EINVAL); 581 582 583 /* 584 * now set it 585 */ 586 if (mask & SSCOP_SET_TCC) 587 sscop->timercc = p->timer_cc; 588 589 if (mask & SSCOP_SET_TPOLL) 590 sscop->timerpoll = p->timer_poll; 591 592 if (mask & SSCOP_SET_TKA) 593 sscop->timerka = p->timer_keep_alive; 594 595 if (mask & SSCOP_SET_TNR) 596 sscop->timernr = p->timer_no_response; 597 598 if (mask & SSCOP_SET_TIDLE) 599 sscop->timeridle = p->timer_idle; 600 601 if (mask & SSCOP_SET_MAXK) 602 sscop->maxk = p->maxk; 603 if (mask & SSCOP_SET_MAXJ) 604 sscop->maxj = p->maxj; 605 606 if (mask & SSCOP_SET_MAXCC) 607 sscop->maxcc = p->maxcc; 608 if (mask & SSCOP_SET_MAXPD) 609 sscop->maxpd = p->maxpd; 610 if (mask & SSCOP_SET_MAXSTAT) 611 sscop->maxstat = p->maxstat; 612 613 if (mask & SSCOP_SET_MR) 614 sscop->mr = p->mr; 615 616 if (mask & SSCOP_SET_ROBUST) 617 sscop->robustness = ((p->flags & SSCOP_ROBUST) != 0); 618 619 if (mask & SSCOP_SET_POLLREX) 620 sscop->poll_after_rex = ((p->flags & SSCOP_POLLREX) != 0); 621 622 return (0); 623} 624 625enum sscop_state 626sscop_getstate(const struct sscop *sscop) 627{ 628 return (sscop->state); 629} 630 631 632/************************************************************/ 633/* 634 * EXTERNAL INPUT SIGNAL MAPPING 635 */ 636 637/* 638 * Map AA signal to SSCOP internal signal 639 */ 640int 641sscop_aasig(struct sscop *sscop, enum sscop_aasig sig, 642 struct SSCOP_MBUF_T *m, u_int arg) 643{ 644 struct sscop_msg *msg; 645 646 if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) { 647 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 648 "AA-Signal %u - bad signal", sig)); 649 MBUF_FREE(m); 650 return (EINVAL); 651 } 652 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 653 "AA-Signal %s in state %s with%s message", 654 sscop_sigs[sig], states[sscop->state], m ? "" : "out")); 655 656 MSG_ALLOC(msg); 657 if (msg == NULL) { 658 FAILURE("sscop: cannot allocate aasig"); 659 MBUF_FREE(m); 660 return (ENOMEM); 661 } 662 663 switch(sig) { 664 665 case SSCOP_ESTABLISH_request: 666 msg->m = m; 667 msg->rexmit = arg; 668 sscop_signal(sscop, SIG_ESTAB_REQ, msg); 669 break; 670 671 case SSCOP_ESTABLISH_response: 672 msg->m = m; 673 msg->rexmit = arg; 674 sscop_signal(sscop, SIG_ESTAB_RESP, msg); 675 break; 676 677 case SSCOP_RELEASE_request: 678 msg->m = m; 679 sscop_signal(sscop, SIG_RELEASE_REQ, msg); 680 break; 681 682 case SSCOP_DATA_request: 683 msg->m = m; 684 sscop_signal(sscop, SIG_USER_DATA, msg); 685 break; 686 687 case SSCOP_UDATA_request: 688 msg->m = m; 689 sscop_signal(sscop, SIG_UDATA, msg); 690 break; 691 692 case SSCOP_RECOVER_response: 693 MBUF_FREE(m); 694 MSG_FREE(msg); 695 sscop_signal(sscop, SIG_RECOVER, NULL); 696 break; 697 698 case SSCOP_RESYNC_request: 699 msg->m = m; 700 sscop_signal(sscop, SIG_SYNC_REQ, msg); 701 break; 702 703 case SSCOP_RESYNC_response: 704 MBUF_FREE(m); 705 MSG_FREE(msg); 706 sscop_signal(sscop, SIG_SYNC_RESP, NULL); 707 break; 708 709 case SSCOP_RETRIEVE_request: 710 MBUF_FREE(m); 711 msg->rexmit = arg; 712 sscop_signal(sscop, SIG_RETRIEVE, msg); 713 break; 714 715 case SSCOP_ESTABLISH_indication: 716 case SSCOP_ESTABLISH_confirm: 717 case SSCOP_RELEASE_indication: 718 case SSCOP_RELEASE_confirm: 719 case SSCOP_DATA_indication: 720 case SSCOP_UDATA_indication: 721 case SSCOP_RECOVER_indication: 722 case SSCOP_RESYNC_indication: 723 case SSCOP_RESYNC_confirm: 724 case SSCOP_RETRIEVE_indication: 725 case SSCOP_RETRIEVE_COMPL_indication: 726 MBUF_FREE(m); 727 MSG_FREE(msg); 728 return EINVAL; 729 } 730 731 return 0; 732} 733 734/* 735 * Signal from layer management. 736 */ 737int 738sscop_maasig(struct sscop *sscop, enum sscop_maasig sig, struct SSCOP_MBUF_T *m) 739{ 740 struct sscop_msg *msg; 741 742 if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) { 743 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 744 "MAA-Signal %u - bad signal", sig)); 745 MBUF_FREE(m); 746 return (EINVAL); 747 } 748 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 749 "MAA-Signal %s in state %s with%s message", 750 sscop_msigs[sig], states[sscop->state], m ? "" : "out")); 751 752 MSG_ALLOC(msg); 753 if (msg == NULL) { 754 FAILURE("sscop: cannot allocate maasig"); 755 MBUF_FREE(m); 756 return (ENOMEM); 757 } 758 759 switch (sig) { 760 761 case SSCOP_MDATA_request: 762 msg->m = m; 763 sscop_signal(sscop, SIG_MDATA, msg); 764 break; 765 766 case SSCOP_MDATA_indication: 767 case SSCOP_MERROR_indication: 768 MBUF_FREE(m); 769 MSG_FREE(msg); 770 return (EINVAL); 771 } 772 return (0); 773} 774 775/* 776 * Map PDU to SSCOP signal. 777 */ 778void 779sscop_input(struct sscop *sscop, struct SSCOP_MBUF_T *m) 780{ 781 struct sscop_msg *msg; 782 union pdu pdu; 783 u_int size; 784 785 MSG_ALLOC(msg); 786 if(msg == NULL) { 787 FAILURE("sscop: cannot allocate in pdu msg"); 788 MBUF_FREE(m); 789 return; 790 } 791 792 msg->m = m; 793 msg->rexmit = 0; 794 795 size = MBUF_LEN(m); 796 797 if(size % 4 != 0 || size < 4) 798 goto err; 799 800 pdu.sscop_null = MBUF_TRAIL32(m, -1); 801 802 VERBOSE(sscop, SSCOP_DBG_PDU, (sscop, sscop->aarg, 803 "got %s, size=%u", pdus[pdu.sscop_type], size)); 804 805#ifdef SSCOP_DEBUG 806#define ENSURE(C,F) if(!(C)) { VERBOSE(sscop, SSCOP_DBG_PDU, F); goto err; } 807#else 808#define ENSURE(C,F) if(!(C)) goto err 809#endif 810 811#ifdef SSCOP_DEBUG 812 if (ISVERBOSE(sscop, SSCOP_DBG_PDU)) 813 sscop_dump_pdu(sscop, "rx", m); 814#endif 815 816 switch(pdu.sscop_type) { 817 818 default: 819 ENSURE(0, (sscop, sscop->aarg, 820 "Bad PDU type %u", pdu.sscop_type)); 821 break; 822 823 case PDU_BGN: 824 ENSURE(size >= 8U, (sscop, sscop->aarg, 825 "PDU_BGN size=%u", size)); 826 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 827 "PDU_BGN size=%u pl=%u", size, pdu.sscop_pl)); 828 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 829 "PDU_BGN size=%u", size)); 830 sscop_signal(sscop, SIG_BGN, msg); 831 break; 832 833 case PDU_BGAK: 834 ENSURE(size >= 8U, (sscop, sscop->aarg, 835 "PDU_BGAK size=%u", size)); 836 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 837 "PDU_BGAK size=%u pl=%u", size, pdu.sscop_pl)); 838 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 839 "PDU_BGAK size=%u", size)); 840 sscop_signal(sscop, SIG_BGAK, msg); 841 break; 842 843 case PDU_END: 844 ENSURE(size >= 8U, (sscop, sscop->aarg, 845 "PDU_END size=%u", size)); 846 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 847 "PDU_END size=%u pl=%u", size, pdu.sscop_pl)); 848 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 849 "PDU_END size=%u", size)); 850 sscop_signal(sscop, SIG_END, msg); 851 break; 852 853 case PDU_ENDAK: 854 ENSURE(size == 8U, (sscop, sscop->aarg, 855 "PDU_ENDAK size=%u", size)); 856 sscop_signal(sscop, SIG_ENDAK, msg); 857 break; 858 859 case PDU_BGREJ: 860 ENSURE(size >= 8U, (sscop, sscop->aarg, 861 "PDU_BGREJ size=%u", size)); 862 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 863 "PDU_BGREJ size=%u pl=%u", size, pdu.sscop_pl)); 864 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 865 "PDU_BGREJ size=%u", size)); 866 sscop_signal(sscop, SIG_BGREJ, msg); 867 break; 868 869 case PDU_SD: 870 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg, 871 "PDU_SD size=%u pl=%u", size, pdu.sscop_pl)); 872 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg, 873 "PDU_SD size=%u", size)); 874 sscop_signal(sscop, SIG_SD, msg); 875 break; 876 877 case PDU_UD: 878 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg, 879 "PDU_UD size=%u pl=%u", size, pdu.sscop_pl)); 880 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg, 881 "PDU_UD size=%u", size)); 882 sscop_signal(sscop, SIG_UD, msg); 883 break; 884 885 case PDU_MD: 886 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg, 887 "PDU_MD size=%u pl=%u", size, pdu.sscop_pl)); 888 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg, 889 "PDU_MD size=%u", size)); 890 sscop_signal(sscop, SIG_MD, msg); 891 break; 892 893 case PDU_POLL: 894 ENSURE(size == 8U, (sscop, sscop->aarg, 895 "PDU_POLL size=%u", size)); 896 sscop_signal(sscop, SIG_POLL, msg); 897 break; 898 899 case PDU_STAT: 900 ENSURE(size >= 12U, (sscop, sscop->aarg, 901 "PDU_STAT size=%u", size)); 902 ENSURE(size <= 12U + 4 * sscop->maxstat, (sscop, sscop->aarg, 903 "PDU_STAT size=%u", size)); 904 sscop_signal(sscop, SIG_STAT, msg); 905 break; 906 907 case PDU_RS: 908 ENSURE(size >= 8U, (sscop, sscop->aarg, 909 "PDU_RS size=%u", size)); 910 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 911 "PDU_RS size=%u pl=%u", size, pdu.sscop_pl)); 912 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 913 "PDU_RS size=%u", size)); 914 sscop_signal(sscop, SIG_RS, msg); 915 break; 916 917 case PDU_RSAK: 918 ENSURE(size == 8U, (sscop, sscop->aarg, 919 "PDU_RSAK size=%u", size)); 920 sscop_signal(sscop, SIG_RSAK, msg); 921 break; 922 923 case PDU_ER: 924 ENSURE(size == 8U, (sscop, sscop->aarg, 925 "PDU_ER size=%u", size)); 926 sscop_signal(sscop, SIG_ER, msg); 927 break; 928 929 case PDU_ERAK: 930 ENSURE(size == 8U, (sscop, sscop->aarg, 931 "PDU_ERAK size=%u", size)); 932 sscop_signal(sscop, SIG_ERAK, msg); 933 break; 934 935 case PDU_USTAT: 936 ENSURE(size == 16U, (sscop, sscop->aarg, 937 "PDU_ERAK size=%u", size)); 938 sscop_signal(sscop, SIG_USTAT, msg); 939 break; 940 } 941#undef ENSURE 942 return; 943 944 err: 945 MAAL_ERROR(sscop, 'U', 0); 946 SSCOP_MSG_FREE(msg); 947} 948 949/************************************************************/ 950/* 951 * UTILITIES 952 */ 953 954/* 955 * Move the receiver window by N packets 956 */ 957u_int 958sscop_window(struct sscop *sscop, u_int n) 959{ 960 sscop->vr_mr += n; 961 return (SEQNO_DIFF(sscop->vr_mr, sscop->vr_r)); 962} 963 964/* 965 * Lower layer busy handling 966 */ 967u_int 968sscop_setbusy(struct sscop *sscop, int busy) 969{ 970 u_int old = sscop->ll_busy; 971 972 if (busy > 0) 973 sscop->ll_busy = 1; 974 else if (busy == 0) { 975 sscop->ll_busy = 0; 976 if(old) 977 handle_sigs(sscop); 978 } 979 980 return (old); 981} 982 983const char * 984sscop_signame(enum sscop_aasig sig) 985{ 986 static char str[40]; 987 988 if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) { 989 sprintf(str, "BAD SSCOP_AASIG %u", sig); 990 return (str); 991 } else { 992 return (sscop_sigs[sig]); 993 } 994} 995 996const char * 997sscop_msigname(enum sscop_maasig sig) 998{ 999 static char str[40]; 1000 1001 if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) { 1002 sprintf(str, "BAD SSCOP_MAASIG %u", sig); 1003 return (str); 1004 } else { 1005 return (sscop_msigs[sig]); 1006 } 1007} 1008 1009const char * 1010sscop_statename(enum sscop_state s) 1011{ 1012 static char str[40]; 1013 1014 if (s >= sizeof(states)/sizeof(states[0])) { 1015 sprintf(str, "BAD SSCOP_STATE %u", s); 1016 return (str); 1017 } else { 1018 return (states[s]); 1019 } 1020} 1021 1022 1023/************************************************************/ 1024/* 1025 * MACROS 1026 */ 1027 1028/* 1029 * p 75: release buffers 1030 */ 1031static void 1032m_release_buffers(struct sscop *sscop) 1033{ 1034 MSGQ_CLEAR(&sscop->xq); 1035 MSGQ_CLEAR(&sscop->xbuf); 1036 sscop->rxq = 0; 1037 MSGQ_CLEAR(&sscop->rbuf); 1038} 1039 1040/* 1041 * P 75: Prepare retrival 1042 */ 1043static void 1044m_prepare_retrieval(struct sscop *sscop) 1045{ 1046 struct sscop_msg *msg; 1047 1048 if (sscop->clear_buffers) { 1049 MSGQ_CLEAR(&sscop->xq); 1050 MSGQ_CLEAR(&sscop->xbuf); 1051 } 1052 MSGQ_FOREACH(msg, &sscop->xbuf) 1053 msg->rexmit = 0; 1054 sscop->rxq = 0; 1055 1056 MSGQ_CLEAR(&sscop->rbuf); 1057} 1058 1059/* 1060 * P 75: Prepare retrival 1061 */ 1062static void 1063m_prepare_recovery(struct sscop *sscop) 1064{ 1065 struct sscop_msg *msg; 1066 1067 if(sscop->clear_buffers) { 1068 MSGQ_CLEAR(&sscop->xq); 1069 MSGQ_CLEAR(&sscop->xbuf); 1070 } 1071 MSGQ_FOREACH(msg, &sscop->xbuf) 1072 msg->rexmit = 0; 1073 sscop->rxq = 0; 1074} 1075 1076 1077/* 1078 * P 75: Clear transmitter 1079 */ 1080static void 1081m_clear_transmitter(struct sscop *sscop) 1082{ 1083 if(!sscop->clear_buffers) { 1084 MSGQ_CLEAR(&sscop->xq); 1085 MSGQ_CLEAR(&sscop->xbuf); 1086 } 1087} 1088 1089 1090/* 1091 * p 75: Deliver data 1092 * Freeing the message is the responibility of the handler function. 1093 */ 1094static void 1095m_deliver_data(struct sscop *sscop) 1096{ 1097 struct sscop_msg *msg; 1098 u_int sn; 1099 1100 if ((msg = MSGQ_GET(&sscop->rbuf)) == NULL) 1101 return; 1102 1103 if (sscop->clear_buffers) { 1104 MSGQ_CLEAR(&sscop->rbuf); 1105 return; 1106 } 1107 1108 sn = msg->seqno + 1; 1109 AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno); 1110 MSG_FREE(msg); 1111 1112 while ((msg = MSGQ_GET(&sscop->rbuf)) != NULL) { 1113 ASSERT(msg->seqno == sn); 1114 if (++sn == SSCOP_MAXSEQNO) 1115 sn = 0; 1116 AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno); 1117 MSG_FREE(msg); 1118 } 1119} 1120 1121/* 1122 * P 75: Initialize state variables 1123 */ 1124static void 1125m_initialize_state(struct sscop *sscop) 1126{ 1127 sscop->vt_s = 0; 1128 sscop->vt_ps = 0; 1129 sscop->vt_a = 0; 1130 1131 sscop->vt_pa = 1; 1132 sscop->vt_pd = 0; 1133 sscop->credit = 1; 1134 1135 sscop->vr_r = 0; 1136 sscop->vr_h = 0; 1137} 1138 1139/* 1140 * p 76: Data retrieval 1141 */ 1142static void 1143m_data_retrieval(struct sscop *sscop, u_int rn) 1144{ 1145 struct sscop_msg *s; 1146 1147 if (rn != SSCOP_RETRIEVE_UNKNOWN) { 1148 if(rn >= SSCOP_RETRIEVE_TOTAL) 1149 rn = sscop->vt_a; 1150 else 1151 rn++; 1152 while(rn >= sscop->vt_a && rn < sscop->vt_s) { 1153 if(rn == SSCOP_MAXSEQNO) rn = 0; 1154 if((s = QFIND(&sscop->xbuf, rn)) != NULL) { 1155 MSGQ_REMOVE(&sscop->xbuf, s); 1156 AAL_DATA(sscop, SSCOP_RETRIEVE_indication, 1157 s->m, 0); 1158 MSG_FREE(s); 1159 } 1160 rn++; 1161 } 1162 } 1163 1164 while((s = MSGQ_GET(&sscop->xq)) != NULL) { 1165 AAL_DATA(sscop, SSCOP_RETRIEVE_indication, s->m, 0); 1166 MSG_FREE(s); 1167 } 1168 AAL_SIG(sscop, SSCOP_RETRIEVE_COMPL_indication); 1169} 1170 1171/* 1172 * P 76: Detect retransmission. PDU type must already be stripped. 1173 */ 1174static int 1175m_detect_retransmission(struct sscop *sscop, struct sscop_msg *msg) 1176{ 1177 union bgn bgn; 1178 1179 bgn.sscop_null = MBUF_TRAIL32(msg->m, -1); 1180 1181 if (sscop->vr_sq == bgn.sscop_bgns) 1182 return (1); 1183 1184 sscop->vr_sq = bgn.sscop_bgns; 1185 return (0); 1186} 1187 1188/* 1189 * P 76: Set POLL timer 1190 */ 1191static void 1192m_set_poll_timer(struct sscop *sscop) 1193{ 1194 if(MSGQ_EMPTY(&sscop->xq) && sscop->vt_s == sscop->vt_a) 1195 TIMER_RESTART(sscop, ka); 1196 else 1197 TIMER_RESTART(sscop, poll); 1198} 1199 1200/* 1201 * P 77: Reset data transfer timers 1202 */ 1203static void 1204m_reset_data_xfer_timers(struct sscop *sscop) 1205{ 1206 TIMER_STOP(sscop, ka); 1207 TIMER_STOP(sscop, nr); 1208 TIMER_STOP(sscop, idle); 1209 TIMER_STOP(sscop, poll); 1210} 1211 1212/* 1213 * P 77: Set data transfer timers 1214 */ 1215static void 1216m_set_data_xfer_timers(struct sscop *sscop) 1217{ 1218 TIMER_RESTART(sscop, poll); 1219 TIMER_RESTART(sscop, nr); 1220} 1221 1222/* 1223 * P 77: Initialize VR(MR) 1224 */ 1225static void 1226m_initialize_mr(struct sscop *sscop) 1227{ 1228 sscop->vr_mr = sscop->mr; 1229} 1230 1231/************************************************************/ 1232/* 1233 * CONDITIONS 1234 */ 1235static int 1236c_ready_pduq(struct sscop *sscop) 1237{ 1238 if (!sscop->ll_busy && 1239 (sscop->rxq != 0 || 1240 sscop->vt_s < sscop->vt_ms || 1241 TIMER_ISACT(sscop, idle))) 1242 return (1); 1243 return (0); 1244} 1245 1246/************************************************************/ 1247/* 1248 * SEND PDUS 1249 */ 1250 1251/* 1252 * Send BG PDU. 1253 */ 1254static void 1255send_bgn(struct sscop *sscop, struct SSCOP_MBUF_T *uu) 1256{ 1257 union pdu pdu; 1258 union bgn bgn; 1259 struct SSCOP_MBUF_T *m; 1260 1261 pdu.sscop_null = 0; 1262 pdu.sscop_type = PDU_BGN; 1263 pdu.sscop_ns = sscop->vr_mr; 1264 1265 bgn.sscop_null = 0; 1266 bgn.sscop_bgns = sscop->vt_sq; 1267 1268 if(uu) { 1269 if ((m = MBUF_DUP(uu)) == NULL) { 1270 FAILURE("sscop: cannot allocate BGN"); 1271 return; 1272 } 1273 pdu.sscop_pl += MBUF_PAD4(m); 1274 } else { 1275 if ((m = MBUF_ALLOC(8)) == NULL) { 1276 FAILURE("sscop: cannot allocate BGN"); 1277 return; 1278 } 1279 } 1280 1281 MBUF_APPEND32(m, bgn.sscop_null); 1282 MBUF_APPEND32(m, pdu.sscop_null); 1283 1284 AAL_SEND(sscop, m); 1285} 1286 1287/* 1288 * Send BGREJ PDU. 1289 */ 1290static void 1291send_bgrej(struct sscop *sscop, struct SSCOP_MBUF_T *uu) 1292{ 1293 union pdu pdu; 1294 union bgn bgn; 1295 struct SSCOP_MBUF_T *m; 1296 1297 pdu.sscop_null = 0; 1298 pdu.sscop_type = PDU_BGREJ; 1299 bgn.sscop_null = 0; 1300 1301 if(uu) { 1302 if((m = MBUF_DUP(uu)) == NULL) { 1303 FAILURE("sscop: cannot allocate BGREJ"); 1304 return; 1305 } 1306 pdu.sscop_pl += MBUF_PAD4(m); 1307 } else { 1308 if((m = MBUF_ALLOC(8)) == NULL) { 1309 FAILURE("sscop: cannot allocate BGREJ"); 1310 return; 1311 } 1312 } 1313 1314 MBUF_APPEND32(m, bgn.sscop_null); 1315 MBUF_APPEND32(m, pdu.sscop_null); 1316 1317 AAL_SEND(sscop, m); 1318} 1319 1320/* 1321 * Send BGAK PDU. 1322 */ 1323static void 1324send_bgak(struct sscop *sscop, struct SSCOP_MBUF_T *uu) 1325{ 1326 union pdu pdu; 1327 union bgn bgn; 1328 struct SSCOP_MBUF_T *m; 1329 1330 pdu.sscop_null = 0; 1331 pdu.sscop_type = PDU_BGAK; 1332 pdu.sscop_ns = sscop->vr_mr; 1333 bgn.sscop_null = 0; 1334 1335 if(uu) { 1336 if((m = MBUF_DUP(uu)) == NULL) { 1337 FAILURE("sscop: cannot allocate BGAK"); 1338 return; 1339 } 1340 pdu.sscop_pl += MBUF_PAD4(m); 1341 } else { 1342 if((m = MBUF_ALLOC(8)) == NULL) { 1343 FAILURE("sscop: cannot allocate BGAK"); 1344 return; 1345 } 1346 } 1347 1348 MBUF_APPEND32(m, bgn.sscop_null); 1349 MBUF_APPEND32(m, pdu.sscop_null); 1350 1351 AAL_SEND(sscop, m); 1352} 1353 1354/* 1355 * Send SD PDU. The function makes a duplicate of the message. 1356 */ 1357static void 1358send_sd(struct sscop *sscop, struct SSCOP_MBUF_T *m, u_int seqno) 1359{ 1360 union pdu pdu; 1361 1362 if((m = MBUF_DUP(m)) == NULL) { 1363 FAILURE("sscop: cannot allocate SD"); 1364 return; 1365 } 1366 1367 pdu.sscop_null = 0; 1368 pdu.sscop_pl = 0; 1369 pdu.sscop_type = PDU_SD; 1370 pdu.sscop_ns = seqno; 1371 1372 pdu.sscop_pl += MBUF_PAD4(m); 1373 1374 MBUF_APPEND32(m, pdu.sscop_null); 1375 1376 AAL_SEND(sscop, m); 1377} 1378 1379/* 1380 * Send a UD PDU. The caller must free the sscop msg part. 1381 */ 1382static void 1383send_ud(struct sscop *sscop, struct SSCOP_MBUF_T *m) 1384{ 1385 union pdu pdu; 1386 1387 pdu.sscop_null = 0; 1388 pdu.sscop_type = PDU_UD; 1389 1390 pdu.sscop_pl += MBUF_PAD4(m); 1391 1392 MBUF_APPEND32(m, pdu.sscop_null); 1393 1394 AAL_SEND(sscop, m); 1395} 1396 1397/* 1398 * Send a MD PDU. The caller must free the sscop msg part. 1399 */ 1400static void 1401send_md(struct sscop *sscop, struct SSCOP_MBUF_T *m) 1402{ 1403 union pdu pdu; 1404 1405 pdu.sscop_null = 0; 1406 pdu.sscop_type = PDU_MD; 1407 1408 pdu.sscop_pl += MBUF_PAD4(m); 1409 1410 MBUF_APPEND32(m, pdu.sscop_null); 1411 1412 AAL_SEND(sscop, m); 1413} 1414 1415/* 1416 * Send END PDU. 1417 */ 1418static void 1419send_end(struct sscop *sscop, int src, struct SSCOP_MBUF_T *uu) 1420{ 1421 union pdu pdu; 1422 struct SSCOP_MBUF_T *m; 1423 1424 sscop->last_end_src = src; 1425 1426 pdu.sscop_null = 0; 1427 pdu.sscop_s = src; 1428 pdu.sscop_type = PDU_END; 1429 1430 if(uu) { 1431 if((m = MBUF_DUP(uu)) == NULL) { 1432 FAILURE("sscop: cannot allocate END"); 1433 return; 1434 } 1435 pdu.sscop_pl += MBUF_PAD4(m); 1436 } else { 1437 if((m = MBUF_ALLOC(8)) == NULL) { 1438 FAILURE("sscop: cannot allocate END"); 1439 return; 1440 } 1441 } 1442 1443 MBUF_APPEND32(m, 0); 1444 MBUF_APPEND32(m, pdu.sscop_null); 1445 1446 AAL_SEND(sscop, m); 1447} 1448 1449/* 1450 * Send USTAT PDU. List must be terminated by -1. 1451 */ 1452static void 1453send_ustat(struct sscop *sscop, ...) 1454{ 1455 va_list ap; 1456 int f; 1457 u_int n; 1458 union pdu pdu; 1459 union seqno seqno; 1460 struct SSCOP_MBUF_T *m; 1461 1462 va_start(ap, sscop); 1463 n = 0; 1464 while((f = va_arg(ap, int)) >= 0) 1465 n++; 1466 va_end(ap); 1467 1468 if((m = MBUF_ALLOC(n * 4 + 8)) == NULL) { 1469 FAILURE("sscop: cannot allocate USTAT"); 1470 return; 1471 } 1472 1473 va_start(ap, sscop); 1474 while((f = va_arg(ap, int)) >= 0) { 1475 seqno.sscop_null = 0; 1476 seqno.sscop_n = f; 1477 MBUF_APPEND32(m, seqno.sscop_null); 1478 } 1479 va_end(ap); 1480 1481 seqno.sscop_null = 0; 1482 seqno.sscop_n = sscop->vr_mr; 1483 MBUF_APPEND32(m, seqno.sscop_null); 1484 1485 pdu.sscop_null = 0; 1486 pdu.sscop_type = PDU_USTAT; 1487 pdu.sscop_ns = sscop->vr_r; 1488 MBUF_APPEND32(m, pdu.sscop_null); 1489 1490 AAL_SEND(sscop, m); 1491} 1492 1493/* 1494 * Send ER PDU. 1495 */ 1496static void 1497send_er(struct sscop *sscop) 1498{ 1499 union pdu pdu; 1500 union bgn bgn; 1501 struct SSCOP_MBUF_T *m; 1502 1503 pdu.sscop_null = 0; 1504 pdu.sscop_type = PDU_ER; 1505 pdu.sscop_ns = sscop->vr_mr; 1506 1507 bgn.sscop_null = 0; 1508 bgn.sscop_bgns = sscop->vt_sq; 1509 1510 if((m = MBUF_ALLOC(8)) == NULL) { 1511 FAILURE("sscop: cannot allocate ER"); 1512 return; 1513 } 1514 MBUF_APPEND32(m, bgn.sscop_null); 1515 MBUF_APPEND32(m, pdu.sscop_null); 1516 1517 AAL_SEND(sscop, m); 1518} 1519 1520/* 1521 * Send POLL PDU. 1522 */ 1523static void 1524send_poll(struct sscop *sscop) 1525{ 1526 union pdu pdu; 1527 union seqno seqno; 1528 struct SSCOP_MBUF_T *m; 1529 1530 seqno.sscop_null = 0; 1531 seqno.sscop_n = sscop->vt_ps; 1532 1533 pdu.sscop_null = 0; 1534 pdu.sscop_ns = sscop->vt_s; 1535 pdu.sscop_type = PDU_POLL; 1536 1537 if((m = MBUF_ALLOC(8)) == NULL) { 1538 FAILURE("sscop: cannot allocate POLL"); 1539 return; 1540 } 1541 MBUF_APPEND32(m, seqno.sscop_null); 1542 MBUF_APPEND32(m, pdu.sscop_null); 1543 1544 AAL_SEND(sscop, m); 1545} 1546 1547/* 1548 * Send STAT PDU. List is already in buffer. 1549 */ 1550static void 1551send_stat(struct sscop *sscop, u_int nps, struct SSCOP_MBUF_T *m) 1552{ 1553 union pdu pdu; 1554 union seqno seqno; 1555 1556 seqno.sscop_null = 0; 1557 seqno.sscop_n = nps; 1558 MBUF_APPEND32(m, seqno.sscop_null); 1559 1560 seqno.sscop_null = 0; 1561 seqno.sscop_n = sscop->vr_mr; 1562 MBUF_APPEND32(m, seqno.sscop_null); 1563 1564 pdu.sscop_null = 0; 1565 pdu.sscop_type = PDU_STAT; 1566 pdu.sscop_ns = sscop->vr_r; 1567 MBUF_APPEND32(m, pdu.sscop_null); 1568 1569 AAL_SEND(sscop, m); 1570} 1571 1572/* 1573 * Send ENDAK PDU. 1574 */ 1575static void 1576send_endak(struct sscop *sscop) 1577{ 1578 union pdu pdu; 1579 union seqno seqno; 1580 struct SSCOP_MBUF_T *m; 1581 1582 seqno.sscop_null = 0; 1583 pdu.sscop_null = 0; 1584 pdu.sscop_type = PDU_ENDAK; 1585 1586 if((m = MBUF_ALLOC(8)) == NULL) { 1587 FAILURE("sscop: cannot allocate ENDAK"); 1588 return; 1589 } 1590 MBUF_APPEND32(m, seqno.sscop_null); 1591 MBUF_APPEND32(m, pdu.sscop_null); 1592 1593 AAL_SEND(sscop, m); 1594} 1595 1596/* 1597 * Send ERAK PDU. 1598 */ 1599static void 1600send_erak(struct sscop *sscop) 1601{ 1602 union pdu pdu; 1603 union seqno seqno; 1604 struct SSCOP_MBUF_T *m; 1605 1606 seqno.sscop_null = 0; 1607 pdu.sscop_null = 0; 1608 pdu.sscop_type = PDU_ERAK; 1609 pdu.sscop_ns = sscop->vr_mr; 1610 1611 if((m = MBUF_ALLOC(8)) == NULL) { 1612 FAILURE("sscop: cannot allocate ERAK"); 1613 return; 1614 } 1615 MBUF_APPEND32(m, seqno.sscop_null); 1616 MBUF_APPEND32(m, pdu.sscop_null); 1617 1618 AAL_SEND(sscop, m); 1619} 1620 1621/* 1622 * Send RS PDU 1623 */ 1624static void 1625send_rs(struct sscop *sscop, int resend, struct SSCOP_MBUF_T *uu) 1626{ 1627 union pdu pdu; 1628 union bgn bgn; 1629 struct SSCOP_MBUF_T *m; 1630 1631 pdu.sscop_null = 0; 1632 pdu.sscop_type = PDU_RS; 1633 pdu.sscop_ns = resend ? sscop->rs_mr : sscop->vr_mr; 1634 1635 bgn.sscop_null = 0; 1636 bgn.sscop_bgns = resend ? sscop->rs_sq : sscop->vt_sq; 1637 1638 sscop->rs_mr = pdu.sscop_ns; 1639 sscop->rs_sq = bgn.sscop_bgns; 1640 1641 if(uu) { 1642 if((m = MBUF_DUP(uu)) == NULL) { 1643 FAILURE("sscop: cannot allocate RS"); 1644 return; 1645 } 1646 pdu.sscop_pl += MBUF_PAD4(m); 1647 } else { 1648 if((m = MBUF_ALLOC(8)) == NULL) { 1649 FAILURE("sscop: cannot allocate RS"); 1650 return; 1651 } 1652 } 1653 1654 MBUF_APPEND32(m, bgn.sscop_null); 1655 MBUF_APPEND32(m, pdu.sscop_null); 1656 1657 AAL_SEND(sscop, m); 1658} 1659 1660/* 1661 * Send RSAK pdu 1662 */ 1663static void 1664send_rsak(struct sscop *sscop) 1665{ 1666 union pdu pdu; 1667 union seqno seqno; 1668 struct SSCOP_MBUF_T *m; 1669 1670 seqno.sscop_null = 0; 1671 pdu.sscop_null = 0; 1672 pdu.sscop_type = PDU_RSAK; 1673 pdu.sscop_ns = sscop->vr_mr; 1674 1675 if((m = MBUF_ALLOC(8)) == NULL) { 1676 FAILURE("sscop: cannot allocate RSAK"); 1677 return; 1678 } 1679 1680 MBUF_APPEND32(m, seqno.sscop_null); 1681 MBUF_APPEND32(m, pdu.sscop_null); 1682 1683 AAL_SEND(sscop, m); 1684} 1685 1686/************************************************************/ 1687/* 1688 * P 31; IDLE && AA-ESTABLISH-request 1689 * arg is UU data (opt). 1690 */ 1691static void 1692sscop_idle_establish_req(struct sscop *sscop, struct sscop_msg *uu) 1693{ 1694 u_int br = uu->rexmit; 1695 1696 SET_UU(uu_bgn, uu); 1697 1698 m_clear_transmitter(sscop); 1699 1700 sscop->clear_buffers = br; 1701 1702 sscop->vt_cc = 1; 1703 sscop->vt_sq++; 1704 1705 m_initialize_mr(sscop); 1706 1707 send_bgn(sscop, sscop->uu_bgn); 1708 1709 TIMER_RESTART(sscop, cc); 1710 1711 sscop_set_state(sscop, SSCOP_OUT_PEND); 1712} 1713 1714/* 1715 * P 31: IDLE && BGN PDU 1716 * arg is the received PDU (freed). 1717 */ 1718static void 1719sscop_idle_bgn(struct sscop *sscop, struct sscop_msg *msg) 1720{ 1721 union pdu pdu; 1722 union bgn bgn; 1723 1724 pdu.sscop_null = MBUF_STRIP32(msg->m); 1725 1726 if(sscop->robustness) { 1727 bgn.sscop_null = MBUF_STRIP32(msg->m); 1728 sscop->vr_sq = bgn.sscop_bgns; 1729 } else { 1730 if(m_detect_retransmission(sscop, msg)) { 1731 send_bgrej(sscop, sscop->uu_bgrej); 1732 SSCOP_MSG_FREE(msg); 1733 return; 1734 } 1735 (void)MBUF_STRIP32(msg->m); 1736 } 1737 1738 sscop->vt_ms = pdu.sscop_ns; 1739 sscop_set_state(sscop, SSCOP_IN_PEND); 1740 1741 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 1742} 1743 1744/* 1745 * p 31: IDLE && ENDAK PDU 1746 * p 34: OUT_PEND && ENDAK PDU 1747 * p 34: OUT_PEND && SD PDU 1748 * p 34: OUT_PEND && ERAK PDU 1749 * p 34: OUT_PEND && END PDU 1750 * p 34: OUT_PEND && STAT PDU 1751 * p 34: OUT_PEND && USTAT PDU 1752 * p 34: OUT_PEND && POLL PDU 1753 * p 36: OUT_PEND && RS PDU 1754 * p 36: OUT_PEND && RSAK PDU 1755 * p 40: OUTGOING_DISCONNECT_PENDING && SD PDU 1756 * p 40: OUTGOING_DISCONNECT_PENDING && BGAK PDU 1757 * p 40: OUTGOING_DISCONNECT_PENDING && POLL PDU 1758 * p 40: OUTGOING_DISCONNECT_PENDING && STAT PDU 1759 * p 40: OUTGOING_DISCONNECT_PENDING && USTAT PDU 1760 * p 41: OUTGOING_DISCONNECT_PENDING && ERAK PDU 1761 * p 42: OUTGOING_DISCONNECT_PENDING && ER PDU 1762 * p 42: OUTGOING_DISCONNECT_PENDING && RS PDU 1763 * p 42: OUTGOING_DISCONNECT_PENDING && RSAK PDU 1764 * p 43: OUTGOING_RESYNC && ER PDU 1765 * p 43: OUTGOING_RESYNC && POLL PDU 1766 * p 44: OUTGOING_RESYNC && STAT PDU 1767 * p 44: OUTGOING_RESYNC && USTAT PDU 1768 * p 45: OUTGOING_RESYNC && BGAK PDU 1769 * p 45: OUTGOING_RESYNC && SD PDU 1770 * p 45: OUTGOING_RESYNC && ERAK PDU 1771 * P 60: READY && BGAK PDU 1772 * P 60: READY && ERAK PDU 1773 * arg is pdu (freed). 1774 */ 1775static void 1776sscop_ignore_pdu(struct sscop *sscop __unused, struct sscop_msg *msg) 1777{ 1778 SSCOP_MSG_FREE(msg); 1779} 1780 1781/* 1782 * p 31: IDLE && END PDU 1783 * arg is pdu (freed). 1784 */ 1785static void 1786sscop_idle_end(struct sscop *sscop, struct sscop_msg *msg) 1787{ 1788 SSCOP_MSG_FREE(msg); 1789 send_endak(sscop); 1790} 1791 1792/* 1793 * p 31: IDLE && ER PDU 1794 * arg is pdu (freed). 1795 */ 1796static void 1797sscop_idle_er(struct sscop *sscop, struct sscop_msg *msg) 1798{ 1799 SSCOP_MSG_FREE(msg); 1800 MAAL_ERROR(sscop, 'L', 0); 1801 FREE_UU(uu_end); 1802 send_end(sscop, 1, NULL); 1803} 1804 1805/* 1806 * p 31: IDLE && BGREJ PDU 1807 * arg is pdu (freed). 1808 */ 1809static void 1810sscop_idle_bgrej(struct sscop *sscop, struct sscop_msg *msg) 1811{ 1812 SSCOP_MSG_FREE(msg); 1813 MAAL_ERROR(sscop, 'D', 0); 1814 FREE_UU(uu_end); 1815} 1816 1817/* 1818 * p 32: IDLE && POLL PDU 1819 * arg is pdu (freed). 1820 */ 1821static void 1822sscop_idle_poll(struct sscop *sscop, struct sscop_msg *msg) 1823{ 1824 SSCOP_MSG_FREE(msg); 1825 MAAL_ERROR(sscop, 'G', 0); 1826 FREE_UU(uu_end); 1827 send_end(sscop, 1, NULL); 1828} 1829 1830/* 1831 * p 32: IDLE && SD PDU 1832 * arg is pdu (freed). 1833 */ 1834static void 1835sscop_idle_sd(struct sscop *sscop, struct sscop_msg *msg) 1836{ 1837 SSCOP_MSG_FREE(msg); 1838 MAAL_ERROR(sscop, 'A', 0); 1839 FREE_UU(uu_end); 1840 send_end(sscop, 1, NULL); 1841} 1842 1843/* 1844 * p 32: IDLE && BGAK PDU 1845 * arg is pdu (freed). 1846 */ 1847static void 1848sscop_idle_bgak(struct sscop *sscop, struct sscop_msg *msg) 1849{ 1850 SSCOP_MSG_FREE(msg); 1851 MAAL_ERROR(sscop, 'C', 0); 1852 FREE_UU(uu_end); 1853 send_end(sscop, 1, NULL); 1854} 1855 1856/* 1857 * p 32: IDLE && ERAK PDU 1858 * arg is pdu (freed). 1859 */ 1860static void 1861sscop_idle_erak(struct sscop *sscop, struct sscop_msg *msg) 1862{ 1863 SSCOP_MSG_FREE(msg); 1864 MAAL_ERROR(sscop, 'M', 0); 1865 FREE_UU(uu_end); 1866 send_end(sscop, 1, NULL); 1867} 1868 1869/* 1870 * p 32: IDLE && STAT PDU 1871 * arg is pdu (freed). 1872 */ 1873static void 1874sscop_idle_stat(struct sscop *sscop, struct sscop_msg *msg) 1875{ 1876 SSCOP_MSG_FREE(msg); 1877 MAAL_ERROR(sscop, 'H', 0); 1878 FREE_UU(uu_end); 1879 send_end(sscop, 1, NULL); 1880} 1881 1882/* 1883 * p 32: IDLE && USTAT PDU 1884 * arg is pdu (freed). 1885 */ 1886static void 1887sscop_idle_ustat(struct sscop *sscop, struct sscop_msg *msg) 1888{ 1889 SSCOP_MSG_FREE(msg); 1890 MAAL_ERROR(sscop, 'I', 0); 1891 FREE_UU(uu_end); 1892 send_end(sscop, 1, NULL); 1893} 1894 1895/* 1896 * p 33: IDLE & RS PDU 1897 * arg is pdu (freed). 1898 */ 1899static void 1900sscop_idle_rs(struct sscop *sscop, struct sscop_msg *msg) 1901{ 1902 SSCOP_MSG_FREE(msg); 1903 MAAL_ERROR(sscop, 'J', 0); 1904 FREE_UU(uu_end); 1905 send_end(sscop, 1, NULL); 1906} 1907 1908/* 1909 * p 33: IDLE & RSAK PDU 1910 * arg is pdu (freed). 1911 */ 1912static void 1913sscop_idle_rsak(struct sscop *sscop, struct sscop_msg *msg) 1914{ 1915 SSCOP_MSG_FREE(msg); 1916 MAAL_ERROR(sscop, 'K', 0); 1917 FREE_UU(uu_end); 1918 send_end(sscop, 1, NULL); 1919} 1920 1921/* 1922 * p 33: IDLE && PDU_Q 1923 * p XX: OUTPEND && PDU_Q 1924 * p 39: IN_PEND && PDU_Q 1925 * p 45: OUT_RESYNC_PEND && PDU_Q 1926 * p 48: IN_RESYNC_PEND && PDU_Q 1927 * no arg 1928 */ 1929static void 1930sscop_flush_pduq(struct sscop *sscop __unused, struct sscop_msg *unused __unused) 1931{ 1932#if 0 1933 MSGQ_CLEAR(&sscop->xq); 1934#endif 1935} 1936 1937/* 1938 * p 34: OUT_PEND && BGAK PDU 1939 * arg is pdu (freed). 1940 */ 1941static void 1942sscop_outpend_bgak(struct sscop *sscop, struct sscop_msg *msg) 1943{ 1944 union pdu pdu; 1945 1946 pdu.sscop_null = MBUF_STRIP32(msg->m); 1947 (void)MBUF_STRIP32(msg->m); 1948 1949 TIMER_STOP(sscop, cc); 1950 sscop->vt_ms = pdu.sscop_ns; 1951 1952 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0); 1953 1954 m_initialize_state(sscop); 1955 m_set_data_xfer_timers(sscop); 1956 1957 sscop_set_state(sscop, SSCOP_READY); 1958} 1959 1960/* 1961 * P 34: OUT_PEND && BGREJ PDU 1962 */ 1963static void 1964sscop_outpend_bgrej(struct sscop *sscop, struct sscop_msg *msg) 1965{ 1966 union pdu pdu; 1967 1968 pdu.sscop_null = MBUF_STRIP32(msg->m); 1969 (void)MBUF_STRIP32(msg->m); 1970 1971 TIMER_STOP(sscop, cc); 1972 1973 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 0); 1974 1975 sscop_set_state(sscop, SSCOP_IDLE); 1976} 1977 1978/* 1979 * P 35: OUT_PEND && TIMER_CC expiry 1980 * no arg 1981 */ 1982static void 1983sscop_outpend_tcc(struct sscop *sscop, struct sscop_msg *unused __unused) 1984{ 1985 if(sscop->vt_cc >= sscop->maxcc) { 1986 MAAL_ERROR(sscop, 'O', 0); 1987 FREE_UU(uu_end); 1988 send_end(sscop, 1, NULL); 1989 1990 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 1991 1992 sscop_set_state(sscop, SSCOP_IDLE); 1993 } else { 1994 sscop->vt_cc++; 1995 send_bgn(sscop, sscop->uu_bgn); 1996 TIMER_RESTART(sscop, cc); 1997 } 1998} 1999 2000/* 2001 * P 35: OUT_PEND && RELEASE_REQ 2002 * arg is UU 2003 */ 2004static void 2005sscop_outpend_release_req(struct sscop *sscop, struct sscop_msg *uu) 2006{ 2007 SET_UU(uu_end, uu); 2008 2009 TIMER_STOP(sscop, cc); 2010 sscop->vt_cc = 1; 2011 send_end(sscop, 0, sscop->uu_end); 2012 TIMER_RESTART(sscop, cc); 2013 2014 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2015} 2016 2017/* 2018 * P 36: OUT_PEND && BGN PDU 2019 * arg is the received PDU (freed). 2020 */ 2021static void 2022sscop_outpend_bgn(struct sscop *sscop, struct sscop_msg *msg) 2023{ 2024 union pdu pdu; 2025 2026 pdu.sscop_null = MBUF_STRIP32(msg->m); 2027 2028 if(m_detect_retransmission(sscop, msg)) { 2029 SSCOP_MSG_FREE(msg); 2030 return; 2031 } 2032 (void)MBUF_STRIP32(msg->m); 2033 2034 TIMER_STOP(sscop, cc); 2035 2036 sscop->vt_ms = pdu.sscop_ns; 2037 2038 m_initialize_mr(sscop); 2039 2040 send_bgak(sscop, sscop->uu_bgak); 2041 2042 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0); 2043 2044 m_initialize_state(sscop); 2045 2046 m_set_data_xfer_timers(sscop); 2047 2048 sscop_set_state(sscop, SSCOP_READY); 2049} 2050 2051/* 2052 * p 37: IN_PEND && AA-ESTABLISH.response 2053 * arg is UU 2054 */ 2055static void 2056sscop_inpend_establish_resp(struct sscop *sscop, struct sscop_msg *uu) 2057{ 2058 u_int br = uu->rexmit; 2059 2060 SET_UU(uu_bgak, uu); 2061 2062 m_clear_transmitter(sscop); 2063 sscop->clear_buffers = br; 2064 m_initialize_mr(sscop); 2065 send_bgak(sscop, sscop->uu_bgak); 2066 m_initialize_state(sscop); 2067 m_set_data_xfer_timers(sscop); 2068 2069 sscop_set_state(sscop, SSCOP_READY); 2070} 2071 2072/* 2073 * p 37: IN_PEND && AA-RELEASE.request 2074 * arg is uu. 2075 */ 2076static void 2077sscop_inpend_release_req(struct sscop *sscop, struct sscop_msg *uu) 2078{ 2079 SET_UU(uu_bgrej, uu); 2080 2081 send_bgrej(sscop, sscop->uu_bgrej); 2082 2083 sscop_set_state(sscop, SSCOP_IDLE); 2084} 2085 2086/* 2087 * p 37: IN_PEND && BGN PDU 2088 * arg is pdu. (freed) 2089 */ 2090static void 2091sscop_inpend_bgn(struct sscop *sscop, struct sscop_msg *msg) 2092{ 2093 union pdu pdu; 2094 2095 pdu.sscop_null = MBUF_STRIP32(msg->m); 2096 2097 if(m_detect_retransmission(sscop, msg)) { 2098 SSCOP_MSG_FREE(msg); 2099 return; 2100 } 2101 (void)MBUF_STRIP32(msg->m); 2102 2103 sscop->vt_ms = pdu.sscop_ns; 2104 2105 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2106 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 2107} 2108 2109/* 2110 * p 37: IN_PEND && ER PDU 2111 * arg is pdu (freed). 2112 */ 2113static void 2114sscop_inpend_er(struct sscop *sscop, struct sscop_msg *msg) 2115{ 2116 MAAL_ERROR(sscop, 'L', 0); 2117 SSCOP_MSG_FREE(msg); 2118} 2119 2120/* 2121 * p 37: IN_PEND && ENDAK PDU 2122 * arg is pdu (freed). 2123 */ 2124static void 2125sscop_inpend_endak(struct sscop *sscop, struct sscop_msg *msg) 2126{ 2127 MAAL_ERROR(sscop, 'F', 0); 2128 2129 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2130 2131 sscop_set_state(sscop, SSCOP_IDLE); 2132 2133 SSCOP_MSG_FREE(msg); 2134} 2135 2136/* 2137 * p 38: IN_PEND && BGAK PDU 2138 * arg is pdu (freed). 2139 */ 2140static void 2141sscop_inpend_bgak(struct sscop *sscop, struct sscop_msg *msg) 2142{ 2143 MAAL_ERROR(sscop, 'C', 0); 2144 2145 SSCOP_MSG_FREE(msg); 2146} 2147 2148/* 2149 * p 38: IN_PEND && BGREJ PDU 2150 * arg is pdu (freed). 2151 */ 2152static void 2153sscop_inpend_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2154{ 2155 MAAL_ERROR(sscop, 'D', 0); 2156 2157 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2158 2159 SSCOP_MSG_FREE(msg); 2160 2161 sscop_set_state(sscop, SSCOP_IDLE); 2162} 2163 2164/* 2165 * p 38: IN_PEND && SD PDU 2166 * arg is pdu (freed). 2167 */ 2168static void 2169sscop_inpend_sd(struct sscop *sscop, struct sscop_msg *msg) 2170{ 2171 MAAL_ERROR(sscop, 'A', 0); 2172 2173 SSCOP_MSG_FREE(msg); 2174 2175 FREE_UU(uu_end); 2176 send_end(sscop, 1, NULL); 2177 2178 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2179 2180 sscop_set_state(sscop, SSCOP_IDLE); 2181} 2182 2183/* 2184 * p 38: IN_PEND && USTAT PDU 2185 * arg is pdu (freed). 2186 */ 2187static void 2188sscop_inpend_ustat(struct sscop *sscop, struct sscop_msg *msg) 2189{ 2190 MAAL_ERROR(sscop, 'I', 0); 2191 2192 SSCOP_MSG_FREE(msg); 2193 2194 FREE_UU(uu_end); 2195 send_end(sscop, 1, NULL); 2196 2197 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2198 2199 sscop_set_state(sscop, SSCOP_IDLE); 2200} 2201 2202/* 2203 * p 38: IN_PEND && STAT PDU 2204 * arg is pdu (freed). 2205 */ 2206static void 2207sscop_inpend_stat(struct sscop *sscop, struct sscop_msg *msg) 2208{ 2209 MAAL_ERROR(sscop, 'H', 0); 2210 2211 SSCOP_MSG_FREE(msg); 2212 2213 FREE_UU(uu_end); 2214 send_end(sscop, 1, NULL); 2215 2216 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2217 2218 sscop_set_state(sscop, SSCOP_IDLE); 2219} 2220 2221/* 2222 * p 38: IN_PEND && POLL PDU 2223 * arg is pdu (freed). 2224 */ 2225static void 2226sscop_inpend_poll(struct sscop *sscop, struct sscop_msg *msg) 2227{ 2228 MAAL_ERROR(sscop, 'G', 0); 2229 2230 SSCOP_MSG_FREE(msg); 2231 2232 FREE_UU(uu_end); 2233 send_end(sscop, 1, NULL); 2234 2235 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2236 2237 sscop_set_state(sscop, SSCOP_IDLE); 2238} 2239 2240/* 2241 * p 39: IN_PEND && ERAK PDU 2242 * arg is pdu (freed). 2243 */ 2244static void 2245sscop_inpend_erak(struct sscop *sscop, struct sscop_msg *msg) 2246{ 2247 SSCOP_MSG_FREE(msg); 2248 MAAL_ERROR(sscop, 'M', 0); 2249} 2250 2251/* 2252 * p 39: IN_PEND & RS PDU 2253 * arg is pdu (freed). 2254 */ 2255static void 2256sscop_inpend_rs(struct sscop *sscop, struct sscop_msg *msg) 2257{ 2258 SSCOP_MSG_FREE(msg); 2259 MAAL_ERROR(sscop, 'J', 0); 2260} 2261 2262/* 2263 * p 39: IN_PEND & RSAK PDU 2264 * arg is pdu (freed). 2265 */ 2266static void 2267sscop_inpend_rsak(struct sscop *sscop, struct sscop_msg *msg) 2268{ 2269 SSCOP_MSG_FREE(msg); 2270 MAAL_ERROR(sscop, 'K', 0); 2271} 2272 2273/* 2274 * p 39: IN_PEND && END PDU 2275 * arg is pdu (freed). 2276 * no uui 2277 */ 2278static void 2279sscop_inpend_end(struct sscop *sscop, struct sscop_msg *msg) 2280{ 2281 union pdu pdu; 2282 2283 pdu.sscop_null = MBUF_STRIP32(msg->m); 2284 (void)MBUF_STRIP32(msg->m); 2285 2286 send_endak(sscop); 2287 2288 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 2289 msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 2290 2291 sscop_set_state(sscop, SSCOP_IDLE); 2292} 2293 2294/* 2295 * p 40: OUT_DIS_PEND && SSCOP_ESTABLISH_request 2296 * no arg. 2297 * no uui. 2298 */ 2299static void 2300sscop_outdis_establish_req(struct sscop *sscop, struct sscop_msg *uu) 2301{ 2302 SET_UU(uu_bgn, uu); 2303 2304 TIMER_STOP(sscop, cc); 2305 m_clear_transmitter(sscop); 2306 sscop->clear_buffers = 1; 2307 sscop->vt_cc = 1; 2308 sscop->vt_sq++; 2309 m_initialize_mr(sscop); 2310 send_bgn(sscop, sscop->uu_bgn); 2311 TIMER_RESTART(sscop, cc); 2312 2313 sscop_set_state(sscop, SSCOP_OUT_PEND); 2314} 2315 2316/* 2317 * p 41: OUT_DIS_PEND && END PDU 2318 * arg is pdu (freed). 2319 */ 2320static void 2321sscop_outdis_end(struct sscop *sscop, struct sscop_msg *msg) 2322{ 2323 union pdu pdu; 2324 2325 pdu.sscop_null = MBUF_STRIP32(msg->m); 2326 (void)MBUF_STRIP32(msg->m); 2327 2328 TIMER_STOP(sscop, cc); 2329 send_endak(sscop); 2330 2331 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0); 2332 2333 sscop_set_state(sscop, SSCOP_IDLE); 2334} 2335 2336/* 2337 * p 41: OUT_DIS_PEND && ENDAK PDU 2338 * p 41: OUT_DIS_PEND && BGREJ PDU 2339 * arg is pdu (freed) 2340 */ 2341static void 2342sscop_outdis_endak(struct sscop *sscop, struct sscop_msg *msg) 2343{ 2344 union pdu pdu; 2345 2346 pdu.sscop_null = MBUF_STRIP32(msg->m); 2347 (void)MBUF_STRIP32(msg->m); 2348 2349 TIMER_STOP(sscop, cc); 2350 2351 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0); 2352 2353 sscop_set_state(sscop, SSCOP_IDLE); 2354} 2355 2356/* 2357 * p 41: OUT_DIS_PEND && TIMER CC expiry 2358 * no arg 2359 */ 2360static void 2361sscop_outdis_cc(struct sscop *sscop, struct sscop_msg *unused __unused) 2362{ 2363 if(sscop->vt_cc >= sscop->maxcc) { 2364 MAAL_ERROR(sscop, 'O', 0); 2365 AAL_SIG(sscop, SSCOP_RELEASE_confirm); 2366 sscop_set_state(sscop, SSCOP_IDLE); 2367 } else { 2368 sscop->vt_cc++; 2369 send_end(sscop, sscop->last_end_src, sscop->uu_end); 2370 TIMER_RESTART(sscop, cc); 2371 } 2372} 2373 2374/* 2375 * p 42: OUT_DIS_PEND && BGN PDU 2376 * arg is pdu (freed). 2377 */ 2378static void 2379sscop_outdis_bgn(struct sscop *sscop, struct sscop_msg *msg) 2380{ 2381 union pdu pdu; 2382 2383 pdu.sscop_null = MBUF_STRIP32(msg->m); 2384 2385 if(m_detect_retransmission(sscop, msg)) { 2386 FREE_UU(uu_bgak); 2387 send_bgak(sscop, NULL); 2388 send_end(sscop, sscop->last_end_src, sscop->uu_end); 2389 SSCOP_MSG_FREE(msg); 2390 2391 } else { 2392 (void)MBUF_STRIP32(msg->m); 2393 2394 TIMER_STOP(sscop, cc); 2395 sscop->vt_ms = pdu.sscop_ns; 2396 AAL_SIG(sscop, SSCOP_RELEASE_confirm); 2397 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, 2398 msg, pdu.sscop_pl, 0); 2399 sscop_set_state(sscop, SSCOP_IN_PEND); 2400 } 2401} 2402 2403/* 2404 * p 43: OUT_RESYNC_PEND && BGN PDU 2405 * arg is pdu (freed). 2406 */ 2407static void 2408sscop_outsync_bgn(struct sscop *sscop, struct sscop_msg *msg) 2409{ 2410 union pdu pdu; 2411 2412 pdu.sscop_null = MBUF_STRIP32(msg->m); 2413 2414 if(m_detect_retransmission(sscop, msg)) { 2415 send_bgak(sscop, sscop->uu_bgak); 2416 send_rs(sscop, 1, sscop->uu_rs); 2417 SSCOP_MSG_FREE(msg); 2418 } else { 2419 (void)MBUF_STRIP32(msg->m); 2420 2421 TIMER_STOP(sscop, cc); 2422 sscop->vt_ms = pdu.sscop_ns; 2423 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2424 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, 2425 msg, pdu.sscop_pl, 0); 2426 sscop_set_state(sscop, SSCOP_IN_PEND); 2427 } 2428} 2429 2430/* 2431 * p 43: OUT_RESYNC_PEND && ENDAK PDU 2432 * arg is pdu (freed). 2433 */ 2434static void 2435sscop_outsync_endak(struct sscop *sscop, struct sscop_msg *msg) 2436{ 2437 SSCOP_MSG_FREE(msg); 2438 TIMER_STOP(sscop, cc); 2439 MAAL_ERROR(sscop, 'F', 0); 2440 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2441 sscop_set_state(sscop, SSCOP_IDLE); 2442} 2443 2444/* 2445 * p 43: OUT_RESYNC_PEND && BGREJ PDU 2446 * arg is pdu (freed). 2447 */ 2448static void 2449sscop_outsync_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2450{ 2451 SSCOP_MSG_FREE(msg); 2452 TIMER_STOP(sscop, cc); 2453 MAAL_ERROR(sscop, 'D', 0); 2454 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2455 sscop_set_state(sscop, SSCOP_IDLE); 2456} 2457 2458/* 2459 * p 43: OUT_RESYNC_PEND && END PDU 2460 * arg is pdu (freed). 2461 * no UU-data 2462 */ 2463static void 2464sscop_outsync_end(struct sscop *sscop, struct sscop_msg *msg) 2465{ 2466 union pdu pdu; 2467 2468 pdu.sscop_null = MBUF_STRIP32(msg->m); 2469 (void)MBUF_STRIP32(msg->m); 2470 2471 TIMER_STOP(sscop, cc); 2472 send_endak(sscop); 2473 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 2474 (u_int)pdu.sscop_s); 2475 sscop_set_state(sscop, SSCOP_IDLE); 2476} 2477 2478/* 2479 * p 44: OUT_RESYNC && TIMER CC expiry 2480 */ 2481static void 2482sscop_outsync_cc(struct sscop *sscop, struct sscop_msg *msg __unused) 2483{ 2484 if(sscop->vt_cc == sscop->maxcc) { 2485 MAAL_ERROR(sscop, 'O', 0); 2486 FREE_UU(uu_end); 2487 send_end(sscop, 1, NULL); 2488 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2489 sscop_set_state(sscop, SSCOP_IDLE); 2490 } else { 2491 sscop->vt_cc++; 2492 send_rs(sscop, 1, sscop->uu_rs); 2493 TIMER_RESTART(sscop, cc); 2494 } 2495} 2496 2497/* 2498 * p 44: OUT_RESYNC && AA-RELEASE.request 2499 * arg is UU 2500 */ 2501static void 2502sscop_outsync_release_req(struct sscop *sscop, struct sscop_msg *uu) 2503{ 2504 SET_UU(uu_end, uu); 2505 2506 TIMER_STOP(sscop, cc); 2507 sscop->vt_cc = 1; 2508 send_end(sscop, 0, sscop->uu_end); 2509 TIMER_RESTART(sscop, cc); 2510 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2511} 2512 2513/* 2514 * p 45: OUT_RESYNC && RS PDU 2515 * arg is pdu (freed). 2516 */ 2517static void 2518sscop_outsync_rs(struct sscop *sscop, struct sscop_msg *msg) 2519{ 2520 union pdu pdu; 2521 2522 pdu.sscop_null = MBUF_STRIP32(msg->m); 2523 2524 if(m_detect_retransmission(sscop, msg)) { 2525 SSCOP_MSG_FREE(msg); 2526 return; 2527 } 2528 (void)MBUF_STRIP32(msg->m); 2529 2530 TIMER_STOP(sscop, cc); 2531 sscop->vt_ms = pdu.sscop_ns; 2532 m_initialize_mr(sscop); 2533 send_rsak(sscop); 2534 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_confirm, msg, pdu.sscop_pl, 0); 2535 m_initialize_state(sscop); 2536 m_set_data_xfer_timers(sscop); 2537 sscop_set_state(sscop, SSCOP_READY); 2538} 2539 2540/* 2541 * p 45: OUT_RESYNC && RSAK PDU 2542 * arg is pdu (freed). 2543 */ 2544static void 2545sscop_outsync_rsak(struct sscop *sscop, struct sscop_msg *msg) 2546{ 2547 union pdu pdu; 2548 2549 pdu.sscop_null = MBUF_STRIP32(msg->m); 2550 2551 SSCOP_MSG_FREE(msg); 2552 2553 TIMER_STOP(sscop, cc); 2554 sscop->vt_ms = pdu.sscop_ns; 2555 AAL_SIG(sscop, SSCOP_RESYNC_confirm); 2556 m_initialize_state(sscop); 2557 m_set_data_xfer_timers(sscop); 2558 sscop_set_state(sscop, SSCOP_READY); 2559} 2560 2561/* 2562 * p 46: IN_RESYNC_PEND && AA-RESYNC.response 2563 */ 2564static void 2565sscop_insync_sync_resp(struct sscop *sscop, struct sscop_msg *noarg __unused) 2566{ 2567 m_initialize_mr(sscop); 2568 send_rsak(sscop); 2569 m_clear_transmitter(sscop); 2570 m_initialize_state(sscop); 2571 m_set_data_xfer_timers(sscop); 2572 sscop_set_state(sscop, SSCOP_READY); 2573} 2574 2575/* 2576 * p 46: IN_RESYNC_PEND && AA-RELEASE.request 2577 * arg is uu 2578 */ 2579static void 2580sscop_insync_release_req(struct sscop *sscop, struct sscop_msg *uu) 2581{ 2582 SET_UU(uu_end, uu); 2583 2584 sscop->vt_cc = 1; 2585 send_end(sscop, 0, sscop->uu_end); 2586 TIMER_RESTART(sscop, cc); 2587 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2588} 2589 2590/* 2591 * p 46: IN_RESYNC_PEND && ENDAK PDU 2592 * arg is pdu (freed). 2593 */ 2594static void 2595sscop_insync_endak(struct sscop *sscop, struct sscop_msg *msg) 2596{ 2597 SSCOP_MSG_FREE(msg); 2598 MAAL_ERROR(sscop, 'F', 0); 2599 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2600 sscop_set_state(sscop, SSCOP_IDLE); 2601} 2602 2603/* 2604 * p 46: IN_RESYNC_PEND && BGREJ PDU 2605 * arg is pdu (freed). 2606 */ 2607static void 2608sscop_insync_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2609{ 2610 SSCOP_MSG_FREE(msg); 2611 MAAL_ERROR(sscop, 'D', 0); 2612 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2613 sscop_set_state(sscop, SSCOP_IDLE); 2614} 2615 2616/* 2617 * p 46: IN_RESYNC_PEND && END PDU 2618 * arg is pdu (freed). 2619 */ 2620static void 2621sscop_insync_end(struct sscop *sscop, struct sscop_msg *msg) 2622{ 2623 union pdu pdu; 2624 2625 pdu.sscop_null = MBUF_STRIP32(msg->m); 2626 (void)MBUF_STRIP32(msg->m); 2627 2628 send_endak(sscop); 2629 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 2630 msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 2631 sscop_set_state(sscop, SSCOP_IDLE); 2632} 2633 2634/* 2635 * p 47: IN_RESYNC_PEND && ER PDU 2636 * arg is pdu (freed). 2637 */ 2638static void 2639sscop_insync_er(struct sscop *sscop, struct sscop_msg *msg) 2640{ 2641 SSCOP_MSG_FREE(msg); 2642 MAAL_ERROR(sscop, 'L', 0); 2643} 2644 2645/* 2646 * p 47: IN_RESYNC_PEND && BGN PDU 2647 * arg is pdu (freed). 2648 */ 2649static void 2650sscop_insync_bgn(struct sscop *sscop, struct sscop_msg *msg) 2651{ 2652 union pdu pdu; 2653 2654 pdu.sscop_null = MBUF_STRIP32(msg->m); 2655 2656 if(m_detect_retransmission(sscop, msg)) { 2657 MAAL_ERROR(sscop, 'B', 0); 2658 SSCOP_MSG_FREE(msg); 2659 return; 2660 } 2661 (void)MBUF_STRIP32(msg->m); 2662 2663 sscop->vt_ms = pdu.sscop_ns; 2664 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2665 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 2666 2667 sscop_set_state(sscop, SSCOP_IN_PEND); 2668} 2669 2670/* 2671 * p 47: IN_RESYNC_PEND && SD PDU 2672 * arg is pdu (freed). 2673 */ 2674static void 2675sscop_insync_sd(struct sscop *sscop, struct sscop_msg *msg) 2676{ 2677 SSCOP_MSG_FREE(msg); 2678 MAAL_ERROR(sscop, 'A', 0); 2679 FREE_UU(uu_end); 2680 send_end(sscop, 1, NULL); 2681 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2682 sscop_set_state(sscop, SSCOP_IDLE); 2683} 2684 2685/* 2686 * p 47: IN_RESYNC_PEND && POLL PDU 2687 * arg is pdu (freed). 2688 */ 2689static void 2690sscop_insync_poll(struct sscop *sscop, struct sscop_msg *msg) 2691{ 2692 SSCOP_MSG_FREE(msg); 2693 MAAL_ERROR(sscop, 'G', 0); 2694 FREE_UU(uu_end); 2695 send_end(sscop, 1, NULL); 2696 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2697 sscop_set_state(sscop, SSCOP_IDLE); 2698} 2699 2700/* 2701 * p 47: IN_RESYNC_PEND && STAT PDU 2702 * arg is pdu (freed). 2703 */ 2704static void 2705sscop_insync_stat(struct sscop *sscop, struct sscop_msg *msg) 2706{ 2707 SSCOP_MSG_FREE(msg); 2708 MAAL_ERROR(sscop, 'H', 0); 2709 FREE_UU(uu_end); 2710 send_end(sscop, 1, NULL); 2711 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2712 sscop_set_state(sscop, SSCOP_IDLE); 2713} 2714 2715/* 2716 * p 47: IN_RESYNC_PEND && USTAT PDU 2717 * arg is pdu (freed). 2718 */ 2719static void 2720sscop_insync_ustat(struct sscop *sscop, struct sscop_msg *msg) 2721{ 2722 SSCOP_MSG_FREE(msg); 2723 MAAL_ERROR(sscop, 'I', 0); 2724 FREE_UU(uu_end); 2725 send_end(sscop, 1, NULL); 2726 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2727 sscop_set_state(sscop, SSCOP_IDLE); 2728} 2729 2730/* 2731 * p 48: IN_RESYNC_PEND && BGAK PDU 2732 * arg is pdu (freed). 2733 */ 2734static void 2735sscop_insync_bgak(struct sscop *sscop, struct sscop_msg *msg) 2736{ 2737 MAAL_ERROR(sscop, 'C', 0); 2738 SSCOP_MSG_FREE(msg); 2739} 2740 2741/* 2742 * p 48: IN_RESYNC_PEND && ERAK PDU 2743 * arg is pdu (freed). 2744 */ 2745static void 2746sscop_insync_erak(struct sscop *sscop, struct sscop_msg *msg) 2747{ 2748 MAAL_ERROR(sscop, 'M', 0); 2749 SSCOP_MSG_FREE(msg); 2750} 2751 2752/* 2753 * p 48: IN_RESYNC_PEND && RS PDU 2754 * arg is pdu (freed). 2755 */ 2756static void 2757sscop_insync_rs(struct sscop *sscop, struct sscop_msg *msg) 2758{ 2759 union pdu pdu; 2760 2761 pdu.sscop_null = MBUF_STRIP32(msg->m); 2762 2763 if(m_detect_retransmission(sscop, msg)) { 2764 SSCOP_MSG_FREE(msg); 2765 return; 2766 } 2767 SSCOP_MSG_FREE(msg); 2768 MAAL_ERROR(sscop, 'J', 0); 2769} 2770 2771/* 2772 * p 48: IN_RESYNC_PEND && RSAK PDU 2773 * arg is pdu (freed). 2774 */ 2775static void 2776sscop_insync_rsak(struct sscop *sscop, struct sscop_msg *msg) 2777{ 2778 MAAL_ERROR(sscop, 'K', 0); 2779 SSCOP_MSG_FREE(msg); 2780} 2781 2782 2783/* 2784 * p 49: OUT_REC_PEND && AA-DATA.request 2785 * arg is message (queued). 2786 */ 2787static void 2788sscop_outrec_userdata(struct sscop *sscop, struct sscop_msg *msg) 2789{ 2790 if(!sscop->clear_buffers) { 2791 MSGQ_APPEND(&sscop->xq, msg); 2792 sscop_signal(sscop, SIG_PDU_Q, msg); 2793 } else { 2794 SSCOP_MSG_FREE(msg); 2795 } 2796} 2797 2798/* 2799 * p 49: OUT_REC_PEND && BGAK PDU 2800 * arg is pdu (freed) 2801 */ 2802static void 2803sscop_outrec_bgak(struct sscop *sscop, struct sscop_msg *msg) 2804{ 2805 MAAL_ERROR(sscop, 'C', 0); 2806 2807 SSCOP_MSG_FREE(msg); 2808} 2809 2810/* 2811 * p 49: OUT_REC_PEND && ERAK PDU 2812 * arg is pdu (freed) 2813 */ 2814static void 2815sscop_outrec_erak(struct sscop *sscop, struct sscop_msg *msg) 2816{ 2817 union pdu pdu; 2818 2819 pdu.sscop_null = MBUF_STRIP32(msg->m); 2820 2821 TIMER_STOP(sscop, cc); 2822 sscop->vt_ms = pdu.sscop_ns; 2823 m_deliver_data(sscop); 2824 2825 AAL_SIG(sscop, SSCOP_RECOVER_indication); 2826 2827 sscop_set_state(sscop, SSCOP_REC_PEND); 2828 2829 SSCOP_MSG_FREE(msg); 2830} 2831 2832/* 2833 * p 49: OUT_REC_PEND && END PDU 2834 * arg is pdu (freed) 2835 */ 2836static void 2837sscop_outrec_end(struct sscop *sscop, struct sscop_msg *msg) 2838{ 2839 union pdu pdu; 2840 2841 pdu.sscop_null = MBUF_STRIP32(msg->m); 2842 (void)MBUF_STRIP32(msg->m); 2843 2844 TIMER_STOP(sscop, cc); 2845 send_endak(sscop); 2846 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 2847 msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 2848 2849 MSGQ_CLEAR(&sscop->rbuf); 2850 2851 sscop_set_state(sscop, SSCOP_IDLE); 2852} 2853 2854/* 2855 * p 49: OUT_REC_PEND && ENDAK PDU 2856 * arg is pdu (freed) 2857 */ 2858static void 2859sscop_outrec_endak(struct sscop *sscop, struct sscop_msg *msg) 2860{ 2861 MAAL_ERROR(sscop, 'F', 0); 2862 TIMER_STOP(sscop, cc); 2863 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2864 MSGQ_CLEAR(&sscop->rbuf); 2865 2866 sscop_set_state(sscop, SSCOP_IDLE); 2867 2868 SSCOP_MSG_FREE(msg); 2869} 2870 2871/* 2872 * p 49: OUT_REC_PEND && BGREJ PDU 2873 * arg is pdu (freed) 2874 */ 2875static void 2876sscop_outrec_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2877{ 2878 MAAL_ERROR(sscop, 'D', 0); 2879 TIMER_STOP(sscop, cc); 2880 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2881 MSGQ_CLEAR(&sscop->rbuf); 2882 2883 sscop_set_state(sscop, SSCOP_IDLE); 2884 2885 SSCOP_MSG_FREE(msg); 2886} 2887 2888/* 2889 * p 50: OUT_REC_PEND && TIMER CC expiry 2890 * no arg. 2891 */ 2892static void 2893sscop_outrec_cc(struct sscop *sscop, struct sscop_msg *unused __unused) 2894{ 2895 if(sscop->vt_cc >= sscop->maxcc) { 2896 MAAL_ERROR(sscop, 'O', 0); 2897 FREE_UU(uu_end); 2898 send_end(sscop, 1, NULL); 2899 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2900 MSGQ_CLEAR(&sscop->rbuf); 2901 sscop_set_state(sscop, SSCOP_IDLE); 2902 } else { 2903 sscop->vt_cc++; 2904 send_er(sscop); 2905 TIMER_RESTART(sscop, cc); 2906 } 2907} 2908 2909/* 2910 * p 50: OUT_REC_PEND && SSCOP_RELEASE_request 2911 * arg is UU 2912 */ 2913static void 2914sscop_outrec_release_req(struct sscop *sscop, struct sscop_msg *uu) 2915{ 2916 SET_UU(uu_end, uu); 2917 2918 TIMER_STOP(sscop, cc); 2919 sscop->vt_cc = 1; 2920 send_end(sscop, 0, sscop->uu_end); 2921 MSGQ_CLEAR(&sscop->rbuf); 2922 TIMER_RESTART(sscop, cc); 2923 2924 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2925} 2926 2927/* 2928 * p 51: OUT_REC_PEND && AA-RESYNC.request 2929 * arg is uu 2930 */ 2931static void 2932sscop_outrec_sync_req(struct sscop *sscop, struct sscop_msg *uu) 2933{ 2934 SET_UU(uu_rs, uu); 2935 2936 TIMER_STOP(sscop, cc); 2937 sscop->vt_cc = 1; 2938 sscop->vt_sq++; 2939 m_initialize_mr(sscop); 2940 send_rs(sscop, 0, sscop->uu_rs); 2941 m_clear_transmitter(sscop); 2942 MSGQ_CLEAR(&sscop->rbuf); 2943 TIMER_RESTART(sscop, cc); 2944} 2945 2946/* 2947 * p 51: OUT_REC_PEND && BGN PDU 2948 * arg is pdu (freed). 2949 * no uui 2950 */ 2951static void 2952sscop_outrec_bgn(struct sscop *sscop, struct sscop_msg *msg) 2953{ 2954 union pdu pdu; 2955 2956 pdu.sscop_null = MBUF_STRIP32(msg->m); 2957 2958 if(m_detect_retransmission(sscop, msg)) { 2959 MAAL_ERROR(sscop, 'B', 0); 2960 SSCOP_MSG_FREE(msg); 2961 } else { 2962 (void)MBUF_STRIP32(msg->m); 2963 2964 TIMER_STOP(sscop, cc); 2965 sscop->vt_ms = pdu.sscop_ns; 2966 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2967 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, 2968 msg, pdu.sscop_pl, 0); 2969 MSGQ_CLEAR(&sscop->rbuf); 2970 2971 sscop_set_state(sscop, SSCOP_IN_PEND); 2972 } 2973} 2974 2975/* 2976 * p 51: OUT_REC_PEND && ER PDU 2977 * arg is pdu (freed). 2978 */ 2979static void 2980sscop_outrec_er(struct sscop *sscop, struct sscop_msg *msg) 2981{ 2982 union pdu pdu; 2983 2984 pdu.sscop_null = MBUF_STRIP32(msg->m); 2985 2986 if(m_detect_retransmission(sscop, msg)) { 2987 MAAL_ERROR(sscop, 'L', 0); 2988 } else { 2989 TIMER_STOP(sscop, cc); 2990 sscop->vt_ms = pdu.sscop_ns; 2991 m_initialize_mr(sscop); 2992 send_erak(sscop); 2993 m_deliver_data(sscop); 2994 2995 AAL_SIG(sscop, SSCOP_RECOVER_indication); 2996 2997 sscop_set_state(sscop, SSCOP_REC_PEND); 2998 } 2999 3000 SSCOP_MSG_FREE(msg); 3001} 3002 3003/* 3004 * p 52: OUT_REC_PEND && SD PDU queued 3005 * no arg. 3006 */ 3007static void 3008sscop_outrec_pduq(struct sscop *sscop, struct sscop_msg *msg) 3009{ 3010 sscop_save_signal(sscop, SIG_PDU_Q, msg); 3011} 3012 3013/* 3014 * p 52: OUT_REC_PEND && RSAK PDU 3015 * arg is pdu (freed). 3016 */ 3017static void 3018sscop_outrec_rsak(struct sscop *sscop, struct sscop_msg *msg) 3019{ 3020 SSCOP_MSG_FREE(msg); 3021 MAAL_ERROR(sscop, 'K', 0); 3022} 3023 3024/* 3025 * p 52: OUT_REC_PEND && RS PDU 3026 * arg is pdu (freed). 3027 */ 3028static void 3029sscop_outrec_rs(struct sscop *sscop, struct sscop_msg *msg) 3030{ 3031 union pdu pdu; 3032 3033 pdu.sscop_null = MBUF_STRIP32(msg->m); 3034 3035 if(m_detect_retransmission(sscop, msg)) { 3036 SSCOP_MSG_FREE(msg); 3037 MAAL_ERROR(sscop, 'J', 0); 3038 return; 3039 } 3040 (void)MBUF_STRIP32(msg->m); 3041 3042 TIMER_STOP(sscop, cc); 3043 sscop->vt_ms = pdu.sscop_ns; 3044 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3045 MSGQ_CLEAR(&sscop->rbuf); 3046 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3047} 3048 3049/* 3050 * p 53: REC_PEND && BGAK PDU 3051 * arg is pdu (freed) 3052 */ 3053static void 3054sscop_rec_bgak(struct sscop *sscop, struct sscop_msg *msg) 3055{ 3056 MAAL_ERROR(sscop, 'C', 0); 3057 3058 SSCOP_MSG_FREE(msg); 3059} 3060 3061/* 3062 * p 53: REC_PEND && END PDU 3063 * arg is pdu (freed) 3064 * no uui 3065 */ 3066static void 3067sscop_rec_end(struct sscop *sscop, struct sscop_msg *msg) 3068{ 3069 union pdu pdu; 3070 3071 pdu.sscop_null = MBUF_STRIP32(msg->m); 3072 (void)MBUF_STRIP32(msg->m); 3073 3074 send_endak(sscop); 3075 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 3076 msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 3077 3078 sscop_set_state(sscop, SSCOP_IDLE); 3079} 3080 3081/* 3082 * p 53: REC_PEND && ENDAK PDU 3083 * arg is pdu (freed) 3084 */ 3085static void 3086sscop_rec_endak(struct sscop *sscop, struct sscop_msg *msg) 3087{ 3088 MAAL_ERROR(sscop, 'F', 0); 3089 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3090 sscop_set_state(sscop, SSCOP_IDLE); 3091 SSCOP_MSG_FREE(msg); 3092} 3093 3094/* 3095 * p 53: REC_PEND && BGREJ PDU 3096 * arg is pdu (freed) 3097 */ 3098static void 3099sscop_rec_bgrej(struct sscop *sscop, struct sscop_msg *msg) 3100{ 3101 MAAL_ERROR(sscop, 'D', 0); 3102 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3103 sscop_set_state(sscop, SSCOP_IDLE); 3104 SSCOP_MSG_FREE(msg); 3105} 3106 3107/* 3108 * p 54: REC_PEND && RELEASE 3109 * arg is UU 3110 */ 3111static void 3112sscop_rec_release_req(struct sscop *sscop, struct sscop_msg *uu) 3113{ 3114 SET_UU(uu_end, uu); 3115 3116 sscop->vt_cc = 1; 3117 send_end(sscop, 0, sscop->uu_end); 3118 TIMER_RESTART(sscop, cc); 3119 3120 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 3121} 3122 3123/* 3124 * p 54: REC_PEND && RSAK PDU 3125 * arg is pdu (freed). 3126 */ 3127static void 3128sscop_rec_rsak(struct sscop *sscop, struct sscop_msg *msg) 3129{ 3130 MAAL_ERROR(sscop, 'K', 0); 3131 SSCOP_MSG_FREE(msg); 3132} 3133 3134 3135/* 3136 * p 54: REC_PEND && RS PDU 3137 * arg is pdu (freed). 3138 */ 3139static void 3140sscop_rec_rs(struct sscop *sscop, struct sscop_msg *msg) 3141{ 3142 union pdu pdu; 3143 3144 pdu.sscop_null = MBUF_STRIP32(msg->m); 3145 3146 if(m_detect_retransmission(sscop, msg)) { 3147 SSCOP_MSG_FREE(msg); 3148 MAAL_ERROR(sscop, 'J', 0); 3149 return; 3150 } 3151 (void)MBUF_STRIP32(msg->m); 3152 3153 sscop->vt_ms = pdu.sscop_ns; 3154 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3155 3156 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3157} 3158 3159/* 3160 * p 54: REC_PEND && RECOVER response 3161 * no arg 3162 */ 3163static void 3164sscop_rec_recover(struct sscop *sscop, struct sscop_msg *unused __unused) 3165{ 3166 if(!sscop->clear_buffers) { 3167 MSGQ_CLEAR(&sscop->xbuf); 3168 } 3169 m_initialize_state(sscop); 3170 m_set_data_xfer_timers(sscop); 3171 3172 sscop_set_state(sscop, SSCOP_READY); 3173} 3174 3175/* 3176 * p 54: REC_PEND && RESYNC request 3177 * arg is uu 3178 */ 3179static void 3180sscop_rec_sync_req(struct sscop *sscop, struct sscop_msg *uu) 3181{ 3182 SET_UU(uu_rs, uu); 3183 3184 m_clear_transmitter(sscop); 3185 sscop->vt_cc = 1; 3186 sscop->vt_sq++; 3187 m_initialize_mr(sscop); 3188 send_rs(sscop, 0, sscop->uu_rs); 3189 TIMER_RESTART(sscop, cc); 3190 3191 sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND); 3192} 3193 3194/* 3195 * p 55: REC_PEND && SD PDU queued 3196 * no arg 3197 */ 3198static void 3199sscop_rec_pduq(struct sscop *sscop, struct sscop_msg *msg) 3200{ 3201 sscop_save_signal(sscop, SIG_PDU_Q, msg); 3202} 3203 3204/* 3205 * p 55: REC_PEND && ER PDU 3206 * arg is pdu (freed). 3207 */ 3208static void 3209sscop_rec_er(struct sscop *sscop, struct sscop_msg *msg) 3210{ 3211 union pdu pdu; 3212 3213 pdu.sscop_null = MBUF_STRIP32(msg->m); 3214 3215 if(m_detect_retransmission(sscop, msg)) { 3216 send_erak(sscop); 3217 } else { 3218 MAAL_ERROR(sscop, 'L', 0); 3219 } 3220 SSCOP_MSG_FREE(msg); 3221} 3222 3223/* 3224 * p 55: REC_PEND && BGN PDU 3225 * arg is pdu (freed) 3226 * no uui 3227 */ 3228static void 3229sscop_rec_bgn(struct sscop *sscop, struct sscop_msg *msg) 3230{ 3231 union pdu pdu; 3232 3233 pdu.sscop_null = MBUF_STRIP32(msg->m); 3234 3235 if(m_detect_retransmission(sscop, msg)) { 3236 MAAL_ERROR(sscop, 'B', 0); 3237 SSCOP_MSG_FREE(msg); 3238 return; 3239 } 3240 (void)MBUF_STRIP32(msg->m); 3241 3242 sscop->vt_ms = pdu.sscop_ns; 3243 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 3244 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 3245 3246 sscop_set_state(sscop, SSCOP_IN_PEND); 3247} 3248 3249/* 3250 * p 55: REC_PEND && STAT PDU 3251 * arg is pdu (freed) 3252 */ 3253static void 3254sscop_rec_stat(struct sscop *sscop, struct sscop_msg *msg) 3255{ 3256 MAAL_ERROR(sscop, 'H', 0); 3257 FREE_UU(uu_end); 3258 send_end(sscop, 1, NULL); 3259 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3260 sscop_set_state(sscop, SSCOP_IDLE); 3261 SSCOP_MSG_FREE(msg); 3262} 3263 3264/* 3265 * p 55: REC_PEND && USTAT PDU 3266 * arg is pdu (freed) 3267 */ 3268static void 3269sscop_rec_ustat(struct sscop *sscop, struct sscop_msg *msg) 3270{ 3271 MAAL_ERROR(sscop, 'I', 0); 3272 FREE_UU(uu_end); 3273 send_end(sscop, 1, NULL); 3274 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3275 sscop_set_state(sscop, SSCOP_IDLE); 3276 SSCOP_MSG_FREE(msg); 3277} 3278 3279/* 3280 * p 56: IN_REC_PEND && AA-RECOVER.response 3281 * no arg 3282 */ 3283static void 3284sscop_inrec_recover(struct sscop *sscop, struct sscop_msg *unused __unused) 3285{ 3286 if(!sscop->clear_buffers) { 3287 MSGQ_CLEAR(&sscop->xbuf); 3288 } 3289 m_initialize_mr(sscop); 3290 send_erak(sscop); 3291 m_initialize_state(sscop); 3292 m_set_data_xfer_timers(sscop); 3293 3294 sscop_set_state(sscop, SSCOP_READY); 3295} 3296 3297/* 3298 * p 56: IN_REC_PEND && SD PDU queued 3299 * no arg 3300 */ 3301static void 3302sscop_inrec_pduq(struct sscop *sscop, struct sscop_msg *msg) 3303{ 3304 sscop_save_signal(sscop, SIG_PDU_Q, msg); 3305} 3306 3307/* 3308 * p 56: IN_REC_PEND && AA-RELEASE.request 3309 * arg is UU 3310 */ 3311static void 3312sscop_inrec_release_req(struct sscop *sscop, struct sscop_msg *uu) 3313{ 3314 SET_UU(uu_end, uu); 3315 3316 sscop->vt_cc = 1; 3317 send_end(sscop, 0, sscop->uu_end); 3318 TIMER_RESTART(sscop, cc); 3319 3320 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 3321} 3322 3323/* 3324 * p 56: IN_REC_PEND && END PDU 3325 * arg is pdu (freed). 3326 * no uui 3327 */ 3328static void 3329sscop_inrec_end(struct sscop *sscop, struct sscop_msg *msg) 3330{ 3331 union pdu pdu; 3332 3333 pdu.sscop_null = MBUF_STRIP32(msg->m); 3334 (void)MBUF_STRIP32(msg->m); 3335 3336 send_endak(sscop); 3337 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 3338 msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 3339 3340 sscop_set_state(sscop, SSCOP_IDLE); 3341} 3342 3343/* 3344 * p 56: IN_REC_PEND && RESYNC_REQ 3345 */ 3346static void 3347sscop_inrec_sync_req(struct sscop *sscop, struct sscop_msg *uu) 3348{ 3349 SET_UU(uu_rs, uu); 3350 3351 m_clear_transmitter(sscop); 3352 sscop->vt_cc = 1; 3353 sscop->vt_sq++; 3354 m_initialize_mr(sscop); 3355 send_rs(sscop, 0, sscop->uu_rs); 3356 TIMER_RESTART(sscop, cc); 3357 3358 sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND); 3359} 3360 3361 3362/* 3363 * p 57: IN_REC_PEND && ENDAK PDU 3364 * arg is pdu (freed) 3365 */ 3366static void 3367sscop_inrec_endak(struct sscop *sscop, struct sscop_msg *msg) 3368{ 3369 MAAL_ERROR(sscop, 'F', 0); 3370 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3371 SSCOP_MSG_FREE(msg); 3372 sscop_set_state(sscop, SSCOP_IDLE); 3373} 3374 3375/* 3376 * p 57: IN_REC_PEND && BGREJ PDU 3377 * arg is pdu (freed) 3378 */ 3379static void 3380sscop_inrec_bgrej(struct sscop *sscop, struct sscop_msg *msg) 3381{ 3382 MAAL_ERROR(sscop, 'D', 0); 3383 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3384 SSCOP_MSG_FREE(msg); 3385 sscop_set_state(sscop, SSCOP_IDLE); 3386} 3387 3388/* 3389 * p 57: IN_REC_PEND && USTAT PDU 3390 * arg is pdu (freed) 3391 */ 3392static void 3393sscop_inrec_ustat(struct sscop *sscop, struct sscop_msg *msg) 3394{ 3395 MAAL_ERROR(sscop, 'I', 0); 3396 FREE_UU(uu_end); 3397 send_end(sscop, 1, NULL); 3398 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3399 SSCOP_MSG_FREE(msg); 3400 sscop_set_state(sscop, SSCOP_IDLE); 3401} 3402 3403/* 3404 * p 57: IN_REC_PEND && STAT PDU 3405 * arg is pdu (freed) 3406 */ 3407static void 3408sscop_inrec_stat(struct sscop *sscop, struct sscop_msg *msg) 3409{ 3410 MAAL_ERROR(sscop, 'H', 0); 3411 FREE_UU(uu_end); 3412 send_end(sscop, 1, NULL); 3413 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3414 SSCOP_MSG_FREE(msg); 3415 sscop_set_state(sscop, SSCOP_IDLE); 3416} 3417 3418/* 3419 * p 57: IN_REC_PEND && POLL PDU 3420 * arg is pdu (freed) 3421 */ 3422static void 3423sscop_inrec_poll(struct sscop *sscop, struct sscop_msg *msg) 3424{ 3425 MAAL_ERROR(sscop, 'G', 0); 3426 FREE_UU(uu_end); 3427 send_end(sscop, 1, NULL); 3428 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3429 SSCOP_MSG_FREE(msg); 3430 sscop_set_state(sscop, SSCOP_IDLE); 3431} 3432 3433/* 3434 * p 57: IN_REC_PEND && SD PDU 3435 * arg is pdu (freed) 3436 */ 3437static void 3438sscop_inrec_sd(struct sscop *sscop, struct sscop_msg *msg) 3439{ 3440 MAAL_ERROR(sscop, 'A', 0); 3441 FREE_UU(uu_end); 3442 send_end(sscop, 1, NULL); 3443 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3444 SSCOP_MSG_FREE(msg); 3445 sscop_set_state(sscop, SSCOP_IDLE); 3446} 3447 3448/* 3449 * p 58: IN_REC_PEND && RSAK PDU 3450 * arg is pdu (freed). 3451 */ 3452static void 3453sscop_inrec_rsak(struct sscop *sscop, struct sscop_msg *msg) 3454{ 3455 SSCOP_MSG_FREE(msg); 3456 MAAL_ERROR(sscop, 'K', 0); 3457} 3458 3459/* 3460 * p 58: IN_REC_PEND && RS PDU 3461 * arg is pdu (freed). 3462 */ 3463static void 3464sscop_inrec_rs(struct sscop *sscop, struct sscop_msg *msg) 3465{ 3466 union pdu pdu; 3467 3468 pdu.sscop_null = MBUF_STRIP32(msg->m); 3469 3470 if(m_detect_retransmission(sscop, msg)) { 3471 SSCOP_MSG_FREE(msg); 3472 MAAL_ERROR(sscop, 'J', 0); 3473 return; 3474 } 3475 (void)MBUF_STRIP32(msg->m); 3476 3477 sscop->vt_ms = pdu.sscop_ns; 3478 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3479 3480 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3481} 3482 3483/* 3484 * p 59: IN_REC_PEND && ER PDU 3485 * arg is pdu (freed) 3486 */ 3487static void 3488sscop_inrec_er(struct sscop *sscop, struct sscop_msg *msg) 3489{ 3490 union pdu pdu; 3491 3492 pdu.sscop_null = MBUF_STRIP32(msg->m); 3493 3494 if(!m_detect_retransmission(sscop, msg)) { 3495 MAAL_ERROR(sscop, 'L', 0); 3496 } 3497 3498 SSCOP_MSG_FREE(msg); 3499} 3500 3501/* 3502 * p 59: IN_REC_PEND && BGN PDU 3503 * arg is pdu (freed). 3504 * no uui 3505 */ 3506static void 3507sscop_inrec_bgn(struct sscop *sscop, struct sscop_msg *msg) 3508{ 3509 union pdu pdu; 3510 3511 pdu.sscop_null = MBUF_STRIP32(msg->m); 3512 3513 if(m_detect_retransmission(sscop, msg)) { 3514 MAAL_ERROR(sscop, 'B', 0); 3515 SSCOP_MSG_FREE(msg); 3516 return; 3517 } 3518 (void)MBUF_STRIP32(msg->m); 3519 3520 sscop->vt_ms = pdu.sscop_ns; 3521 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 3522 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 3523 3524 sscop_set_state(sscop, SSCOP_IN_PEND); 3525} 3526 3527/* 3528 * p 59: IN_REC_PEND && BGAK PDU 3529 * arg is pdu (freed) 3530 * no uui 3531 */ 3532static void 3533sscop_inrec_bgak(struct sscop *sscop, struct sscop_msg *msg) 3534{ 3535 MAAL_ERROR(sscop, 'C', 0); 3536 SSCOP_MSG_FREE(msg); 3537} 3538 3539/* 3540 * p 59: IN_REC_PEND && ERAK PDU 3541 * arg is pdu (freed) 3542 * no uui 3543 */ 3544static void 3545sscop_inrec_erak(struct sscop *sscop, struct sscop_msg *msg) 3546{ 3547 MAAL_ERROR(sscop, 'M', 0); 3548 SSCOP_MSG_FREE(msg); 3549} 3550 3551/* 3552 * p 60: READY && RESYNC request 3553 * arg is UU 3554 */ 3555static void 3556sscop_ready_sync_req(struct sscop *sscop, struct sscop_msg *uu) 3557{ 3558 SET_UU(uu_rs, uu); 3559 3560 m_reset_data_xfer_timers(sscop); 3561 sscop->vt_cc = 1; 3562 sscop->vt_sq++; 3563 m_initialize_mr(sscop); 3564 send_rs(sscop, 0, sscop->uu_rs); 3565 m_release_buffers(sscop); 3566 TIMER_RESTART(sscop, cc); 3567 3568 sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND); 3569} 3570 3571 3572/* 3573 * p 60: READY && AA-RELEASE.request 3574 * arg is uu. 3575 */ 3576static void 3577sscop_ready_release_req(struct sscop *sscop, struct sscop_msg *uu) 3578{ 3579 SET_UU(uu_end, uu); 3580 3581 m_reset_data_xfer_timers(sscop); 3582 sscop->vt_cc = 1; 3583 send_end(sscop, 0, sscop->uu_end); 3584 m_prepare_retrieval(sscop); 3585 TIMER_RESTART(sscop, cc); 3586 3587 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 3588} 3589 3590/* 3591 * p 61: READY && ER PDU 3592 * arg is pdu (freed). 3593 */ 3594static void 3595sscop_ready_er(struct sscop *sscop, struct sscop_msg *msg) 3596{ 3597 union pdu pdu; 3598 3599 pdu.sscop_null = MBUF_STRIP32(msg->m); 3600 3601 if(m_detect_retransmission(sscop, msg)) { 3602 TIMER_RESTART(sscop, nr); 3603 send_erak(sscop); 3604 } else { 3605 m_reset_data_xfer_timers(sscop); 3606 sscop->vt_ms = pdu.sscop_ns; 3607 m_prepare_recovery(sscop); 3608 m_deliver_data(sscop); 3609 3610 AAL_SIG(sscop, SSCOP_RECOVER_indication); 3611 3612 sscop_set_state(sscop, SSCOP_IN_REC_PEND); 3613 } 3614 3615 SSCOP_MSG_FREE(msg); 3616} 3617 3618/* 3619 * p 61: READY && BGN PDU 3620 * arg is pdu (freed) 3621 */ 3622static void 3623sscop_ready_bgn(struct sscop *sscop, struct sscop_msg *msg) 3624{ 3625 union pdu pdu; 3626 3627 pdu.sscop_null = MBUF_STRIP32(msg->m); 3628 3629 if(m_detect_retransmission(sscop, msg)) { 3630 TIMER_RESTART(sscop, nr); 3631 send_bgak(sscop, sscop->uu_bgak); 3632 SSCOP_MSG_FREE(msg); 3633 return; 3634 } 3635 (void)MBUF_STRIP32(msg->m); 3636 3637 m_reset_data_xfer_timers(sscop); 3638 sscop->vt_ms = pdu.sscop_ns; 3639 3640 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 3641 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 3642 3643 m_prepare_retrieval(sscop); 3644 3645 sscop_set_state(sscop, SSCOP_IN_PEND); 3646} 3647 3648/* 3649 * p 62: READY && ENDAK PDU 3650 * arg is pdu (freed) 3651 */ 3652static void 3653sscop_ready_endak(struct sscop *sscop, struct sscop_msg *msg) 3654{ 3655 m_reset_data_xfer_timers(sscop); 3656 MAAL_ERROR(sscop, 'F', 0); 3657 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3658 m_prepare_retrieval(sscop); 3659 SSCOP_MSG_FREE(msg); 3660 sscop_set_state(sscop, SSCOP_IDLE); 3661} 3662 3663/* 3664 * p 62: READY && BGREJ PDU 3665 * arg is pdu (freed) 3666 */ 3667static void 3668sscop_ready_bgrej(struct sscop *sscop, struct sscop_msg *msg) 3669{ 3670 m_reset_data_xfer_timers(sscop); 3671 MAAL_ERROR(sscop, 'D', 0); 3672 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3673 m_prepare_retrieval(sscop); 3674 SSCOP_MSG_FREE(msg); 3675 sscop_set_state(sscop, SSCOP_IDLE); 3676} 3677 3678/* 3679 * p 62: READY && RS PDU 3680 * arg is pdu (freed) 3681 */ 3682static void 3683sscop_ready_rs(struct sscop *sscop, struct sscop_msg *msg) 3684{ 3685 union pdu pdu; 3686 3687 pdu.sscop_null = MBUF_STRIP32(msg->m); 3688 3689 if(m_detect_retransmission(sscop, msg)) { 3690 SSCOP_MSG_FREE(msg); 3691 TIMER_RESTART(sscop, nr); 3692 send_rsak(sscop); 3693 return; 3694 } 3695 (void)MBUF_STRIP32(msg->m); 3696 3697 m_reset_data_xfer_timers(sscop); 3698 sscop->vt_ms = pdu.sscop_ns; 3699 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3700 m_prepare_retrieval(sscop); 3701 3702 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3703} 3704 3705/* 3706 * p 62: READY && END PDU 3707 * arg is pdu (freed) 3708 */ 3709static void 3710sscop_ready_end(struct sscop *sscop, struct sscop_msg *msg) 3711{ 3712 union pdu pdu; 3713 3714 pdu.sscop_null = MBUF_STRIP32(msg->m); 3715 (void)MBUF_STRIP32(msg->m); 3716 3717 m_reset_data_xfer_timers(sscop); 3718 send_endak(sscop); 3719 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 3720 msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 3721 m_prepare_retrieval(sscop); 3722 3723 sscop_set_state(sscop, SSCOP_IDLE); 3724} 3725 3726/* 3727 * p 63: READY && POLL expiry 3728 */ 3729static void 3730sscop_ready_tpoll(struct sscop *sscop, struct sscop_msg *unused __unused) 3731{ 3732 sscop->vt_ps++; 3733 send_poll(sscop); 3734 sscop->vt_pd = 0; 3735 m_set_poll_timer(sscop); 3736} 3737 3738/* 3739 * p 63: READY && KEEP_ALIVE expiry 3740 */ 3741static void 3742sscop_ready_tka(struct sscop *sscop, struct sscop_msg *unused __unused) 3743{ 3744 sscop->vt_ps++; 3745 send_poll(sscop); 3746 sscop->vt_pd = 0; 3747 m_set_poll_timer(sscop); 3748} 3749 3750/* 3751 * p 63: READY && IDLE expiry 3752 */ 3753static void 3754sscop_ready_tidle(struct sscop *sscop, struct sscop_msg *unused __unused) 3755{ 3756 TIMER_RESTART(sscop, nr); 3757 sscop->vt_ps++; 3758 send_poll(sscop); 3759 sscop->vt_pd = 0; 3760 m_set_poll_timer(sscop); 3761} 3762 3763/* 3764 * p 63: READY && NO_RESPONSE expiry 3765 * no arg 3766 */ 3767static void 3768sscop_ready_nr(struct sscop *sscop, struct sscop_msg *unused __unused) 3769{ 3770 m_reset_data_xfer_timers(sscop); 3771 MAAL_ERROR(sscop, 'P', 0); 3772 FREE_UU(uu_end); 3773 send_end(sscop, 1, NULL); 3774 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3775 m_prepare_retrieval(sscop); 3776 sscop_set_state(sscop, SSCOP_IDLE); 3777} 3778 3779/* 3780 * p 63: READY && AA-DATA.request 3781 * arg is message (queued). 3782 */ 3783static void 3784sscop_ready_userdata(struct sscop *sscop, struct sscop_msg *msg) 3785{ 3786 MSGQ_APPEND(&sscop->xq, msg); 3787 3788 sscop_signal(sscop, SIG_PDU_Q, msg); 3789} 3790 3791/* 3792 * p 64: READY && SD PDU queued up 3793 * arg is unused. 3794 */ 3795static void 3796sscop_ready_pduq(struct sscop *sscop, struct sscop_msg *unused __unused) 3797{ 3798 struct sscop_msg *msg; 3799 3800 if(sscop->rxq != 0) { 3801 TAILQ_FOREACH(msg, &sscop->xbuf, link) 3802 if(msg->rexmit) 3803 break; 3804 ASSERT(msg != NULL); 3805 msg->rexmit = 0; 3806 sscop->rxq--; 3807 send_sd(sscop, msg->m, msg->seqno); 3808 msg->poll_seqno = sscop->vt_ps; 3809 if(sscop->poll_after_rex && sscop->rxq == 0) 3810 goto poll; /* -> A */ 3811 else 3812 goto maybe_poll; /* -> B */ 3813 3814 } 3815 if(MSGQ_EMPTY(&sscop->xq)) 3816 return; 3817 3818 if(sscop->vt_s >= sscop->vt_ms) { 3819 /* Send windows closed */ 3820 TIMER_STOP(sscop, idle); 3821 TIMER_RESTART(sscop, nr); 3822 goto poll; /* -> A */ 3823 3824 } else { 3825 msg = MSGQ_GET(&sscop->xq); 3826 msg->seqno = sscop->vt_s; 3827 send_sd(sscop, msg->m, msg->seqno); 3828 msg->poll_seqno = sscop->vt_ps; 3829 sscop->vt_s++; 3830 MSGQ_APPEND(&sscop->xbuf, msg); 3831 goto maybe_poll; /* -> B */ 3832 } 3833 3834 /* 3835 * p 65: Poll handling 3836 */ 3837 maybe_poll: /* label B */ 3838 sscop->vt_pd++; 3839 if(TIMER_ISACT(sscop, poll)) { 3840 if(sscop->vt_pd < sscop->maxpd) 3841 return; 3842 } else { 3843 if(TIMER_ISACT(sscop, idle)) { 3844 TIMER_STOP(sscop, idle); 3845 TIMER_RESTART(sscop, nr); 3846 } else { 3847 TIMER_STOP(sscop, ka); 3848 } 3849 if(sscop->vt_pd < sscop->maxpd) { 3850 TIMER_RESTART(sscop, poll); 3851 return; 3852 } 3853 } 3854 poll: /* label A */ 3855 sscop->vt_ps++; 3856 send_poll(sscop); 3857 sscop->vt_pd = 0; 3858 TIMER_RESTART(sscop, poll); 3859} 3860 3861/* 3862 * p 67: common recovery start 3863 */ 3864static void 3865sscop_recover(struct sscop *sscop) 3866{ 3867 sscop->vt_cc = 1; 3868 sscop->vt_sq++; 3869 3870 m_initialize_mr(sscop); 3871 send_er(sscop); 3872 m_prepare_recovery(sscop); 3873 3874 TIMER_RESTART(sscop, cc); 3875 3876 sscop_set_state(sscop, SSCOP_OUT_REC_PEND); 3877} 3878 3879/* 3880 * p 66: READY && SD PDU 3881 * arg is received message. 3882 */ 3883static void 3884sscop_ready_sd(struct sscop *sscop, struct sscop_msg *msg) 3885{ 3886 union pdu pdu; 3887 u_int sn; 3888 3889 pdu.sscop_null = MBUF_STRIP32(msg->m); 3890 msg->seqno = pdu.sscop_ns; 3891 3892 /* Fix padding */ 3893 MBUF_UNPAD(msg->m, pdu.sscop_pl); 3894 3895 if(msg->seqno >= sscop->vr_mr) { 3896 /* message outside window */ 3897 if(sscop->vr_h < sscop->vr_mr) { 3898 send_ustat(sscop, sscop->vr_h, sscop->vr_mr, -1); 3899 sscop->vr_h = sscop->vr_mr; 3900 } 3901 SSCOP_MSG_FREE(msg); 3902 return; 3903 } 3904 3905 if(msg->seqno == sscop->vr_r) { 3906 if(msg->seqno == sscop->vr_h) { 3907 sscop->vr_r = msg->seqno + 1; 3908 sscop->vr_h = msg->seqno + 1; 3909 3910 AAL_DATA(sscop, SSCOP_DATA_indication, 3911 msg->m, msg->seqno); 3912 msg->m = NULL; 3913 SSCOP_MSG_FREE(msg); 3914 3915 return; 3916 } 3917 for(;;) { 3918 AAL_DATA(sscop, SSCOP_DATA_indication, 3919 msg->m, msg->seqno); 3920 msg->m = NULL; 3921 SSCOP_MSG_FREE(msg); 3922 3923 sscop->vr_r++; 3924 if((msg = MSGQ_PEEK(&sscop->rbuf)) == NULL) 3925 break; 3926 sn = msg->seqno; 3927 ASSERT(sn >= sscop->vr_r); 3928 if(sn != sscop->vr_r) 3929 break; 3930 msg = MSGQ_GET(&sscop->rbuf); 3931 } 3932 return; 3933 } 3934 3935 /* Messages were lost */ 3936 3937 /* XXX Flow control */ 3938 if(msg->seqno == sscop->vr_h) { 3939 QINSERT(&sscop->rbuf, msg); 3940 sscop->vr_h++; 3941 return; 3942 } 3943 if(sscop->vr_h < msg->seqno) { 3944 QINSERT(&sscop->rbuf, msg); 3945 send_ustat(sscop, sscop->vr_h, msg->seqno, -1); 3946 sscop->vr_h = msg->seqno + 1; 3947 return; 3948 } 3949 3950 if(QFIND(&sscop->rbuf, msg->seqno) == NULL) { 3951 QINSERT(&sscop->rbuf, msg); 3952 return; 3953 } 3954 3955 /* error: start recovery */ 3956 SSCOP_MSG_FREE(msg); 3957 m_reset_data_xfer_timers(sscop); 3958 MAAL_ERROR(sscop, 'Q', 0); 3959 sscop_recover(sscop); 3960} 3961 3962/* 3963 * p 67: READY && POLL PDU 3964 */ 3965static void 3966sscop_ready_poll(struct sscop *sscop, struct sscop_msg *msg) 3967{ 3968 union pdu pdu; 3969 union seqno seqno; 3970 u_int sn, nps; 3971 struct SSCOP_MBUF_T *m; 3972 3973 pdu.sscop_null = MBUF_STRIP32(msg->m); 3974 seqno.sscop_null = MBUF_STRIP32(msg->m); 3975 3976 if((u_int)pdu.sscop_ns < sscop->vr_h) { 3977 SSCOP_MSG_FREE(msg); 3978 m_reset_data_xfer_timers(sscop); 3979 MAAL_ERROR(sscop, 'Q', 0); 3980 sscop_recover(sscop); 3981 return; 3982 } 3983 nps = seqno.sscop_n; 3984 3985 if((u_int)pdu.sscop_ns > sscop->vr_mr) 3986 sscop->vr_h = sscop->vr_mr; 3987 else 3988 sscop->vr_h = pdu.sscop_ns; 3989 3990 SSCOP_MSG_FREE(msg); 3991 3992 /* build stat pdu */ 3993 if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) { 3994 FAILURE("sscop: cannot allocate STAT"); 3995 return; 3996 } 3997 sn = sscop->vr_r; 3998 3999 while(sn != sscop->vr_h) { 4000 /* loop through burst we already have */ 4001 for(;;) { 4002 if(sn >= sscop->vr_h) { 4003 seqno.sscop_null = 0; 4004 seqno.sscop_n = sn; 4005 MBUF_APPEND32(m, seqno.sscop_null); 4006 goto out; 4007 } 4008 if(QFIND(&sscop->rbuf, sn) == NULL) 4009 break; 4010 sn++; 4011 } 4012 4013 /* start of a hole */ 4014 seqno.sscop_null = 0; 4015 seqno.sscop_n = sn; 4016 MBUF_APPEND32(m, seqno.sscop_null); 4017 if(MBUF_LEN(m)/4 >= sscop->maxstat) { 4018 send_stat(sscop, nps, m); 4019 if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) { 4020 FAILURE("sscop: cannot allocate STAT"); 4021 return; 4022 } 4023 seqno.sscop_null = 0; 4024 seqno.sscop_n = sn; 4025 MBUF_APPEND32(m, seqno.sscop_null); 4026 } 4027 do { 4028 sn++; 4029 } while(sn < sscop->vr_h && !QFIND(&sscop->rbuf, sn)); 4030 seqno.sscop_null = 0; 4031 seqno.sscop_n = sn; 4032 MBUF_APPEND32(m, seqno.sscop_null); 4033 } 4034 out: 4035 send_stat(sscop, nps, m); 4036} 4037 4038/* 4039 * p 69: READY && USTAT PDU 4040 * arg is msg (freed) 4041 */ 4042static void 4043sscop_ready_ustat(struct sscop *sscop, struct sscop_msg *msg) 4044{ 4045 union pdu pdu; 4046 union seqno nmr, sq1, sq2; 4047 u_int cnt; 4048 4049 pdu.sscop_null = MBUF_STRIP32(msg->m); 4050 nmr.sscop_null = MBUF_STRIP32(msg->m); 4051 sq2.sscop_null = MBUF_STRIP32(msg->m); 4052 sq1.sscop_null = MBUF_STRIP32(msg->m); 4053 4054 SSCOP_MSG_FREE(msg); 4055 4056 cnt = sq1.sscop_n - sq2.sscop_n; 4057 4058 if((u_int)pdu.sscop_ns < sscop->vt_a || (u_int)pdu.sscop_ns >= sscop->vt_s) { 4059 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4060 "USTAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u " 4061 "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s)); 4062 goto err_f; 4063 } 4064 4065 /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new 4066 * next in sequence-SD-number of the receiver and means, it has all 4067 * messages below N(R). Remove all message below N(R) from the 4068 * transmission buffer. It may already be removed because of an 4069 * earlier selective ACK in a STAT message. 4070 */ 4071 while((msg = MSGQ_PEEK(&sscop->xbuf)) != NULL && msg->seqno < (u_int)pdu.sscop_ns) { 4072 ASSERT(msg->seqno >= sscop->vt_a); 4073 MSGQ_REMOVE(&sscop->xbuf, msg); 4074 SSCOP_MSG_FREE(msg); 4075 } 4076 4077 /* Update the in-sequence acknowledge and the send window */ 4078 sscop->vt_a = pdu.sscop_ns; 4079 sscop->vt_ms = nmr.sscop_n; 4080 4081 /* check, that the range of requested re-transmissions is between 4082 * the in-sequence-ack and the highest up-to-now transmitted SD 4083 */ 4084 if(sq1.sscop_n >= sq2.sscop_n 4085 || (u_int)sq1.sscop_n < sscop->vt_a 4086 || (u_int)sq2.sscop_n >= sscop->vt_s) { 4087 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4088 "USTAT: seq1 or seq2 outside VT(A)...VT(S)-1 or seq1>=seq2:" 4089 " seq1=%u seq2=%u VT(A)=%u VT(S)=%u", 4090 sq1.sscop_n, sq2.sscop_n, sscop->vt_a, sscop->vt_s)); 4091 goto err_f; 4092 } 4093 4094 /* 4095 * Retransmit all messages from seq1 to seq2-1 4096 */ 4097 do { 4098 /* 4099 * The message may not be in the transmit buffer if it was 4100 * already acked by a STAT. This means, the receiver is 4101 * confused. 4102 */ 4103 if((msg = QFIND(&sscop->xbuf, sq1.sscop_n)) == NULL) { 4104 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4105 "USTAT: message %u not found in xmit buffer", 4106 sq1.sscop_n)); 4107 goto err_f; 4108 } 4109 4110 /* 4111 * If it is not yet in the re-transmission queue, put it there 4112 */ 4113 if(!msg->rexmit) { 4114 msg->rexmit = 1; 4115 sscop->rxq++; 4116 sscop_signal(sscop, SIG_PDU_Q, msg); 4117 } 4118 sq1.sscop_n++; 4119 } while(sq1.sscop_n != sq2.sscop_n); 4120 4121 /* 4122 * report the re-transmission to the management 4123 */ 4124 MAAL_ERROR(sscop, 'V', cnt); 4125 return; 4126 4127 err_f: 4128 m_reset_data_xfer_timers(sscop); 4129 MAAL_ERROR(sscop, 'T', 0); 4130 sscop_recover(sscop); 4131} 4132 4133/* 4134 * p 70: READY && STAT PDU 4135 * arg is msg (freed). 4136 */ 4137static void 4138sscop_ready_stat(struct sscop *sscop, struct sscop_msg *msg) 4139{ 4140 union pdu pdu; 4141 union seqno nps, nmr; 4142 u_int len, seq1, seq2, cnt; 4143 struct sscop_msg *m; 4144 4145 pdu.sscop_null = MBUF_STRIP32(msg->m); 4146 nmr.sscop_null = MBUF_STRIP32(msg->m); 4147 nps.sscop_null = MBUF_STRIP32(msg->m); 4148 4149 len = MBUF_LEN(msg->m) / 4; 4150 4151 if((u_int)nps.sscop_n < sscop->vt_pa 4152 || (u_int)nps.sscop_n > sscop->vt_ps) { 4153 SSCOP_MSG_FREE(msg); 4154 m_reset_data_xfer_timers(sscop); 4155 MAAL_ERROR(sscop, 'R', 0); 4156 sscop_recover(sscop); 4157 return; 4158 } 4159 4160 if((u_int)pdu.sscop_ns < sscop->vt_a 4161 || (u_int)pdu.sscop_ns > sscop->vt_s) { 4162 /* 4163 * The in-sequence acknowledge, i.e. the receivers's next 4164 * expected in-sequence msg is outside the window between 4165 * the transmitters in-sequence ack and highest seqno - 4166 * the receiver seems to be confused. 4167 */ 4168 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4169 "STAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u " 4170 "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s)); 4171 err_H: 4172 SSCOP_MSG_FREE(msg); 4173 m_reset_data_xfer_timers(sscop); 4174 MAAL_ERROR(sscop, 'S', 0); 4175 sscop_recover(sscop); 4176 return; 4177 } 4178 4179 /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new 4180 * next in sequence-SD-number of the receiver and means, it has all 4181 * messages below N(R). Remove all message below N(R) from the 4182 * transmission buffer. It may already be removed because of an 4183 * earlier selective ACK in a STAT message. 4184 */ 4185 while((m = MSGQ_PEEK(&sscop->xbuf)) != NULL 4186 && m->seqno < (u_int)pdu.sscop_ns) { 4187 ASSERT(m->seqno >= sscop->vt_a); 4188 MSGQ_REMOVE(&sscop->xbuf, m); 4189 SSCOP_MSG_FREE(m); 4190 } 4191 4192 /* 4193 * Update in-sequence ack, poll-ack and send window. 4194 */ 4195 sscop->vt_a = pdu.sscop_ns; 4196 sscop->vt_pa = nps.sscop_n; 4197 sscop->vt_ms = nmr.sscop_n; 4198 4199 cnt = 0; 4200 if(len > 1) { 4201 seq1 = MBUF_GET32(msg->m); 4202 len--; 4203 if(seq1 >= sscop->vt_s) { 4204 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4205 "STAT: seq1 >= VT(S): seq1=%u VT(S)=%u", 4206 seq1, sscop->vt_s)); 4207 goto err_H; 4208 } 4209 4210 for(;;) { 4211 seq2 = MBUF_GET32(msg->m); 4212 len--; 4213 if(seq1 >= seq2 || seq2 > sscop->vt_s) { 4214 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, 4215 sscop->aarg, "STAT: seq1 >= seq2 or " 4216 "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u", 4217 seq1, seq2, sscop->vt_s)); 4218 goto err_H; 4219 } 4220 4221 do { 4222 /* 4223 * The receiver requests the re-transmission 4224 * of some message, but has acknowledged it 4225 * already in an earlier STAT (it isn't in the 4226 * transmitt buffer anymore). 4227 */ 4228 if((m = QFIND(&sscop->xbuf, seq1)) == NULL) { 4229 VERBERR(sscop, SSCOP_DBG_ERR, 4230 (sscop, sscop->aarg, "STAT: message" 4231 " %u not found in xmit buffer", 4232 seq1)); 4233 goto err_H; 4234 } 4235 if(m->poll_seqno < (u_int)nps.sscop_n 4236 && (u_int)nps.sscop_n <= sscop->vt_ps) 4237 if(!m->rexmit) { 4238 m->rexmit = 1; 4239 sscop->rxq++; 4240 cnt++; 4241 sscop_signal(sscop, SIG_PDU_Q, msg); 4242 } 4243 } while(++seq1 < seq2); 4244 4245 if(len == 0) 4246 break; 4247 4248 seq2 = MBUF_GET32(msg->m); 4249 len--; 4250 4251 if(seq1 >= seq2 || seq2 > sscop->vt_s) { 4252 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, 4253 sscop->aarg, "STAT: seq1 >= seq2 or " 4254 "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u", 4255 seq1, seq2, sscop->vt_s)); 4256 goto err_H; 4257 } 4258 4259 /* OK now the sucessful transmitted messages. Note, that 4260 * some messages may already be out of the buffer because 4261 * of earlier STATS */ 4262 do { 4263 if(sscop->clear_buffers) { 4264 if((m = QFIND(&sscop->xbuf, seq1)) != NULL) { 4265 MSGQ_REMOVE(&sscop->xbuf, m); 4266 SSCOP_MSG_FREE(m); 4267 } 4268 } 4269 } while(++seq1 != seq2); 4270 4271 if(len == 0) 4272 break; 4273 } 4274 MAAL_ERROR(sscop, 'V', cnt); 4275 } 4276 SSCOP_MSG_FREE(msg); 4277 4278 /* label L: */ 4279 if(sscop->vt_s >= sscop->vt_ms) { 4280 /* 4281 * The receiver has closed the window: report to management 4282 */ 4283 if(sscop->credit) { 4284 sscop->credit = 0; 4285 MAAL_ERROR(sscop, 'W', 0); 4286 } 4287 } else if(!sscop->credit) { 4288 /* 4289 * The window was forcefully closed above, but 4290 * now re-opened. Report to management. 4291 */ 4292 sscop->credit = 1; 4293 MAAL_ERROR(sscop, 'X', 0); 4294 } 4295 4296 if(TIMER_ISACT(sscop, poll)) { 4297 TIMER_RESTART(sscop, nr); 4298 } else if(!TIMER_ISACT(sscop, idle)) { 4299 TIMER_STOP(sscop, ka); 4300 TIMER_STOP(sscop, nr); 4301 TIMER_RESTART(sscop, idle); 4302 } 4303} 4304 4305/* 4306 * P. 73: any state & UDATA_REQUEST 4307 * arg is pdu (queued) 4308 */ 4309static void 4310sscop_udata_req(struct sscop *sscop, struct sscop_msg *msg) 4311{ 4312 MSGQ_APPEND(&sscop->uxq, msg); 4313 sscop_signal(sscop, SIG_UPDU_Q, msg); 4314} 4315 4316/* 4317 * P. 73: any state & MDATA_REQUEST 4318 * arg is pdu (queued) 4319 */ 4320static void 4321sscop_mdata_req(struct sscop *sscop, struct sscop_msg *msg) 4322{ 4323 MSGQ_APPEND(&sscop->mxq, msg); 4324 sscop_signal(sscop, SIG_MPDU_Q, msg); 4325} 4326 4327/* 4328 * P. 74: any state & UDATA queued 4329 * no arg. 4330 */ 4331static void 4332sscop_upduq(struct sscop *sscop, struct sscop_msg *unused __unused) 4333{ 4334 struct sscop_msg *msg; 4335 4336 if(sscop->ll_busy) 4337 return; 4338 while((msg = MSGQ_GET(&sscop->uxq)) != NULL) { 4339 send_ud(sscop, msg->m); 4340 msg->m = NULL; 4341 SSCOP_MSG_FREE(msg); 4342 } 4343} 4344 4345/* 4346 * P. 74: any state & MDATA queued 4347 * no arg. 4348 */ 4349static void 4350sscop_mpduq(struct sscop *sscop, struct sscop_msg *unused __unused) 4351{ 4352 struct sscop_msg *msg; 4353 4354 if(sscop->ll_busy) 4355 return; 4356 while((msg = MSGQ_GET(&sscop->mxq)) != NULL) { 4357 send_md(sscop, msg->m); 4358 msg->m = NULL; 4359 SSCOP_MSG_FREE(msg); 4360 } 4361} 4362 4363/* 4364 * p 73: MD PDU 4365 * arg is PDU 4366 */ 4367static void 4368sscop_md(struct sscop *sscop, struct sscop_msg *msg) 4369{ 4370 union pdu pdu; 4371 4372 pdu.sscop_null = MBUF_STRIP32(msg->m); 4373 4374 MBUF_UNPAD(msg->m, pdu.sscop_pl); 4375 4376 MAAL_DATA(sscop, msg->m); 4377 msg->m = NULL; 4378 SSCOP_MSG_FREE(msg); 4379} 4380 4381/* 4382 * p 73: UD PDU 4383 * arg is PDU 4384 */ 4385static void 4386sscop_ud(struct sscop *sscop, struct sscop_msg *msg) 4387{ 4388 union pdu pdu; 4389 4390 pdu.sscop_null = MBUF_STRIP32(msg->m); 4391 4392 MBUF_UNPAD(msg->m, pdu.sscop_pl); 4393 4394 AAL_DATA(sscop, SSCOP_UDATA_indication, msg->m, 0); 4395 msg->m = NULL; 4396 SSCOP_MSG_FREE(msg); 4397} 4398 4399 4400/* 4401 * p 33: IDLE & RETRIEVE 4402 * p 39: IN_PEND & RETRIEVE 4403 * p 42: OUT_DIS_PEND & RETRIEVE 4404 * p 48: IN_RESYNC_PEND & RETRIEVE 4405 * p 53: REC_PEND & RETRIEVE 4406 * p 58: IN_REC_PEND & RETRIEVE 4407 */ 4408static void 4409sscop_retrieve(struct sscop *sscop, struct sscop_msg *msg) 4410{ 4411 m_data_retrieval(sscop, msg->rexmit); 4412 SSCOP_MSG_FREE(msg); 4413} 4414 4415/************************************************************/ 4416/* 4417 * GENERAL EVENT HANDLING 4418 */ 4419 4420/* 4421 * State/event matrix. 4422 * 4423 * Entries marked with Z are not specified in Q.2110, but are added for 4424 * the sake of stability. 4425 */ 4426static struct { 4427 void (*func)(struct sscop *, struct sscop_msg *); 4428 int (*cond)(struct sscop *); 4429} state_matrix[SSCOP_NSTATES][SIG_NUM] = { 4430 /* SSCOP_IDLE */ { 4431 /* SIG_BGN */ { sscop_idle_bgn, NULL }, 4432 /* SIG_BGAK */ { sscop_idle_bgak, NULL }, 4433 /* SIG_END */ { sscop_idle_end, NULL }, 4434 /* SIG_ENDAK */ { sscop_ignore_pdu, NULL }, 4435 /* SIG_RS */ { sscop_idle_rs, NULL }, 4436 /* SIG_RSAK */ { sscop_idle_rsak, NULL }, 4437 /* SIG_BGREJ */ { sscop_idle_bgrej, NULL }, 4438 /* SIG_SD */ { sscop_idle_sd, NULL }, 4439 /* SIG_ER */ { sscop_idle_er, NULL }, 4440 /* SIG_POLL */ { sscop_idle_poll, NULL }, 4441 /* SIG_STAT */ { sscop_idle_stat, NULL }, 4442 /* SIG_USTAT */ { sscop_idle_ustat, NULL }, 4443 /* SIG_UD */ { sscop_ud, NULL }, 4444 /* SIG_MD */ { sscop_md, NULL }, 4445 /* SIG_ERAK */ { sscop_idle_erak, NULL }, 4446 /* SIG_T_CC */ { NULL, NULL }, 4447 /* SIG_T_POLL */ { NULL, NULL }, 4448 /* SIG_T_KA */ { NULL, NULL }, 4449 /* SIG_T_NR */ { NULL, NULL }, 4450 /* SIG_T_IDLE */ { NULL, NULL }, 4451 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4452 /* SIG_USER_DATA */ { NULL, NULL }, 4453 /* SIG_ESTAB_REQ */ { sscop_idle_establish_req, NULL }, 4454 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4455 /* SIG_RELEASE_REQ */ { NULL, NULL }, 4456 /* SIG_RECOVER */ { NULL, NULL }, 4457 /* SIG_SYNC_REQ */ { NULL, NULL }, 4458 /* SIG_SYNC_RESP */ { NULL, NULL }, 4459 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4460 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4461 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4462 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4463 /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4464 }, 4465 /* SSCOP_OUT_PEND */ { 4466 /* SIG_BGN */ { sscop_outpend_bgn, NULL }, 4467 /* SIG_BGAK */ { sscop_outpend_bgak, NULL }, 4468 /* SIG_END */ { sscop_ignore_pdu, NULL }, 4469 /* SIG_ENDAK */ { sscop_ignore_pdu, NULL }, 4470 /* SIG_RS */ { sscop_ignore_pdu, NULL }, 4471 /* SIG_RSAK */ { sscop_ignore_pdu, NULL }, 4472 /* SIG_BGREJ */ { sscop_outpend_bgrej, NULL }, 4473 /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4474 /* SIG_ER */ { sscop_ignore_pdu, NULL }, 4475 /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4476 /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4477 /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4478 /* SIG_UD */ { sscop_ud, NULL }, 4479 /* SIG_MD */ { sscop_md, NULL }, 4480 /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4481 /* SIG_T_CC */ { sscop_outpend_tcc, NULL }, 4482 /* SIG_T_POLL */ { NULL, NULL }, 4483 /* SIG_T_KA */ { NULL, NULL }, 4484 /* SIG_T_NR */ { NULL, NULL }, 4485 /* SIG_T_IDLE */ { NULL, NULL }, 4486 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4487 /* SIG_USER_DATA */ { NULL, NULL }, 4488 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4489 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4490 /* SIG_RELEASE_REQ */ { sscop_outpend_release_req, NULL }, 4491 /* SIG_RECOVER */ { NULL, NULL }, 4492 /* SIG_SYNC_REQ */ { NULL, NULL }, 4493 /* SIG_SYNC_RESP */ { NULL, NULL }, 4494 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4495 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4496 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4497 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4498 /* SIG_RETRIEVE */ { NULL, NULL }, 4499 }, 4500 /* SSCOP_IN_PEND */ { 4501 /* SIG_BGN */ { sscop_inpend_bgn, NULL }, 4502 /* SIG_BGAK */ { sscop_inpend_bgak, NULL }, 4503 /* SIG_END */ { sscop_inpend_end, NULL }, 4504 /* SIG_ENDAK */ { sscop_inpend_endak, NULL }, 4505 /* SIG_RS */ { sscop_inpend_rs, NULL }, 4506 /* SIG_RSAK */ { sscop_inpend_rsak, NULL }, 4507 /* SIG_BGREJ */ { sscop_inpend_bgrej, NULL }, 4508 /* SIG_SD */ { sscop_inpend_sd, NULL }, 4509 /* SIG_ER */ { sscop_inpend_er, NULL }, 4510 /* SIG_POLL */ { sscop_inpend_poll, NULL }, 4511 /* SIG_STAT */ { sscop_inpend_stat, NULL }, 4512 /* SIG_USTAT */ { sscop_inpend_ustat, NULL }, 4513 /* SIG_UD */ { sscop_ud, NULL }, 4514 /* SIG_MD */ { sscop_md, NULL }, 4515 /* SIG_ERAK */ { sscop_inpend_erak, NULL }, 4516 /* SIG_T_CC */ { NULL, NULL }, 4517 /* SIG_T_POLL */ { NULL, NULL }, 4518 /* SIG_T_KA */ { NULL, NULL }, 4519 /* SIG_T_NR */ { NULL, NULL }, 4520 /* SIG_T_IDLE */ { NULL, NULL }, 4521 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4522 /* SIG_USER_DATA */ { NULL, NULL }, 4523 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4524 /* SIG_ESTAB_RESP */ { sscop_inpend_establish_resp, NULL }, 4525 /* SIG_RELEASE_REQ */ { sscop_inpend_release_req, NULL }, 4526 /* SIG_RECOVER */ { NULL, NULL }, 4527 /* SIG_SYNC_REQ */ { NULL, NULL }, 4528 /* SIG_SYNC_RESP */ { NULL, NULL }, 4529 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4530 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4531 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4532 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4533 /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4534 }, 4535 /* SSCOP_OUT_DIS_PEND */ { 4536 /* SIG_BGN */ { sscop_outdis_bgn, NULL }, 4537 /* SIG_BGAK */ { sscop_ignore_pdu, NULL }, 4538 /* SIG_END */ { sscop_outdis_end, NULL }, 4539 /* SIG_ENDAK */ { sscop_outdis_endak, NULL }, 4540 /* SIG_RS */ { sscop_ignore_pdu, NULL }, 4541 /* SIG_RSAK */ { sscop_ignore_pdu, NULL }, 4542 /* SIG_BGREJ */ { sscop_outdis_endak, NULL }, 4543 /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4544 /* SIG_ER */ { sscop_ignore_pdu, NULL }, 4545 /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4546 /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4547 /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4548 /* SIG_UD */ { sscop_ud, NULL }, 4549 /* SIG_MD */ { sscop_md, NULL }, 4550 /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4551 /* SIG_T_CC */ { sscop_outdis_cc, NULL }, 4552 /* SIG_T_POLL */ { NULL, NULL }, 4553 /* SIG_T_KA */ { NULL, NULL }, 4554 /* SIG_T_NR */ { NULL, NULL }, 4555 /* SIG_T_IDLE */ { NULL, NULL }, 4556 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4557 /* SIG_USER_DATA */ { NULL, NULL }, 4558 /* SIG_ESTAB_REQ */ { sscop_outdis_establish_req, NULL }, 4559 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4560 /* SIG_RELEASE_REQ */ { NULL, NULL }, 4561 /* SIG_RECOVER */ { NULL, NULL }, 4562 /* SIG_SYNC_REQ */ { NULL, NULL }, 4563 /* SIG_SYNC_RESP */ { NULL, NULL }, 4564 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4565 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4566 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4567 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4568 /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4569 }, 4570 /* SSCOP_OUT_RESYNC_PEND */ { 4571 /* SIG_BGN */ { sscop_outsync_bgn, NULL }, 4572 /* SIG_BGAK */ { sscop_ignore_pdu, NULL }, 4573 /* SIG_END */ { sscop_outsync_end, NULL }, 4574 /* SIG_ENDAK */ { sscop_outsync_endak, NULL }, 4575 /* SIG_RS */ { sscop_outsync_rs, NULL }, 4576 /* SIG_RSAK */ { sscop_outsync_rsak, NULL }, 4577 /* SIG_BGREJ */ { sscop_outsync_bgrej, NULL }, 4578 /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4579 /* SIG_ER */ { sscop_ignore_pdu, NULL }, 4580 /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4581 /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4582 /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4583 /* SIG_UD */ { sscop_ud, NULL }, 4584 /* SIG_MD */ { sscop_md, NULL }, 4585 /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4586 /* SIG_T_CC */ { sscop_outsync_cc, NULL }, 4587 /* SIG_T_POLL */ { NULL, NULL }, 4588 /* SIG_T_KA */ { NULL, NULL }, 4589 /* SIG_T_NR */ { NULL, NULL }, 4590 /* SIG_T_IDLE */ { NULL, NULL }, 4591 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4592 /* SIG_USER_DATA */ { NULL, NULL }, 4593 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4594 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4595 /* SIG_RELEASE_REQ */ { sscop_outsync_release_req, NULL }, 4596 /* SIG_RECOVER */ { NULL, NULL }, 4597 /* SIG_SYNC_REQ */ { NULL, NULL }, 4598 /* SIG_SYNC_RESP */ { NULL, NULL }, 4599 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4600 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4601 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4602 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4603 /* SIG_RETRIEVE */ { NULL, NULL }, 4604 }, 4605 /* SSCOP_IN_RESYNC_PEND */ { 4606 /* SIG_BGN */ { sscop_insync_bgn, NULL }, 4607 /* SIG_BGAK */ { sscop_insync_bgak, NULL }, 4608 /* SIG_END */ { sscop_insync_end, NULL }, 4609 /* SIG_ENDAK */ { sscop_insync_endak, NULL }, 4610 /* SIG_RS */ { sscop_insync_rs, NULL }, 4611 /* SIG_RSAK */ { sscop_insync_rsak, NULL }, 4612 /* SIG_BGREJ */ { sscop_insync_bgrej, NULL }, 4613 /* SIG_SD */ { sscop_insync_sd, NULL }, 4614 /* SIG_ER */ { sscop_insync_er, NULL }, 4615 /* SIG_POLL */ { sscop_insync_poll, NULL }, 4616 /* SIG_STAT */ { sscop_insync_stat, NULL }, 4617 /* SIG_USTAT */ { sscop_insync_ustat, NULL }, 4618 /* SIG_UD */ { sscop_ud, NULL }, 4619 /* SIG_MD */ { sscop_md, NULL }, 4620 /* SIG_ERAK */ { sscop_insync_erak, NULL }, 4621 /* SIG_T_CC */ { NULL, NULL }, 4622 /* SIG_T_POLL */ { NULL, NULL }, 4623 /* SIG_T_KA */ { NULL, NULL }, 4624 /* SIG_T_NR */ { NULL, NULL }, 4625 /* SIG_T_IDLE */ { NULL, NULL }, 4626 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4627 /* SIG_USER_DATA */ { NULL, NULL }, 4628 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4629 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4630 /* SIG_RELEASE_REQ */ { sscop_insync_release_req, NULL }, 4631 /* SIG_RECOVER */ { NULL, NULL }, 4632 /* SIG_SYNC_REQ */ { NULL, NULL }, 4633 /* SIG_SYNC_RESP */ { sscop_insync_sync_resp, NULL }, 4634 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4635 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4636 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4637 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4638 /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4639 }, 4640 /* SSCOP_OUT_REC_PEND */ { 4641 /* SIG_BGN */ { sscop_outrec_bgn, NULL }, 4642 /* SIG_BGAK */ { sscop_outrec_bgak, NULL }, 4643 /* SIG_END */ { sscop_outrec_end, NULL }, 4644 /* SIG_ENDAK */ { sscop_outrec_endak, NULL }, 4645 /* SIG_RS */ { sscop_outrec_rs, NULL }, 4646 /* SIG_RSAK */ { sscop_outrec_rsak, NULL }, 4647 /* SIG_BGREJ */ { sscop_outrec_bgrej, NULL }, 4648 /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4649 /* SIG_ER */ { sscop_outrec_er, NULL }, 4650 /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4651 /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4652 /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4653 /* SIG_UD */ { sscop_ud, NULL }, 4654 /* SIG_MD */ { sscop_md, NULL }, 4655 /* SIG_ERAK */ { sscop_outrec_erak, NULL }, 4656 /* SIG_T_CC */ { sscop_outrec_cc, NULL }, 4657 /* SIG_T_POLL */ { NULL, NULL }, 4658 /* SIG_T_KA */ { NULL, NULL }, 4659 /* SIG_T_NR */ { NULL, NULL }, 4660 /* SIG_T_IDLE */ { NULL, NULL }, 4661 /* SIG_PDU_Q */ { sscop_outrec_pduq, NULL }, 4662 /* SIG_USER_DATA */ { sscop_outrec_userdata, NULL }, 4663 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4664 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4665 /* SIG_RELEASE_REQ */ { sscop_outrec_release_req, NULL }, 4666 /* SIG_RECOVER */ { NULL, NULL }, 4667 /* SIG_SYNC_REQ */ { sscop_outrec_sync_req, NULL }, 4668 /* SIG_SYNC_RESP */ { NULL, NULL }, 4669 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4670 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4671 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4672 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4673 /* SIG_RETRIEVE */ { NULL, NULL }, 4674 }, 4675 /* SSCOP_REC_PEND */ { 4676 /* SIG_BGN */ { sscop_rec_bgn, NULL }, 4677 /* SIG_BGAK */ { sscop_rec_bgak, NULL }, 4678 /* SIG_END */ { sscop_rec_end, NULL }, 4679 /* SIG_ENDAK */ { sscop_rec_endak, NULL }, 4680 /* SIG_RS */ { sscop_rec_rs, NULL }, 4681 /* SIG_RSAK */ { sscop_rec_rsak, NULL }, 4682 /* SIG_BGREJ */ { sscop_rec_bgrej, NULL }, 4683 /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4684 /* SIG_ER */ { sscop_rec_er, NULL }, 4685 /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4686 /* SIG_STAT */ { sscop_rec_stat, NULL }, 4687 /* SIG_USTAT */ { sscop_rec_ustat, NULL }, 4688 /* SIG_UD */ { sscop_ud, NULL }, 4689 /* SIG_MD */ { sscop_md, NULL }, 4690 /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4691 /* SIG_T_CC */ { NULL, NULL }, 4692 /* SIG_T_POLL */ { NULL, NULL }, 4693 /* SIG_T_KA */ { NULL, NULL }, 4694 /* SIG_T_NR */ { NULL, NULL }, 4695 /* SIG_T_IDLE */ { NULL, NULL }, 4696 /* SIG_PDU_Q */ { sscop_rec_pduq, NULL }, 4697 /* SIG_USER_DATA */ { NULL, NULL }, 4698 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4699 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4700 /* SIG_RELEASE_REQ */ { sscop_rec_release_req, NULL }, 4701 /* SIG_RECOVER */ { sscop_rec_recover, NULL }, 4702 /* SIG_SYNC_REQ */ { sscop_rec_sync_req, NULL }, 4703 /* SIG_SYNC_RESP */ { NULL, NULL }, 4704 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4705 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4706 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4707 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4708 /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4709 }, 4710 /* SSCOP_IN_REC_PEND */ { 4711 /* SIG_BGN */ { sscop_inrec_bgn, NULL }, 4712 /* SIG_BGAK */ { sscop_inrec_bgak, NULL }, 4713 /* SIG_END */ { sscop_inrec_end, NULL }, 4714 /* SIG_ENDAK */ { sscop_inrec_endak, NULL }, 4715 /* SIG_RS */ { sscop_inrec_rs, NULL }, 4716 /* SIG_RSAK */ { sscop_inrec_rsak, NULL }, 4717 /* SIG_BGREJ */ { sscop_inrec_bgrej, NULL }, 4718 /* SIG_SD */ { sscop_inrec_sd, NULL }, 4719 /* SIG_ER */ { sscop_inrec_er, NULL }, 4720 /* SIG_POLL */ { sscop_inrec_poll, NULL }, 4721 /* SIG_STAT */ { sscop_inrec_stat, NULL }, 4722 /* SIG_USTAT */ { sscop_inrec_ustat, NULL }, 4723 /* SIG_UD */ { sscop_ud, NULL }, 4724 /* SIG_MD */ { sscop_md, NULL }, 4725 /* SIG_ERAK */ { sscop_inrec_erak, NULL }, 4726 /* SIG_T_CC */ { NULL, NULL }, 4727 /* SIG_T_POLL */ { NULL, NULL }, 4728 /* SIG_T_KA */ { NULL, NULL }, 4729 /* SIG_T_NR */ { NULL, NULL }, 4730 /* SIG_T_IDLE */ { NULL, NULL }, 4731 /* SIG_PDU_Q */ { sscop_inrec_pduq, NULL }, 4732 /* SIG_USER_DATA */ { NULL, NULL }, 4733 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4734 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4735 /* SIG_RELEASE_REQ */ { sscop_inrec_release_req, NULL }, 4736 /* SIG_RECOVER */ { sscop_inrec_recover, NULL }, 4737 /* SIG_SYNC_REQ */ { sscop_inrec_sync_req, NULL }, 4738 /* SIG_SYNC_RESP */ { NULL, NULL }, 4739 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4740 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4741 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4742 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4743 /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4744 }, 4745 /* SSCOP_READY */ { 4746 /* SIG_BGN */ { sscop_ready_bgn, NULL }, 4747 /* SIG_BGAK */ { sscop_ignore_pdu, NULL }, 4748 /* SIG_END */ { sscop_ready_end, NULL }, 4749 /* SIG_ENDAK */ { sscop_ready_endak, NULL }, 4750 /* SIG_RS */ { sscop_ready_rs, NULL }, 4751 /* SIG_RSAK */ { sscop_ignore_pdu, NULL }, 4752 /* SIG_BGREJ */ { sscop_ready_bgrej, NULL }, 4753 /* SIG_SD */ { sscop_ready_sd, NULL }, 4754 /* SIG_ER */ { sscop_ready_er, NULL }, 4755 /* SIG_POLL */ { sscop_ready_poll, NULL }, 4756 /* SIG_STAT */ { sscop_ready_stat, NULL }, 4757 /* SIG_USTAT */ { sscop_ready_ustat, NULL }, 4758 /* SIG_UD */ { sscop_ud, NULL }, 4759 /* SIG_MD */ { sscop_md, NULL }, 4760 /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4761 /* SIG_T_CC */ { NULL, NULL }, 4762 /* SIG_T_POLL */ { sscop_ready_tpoll, NULL }, 4763 /* SIG_T_KA */ { sscop_ready_tka, NULL }, 4764 /* SIG_T_NR */ { sscop_ready_nr, NULL }, 4765 /* SIG_T_IDLE */ { sscop_ready_tidle, NULL }, 4766 /* SIG_PDU_Q */ { sscop_ready_pduq, c_ready_pduq }, 4767 /* SIG_USER_DATA */ { sscop_ready_userdata, NULL }, 4768 /* SIG_ESTAB_REQ */ { NULL, NULL }, 4769 /* SIG_ESTAB_RESP */ { NULL, NULL }, 4770 /* SIG_RELEASE_REQ */ { sscop_ready_release_req, NULL }, 4771 /* SIG_RECOVER */ { NULL, NULL }, 4772 /* SIG_SYNC_REQ */ { sscop_ready_sync_req, NULL }, 4773 /* SIG_SYNC_RESP */ { NULL, NULL }, 4774 /* SIG_UDATA */ { sscop_udata_req, NULL }, 4775 /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4776 /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4777 /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4778 /* SIG_RETRIEVE */ { NULL, NULL }, 4779 } 4780}; 4781 4782/* 4783 * Try to execute a signal. It is executed if 4784 * - it is illegal (in this case it is effectively ignored) 4785 * - it has no condition 4786 * - its condition is true 4787 * If it has a condition and that is false, the function does nothing and 4788 * returns 0. 4789 * If the signal gets executed, the signal function is responsible to release 4790 * the message (if any). 4791 */ 4792static int 4793sig_exec(struct sscop *sscop, u_int sig, struct sscop_msg *msg) 4794{ 4795 void (*func)(struct sscop *, struct sscop_msg *); 4796 int (*cond)(struct sscop *); 4797 4798 func = state_matrix[sscop->state][sig].func; 4799 cond = state_matrix[sscop->state][sig].cond; 4800 4801 if(func == NULL) { 4802 VERBOSE(sscop, SSCOP_DBG_BUG, (sscop, sscop->aarg, 4803 "no handler for %s in state %s - ignored", 4804 events[sig], states[sscop->state])); 4805 SSCOP_MSG_FREE(msg); 4806 return 1; 4807 } 4808 if(cond == NULL || (*cond)(sscop)) { 4809 VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg, 4810 "executing %s in %s", events[sig], 4811 states[sscop->state])); 4812 (*func)(sscop, msg); 4813 return 1; 4814 } 4815 VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg, 4816 "delaying %s in %s", events[sig], 4817 states[sscop->state])); 4818 4819 return 0; 4820} 4821 4822/* 4823 * Deliver a signal to the given sscop 4824 * If it is delivered from inside a signal handler - queue it. If not, 4825 * execute it. After execution loop through the queue and execute all 4826 * pending signals. Signals, that cannot be executed because of entry 4827 * conditions are skipped. 4828 */ 4829static void 4830sscop_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg) 4831{ 4832 struct sscop_sig *s; 4833 4834 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 4835 "got signal %s in state %s%s", events[sig], 4836 states[sscop->state], sscop->in_sig ? " -- queuing" : "")); 4837 4838 SIG_ALLOC(s); 4839 if(s == NULL) { 4840 FAILURE("sscop: cannot allocate signal"); 4841 SSCOP_MSG_FREE(msg); 4842 return; 4843 } 4844 s->sig = sig; 4845 s->msg = msg; 4846 SIGQ_APPEND(&sscop->sigs, s); 4847 4848 if(!sscop->in_sig) 4849 handle_sigs(sscop); 4850} 4851 4852/* 4853 * Loop through the signal queue until we can't execute any signals. 4854 */ 4855static void 4856handle_sigs(struct sscop *sscop) 4857{ 4858 struct sscop_sig *s; 4859 sscop_sigq_head_t dsigs, q; 4860 int exec; 4861 4862 sscop->in_sig++; 4863 4864 /* 4865 * Copy the current signal queue to the local one and empty 4866 * the signal queue. Then loop through the signals. After one 4867 * pass we have a list of delayed signals because of entry 4868 * conditions and a new list of signals. Merge them. Repeat until 4869 * the signal queue is either empty or contains only delayed signals. 4870 */ 4871 SIGQ_INIT(&q); 4872 SIGQ_INIT(&dsigs); 4873 do { 4874 exec = 0; 4875 4876 /* 4877 * Copy signal list and make sscop list empty 4878 */ 4879 SIGQ_MOVE(&sscop->sigs, &q); 4880 4881 /* 4882 * Loop through the list 4883 */ 4884 while((s = SIGQ_GET(&q)) != NULL) { 4885 if(sig_exec(sscop, s->sig, s->msg)) { 4886 exec = 1; 4887 SIG_FREE(s); 4888 } else { 4889 SIGQ_APPEND(&dsigs, s); 4890 } 4891 } 4892 4893 /* 4894 * Merge lists by inserting delayed signals in front of 4895 * the signal list. preserving the order. 4896 */ 4897 SIGQ_PREPEND(&dsigs, &sscop->sigs); 4898 } while(exec); 4899 sscop->in_sig--; 4900} 4901 4902/* 4903 * Save a signal that should be executed only if state changes. 4904 */ 4905static void 4906sscop_save_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg) 4907{ 4908 struct sscop_sig *s; 4909 4910 SIG_ALLOC(s); 4911 if(s == NULL) { 4912 FAILURE("sscop: cannot allocate signal"); 4913 SSCOP_MSG_FREE(msg); 4914 return; 4915 } 4916 s->sig = sig; 4917 s->msg = msg; 4918 SIGQ_APPEND(&sscop->saved_sigs, s); 4919} 4920 4921/* 4922 * Set a new state. If signals are waiting for a state change - append them to 4923 * the signal queue, so they get executed. 4924 */ 4925static void 4926sscop_set_state(struct sscop *sscop, u_int nstate) 4927{ 4928 VERBOSE(sscop, SSCOP_DBG_STATE, (sscop, sscop->aarg, 4929 "changing state from %s to %s", 4930 states[sscop->state], states[nstate])); 4931 4932 sscop->state = nstate; 4933 SIGQ_MOVE(&sscop->saved_sigs, &sscop->sigs); 4934} 4935 4936void 4937sscop_setdebug(struct sscop *sscop, u_int n) 4938{ 4939 sscop->debug = n; 4940} 4941 4942u_int 4943sscop_getdebug(const struct sscop *sscop) 4944{ 4945 return (sscop->debug); 4946} 4947