summaryrefslogtreecommitdiffstats
path: root/sys/netatm/spans/spans_proto.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/spans/spans_proto.c')
-rw-r--r--sys/netatm/spans/spans_proto.c558
1 files changed, 558 insertions, 0 deletions
diff --git a/sys/netatm/spans/spans_proto.c b/sys/netatm/spans/spans_proto.c
new file mode 100644
index 0000000..e298ed8
--- /dev/null
+++ b/sys/netatm/spans/spans_proto.c
@@ -0,0 +1,558 @@
+/*
+ *
+ * ===================================
+ * 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: spans_proto.c,v 1.7 1998/08/26 23:29:10 mks Exp $
+ *
+ */
+
+/*
+ * SPANS Signalling Manager
+ * ---------------------------
+ *
+ * SPANS protocol processing module.
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: spans_proto.c,v 1.7 1998/08/26 23:29:10 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include "spans_xdr.h"
+#include <netatm/spans/spans_var.h>
+
+/*
+ * Internal functions
+ */
+caddr_t spans_getname __P((void *));
+void spans_connected __P((void *));
+void spans_cleared __P((void *, struct t_atm_cause *));
+void spans_cpcs_data __P((void *, KBuffer *));
+
+
+/*
+ * ATM endpoint for SPANS signalling channel
+ */
+static Atm_endpoint spans_endpt = {
+ NULL, /* ep_next */
+ ENDPT_SPANS_SIG, /* ep_id */
+ NULL, /* ep_ioctl */
+ spans_getname, /* ep_getname */
+ spans_connected, /* ep_connected */
+ spans_cleared, /* ep_cleared */
+ NULL, /* ep_incoming */
+ NULL, /* ep_addparty */
+ NULL, /* ep_dropparty */
+ NULL, /* ep_cpcs_ctl */
+ spans_cpcs_data, /* ep_cpcs_data */
+ NULL, /* ep_saal_ctl */
+ NULL, /* ep_saal_data */
+ NULL, /* ep_sscop_ctl */
+ NULL /* ep_sscop_data */
+};
+
+
+/*
+ * ATM connection attributes for UNI signalling channel
+ */
+static Atm_attributes spans_attr = {
+ NULL, /* nif */
+ CMAPI_CPCS, /* api */
+ 0, /* api_init */
+ 0, /* headin */
+ 0, /* headout */
+ { /* aal */
+ T_ATM_PRESENT, /* aal.tag */
+ ATM_AAL3_4 /* aal.aal_type */
+ },
+ { /* traffic */
+ T_ATM_PRESENT, /* traffic.tag */
+ { /* traffic.v */
+ { /* traffic.v.forward */
+ T_ATM_ABSENT, /* PCR_high */
+ 0, /* PCR_all */
+ T_ATM_ABSENT, /* SCR_high */
+ T_ATM_ABSENT, /* SCR_all */
+ T_ATM_ABSENT, /* MBS_high */
+ T_ATM_ABSENT, /* MBS_all */
+ T_NO, /* tagging */
+ },
+ { /* traffic.v.backward */
+ T_ATM_ABSENT, /* PCR_high */
+ 0, /* PCR_all */
+ T_ATM_ABSENT, /* SCR_high */
+ T_ATM_ABSENT, /* SCR_all */
+ T_ATM_ABSENT, /* MBS_high */
+ T_ATM_ABSENT, /* MBS_all */
+ T_NO, /* tagging */
+ },
+ T_YES, /* best_effort */
+ }
+ },
+ { /* bearer */
+ T_ATM_PRESENT, /* bearer.tag */
+ { /* bearer.v */
+ T_ATM_CLASS_X, /* class */
+ T_ATM_NULL, /* traffic_type */
+ T_ATM_NO_END_TO_END, /* timing_req */
+ T_NO, /* clipping */
+ T_ATM_1_TO_1, /* conn_conf */
+ }
+ },
+ { /* bhli */
+ T_ATM_ABSENT, /* bhli.tag */
+ },
+ { /* blli */
+ T_ATM_ABSENT, /* blli.tag_l2 */
+ T_ATM_ABSENT, /* blli.tag_l3 */
+ },
+ { /* llc */
+ T_ATM_ABSENT, /* llc.tag */
+ },
+ { /* called */
+ T_ATM_PRESENT, /* called.tag */
+ },
+ { /* calling */
+ T_ATM_ABSENT, /* calling.tag */
+ },
+ { /* qos */
+ T_ATM_PRESENT, /* qos.tag */
+ { /* qos.v */
+ T_ATM_NETWORK_CODING, /* coding_standard */
+ { /* qos.v.forward */
+ T_ATM_QOS_CLASS_0, /* class */
+ },
+ { /* qos.v.backward */
+ T_ATM_QOS_CLASS_0, /* class */
+ }
+ }
+ },
+ { /* transit */
+ T_ATM_ABSENT, /* transit.tag */
+ },
+ { /* cause */
+ T_ATM_ABSENT, /* cause.tag */
+ }
+};
+
+
+/*
+ * SPANS cause structre
+ */
+struct t_atm_cause spans_cause = {
+ T_ATM_ITU_CODING, /* coding_standard */
+ T_ATM_LOC_USER, /* location */
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL, /* cause_value */
+ { 0, 0, 0, 0 } /* diagnostics */
+};
+
+
+/*
+ * Process a SPANS timeout
+ *
+ * Called when a previously scheduled spans control block timer expires.
+ * Processing will based on the current SPANS state.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * tip pointer to spans timer control block
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spans_timer(tip)
+ struct atm_time *tip;
+{
+ struct spans *spp;
+ spans_msg *msg;
+ Atm_addr_pvc *pvcp;
+ int err;
+
+ /*
+ * Back-off to SPANS control block
+ */
+ spp = (struct spans *)
+ ((caddr_t)tip - (int)(&((struct spans *)0)->sp_time));
+
+ ATM_DEBUG2("spans_timer: spp=0x%x,state=%d\n",
+ (int)spp, spp->sp_state);
+
+ /*
+ * Process timeout based on protocol state
+ */
+ switch (spp->sp_state) {
+
+ case SPANS_INIT:
+
+ /*
+ * Open signalling channel
+ */
+ spans_attr.nif = spp->sp_pif->pif_nif;
+
+ spans_attr.aal.v.aal4.forward_max_SDU_size =
+ ATM_NIF_MTU;
+ spans_attr.aal.v.aal4.backward_max_SDU_size =
+ ATM_NIF_MTU;
+ spans_attr.aal.v.aal4.SSCS_type =
+ T_ATM_SSCS_SSCOP_UNREL;
+ spans_attr.aal.v.aal4.mid_low = 0;
+ spans_attr.aal.v.aal4.mid_high = 0;
+
+ spans_attr.called.tag = T_ATM_PRESENT;
+ spans_attr.called.addr.address_format = T_ATM_PVC_ADDR;
+ spans_attr.called.addr.address_length =
+ sizeof(Atm_addr_pvc);
+ pvcp = (Atm_addr_pvc *)spans_attr.called.addr.address;
+ ATM_PVC_SET_VPI(pvcp, SPANS_SIG_VPI);
+ ATM_PVC_SET_VCI(pvcp, SPANS_SIG_VCI);
+ spans_attr.called.subaddr.address_format = T_ATM_ABSENT;
+ spans_attr.called.subaddr.address_length = 0;
+
+ spans_attr.traffic.v.forward.PCR_all_traffic =
+ spp->sp_pif->pif_pcr;
+ spans_attr.traffic.v.backward.PCR_all_traffic =
+ spp->sp_pif->pif_pcr;
+
+ err = atm_cm_connect(&spans_endpt, spp, &spans_attr,
+ &spp->sp_conn);
+ if (err) {
+ log(LOG_CRIT, "spans: signalling channel setup failed\n");
+ return;
+ }
+
+ /*
+ * Signalling channel open, start probing
+ */
+ spp->sp_state = SPANS_PROBE;
+
+ /* FALLTHRU */
+
+ case SPANS_PROBE:
+ case SPANS_ACTIVE:
+
+ /*
+ * Send out SPANS_STAT_REQ message
+ */
+ msg = (spans_msg *)atm_allocate(&spans_msgpool);
+ if (msg == NULL) {
+ /* Retry later if no memory */
+ SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
+ break;
+ }
+ msg->sm_vers = SPANS_VERS_1_0;
+ msg->sm_type = SPANS_STAT_REQ;
+ msg->sm_stat_req.streq_es_epoch = spp->sp_h_epoch;
+ if (spans_send_msg(spp, msg)) {
+ /* Retry later if send fails */
+ SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
+ atm_free(msg);
+ break;
+ }
+ atm_free(msg);
+ spp->sp_probe_ct++;
+
+ /*
+ * Check whether we're getting an answer to our probes
+ */
+ if (spp->sp_state == SPANS_ACTIVE &&
+ spp->sp_probe_ct > SPANS_PROBE_THRESH) {
+ /*
+ * Interface is down, notify VCC owners
+ */
+ spans_switch_reset(spp, SPANS_UNI_DOWN);
+
+ /*
+ * Set new state and increment host epoch so
+ * switch knows we reset everyting.
+ */
+ spp->sp_state = SPANS_PROBE;
+ spp->sp_h_epoch++;
+ spp->sp_s_epoch = 0;
+ }
+
+ /*
+ * Keep sending status requests
+ */
+ SPANS_TIMER(spp, SPANS_PROBE_INTERVAL);
+
+ break;
+
+ case SPANS_DETACH:
+ /*
+ * Try to terminate the SPANS signalling PVC
+ */
+ err = atm_cm_release(spp->sp_conn, &spans_cause);
+ if (err) {
+ log(LOG_ERR, "spans: can't close signalling channel\n");
+ }
+ break;
+
+ default:
+ log(LOG_ERR, "spans: timer state: spp=0x%x, state=%d\n",
+ (int)spp, spp->sp_state);
+ }
+}
+
+
+/*
+ * Process a SPANS VCC timeout
+ *
+ * Called when a previously scheduled SPANS VCCB timer expires.
+ * Processing will based on the current VCC state.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * tip pointer to vccb timer control block
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spans_vctimer(tip)
+ struct atm_time *tip;
+{
+ int err;
+ struct spans *spp;
+ struct spans_vccb *svp;
+
+ /*
+ * Get VCCB and SPANS control block addresses
+ */
+ svp = (struct spans_vccb *) ((caddr_t)tip -
+ (int)(&((struct vccb *)0)->vc_time));
+ spp = (struct spans *)svp->sv_pif->pif_siginst;
+
+ ATM_DEBUG3("spans_vctimer: svp=0x%x, sstate=%d, ustate=%d\n",
+ (int)svp, svp->sv_sstate, svp->sv_ustate);
+
+ /*
+ * Process timeout based on protocol state
+ */
+ switch (svp->sv_sstate) {
+
+ case SPANS_VC_ABORT:
+ /*
+ * Kill the VCCB and notify the owner
+ */
+ err = spans_clear_vcc(spp, svp);
+ break;
+
+ case SPANS_VC_FREE:
+ /*
+ * Free VCCB storage
+ */
+ svp->sv_ustate = VCCU_CLOSED;
+ svp->sv_sstate = SPANS_VC_FREE;
+ spans_free((struct vccb *)svp);
+ break;
+
+ case SPANS_VC_POPEN:
+ /*
+ * Issued open request, but didn't get response.
+ */
+ if (svp->sv_retry < SV_MAX_RETRY) {
+ /*
+ * Retransmit the open request
+ */
+ err = spans_send_open_req(spp, svp);
+ svp->sv_retry++;
+ SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
+ } else {
+ /*
+ * Retry limit exceeded--report the open failed
+ */
+ svp->sv_ustate = VCCU_CLOSED;
+ svp->sv_sstate = SPANS_VC_FREE;
+ svp->sv_connvc->cvc_attr.cause.tag =
+ T_ATM_PRESENT;
+ svp->sv_connvc->cvc_attr.cause.v.coding_standard =
+ T_ATM_ITU_CODING;
+ svp->sv_connvc->cvc_attr.cause.v.location =
+ T_ATM_LOC_USER;
+ svp->sv_connvc->cvc_attr.cause.v.cause_value =
+ T_ATM_CAUSE_NO_USER_RESPONDING;
+ KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
+ sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
+ atm_cm_cleared(svp->sv_connvc);
+ }
+ break;
+
+ case SPANS_VC_CLOSE:
+ /*
+ * Issued close request, but didn't get response.
+ */
+ if (svp->sv_retry < SV_MAX_RETRY) {
+ /*
+ * Retransmit the close request
+ */
+ err = spans_send_close_req(spp, svp);
+ svp->sv_retry++;
+ SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
+ } else {
+ /*
+ * Retry limit exceeded--just finish the close
+ */
+ svp->sv_sstate = SPANS_VC_FREE;
+ svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
+ svp->sv_connvc->cvc_attr.cause.v.coding_standard =
+ T_ATM_ITU_CODING;
+ svp->sv_connvc->cvc_attr.cause.v.location =
+ T_ATM_LOC_USER;
+ svp->sv_connvc->cvc_attr.cause.v.cause_value =
+ T_ATM_CAUSE_NO_USER_RESPONDING;
+ KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
+ sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
+ atm_cm_cleared(svp->sv_connvc);
+ }
+ break;
+
+ case SPANS_VC_ACTIVE:
+ case SPANS_VC_ACT_DOWN:
+ /*
+ * Shouldn't happen
+ */
+ log(LOG_ERR, "spans_vctimer: unexpected state %d\n",
+ svp->sv_sstate);
+ break;
+
+ default:
+ log(LOG_ERR, "spans: vctimer state: svp=0x%x, sstate=%d\n",
+ (int)svp, svp->sv_sstate);
+ }
+}
+
+
+/*
+ * SPANS name routine
+ *
+ * Arguments:
+ * tok SPANS signalling channel token (ignored)
+ *
+ * Returns:
+ * pointer to a string identifying the SPANS signalling manager
+ *
+ */
+caddr_t
+spans_getname(tok)
+ void *tok;
+{
+ return("SPANS");
+}
+
+
+/*
+ * Process a VCC connection notification
+ *
+ * Should never be called
+ *
+ * Arguments:
+ * tok user's connection token (SPANS protocol block)
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spans_connected(tok)
+ void *tok;
+{
+ struct spans *spp = (struct spans *)tok;
+
+ ATM_DEBUG2("spans_connected: spp=0x%x,state=%d\n",
+ (int)spp, spp->sp_state);
+
+ /*
+ * Connected routine shouldn't ever get called for a PVC
+ */
+ log(LOG_ERR, "spans: connected function called, tok=0x%x\n",
+ (int)spp);
+}
+
+
+/*
+ * Process a VCC close notification
+ *
+ * Called when the SPANS signalling channel is closed
+ *
+ * Arguments:
+ * tok user's connection token (spans protocol block)
+ * cp pointer to cause structure
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spans_cleared(tok, cp)
+ void *tok;
+ struct t_atm_cause *cp;
+{
+ struct spans *spp = (struct spans *)tok;
+
+ /*
+ * VCC has been closed.
+ */
+ log(LOG_ERR, "spans: signalling channel closed\n");
+ SPANS_CANCEL(spp);
+ spp->sp_conn = 0;
+}
+
+
+/*
+ * SPANS CPCS data handler
+ *
+ * This is the module which receives data on the SPANS signalling
+ * channel. Processing is based on the indication received from the
+ * AAL and the protocol state.
+ *
+ * Arguments:
+ * tok session token (pointer to spans protocol control block)
+ * m pointer to buffer with data
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spans_cpcs_data(tok, m)
+ void *tok;
+ KBuffer *m;
+{
+ struct spans *spp = tok;
+
+ ATM_DEBUG3("spans_cpcs_data: spp=0x%x,state=%d,m=0x%x,\n",
+ (int)spp, spp->sp_state, m);
+
+ /*
+ * Process data
+ */
+ spans_rcv_msg(spp, m);
+}
OpenPOWER on IntegriCloud