summaryrefslogtreecommitdiffstats
path: root/sys/netatm/spans/spans_cls.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
committerphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
commitc3dd1fa899d435ea4bf79897f646a93cb80c94ac (patch)
tree98dfbc96e3c6aa7ff1f322855f6484c4e609819d /sys/netatm/spans/spans_cls.c
parent9ed6892f4808d56de443849229e151f8f7ad43b0 (diff)
downloadFreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.zip
FreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.tar.gz
Add new files for HARP3
Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA).
Diffstat (limited to 'sys/netatm/spans/spans_cls.c')
-rw-r--r--sys/netatm/spans/spans_cls.c848
1 files changed, 848 insertions, 0 deletions
diff --git a/sys/netatm/spans/spans_cls.c b/sys/netatm/spans/spans_cls.c
new file mode 100644
index 0000000..f496311
--- /dev/null
+++ b/sys/netatm/spans/spans_cls.c
@@ -0,0 +1,848 @@
+/*
+ *
+ * ===================================
+ * 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_cls.c,v 1.11 1998/06/29 22:04:29 mks Exp $
+ *
+ */
+
+/*
+ * SPANS Signalling Manager
+ * ---------------------------
+ *
+ * SPANS Connectionless Datagram Service (CLS) module
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: spans_cls.c,v 1.11 1998/06/29 22:04:29 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/ipatm/ipatm_var.h>
+#include <netatm/ipatm/ipatm_serv.h>
+#include "spans_xdr.h"
+#include <netatm/spans/spans_var.h>
+#include <netatm/spans/spans_cls.h>
+
+
+/*
+ * Global variables
+ */
+int spanscls_print = 0;
+
+struct spanscls *spanscls_head = NULL;
+
+struct spans_addr spans_bcastaddr = {
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+};
+
+struct spanscls_hdr spanscls_hdr = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* dst */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* src */
+ 0x00, 0x00, 0,
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0 /* LLC SNAP */
+};
+
+
+/*
+ * Local functions
+ */
+static int spanscls_ipact __P((struct ip_nif *));
+static int spanscls_ipdact __P((struct ip_nif *));
+static int spanscls_bcast_output __P((struct ip_nif *, KBuffer *));
+static void spanscls_cpcs_data __P((void *, KBuffer *));
+static void spanscls_connected __P((void *));
+static void spanscls_cleared __P((void *, struct t_atm_cause *));
+static caddr_t spanscls_getname __P((void *));
+static void spanscls_pdu_print __P((struct spanscls *, KBuffer *,
+ char *));
+
+/*
+ * Local variables
+ */
+static struct sp_info spanscls_pool = {
+ "spans cls pool", /* si_name */
+ sizeof(struct spanscls), /* si_blksiz */
+ 2, /* si_blkcnt */
+ 100 /* si_maxallow */
+};
+
+static struct ip_serv spanscls_ipserv = {
+ spanscls_ipact,
+ spanscls_ipdact,
+ spansarp_ioctl,
+ NULL,
+ spansarp_svcout,
+ spansarp_svcin,
+ spansarp_svcactive,
+ spansarp_vcclose,
+ spanscls_bcast_output,
+ {
+ {ATM_AAL5, ATM_ENC_NULL},
+ {ATM_AAL3_4, ATM_ENC_NULL}
+ }
+};
+
+static u_char spanscls_bridged[] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2 /* LLC SNAP */
+};
+
+static Atm_endpoint spanscls_endpt = {
+ NULL,
+ ENDPT_SPANS_CLS,
+ NULL,
+ spanscls_getname,
+ spanscls_connected,
+ spanscls_cleared,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ spanscls_cpcs_data,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static Atm_attributes spanscls_attr = {
+ NULL, /* nif */
+ CMAPI_CPCS, /* api */
+ 0, /* api_init */
+ 0, /* headin */
+ 0, /* headout */
+ { /* aal */
+ T_ATM_PRESENT,
+ ATM_AAL3_4
+ },
+ { /* traffic */
+ T_ATM_PRESENT,
+ {
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ T_YES
+ },
+ },
+ { /* bearer */
+ T_ATM_PRESENT,
+ {
+ T_ATM_CLASS_X,
+ T_ATM_NULL,
+ T_ATM_NULL,
+ T_NO,
+ T_ATM_1_TO_1
+ }
+ },
+ { /* bhli */
+ T_ATM_ABSENT
+ },
+ { /* blli */
+ T_ATM_ABSENT,
+ T_ATM_ABSENT
+ },
+ { /* llc */
+ T_ATM_ABSENT
+ },
+ { /* called */
+ T_ATM_PRESENT,
+ },
+ { /* calling */
+ T_ATM_ABSENT
+ },
+ { /* qos */
+ T_ATM_PRESENT,
+ {
+ T_ATM_NETWORK_CODING,
+ {
+ T_ATM_QOS_CLASS_0,
+ },
+ {
+ T_ATM_QOS_CLASS_0
+ }
+ }
+ },
+ { /* transit */
+ T_ATM_ABSENT
+ },
+ { /* cause */
+ T_ATM_ABSENT
+ }
+};
+
+static struct t_atm_cause spanscls_cause = {
+ T_ATM_ITU_CODING,
+ T_ATM_LOC_USER,
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL,
+ {0, 0, 0, 0}
+};
+
+
+/*
+ * Process module loading
+ *
+ * Called whenever the spans module is initializing.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 initialization successful
+ * errno initialization failed - reason indicated
+ *
+ */
+int
+spanscls_start()
+{
+ int err;
+
+ /*
+ * Fill in union fields
+ */
+ spanscls_attr.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
+ spanscls_attr.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
+ spanscls_attr.aal.v.aal4.SSCS_type = T_ATM_NULL;
+ spanscls_attr.aal.v.aal4.mid_low = 0;
+ spanscls_attr.aal.v.aal4.mid_high = 1023;
+
+ /*
+ * Register our endpoint
+ */
+ err = atm_endpoint_register(&spanscls_endpt);
+
+ return (err);
+}
+
+
+/*
+ * Process module unloading notification
+ *
+ * Called whenever the spans module is about to be unloaded. All signalling
+ * instances will have been previously detached. All spanscls resources
+ * must be freed now.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spanscls_stop()
+{
+ int s = splnet();
+
+ /*
+ * Tell ARP to stop
+ */
+ spansarp_stop();
+
+ /*
+ * Nothing should be left here...
+ */
+ if (spanscls_head) {
+ panic("spanscls_stop: bad state");
+ }
+ (void) splx(s);
+
+ /*
+ * De-register ourselves
+ */
+ (void) atm_endpoint_deregister(&spanscls_endpt);
+
+ /*
+ * Free our storage pools
+ */
+ atm_release_pool(&spanscls_pool);
+}
+
+
+/*
+ * Process signalling interface attach
+ *
+ * This function is called whenever a physical interface has been attached
+ * to spans. We will open the CLS PVC and await further events.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * spp pointer to spans signalling protocol instance
+ *
+ * Returns:
+ * 0 attach successful
+ * errno attach failed - reason indicated
+ *
+ */
+int
+spanscls_attach(spp)
+ struct spans *spp;
+{
+ struct spanscls *clp;
+ Atm_addr_pvc *pvcp;
+ int err;
+
+ /*
+ * Get a new cls control block
+ */
+ clp = (struct spanscls *)atm_allocate(&spanscls_pool);
+ if (clp == NULL)
+ return (ENOMEM);
+
+ /*
+ * Initialize some stuff
+ */
+ clp->cls_state = CLS_CLOSED;
+ clp->cls_spans = spp;
+ spp->sp_ipserv = &spanscls_ipserv;
+
+ /*
+ * Fill out connection attributes
+ */
+ spanscls_attr.nif = spp->sp_pif->pif_nif;
+ spanscls_attr.traffic.v.forward.PCR_all_traffic = spp->sp_pif->pif_pcr;
+ spanscls_attr.traffic.v.backward.PCR_all_traffic = spp->sp_pif->pif_pcr;
+ spanscls_attr.called.addr.address_format = T_ATM_PVC_ADDR;
+ spanscls_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
+ pvcp = (Atm_addr_pvc *)spanscls_attr.called.addr.address;
+ ATM_PVC_SET_VPI(pvcp, SPANS_CLS_VPI);
+ ATM_PVC_SET_VCI(pvcp, SPANS_CLS_VCI);
+ spanscls_attr.called.subaddr.address_format = T_ATM_ABSENT;
+ spanscls_attr.called.subaddr.address_length = 0;
+
+ /*
+ * Create SPANS Connectionless Service (CLS) PVC
+ */
+ err = atm_cm_connect(&spanscls_endpt, clp, &spanscls_attr,
+ &clp->cls_conn);
+ if (err) {
+ atm_free((caddr_t)clp);
+ return (err);
+ }
+
+ /*
+ * Set new state and link instance
+ */
+ clp->cls_state = CLS_OPEN;
+ LINK2TAIL(clp, struct spanscls, spanscls_head, cls_next);
+ spp->sp_cls = clp;
+
+ return (0);
+}
+
+
+/*
+ * Process signalling interface detach
+ *
+ * This function is called whenever a physical interface has been detached
+ * from spans. We will close the CLS PVC and clean up everything.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * spp pointer to spans signalling protocol instance
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spanscls_detach(spp)
+ struct spans *spp;
+{
+ struct spanscls *clp;
+
+ /*
+ * Get our control block
+ */
+ clp = spp->sp_cls;
+ if (clp == NULL)
+ return;
+
+ /*
+ * Just checking up on things...
+ */
+ if (clp->cls_ipnif)
+ panic("spanscls_detach: IP interface still active");
+
+ /*
+ * Close CLS PVC
+ */
+ spanscls_closevc(clp, &spanscls_cause);
+
+ /*
+ * Sever links and free server block, if possible
+ */
+ clp->cls_spans = NULL;
+ spp->sp_cls = NULL;
+ if (clp->cls_state == CLS_CLOSED) {
+ UNLINK(clp, struct spanscls, spanscls_head, cls_next);
+ atm_free((caddr_t)clp);
+ }
+}
+
+
+/*
+ * Process IP Network Interface Activation
+ *
+ * Called whenever an IP network interface becomes active.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * inp pointer to IP network interface
+ *
+ * Returns:
+ * 0 command successful
+ * errno command failed - reason indicated
+ *
+ */
+static int
+spanscls_ipact(inp)
+ struct ip_nif *inp;
+{
+ struct spans *spp;
+ struct spanscls *clp;
+
+ /*
+ * Get corresponding cls instance
+ */
+ spp = (struct spans *)inp->inf_nif->nif_pif->pif_siginst;
+ if ((spp == NULL) || ((clp = spp->sp_cls) == NULL))
+ return (ENXIO);
+
+ /*
+ * Make sure it's not already activated
+ */
+ if (clp->cls_ipnif)
+ return (EEXIST);
+
+ /*
+ * Set two-way links with IP world
+ */
+ clp->cls_ipnif = inp;
+ inp->inf_isintf = (caddr_t)clp;
+
+ /*
+ * Tell arp about new interface
+ */
+ spansarp_ipact(clp);
+
+ return (0);
+}
+
+
+/*
+ * Process IP Network Interface Deactivation
+ *
+ * Called whenever an IP network interface becomes inactive.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * inp pointer to IP network interface
+ *
+ * Returns:
+ * 0 command successful
+ * errno command failed - reason indicated
+ *
+ */
+static int
+spanscls_ipdact(inp)
+ struct ip_nif *inp;
+{
+ struct spanscls *clp;
+
+ /*
+ * Get cls instance and make sure it's been activated
+ */
+ clp = (struct spanscls *)inp->inf_isintf;
+ if ((clp == NULL) || (clp->cls_ipnif == NULL))
+ return (ENXIO);
+
+ /*
+ * Let arp know about this
+ */
+ spansarp_ipdact(clp);
+
+ /*
+ * Clear IP interface pointer
+ */
+ clp->cls_ipnif = NULL;
+ return (0);
+}
+
+
+/*
+ * Output IP Broadcast Packet
+ *
+ * Called whenever an IP broadcast packet is sent to this interface.
+ *
+ * Arguments:
+ * inp pointer to IP network interface
+ * m pointer to packet buffer chain
+ *
+ * Returns:
+ * 0 packet sent successfully
+ * errno send failed - reason indicated
+ *
+ */
+static int
+spanscls_bcast_output(inp, m)
+ struct ip_nif *inp;
+ KBuffer *m;
+{
+ struct spans *spp;
+ struct spanscls *clp;
+ struct spanscls_hdr *chp;
+ int err, space;
+
+ /*
+ * Get cls instance and make sure it's been activated
+ */
+ clp = (struct spanscls *)inp->inf_isintf;
+ if ((clp == NULL) || (clp->cls_ipnif == NULL)) {
+ KB_FREEALL(m);
+ return (ENETDOWN);
+ }
+
+ /*
+ * Make sure that we know our addresses
+ */
+ spp = clp->cls_spans;
+ if (spp->sp_addr.address_format != T_ATM_SPANS_ADDR) {
+ KB_FREEALL(m);
+ return (ENETDOWN);
+ }
+
+ /*
+ * See if there's room to add CLS header to front of packet.
+ */
+ KB_HEADROOM(m, space);
+ if (space < sizeof(struct spanscls_hdr)) {
+ KBuffer *n;
+
+ /*
+ * We have to allocate another buffer and tack it
+ * onto the front of the packet
+ */
+ KB_ALLOCPKT(n, sizeof(struct spanscls_hdr),
+ KB_F_NOWAIT, KB_T_HEADER);
+ if (n == 0) {
+ KB_FREEALL(m);
+ return (ENOBUFS);
+ }
+ KB_TAILALIGN(n, sizeof(struct spanscls_hdr));
+ KB_LINKHEAD(n, m);
+ m = n;
+ } else {
+ /*
+ * Header fits, just adjust buffer controls
+ */
+ KB_HEADADJ(m, sizeof(struct spanscls_hdr));
+ }
+
+ /*
+ * Now, build the CLS header
+ */
+ KB_DATASTART(m, chp, struct spanscls_hdr *);
+ spans_addr_copy(&spans_bcastaddr, &chp->ch_dst);
+ spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
+ *(u_int *)&chp->ch_proto = *(u_int *)&spanscls_hdr.ch_proto;
+ *(u_int *)&chp->ch_dsap = *(u_int *)&spanscls_hdr.ch_dsap;
+ *(u_short *)&chp->ch_oui[1] = *(u_short *)&spanscls_hdr.ch_oui[1];
+ chp->ch_pid = htons(ETHERTYPE_IP);
+
+#ifdef DIAGNOSTIC
+ if (spanscls_print)
+ spanscls_pdu_print(clp, m, "output");
+#endif
+
+ /*
+ * Finally, send the pdu via the CLS service
+ */
+ err = atm_cm_cpcs_data(clp->cls_conn, m);
+ if (err) {
+ KB_FREEALL(m);
+ return (ENOBUFS);
+ }
+
+ return (0);
+}
+
+
+/*
+ * Process VCC Input Data
+ *
+ * All input packets received from CLS VCC lower layers are processed here.
+ *
+ * Arguments:
+ * tok connection token (pointer to CLS VCC control block)
+ * m pointer to input packet buffer chain
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+spanscls_cpcs_data(tok, m)
+ void *tok;
+ KBuffer *m;
+{
+ struct spanscls *clp = tok;
+ struct spans *spp = clp->cls_spans;
+ struct spanscls_hdr *chp;
+ struct ip_nif *inp;
+
+ /*
+ * Make sure we're ready
+ */
+ if ((clp->cls_state != CLS_OPEN) || (spp->sp_state != SPANS_ACTIVE)) {
+ KB_FREEALL(m);
+ return;
+ }
+
+#ifdef DIAGNOSTIC
+ if (spanscls_print)
+ spanscls_pdu_print(clp, m, "input");
+#endif
+
+ /*
+ * Get CLS header into buffer
+ */
+ if (KB_LEN(m) < sizeof(struct spanscls_hdr)) {
+ KB_PULLUP(m, sizeof(struct spanscls_hdr), m);
+ if (m == 0)
+ return;
+ }
+ KB_DATASTART(m, chp, struct spanscls_hdr *);
+
+ /*
+ * Verify packet information
+ */
+ if ((*(u_int *)&chp->ch_proto != *(u_int *)&spanscls_hdr.ch_proto) ||
+ (*(u_int *)&chp->ch_dsap != *(u_int *)&spanscls_hdr.ch_dsap) ||
+ (*(u_short *)&chp->ch_oui[1] !=
+ *(u_short *)&spanscls_hdr.ch_oui[1])) {
+
+ /*
+ * Check for bridged PDU
+ */
+ if (bcmp((char *)&chp->ch_proto, (char *)spanscls_bridged,
+ sizeof(spanscls_bridged))) {
+ log(LOG_ERR, "spanscls_input: bad format\n");
+#ifdef DIAGNOSTIC
+ spanscls_pdu_print(clp, m, "input error");
+#endif
+ }
+
+ KB_FREEALL(m);
+ return;
+ }
+
+ /*
+ * Make sure packet is for us
+ */
+ if (spans_addr_cmp(&chp->ch_dst, spp->sp_addr.address) &&
+ spans_addr_cmp(&chp->ch_dst, &spans_bcastaddr)) {
+ KB_FREEALL(m);
+ return;
+ }
+
+ /*
+ * Do protocol processing
+ */
+ switch (ntohs(chp->ch_pid)) {
+
+ case ETHERTYPE_IP:
+ /*
+ * Drop CLS header
+ */
+ KB_HEADADJ(m, -sizeof(struct spanscls_hdr));
+ KB_PLENADJ(m, -sizeof(struct spanscls_hdr));
+
+ /*
+ * Packet is ready for input to IP
+ */
+ if (inp = clp->cls_ipnif)
+ (void) (*inp->inf_ipinput)(inp, m);
+ else
+ KB_FREEALL(m);
+ break;
+
+ case ETHERTYPE_ARP:
+ spansarp_input(clp, m);
+ break;
+
+ default:
+ log(LOG_ERR, "spanscls_input: unknown protocol 0x%x\n",
+ chp->ch_pid);
+ KB_FREEALL(m);
+ return;
+ }
+}
+
+
+/*
+ * Close a SPANS CLS VCC
+ *
+ * This function will close a SPANS CLS VCC.
+ *
+ * Arguments:
+ * clp pointer to CLS instance
+ * cause pointer to cause code
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+spanscls_closevc(clp, cause)
+ struct spanscls *clp;
+ struct t_atm_cause *cause;
+{
+ int err;
+
+ /*
+ * Close VCC
+ */
+ if (clp->cls_conn) {
+ err = atm_cm_release(clp->cls_conn, cause);
+ if (err) {
+ log(LOG_ERR, "spanscls_closevc: release err=%d\n", err);
+ }
+ clp->cls_conn = NULL;
+ }
+
+ clp->cls_state = CLS_CLOSED;
+}
+
+
+/*
+ * Process CLS VCC Connected Notification
+ *
+ * Arguments:
+ * toku user's connection token (spanscls protocol block)
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+spanscls_connected(toku)
+ void *toku;
+{
+ /*
+ * We should never get one of these
+ */
+ log(LOG_ERR, "spanscls: unexpected connected event\n");
+}
+
+
+/*
+ * Process CLS VCC Cleared Notification
+ *
+ * Arguments:
+ * toku user's connection token (spanscls protocol block)
+ * cause pointer to cause code
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+spanscls_cleared(toku, cause)
+ void *toku;
+ struct t_atm_cause *cause;
+{
+ struct spanscls *clp = (struct spanscls *)toku;
+
+ /*
+ * CLS VCC has been closed, so clean up our side
+ */
+ clp->cls_conn = NULL;
+ spanscls_closevc(clp, cause);
+}
+
+
+/*
+ * Get Connection's Application/Owner Name
+ *
+ * Arguments:
+ * tok spanscls connection token
+ *
+ * Returns:
+ * addr pointer to string containing our name
+ *
+ */
+static caddr_t
+spanscls_getname(tok)
+ void *tok;
+{
+ return ("SPANSCLS");
+}
+
+
+/*
+ * Print a SPANS CLS PDU
+ *
+ * Arguments:
+ * clp pointer to cls instance
+ * m pointer to pdu buffer chain
+ * msg pointer to message string
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+spanscls_pdu_print(clp, m, msg)
+ struct spanscls *clp;
+ KBuffer *m;
+ char *msg;
+{
+ char buf[128];
+
+ sprintf(buf, "spanscls %s:\n", msg);
+ atm_pdu_print(m, buf);
+}
+
OpenPOWER on IntegriCloud