3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/spans/spans_cls.c,v 1.6 1999/08/28 00:48:49 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_cls.c,v 1.3 2003/08/07 21:17:35 dillon Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS Connectionless Datagram Service (CLS) module
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm_var.h>
41 #include <netatm/ipatm/ipatm_serv.h>
42 #include "spans_xdr.h"
43 #include "spans_var.h"
44 #include "spans_cls.h"
49 int spanscls_print = 0;
51 struct spanscls *spanscls_head = NULL;
53 struct spans_addr spans_bcastaddr = {
54 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
57 struct spanscls_hdr spanscls_hdr = {
58 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* dst */
59 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* src */
61 0xaa, 0xaa, 0x03, { 0x00, 0x00, 0x00 }, 0 /* LLC SNAP */
68 static int spanscls_ipact __P((struct ip_nif *));
69 static int spanscls_ipdact __P((struct ip_nif *));
70 static int spanscls_bcast_output __P((struct ip_nif *, KBuffer *));
71 static void spanscls_cpcs_data __P((void *, KBuffer *));
72 static void spanscls_connected __P((void *));
73 static void spanscls_cleared __P((void *, struct t_atm_cause *));
74 static caddr_t spanscls_getname __P((void *));
75 static void spanscls_pdu_print __P((struct spanscls *, KBuffer *,
81 static struct sp_info spanscls_pool = {
82 "spans cls pool", /* si_name */
83 sizeof(struct spanscls), /* si_blksiz */
88 static struct ip_serv spanscls_ipserv = {
97 spanscls_bcast_output,
99 {ATM_AAL5, ATM_ENC_NULL},
100 {ATM_AAL3_4, ATM_ENC_NULL}
104 static u_char spanscls_bridged[] = {
105 0x00, 0x00, 0x00, 0x00,
106 0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2 /* LLC SNAP */
109 static Atm_endpoint spanscls_endpt = {
127 static Atm_attributes spanscls_attr = {
129 CMAPI_CPCS, /* api */
190 T_ATM_NETWORK_CODING,
207 static struct t_atm_cause spanscls_cause = {
210 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
216 * Process module loading
218 * Called whenever the spans module is initializing.
224 * 0 initialization successful
225 * errno initialization failed - reason indicated
234 * Fill in union fields
236 spanscls_attr.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
237 spanscls_attr.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
238 spanscls_attr.aal.v.aal4.SSCS_type = T_ATM_NULL;
239 spanscls_attr.aal.v.aal4.mid_low = 0;
240 spanscls_attr.aal.v.aal4.mid_high = 1023;
243 * Register our endpoint
245 err = atm_endpoint_register(&spanscls_endpt);
252 * Process module unloading notification
254 * Called whenever the spans module is about to be unloaded. All signalling
255 * instances will have been previously detached. All spanscls resources
276 * Nothing should be left here...
279 panic("spanscls_stop: bad state");
284 * De-register ourselves
286 (void) atm_endpoint_deregister(&spanscls_endpt);
289 * Free our storage pools
291 atm_release_pool(&spanscls_pool);
296 * Process signalling interface attach
298 * This function is called whenever a physical interface has been attached
299 * to spans. We will open the CLS PVC and await further events.
304 * spp pointer to spans signalling protocol instance
307 * 0 attach successful
308 * errno attach failed - reason indicated
315 struct spanscls *clp;
320 * Get a new cls control block
322 clp = (struct spanscls *)atm_allocate(&spanscls_pool);
327 * Initialize some stuff
329 clp->cls_state = CLS_CLOSED;
330 clp->cls_spans = spp;
331 spp->sp_ipserv = &spanscls_ipserv;
334 * Fill out connection attributes
336 spanscls_attr.nif = spp->sp_pif->pif_nif;
337 spanscls_attr.traffic.v.forward.PCR_all_traffic = spp->sp_pif->pif_pcr;
338 spanscls_attr.traffic.v.backward.PCR_all_traffic = spp->sp_pif->pif_pcr;
339 spanscls_attr.called.addr.address_format = T_ATM_PVC_ADDR;
340 spanscls_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
341 pvcp = (Atm_addr_pvc *)spanscls_attr.called.addr.address;
342 ATM_PVC_SET_VPI(pvcp, SPANS_CLS_VPI);
343 ATM_PVC_SET_VCI(pvcp, SPANS_CLS_VCI);
344 spanscls_attr.called.subaddr.address_format = T_ATM_ABSENT;
345 spanscls_attr.called.subaddr.address_length = 0;
348 * Create SPANS Connectionless Service (CLS) PVC
350 err = atm_cm_connect(&spanscls_endpt, clp, &spanscls_attr,
353 atm_free((caddr_t)clp);
358 * Set new state and link instance
360 clp->cls_state = CLS_OPEN;
361 LINK2TAIL(clp, struct spanscls, spanscls_head, cls_next);
369 * Process signalling interface detach
371 * This function is called whenever a physical interface has been detached
372 * from spans. We will close the CLS PVC and clean up everything.
377 * spp pointer to spans signalling protocol instance
387 struct spanscls *clp;
390 * Get our control block
397 * Just checking up on things...
400 panic("spanscls_detach: IP interface still active");
405 spanscls_closevc(clp, &spanscls_cause);
408 * Sever links and free server block, if possible
410 clp->cls_spans = NULL;
412 if (clp->cls_state == CLS_CLOSED) {
413 UNLINK(clp, struct spanscls, spanscls_head, cls_next);
414 atm_free((caddr_t)clp);
420 * Process IP Network Interface Activation
422 * Called whenever an IP network interface becomes active.
427 * inp pointer to IP network interface
430 * 0 command successful
431 * errno command failed - reason indicated
439 struct spanscls *clp;
442 * Get corresponding cls instance
444 spp = (struct spans *)inp->inf_nif->nif_pif->pif_siginst;
445 if ((spp == NULL) || ((clp = spp->sp_cls) == NULL))
449 * Make sure it's not already activated
455 * Set two-way links with IP world
457 clp->cls_ipnif = inp;
458 inp->inf_isintf = (caddr_t)clp;
461 * Tell arp about new interface
470 * Process IP Network Interface Deactivation
472 * Called whenever an IP network interface becomes inactive.
477 * inp pointer to IP network interface
480 * 0 command successful
481 * errno command failed - reason indicated
488 struct spanscls *clp;
491 * Get cls instance and make sure it's been activated
493 clp = (struct spanscls *)inp->inf_isintf;
494 if ((clp == NULL) || (clp->cls_ipnif == NULL))
498 * Let arp know about this
500 spansarp_ipdact(clp);
503 * Clear IP interface pointer
505 clp->cls_ipnif = NULL;
511 * Output IP Broadcast Packet
513 * Called whenever an IP broadcast packet is sent to this interface.
516 * inp pointer to IP network interface
517 * m pointer to packet buffer chain
520 * 0 packet sent successfully
521 * errno send failed - reason indicated
525 spanscls_bcast_output(inp, m)
530 struct spanscls *clp;
531 struct spanscls_hdr *chp;
535 * Get cls instance and make sure it's been activated
537 clp = (struct spanscls *)inp->inf_isintf;
538 if ((clp == NULL) || (clp->cls_ipnif == NULL)) {
544 * Make sure that we know our addresses
546 spp = clp->cls_spans;
547 if (spp->sp_addr.address_format != T_ATM_SPANS_ADDR) {
553 * See if there's room to add CLS header to front of packet.
555 KB_HEADROOM(m, space);
556 if (space < sizeof(struct spanscls_hdr)) {
560 * We have to allocate another buffer and tack it
561 * onto the front of the packet
563 KB_ALLOCPKT(n, sizeof(struct spanscls_hdr),
564 KB_F_NOWAIT, KB_T_HEADER);
569 KB_TAILALIGN(n, sizeof(struct spanscls_hdr));
574 * Header fits, just adjust buffer controls
576 KB_HEADADJ(m, sizeof(struct spanscls_hdr));
580 * Now, build the CLS header
582 KB_DATASTART(m, chp, struct spanscls_hdr *);
583 spans_addr_copy(&spans_bcastaddr, &chp->ch_dst);
584 spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
585 *(u_int *)&chp->ch_proto = *(u_int *)&spanscls_hdr.ch_proto;
586 *(u_int *)&chp->ch_dsap = *(u_int *)&spanscls_hdr.ch_dsap;
587 *(u_short *)&chp->ch_oui[1] = *(u_short *)&spanscls_hdr.ch_oui[1];
588 chp->ch_pid = htons(ETHERTYPE_IP);
592 spanscls_pdu_print(clp, m, "output");
596 * Finally, send the pdu via the CLS service
598 err = atm_cm_cpcs_data(clp->cls_conn, m);
609 * Process VCC Input Data
611 * All input packets received from CLS VCC lower layers are processed here.
614 * tok connection token (pointer to CLS VCC control block)
615 * m pointer to input packet buffer chain
622 spanscls_cpcs_data(tok, m)
626 struct spanscls *clp = tok;
627 struct spans *spp = clp->cls_spans;
628 struct spanscls_hdr *chp;
632 * Make sure we're ready
634 if ((clp->cls_state != CLS_OPEN) || (spp->sp_state != SPANS_ACTIVE)) {
641 spanscls_pdu_print(clp, m, "input");
645 * Get CLS header into buffer
647 if (KB_LEN(m) < sizeof(struct spanscls_hdr)) {
648 KB_PULLUP(m, sizeof(struct spanscls_hdr), m);
652 KB_DATASTART(m, chp, struct spanscls_hdr *);
655 * Verify packet information
657 if ((*(u_int *)&chp->ch_proto != *(u_int *)&spanscls_hdr.ch_proto) ||
658 (*(u_int *)&chp->ch_dsap != *(u_int *)&spanscls_hdr.ch_dsap) ||
659 (*(u_short *)&chp->ch_oui[1] !=
660 *(u_short *)&spanscls_hdr.ch_oui[1])) {
663 * Check for bridged PDU
665 if (bcmp((char *)&chp->ch_proto, (char *)spanscls_bridged,
666 sizeof(spanscls_bridged))) {
667 log(LOG_ERR, "spanscls_input: bad format\n");
669 spanscls_pdu_print(clp, m, "input error");
678 * Make sure packet is for us
680 if (spans_addr_cmp(&chp->ch_dst, spp->sp_addr.address) &&
681 spans_addr_cmp(&chp->ch_dst, &spans_bcastaddr)) {
687 * Do protocol processing
689 switch (ntohs(chp->ch_pid)) {
695 KB_HEADADJ(m, -sizeof(struct spanscls_hdr));
696 KB_PLENADJ(m, -sizeof(struct spanscls_hdr));
699 * Packet is ready for input to IP
701 if ((inp = clp->cls_ipnif) != NULL)
702 (void) (*inp->inf_ipinput)(inp, m);
708 spansarp_input(clp, m);
712 log(LOG_ERR, "spanscls_input: unknown protocol 0x%x\n",
721 * Close a SPANS CLS VCC
723 * This function will close a SPANS CLS VCC.
726 * clp pointer to CLS instance
727 * cause pointer to cause code
734 spanscls_closevc(clp, cause)
735 struct spanscls *clp;
736 struct t_atm_cause *cause;
744 err = atm_cm_release(clp->cls_conn, cause);
746 log(LOG_ERR, "spanscls_closevc: release err=%d\n", err);
748 clp->cls_conn = NULL;
751 clp->cls_state = CLS_CLOSED;
756 * Process CLS VCC Connected Notification
759 * toku user's connection token (spanscls protocol block)
766 spanscls_connected(toku)
770 * We should never get one of these
772 log(LOG_ERR, "spanscls: unexpected connected event\n");
777 * Process CLS VCC Cleared Notification
780 * toku user's connection token (spanscls protocol block)
781 * cause pointer to cause code
788 spanscls_cleared(toku, cause)
790 struct t_atm_cause *cause;
792 struct spanscls *clp = (struct spanscls *)toku;
795 * CLS VCC has been closed, so clean up our side
797 clp->cls_conn = NULL;
798 spanscls_closevc(clp, cause);
803 * Get Connection's Application/Owner Name
806 * tok spanscls connection token
809 * addr pointer to string containing our name
813 spanscls_getname(tok)
821 * Print a SPANS CLS PDU
824 * clp pointer to cls instance
825 * m pointer to pdu buffer chain
826 * msg pointer to message string
833 spanscls_pdu_print(clp, m, msg)
834 struct spanscls *clp;
840 snprintf(buf, sizeof(buf), "spanscls %s:\n", msg);
841 atm_pdu_print(m, buf);