diff options
Diffstat (limited to 'sys/netatm/uni/sscop.c')
-rw-r--r-- | sys/netatm/uni/sscop.c | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/sys/netatm/uni/sscop.c b/sys/netatm/uni/sscop.c new file mode 100644 index 000000000000..d65118b7d7c4 --- /dev/null +++ b/sys/netatm/uni/sscop.c @@ -0,0 +1,409 @@ +/* + * + * =================================== + * HARP | Host ATM Research Platform + * =================================== + * + * + * This Host ATM Research Platform ("HARP") file (the "Software") is + * made available by Network Computing Services, Inc. ("NetworkCS") + * "AS IS". NetworkCS does not provide maintenance, improvements or + * support of any kind. + * + * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, + * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE + * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. + * In no event shall NetworkCS be responsible for any damages, including + * but not limited to consequential damages, arising from or relating to + * any use of the Software or related support. + * + * Copyright 1994-1998 Network Computing Services, Inc. + * + * Copies of this Software may be made, however, the above copyright + * notice must be reproduced on all copies. + * + * @(#) $Id: sscop.c,v 1.6 1998/03/24 21:10:43 mks Exp $ + * + */ + +/* + * ATM Forum UNI Support + * --------------------- + * + * Service Specific Connection Oriented Protocol (SSCOP) + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: sscop.c,v 1.6 1998/03/24 21:10:43 mks Exp $"; +#endif + +#include <netatm/kern_include.h> + +#include <netatm/uni/uni.h> +#include <netatm/uni/sscop.h> +#include <netatm/uni/sscop_misc.h> +#include <netatm/uni/sscop_pdu.h> +#include <netatm/uni/sscop_var.h> + + +/* + * Global variables + */ +int sscop_vccnt = 0; + +struct sscop *sscop_head = NULL; + +struct sscop_stat sscop_stat = {0}; + +struct atm_time sscop_timer = {0, 0}; + +struct sp_info sscop_pool = { + "sscop pool", /* si_name */ + sizeof(struct sscop), /* si_blksiz */ + 5, /* si_blkcnt */ + 100 /* si_maxallow */ +}; + + +/* + * Local functions + */ +static int sscop_inst __P((struct stack_defn **, Atm_connvc *)); + + +/* + * Local variables + */ +static struct stack_defn sscop_service = { + NULL, + SAP_SSCOP, + 0, + sscop_inst, + sscop_lower, + sscop_upper, + 0 +}; + +static struct t_atm_cause sscop_cause = { + T_ATM_ITU_CODING, + T_ATM_LOC_USER, + T_ATM_CAUSE_TEMPORARY_FAILURE, + {0, 0, 0, 0} +}; + +static u_char sscop_maa_log[MAA_ERROR_COUNT] = { + 1, /* A */ + 1, /* B */ + 1, /* C */ + 1, /* D */ + 1, /* E */ + 1, /* F */ + 1, /* G */ + 1, /* H */ + 1, /* I */ + 1, /* J */ + 1, /* K */ + 1, /* L */ + 1, /* M */ + 0, /* N */ + 0, /* O */ + 0, /* P */ + 1, /* Q */ + 1, /* R */ + 1, /* S */ + 1, /* T */ + 1, /* U */ + 0, /* V */ + 0, /* W */ + 0, /* X */ + 1 /* INVAL */ +}; + + +/* + * Initialize SSCOP processing + * + * This will be called during module loading. We will register our stack + * service and wait for someone to talk to us. + * + * Arguments: + * none + * + * Returns: + * 0 initialization was successful + * errno initialization failed - reason indicated + * + */ +int +sscop_start() +{ + int err = 0; + + /* + * Register stack service + */ + if (err = atm_stack_register(&sscop_service)) + goto done; + + /* + * Start up timer + */ + atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout); + +done: + return (err); +} + + +/* + * Terminate SSCOP processing + * + * This will be called just prior to unloading the module from memory. All + * signalling instances should have been terminated by now, so we just free + * up all of our resources. + * + * Called at splnet. + * + * Arguments: + * none + * + * Returns: + * 0 termination was successful + * errno termination failed - reason indicated + * + */ +int +sscop_stop() +{ + int err = 0; + + /* + * Any connections still exist?? + */ + if (sscop_vccnt) { + + /* + * Yes, can't stop yet + */ + return (EBUSY); + } + + /* + * Stop our timer + */ + (void) atm_untimeout(&sscop_timer); + + /* + * Deregister the stack service + */ + (void) atm_stack_deregister(&sscop_service); + + /* + * Free our storage pools + */ + atm_release_pool(&sscop_pool); + +done: + return (err); +} + + +/* + * SSCOP Stack Instantiation + * + * Called at splnet. + * + * Arguments: + * ssp pointer to array of stack definition pointers for connection + * ssp[0] points to upper layer's stack service definition + * ssp[1] points to this layer's stack service definition + * ssp[2] points to lower layer's stack service definition + * cvp pointer to connection vcc for this stack + * + * Returns: + * 0 instantiation successful + * errno instantiation failed - reason indicated + * + */ +static int +sscop_inst(ssp, cvp) + struct stack_defn **ssp; + Atm_connvc *cvp; +{ + struct stack_defn *sdp_up = ssp[0], + *sdp_me = ssp[1], + *sdp_low = ssp[2]; + struct sscop *sop; + int err; + + ATM_DEBUG2("sscop_inst: ssp=0x%x, cvp=0x%x\n", ssp, cvp); + + /* + * Validate lower SAP + */ + if ((sdp_low->sd_sap & SAP_CLASS_MASK) != SAP_CPCS) + return (EINVAL); + + /* + * Allocate our control block + */ + sop = (struct sscop *)atm_allocate(&sscop_pool); + if (sop == NULL) + return (ENOMEM); + + sop->so_state = SOS_INST; + sop->so_connvc = cvp; + sop->so_toku = sdp_up->sd_toku; + sop->so_upper = sdp_up->sd_upper; + + /* + * Store my token into service definition + */ + sdp_me->sd_toku = sop; + + /* + * Update and save input buffer headroom + */ + HEADIN(cvp, sizeof(struct pdu_hdr), 0); + /* sop->so_headin = cvp->cvc_attr.headin; */ + + /* + * Pass instantiation down the stack + */ + err = sdp_low->sd_inst(ssp + 1, cvp); + if (err) { + /* + * Lower layer instantiation failed, free our resources + */ + atm_free((caddr_t)sop); + return (err); + } + + /* + * Link in connection block + */ + LINK2TAIL(sop, struct sscop, sscop_head, so_next); + sscop_vccnt++; + sscop_stat.sos_connects++; + + /* + * Save and update output buffer headroom + */ + sop->so_headout = cvp->cvc_attr.headout; + HEADOUT(cvp, sizeof(struct pdu_hdr), 0); + + /* + * Save lower layer's interface info + */ + sop->so_lower = sdp_low->sd_lower; + sop->so_tokl = sdp_low->sd_toku; + + /* + * Initialize version (until INIT received) + */ + sop->so_vers = SSCOP_VERS_Q2110; + + return (0); +} + + +/* + * Report Management Error + * + * Called to report an error to the layer management entity. + * + * Arguments: + * sop pointer to sscop control block + * code error code + * + * Returns: + * none + * + */ +void +sscop_maa_error(sop, code) + struct sscop *sop; + int code; +{ + int i; + + /* + * Validate error code + */ + if ((code < MAA_ERROR_MIN) || + (code > MAA_ERROR_MAX)) + code = MAA_ERROR_INVAL; + i = code - MAA_ERROR_MIN; + + /* + * Bump statistics counters + */ + sscop_stat.sos_maa_error[i]++; + + /* + * Log error message + */ + if (sscop_maa_log[i] != 0) { + struct vccb *vcp = sop->so_connvc->cvc_vcc; + struct atm_pif *pip = vcp->vc_pif; + + log(LOG_ERR, + "sscop_maa_error: intf=%s%d vpi=%d vci=%d code=%c state=%d\n", + pip->pif_name, pip->pif_unit, + vcp->vc_vpi, vcp->vc_vci, code, sop->so_state); + } +} + + +/* + * Abort an SSCOP connection + * + * Called when an unrecoverable or "should never happen" error occurs. + * We log a message, send an END PDU to our peer and request the signalling + * manager to abort the connection. + * + * Arguments: + * sop pointer to sscop control block + * msg pointer to error message + * + * Returns: + * none + * + */ +void +sscop_abort(sop, msg) + struct sscop *sop; + char *msg; +{ + Atm_connvc *cvp = sop->so_connvc; + + /* + * Log and count error + */ + log(LOG_ERR, msg); + sscop_stat.sos_aborts++; + + /* + * Send an END PDU as a courtesy to peer + */ + (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP); + + /* + * Set termination state + */ + sop->so_state = SOS_TERM; + + /* + * Flush all of our queues + */ + sscop_xmit_drain(sop); + sscop_rcvr_drain(sop); + + /* + * Tell Connection Manager to abort this connection + */ + (void) atm_cm_abort(cvp, &sscop_cause); +} + |