saal_sscfu.c revision 121326
160812Sps/* 2238730Sdelphij * Copyright (c) 1996-2003 3238730Sdelphij * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4238730Sdelphij * All rights reserved. 5238730Sdelphij * 6238730Sdelphij * Redistribution and use in source and binary forms, with or without 7238730Sdelphij * modification, are permitted provided that the following conditions 8238730Sdelphij * are met: 9238730Sdelphij * 1. Redistributions of source code must retain the above copyright 1060786Sps * notice, this list of conditions and the following disclaimer. 1160786Sps * 2. Redistributions in binary form must reproduce the above copyright 1260786Sps * notice, this list of conditions and the following disclaimer in the 1360786Sps * documentation and/or other materials provided with the distribution. 1460786Sps * 1560786Sps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1660786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1760786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1860786Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1960786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2060786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2160786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2260786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23170259Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2460786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2560786Sps * SUCH DAMAGE. 2660786Sps * 2760786Sps * Author: Hartmut Brandt <harti@freebsd.org> 2860786Sps * 29170259Sdelphij * $Begemot: libunimsg/atm/saal/saal_sscfu.c,v 1.3 2003/09/19 12:02:03 hbb Exp $ 3060786Sps * 3160786Sps * SSCF on the UNI 3260786Sps */ 3360786Sps 3460786Sps#include <netnatm/saal/sscfu.h> 3560786Sps#include <netnatm/saal/sscfupriv.h> 36170259Sdelphij 3760786Sps#define MKSTR(S) #S 3860786Sps 3960786Spsstatic const char *const sscf_sigs[] = { 4060786Sps MKSTR(SAAL_ESTABLISH_request), 4160786Sps MKSTR(SAAL_ESTABLISH_indication), 4260786Sps MKSTR(SAAL_ESTABLISH_confirm), 4360786Sps MKSTR(SAAL_RELEASE_request), 4460786Sps MKSTR(SAAL_RELEASE_confirm), 4560786Sps MKSTR(SAAL_RELEASE_indication), 4660786Sps MKSTR(SAAL_DATA_request), 4760786Sps MKSTR(SAAL_DATA_indication), 4860786Sps MKSTR(SAAL_UDATA_request), 4960786Sps MKSTR(SAAL_UDATA_indication), 5060786Sps}; 5160786Sps 5260786Spsstatic const char *const sscf_states[] = { 5360786Sps MKSTR(SSCF_RELEASED), 54191930Sdelphij MKSTR(SSCF_AWAITING_ESTABLISH), 5560786Sps MKSTR(SSCF_AWAITING_RELEASE), 56191930Sdelphij MKSTR(SSCF_ESTABLISHED), 57191930Sdelphij MKSTR(SSCF_RESYNC), 5860786Sps}; 5960786Sps 6060786Sps#define AA_SIG(S,G,M) \ 6160786Sps ((S)->funcs->send_upper((S), (S)->aarg, (G), (M))) 62191930Sdelphij 63191930Sdelphij#define SSCOP_AASIG(S,G,M,P) \ 64191930Sdelphij ((S)->funcs->send_lower((S), (S)->aarg, (G), (M), (P))) 65191930Sdelphij 66191930SdelphijMEMINIT(); 67191930Sdelphij 68191930Sdelphijstatic void sscfu_unqueue(struct sscfu *sscf); 69191930Sdelphij 70191930Sdelphij/************************************************************/ 7160786Sps/* 7260786Sps * INSTANCE AND CLASS MANAGEMENT 7360786Sps */ 7460786Sps 7560786Sps/* 7660786Sps * Initialize SSCF. 77191930Sdelphij */ 7860786Spsstruct sscfu * 7960786Spssscfu_create(void *a, const struct sscfu_funcs *funcs) 8060786Sps{ 81191930Sdelphij struct sscfu *sscf; 82191930Sdelphij 83191930Sdelphij MEMZALLOC(sscf, struct sscfu *, sizeof(struct sscfu)); 84191930Sdelphij if (sscf == NULL) 85191930Sdelphij return (NULL); 86191930Sdelphij 87191930Sdelphij sscf->funcs = funcs; 88191930Sdelphij sscf->aarg = a; 89191930Sdelphij sscf->state = SSCFU_RELEASED; 90191930Sdelphij sscf->inhand = 0; 91191930Sdelphij SIGQ_INIT(&sscf->sigs); 92191930Sdelphij sscf->debug = 0; 93191930Sdelphij 94191930Sdelphij return (sscf); 95191930Sdelphij} 96191930Sdelphij 97191930Sdelphij/* 9860786Sps * Reset the instance. Call only if you know, what you're doing. 9960786Sps */ 10060786Spsvoid 10160786Spssscfu_reset(struct sscfu *sscf) 10260786Sps{ 103170259Sdelphij sscf->state = SSCFU_RELEASED; 10460786Sps sscf->inhand = 0; 10560786Sps SIGQ_CLEAR(&sscf->sigs); 10660786Sps} 10760786Sps 10860786Sps/* 10960786Sps * Destroy SSCF 11060786Sps */ 11160786Spsvoid 11260786Spssscfu_destroy(struct sscfu *sscf) 11360786Sps{ 11460786Sps SIGQ_CLEAR(&sscf->sigs); 11560786Sps MEMFREE(sscf); 11660786Sps} 11760786Sps 11860786Spsenum sscfu_state 11960786Spssscfu_getstate(const struct sscfu *sscf) 12060786Sps{ 12160786Sps return (sscf->state); 12260786Sps} 12360786Sps 12460786Spsu_int 12560786Spssscfu_getdefparam(struct sscop_param *p) 12660786Sps{ 12760786Sps memset(p, 0, sizeof(*p)); 12860786Sps 12960786Sps p->timer_cc = 1000; 13060786Sps p->timer_poll = 750; 13160786Sps p->timer_keep_alive = 2000; 13260786Sps p->timer_no_response = 7000; 13360786Sps p->timer_idle = 15000; 13460786Sps p->maxk = 4096; 13560786Sps p->maxj = 4096; 13660786Sps p->maxcc = 4; 13760786Sps p->maxpd = 25; 13860786Sps 13960786Sps return (SSCOP_SET_TCC | SSCOP_SET_TPOLL | SSCOP_SET_TKA | 14060786Sps SSCOP_SET_TNR | SSCOP_SET_TIDLE | SSCOP_SET_MAXK | 14160786Sps SSCOP_SET_MAXJ | SSCOP_SET_MAXCC | SSCOP_SET_MAXPD); 14260786Sps} 14360786Sps 14460786Spsconst char * 14560786Spssscfu_signame(enum saal_sig sig) 14660786Sps{ 14760786Sps static char str[40]; 14860786Sps 14960786Sps if (sig >= sizeof(sscf_sigs)/sizeof(sscf_sigs[0])) { 15060786Sps sprintf(str, "BAD SAAL_SIGNAL %u", sig); 15160786Sps return (str); 15260786Sps } else { 15360786Sps return (sscf_sigs[sig]); 15460786Sps } 15560786Sps} 15660786Sps 15760786Spsconst char * 15860786Spssscfu_statename(enum sscfu_state s) 15960786Sps{ 16060786Sps static char str[40]; 161170259Sdelphij 162170259Sdelphij if (s >= sizeof(sscf_states)/sizeof(sscf_states[0])) { 16360812Sps sprintf(str, "BAD SSCFU state %u", s); 16460812Sps return (str); 16560786Sps } else { 16660786Sps return (sscf_states[s]); 16760786Sps } 16860786Sps} 16960786Sps 17060786Sps/************************************************************/ 17160786Sps/* 17260786Sps * EXTERNAL INPUT SIGNAL MAPPING 17360786Sps */ 17460786Spsstatic __inline void 17560786Spsset_state(struct sscfu *sscf, enum sscfu_state state) 17660786Sps{ 17760786Sps VERBOSE(sscf, SSCFU_DBG_STATE, (sscf, sscf->aarg, 17860786Sps "change state from %s to %s", 179170259Sdelphij sscf_states[sscf->state], sscf_states[state])); 18060786Sps sscf->state = state; 18160786Sps} 18260786Sps 18360786Sps/* 18460786Sps * signal from SSCOP to SSCF 18560786Sps * Message must be freed by the user specified handler, if 18660786Sps * it is passed. 18760786Sps */ 18860786Spsvoid 18960786Spssscfu_input(struct sscfu *sscf, enum sscop_aasig sig, 19060786Sps struct SSCFU_MBUF_T *m, u_int arg __unused) 19160786Sps{ 19260786Sps sscf->inhand = 1; 19360786Sps 19460786Sps VERBOSE(sscf, SSCFU_DBG_LSIG, (sscf, sscf->aarg, 19560786Sps "SSCF got signal %d. in state %s", sig, sscf_states[sscf->state])); 19660786Sps 19760786Sps switch (sig) { 19860786Sps 19960786Sps case SSCOP_RELEASE_indication: 20060786Sps /* arg is: UU, SRC */ 20160786Sps switch (sscf->state) { 20260786Sps 20360786Sps case SSCFU_RELEASED: 20460786Sps if (m) 20560786Sps MBUF_FREE(m); 20660786Sps goto badsig; 20760786Sps 20860786Sps case SSCFU_AWAITING_ESTABLISH: 20960786Sps set_state(sscf, SSCFU_RELEASED); 21060786Sps AA_SIG(sscf, SAAL_RELEASE_indication, m); 21160786Sps break; 21260786Sps 21360786Sps case SSCFU_AWAITING_RELEASE: 21460786Sps if (m) 21560786Sps MBUF_FREE(m); 21660786Sps goto badsig; 21760786Sps 21860786Sps case SSCFU_ESTABLISHED: 21960786Sps set_state(sscf, SSCFU_RELEASED); 22060786Sps AA_SIG(sscf, SAAL_RELEASE_indication, m); 22160786Sps break; 22260786Sps 22360786Sps case SSCFU_RESYNC: 22460786Sps set_state(sscf, SSCFU_RELEASED); 22560786Sps AA_SIG(sscf, SAAL_RELEASE_indication, m); 22660786Sps break; 22760786Sps } 22860786Sps break; 22960786Sps 23060786Sps case SSCOP_ESTABLISH_indication: 23160786Sps /* arg is: UU */ 23260786Sps switch (sscf->state) { 23360786Sps 23460786Sps case SSCFU_RELEASED: 23560786Sps set_state(sscf, SSCFU_ESTABLISHED); 23660786Sps SSCOP_AASIG(sscf, SSCOP_ESTABLISH_response, NULL, 1); 23760786Sps AA_SIG(sscf, SAAL_ESTABLISH_indication, m); 23860786Sps break; 23960786Sps 24060786Sps case SSCFU_AWAITING_ESTABLISH: 24160786Sps case SSCFU_AWAITING_RELEASE: 24260786Sps case SSCFU_ESTABLISHED: 24360786Sps case SSCFU_RESYNC: 244170259Sdelphij if (m) 24560816Sps MBUF_FREE(m); 24660786Sps goto badsig; 24760786Sps } 24860786Sps break; 24960786Sps 25060786Sps case SSCOP_ESTABLISH_confirm: 25160786Sps /* arg is: UU */ 25260786Sps switch (sscf->state) { 25360786Sps 25460786Sps case SSCFU_RELEASED: 255170259Sdelphij if (m) 256170259Sdelphij MBUF_FREE(m); 257170259Sdelphij goto badsig; 258170259Sdelphij 259170259Sdelphij case SSCFU_AWAITING_ESTABLISH: 260170259Sdelphij set_state(sscf, SSCFU_ESTABLISHED); 261170259Sdelphij AA_SIG(sscf, SAAL_ESTABLISH_confirm, m); 262170259Sdelphij break; 263170259Sdelphij 264161478Sdelphij case SSCFU_AWAITING_RELEASE: 26560786Sps case SSCFU_ESTABLISHED: 26660786Sps case SSCFU_RESYNC: 26760786Sps if (m) 26860786Sps MBUF_FREE(m); 26960786Sps goto badsig; 27060786Sps } 27160786Sps break; 27260786Sps 27360786Sps case SSCOP_RELEASE_confirm: 27460786Sps /* arg is: */ 275170259Sdelphij switch (sscf->state) { 276170259Sdelphij 27760786Sps case SSCFU_RELEASED: 27860786Sps case SSCFU_AWAITING_ESTABLISH: 27960786Sps goto badsig; 28060786Sps 28160786Sps case SSCFU_AWAITING_RELEASE: 28260786Sps set_state(sscf, SSCFU_RELEASED); 28360786Sps AA_SIG(sscf, SAAL_RELEASE_confirm, NULL); 28460786Sps break; 28560786Sps 28660786Sps case SSCFU_ESTABLISHED: 28760786Sps case SSCFU_RESYNC: 28860786Sps goto badsig; 28960786Sps } 29060786Sps break; 29160786Sps 29260786Sps case SSCOP_DATA_indication: 29360786Sps /* arg is: MU */ 29460786Sps sscf->funcs->window(sscf, sscf->aarg, 1); 29560786Sps switch (sscf->state) { 29660786Sps 29760786Sps case SSCFU_RELEASED: 29860786Sps case SSCFU_AWAITING_ESTABLISH: 29960786Sps case SSCFU_AWAITING_RELEASE: 30060786Sps MBUF_FREE(m); 30160786Sps goto badsig; 30260786Sps 30360786Sps case SSCFU_ESTABLISHED: 30460786Sps AA_SIG(sscf, SAAL_DATA_indication, m); 30560786Sps break; 30660786Sps 30760786Sps case SSCFU_RESYNC: 30860786Sps MBUF_FREE(m); 30960786Sps goto badsig; 31060786Sps } 31160786Sps break; 31260786Sps 31360786Sps case SSCOP_RECOVER_indication: 31460786Sps /* arg is: */ 31560786Sps switch (sscf->state) { 31660786Sps 31760786Sps case SSCFU_RELEASED: 31860786Sps case SSCFU_AWAITING_ESTABLISH: 31960786Sps case SSCFU_AWAITING_RELEASE: 32060786Sps goto badsig; 32160786Sps 32260786Sps case SSCFU_ESTABLISHED: 32360786Sps SSCOP_AASIG(sscf, SSCOP_RECOVER_response, NULL, 0); 32460786Sps AA_SIG(sscf, SAAL_ESTABLISH_indication, NULL); 32560786Sps break; 32660786Sps 32760786Sps case SSCFU_RESYNC: 32860786Sps goto badsig; 32960786Sps } 33060786Sps break; 33160786Sps 33260786Sps case SSCOP_RESYNC_indication: 33360786Sps /* arg is: UU */ 334170259Sdelphij switch (sscf->state) { 335170259Sdelphij 33660786Sps case SSCFU_RELEASED: 33760786Sps case SSCFU_AWAITING_ESTABLISH: 33860786Sps case SSCFU_AWAITING_RELEASE: 33960786Sps if (m) 34060786Sps MBUF_FREE(m); 34160786Sps goto badsig; 34260786Sps 34360786Sps case SSCFU_ESTABLISHED: 34460786Sps SSCOP_AASIG(sscf, SSCOP_RESYNC_response, NULL, 0); 34560786Sps AA_SIG(sscf, SAAL_ESTABLISH_indication, m); 34660786Sps break; 34760786Sps 34860786Sps case SSCFU_RESYNC: 34960786Sps if (m) 35060786Sps MBUF_FREE(m); 351191930Sdelphij goto badsig; 35260786Sps } 35360786Sps break; 35460786Sps 35560786Sps case SSCOP_RESYNC_confirm: 35660786Sps /* arg is: */ 35760786Sps switch (sscf->state) { 35860786Sps 35960786Sps case SSCFU_RELEASED: 36060786Sps case SSCFU_AWAITING_ESTABLISH: 36160786Sps case SSCFU_AWAITING_RELEASE: 36260786Sps case SSCFU_ESTABLISHED: 36360786Sps 36460786Sps case SSCFU_RESYNC: 36560786Sps set_state(sscf, SSCFU_ESTABLISHED); 36660786Sps AA_SIG(sscf, SAAL_ESTABLISH_confirm, NULL); 36760786Sps break; 36860786Sps } 36960786Sps break; 37060786Sps 37160786Sps case SSCOP_UDATA_indication: 37260786Sps /* arg is: MD */ 37360786Sps AA_SIG(sscf, SAAL_UDATA_indication, m); 37460786Sps break; 37560786Sps 37660786Sps 37760786Sps case SSCOP_RETRIEVE_indication: 37860786Sps if (m) 37960786Sps MBUF_FREE(m); 38060786Sps goto badsig; 38160786Sps 38260786Sps case SSCOP_RETRIEVE_COMPL_indication: 38360786Sps goto badsig; 38460786Sps 38560786Sps case SSCOP_ESTABLISH_request: 38660786Sps case SSCOP_RELEASE_request: 38760786Sps case SSCOP_ESTABLISH_response: 38860786Sps case SSCOP_DATA_request: 38960786Sps case SSCOP_RECOVER_response: 39060786Sps case SSCOP_RESYNC_request: 39160786Sps case SSCOP_RESYNC_response: 39260786Sps case SSCOP_UDATA_request: 39360786Sps case SSCOP_RETRIEVE_request: 39460786Sps ASSERT(0); 39560786Sps break; 39660786Sps } 39760786Sps 39860786Sps sscfu_unqueue(sscf); 39960786Sps return; 40060786Sps 40160786Sps badsig: 40260786Sps VERBOSE(sscf, SSCFU_DBG_ERR, (sscf, sscf->aarg, 40360786Sps "bad signal %d. in state %s", sig, sscf_states[sscf->state])); 40460786Sps sscfu_unqueue(sscf); 40560786Sps} 40660786Sps 40760786Sps 40860786Sps/* 40960786Sps * Handle signals from the user 41060786Sps */ 41160786Spsstatic void 41260786Spssscfu_dosig(struct sscfu *sscf, enum saal_sig sig, struct SSCFU_MBUF_T *m) 41360786Sps{ 41460786Sps VERBOSE(sscf, SSCFU_DBG_EXEC, (sscf, sscf->aarg, 41560786Sps "executing signal %s(%s)", 41660786Sps sscf_sigs[sig], sscf_states[sscf->state])); 41760786Sps 41860786Sps switch (sig) { 41960786Sps 42060786Sps case SAAL_ESTABLISH_request: 42160786Sps /* arg is opt UU */ 42260786Sps switch (sscf->state) { 42360786Sps 42460786Sps case SSCFU_RELEASED: 42560786Sps set_state(sscf, SSCFU_AWAITING_ESTABLISH); 42660786Sps SSCOP_AASIG(sscf, SSCOP_ESTABLISH_request, m, 1); 42760786Sps break; 42860786Sps 429 case SSCFU_AWAITING_ESTABLISH: 430 if (m) 431 MBUF_FREE(m); 432 goto badsig; 433 434 case SSCFU_AWAITING_RELEASE: 435 set_state(sscf, SSCFU_AWAITING_ESTABLISH); 436 SSCOP_AASIG(sscf, SSCOP_ESTABLISH_request, m, 1); 437 break; 438 439 case SSCFU_ESTABLISHED: 440 set_state(sscf, SSCFU_RESYNC); 441 SSCOP_AASIG(sscf, SSCOP_RESYNC_request, m, 0); 442 break; 443 444 case SSCFU_RESYNC: 445 if (m) 446 MBUF_FREE(m); 447 goto badsig; 448 } 449 break; 450 451 case SAAL_RELEASE_request: 452 /* arg is opt UU */ 453 switch(sscf->state) { 454 455 case SSCFU_RELEASED: 456 if (m) 457 MBUF_FREE(m); 458 AA_SIG(sscf, SAAL_RELEASE_confirm, NULL); 459 break; 460 461 case SSCFU_AWAITING_ESTABLISH: 462 set_state(sscf, SSCFU_AWAITING_RELEASE); 463 SSCOP_AASIG(sscf, SSCOP_RELEASE_request, m, 0); 464 break; 465 466 case SSCFU_AWAITING_RELEASE: 467 if (m) 468 MBUF_FREE(m); 469 goto badsig; 470 471 case SSCFU_ESTABLISHED: 472 set_state(sscf, SSCFU_AWAITING_RELEASE); 473 SSCOP_AASIG(sscf, SSCOP_RELEASE_request, m, 0); 474 break; 475 476 case SSCFU_RESYNC: 477 set_state(sscf, SSCFU_AWAITING_RELEASE); 478 SSCOP_AASIG(sscf, SSCOP_RELEASE_request, m, 0); 479 break; 480 } 481 break; 482 483 case SAAL_DATA_request: 484 /* arg is DATA */ 485 switch (sscf->state) { 486 487 case SSCFU_RELEASED: 488 case SSCFU_AWAITING_ESTABLISH: 489 case SSCFU_AWAITING_RELEASE: 490 MBUF_FREE(m); 491 goto badsig; 492 493 case SSCFU_ESTABLISHED: 494 SSCOP_AASIG(sscf, SSCOP_DATA_request, m, 0); 495 break; 496 497 case SSCFU_RESYNC: 498 MBUF_FREE(m); 499 goto badsig; 500 } 501 break; 502 503 case SAAL_UDATA_request: 504 /* arg is UDATA */ 505 SSCOP_AASIG(sscf, SSCOP_UDATA_request, m, 0); 506 break; 507 508 case SAAL_ESTABLISH_indication: 509 case SAAL_ESTABLISH_confirm: 510 case SAAL_RELEASE_confirm: 511 case SAAL_RELEASE_indication: 512 case SAAL_DATA_indication: 513 case SAAL_UDATA_indication: 514 ASSERT(0); 515 break; 516 } 517 return; 518 519 badsig: 520 VERBOSE(sscf, SSCFU_DBG_ERR, (sscf, sscf->aarg, 521 "bad signal %s in state %s", sscf_sigs[sig], 522 sscf_states[sscf->state])); 523} 524 525/* 526 * Handle user signal. 527 */ 528int 529sscfu_saalsig(struct sscfu *sscf, enum saal_sig sig, struct SSCFU_MBUF_T *m) 530{ 531 struct sscfu_sig *s; 532 533 if (sscf->inhand) { 534 VERBOSE(sscf, SSCFU_DBG_EXEC, (sscf, sscf->aarg, 535 "queuing user signal %s(%s)", 536 sscf_sigs[sig], sscf_states[sscf->state])); 537 SIG_ALLOC(s); 538 if (s == NULL) 539 return (ENOMEM); 540 s->sig = sig; 541 s->m = m; 542 SIGQ_APPEND(&sscf->sigs, s); 543 return (0); 544 } 545 546 sscf->inhand = 1; 547 sscfu_dosig(sscf, sig, m); 548 sscfu_unqueue(sscf); 549 return (0); 550} 551 552/* 553 * Unqueue all qeueued signals. Must be called with inhand==1. 554 */ 555static void 556sscfu_unqueue(struct sscfu *sscf) 557{ 558 struct sscfu_sig *s; 559 560 while ((s = SIGQ_GET(&sscf->sigs)) != NULL) { 561 sscfu_dosig(sscf, s->sig, s->m); 562 SIG_FREE(s); 563 } 564 sscf->inhand = 0; 565} 566 567void 568sscfu_setdebug(struct sscfu *sscf, u_int n) 569{ 570 sscf->debug = n; 571} 572 573u_int 574sscfu_getdebug(const struct sscfu *sscf) 575{ 576 return (sscf->debug); 577} 578