aboutsummaryrefslogtreecommitdiff
path: root/sys/netatm/uni/sscop.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/uni/sscop.c')
-rw-r--r--sys/netatm/uni/sscop.c409
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);
+}
+