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 $
30 * SPANS Signalling Manager
31 * ---------------------------
33 * SPANS Connectionless Datagram Service (CLS) module
37 #include <netproto/atm/kern_include.h>
39 #include <netproto/atm/ipatm/ipatm_var.h>
40 #include <netproto/atm/ipatm/ipatm_serv.h>
41 #include "spans_xdr.h"
42 #include "spans_var.h"
43 #include "spans_cls.h"
48 int spanscls_print = 0;
50 struct spanscls *spanscls_head = NULL;
52 struct spans_addr spans_bcastaddr = {
53 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
56 struct spanscls_hdr spanscls_hdr = {
57 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* dst */
58 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* src */
60 0xaa, 0xaa, 0x03, { 0x00, 0x00, 0x00 }, 0 /* LLC SNAP */
67 static int spanscls_ipact (struct ip_nif *);
68 static int spanscls_ipdact (struct ip_nif *);
69 static int spanscls_bcast_output (struct ip_nif *, KBuffer *);
70 static void spanscls_cpcs_data (void *, KBuffer *);
71 static void spanscls_connected (void *);
72 static void spanscls_cleared (void *, struct t_atm_cause *);
73 static caddr_t spanscls_getname (void *);
74 static void spanscls_pdu_print (struct spanscls *, KBuffer *,
80 static struct sp_info spanscls_pool = {
81 "spans cls pool", /* si_name */
82 sizeof(struct spanscls), /* si_blksiz */
87 static struct ip_serv spanscls_ipserv = {
96 spanscls_bcast_output,
98 {ATM_AAL5, ATM_ENC_NULL},
99 {ATM_AAL3_4, ATM_ENC_NULL}
103 static u_char spanscls_bridged[] = {
104 0x00, 0x00, 0x00, 0x00,
105 0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2 /* LLC SNAP */
108 static Atm_endpoint spanscls_endpt = {
126 static Atm_attributes spanscls_attr = {
128 CMAPI_CPCS, /* api */
189 T_ATM_NETWORK_CODING,
206 static struct t_atm_cause spanscls_cause = {
209 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
215 * Process module loading
217 * Called whenever the spans module is initializing.
223 * 0 initialization successful
224 * errno initialization failed - reason indicated
233 * Fill in union fields
235 spanscls_attr.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
236 spanscls_attr.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
237 spanscls_attr.aal.v.aal4.SSCS_type = T_ATM_NULL;
238 spanscls_attr.aal.v.aal4.mid_low = 0;
239 spanscls_attr.aal.v.aal4.mid_high = 1023;
242 * Register our endpoint
244 err = atm_endpoint_register(&spanscls_endpt);
251 * Process module unloading notification
253 * Called whenever the spans module is about to be unloaded. All signalling
254 * instances will have been previously detached. All spanscls resources
275 * Nothing should be left here...
278 panic("spanscls_stop: bad state");
283 * De-register ourselves
285 atm_endpoint_deregister(&spanscls_endpt);
288 * Free our storage pools
290 atm_release_pool(&spanscls_pool);
295 * Process signalling interface attach
297 * This function is called whenever a physical interface has been attached
298 * to spans. We will open the CLS PVC and await further events.
300 * Called from a critical section.
303 * spp pointer to spans signalling protocol instance
306 * 0 attach successful
307 * errno attach failed - reason indicated
311 spanscls_attach(struct spans *spp)
313 struct spanscls *clp;
318 * Get a new cls control block
320 clp = (struct spanscls *)atm_allocate(&spanscls_pool);
325 * Initialize some stuff
327 clp->cls_state = CLS_CLOSED;
328 clp->cls_spans = spp;
329 spp->sp_ipserv = &spanscls_ipserv;
332 * Fill out connection attributes
334 spanscls_attr.nif = spp->sp_pif->pif_nif;
335 spanscls_attr.traffic.v.forward.PCR_all_traffic = spp->sp_pif->pif_pcr;
336 spanscls_attr.traffic.v.backward.PCR_all_traffic = spp->sp_pif->pif_pcr;
337 spanscls_attr.called.addr.address_format = T_ATM_PVC_ADDR;
338 spanscls_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
339 pvcp = (Atm_addr_pvc *)spanscls_attr.called.addr.address;
340 ATM_PVC_SET_VPI(pvcp, SPANS_CLS_VPI);
341 ATM_PVC_SET_VCI(pvcp, SPANS_CLS_VCI);
342 spanscls_attr.called.subaddr.address_format = T_ATM_ABSENT;
343 spanscls_attr.called.subaddr.address_length = 0;
346 * Create SPANS Connectionless Service (CLS) PVC
348 err = atm_cm_connect(&spanscls_endpt, clp, &spanscls_attr,
351 atm_free((caddr_t)clp);
356 * Set new state and link instance
358 clp->cls_state = CLS_OPEN;
359 LINK2TAIL(clp, struct spanscls, spanscls_head, cls_next);
367 * Process signalling interface detach
369 * This function is called whenever a physical interface has been detached
370 * from spans. We will close the CLS PVC and clean up everything.
372 * Called from a critical section.
375 * spp pointer to spans signalling protocol instance
382 spanscls_detach(struct spans *spp)
384 struct spanscls *clp;
387 * Get our control block
394 * Just checking up on things...
397 panic("spanscls_detach: IP interface still active");
402 spanscls_closevc(clp, &spanscls_cause);
405 * Sever links and free server block, if possible
407 clp->cls_spans = NULL;
409 if (clp->cls_state == CLS_CLOSED) {
410 UNLINK(clp, struct spanscls, spanscls_head, cls_next);
411 atm_free((caddr_t)clp);
417 * Process IP Network Interface Activation
419 * Called whenever an IP network interface becomes active.
421 * Called from a critical section.
424 * inp pointer to IP network interface
427 * 0 command successful
428 * errno command failed - reason indicated
432 spanscls_ipact(struct ip_nif *inp)
435 struct spanscls *clp;
438 * Get corresponding cls instance
440 spp = (struct spans *)inp->inf_nif->nif_pif->pif_siginst;
441 if ((spp == NULL) || ((clp = spp->sp_cls) == NULL))
445 * Make sure it's not already activated
451 * Set two-way links with IP world
453 clp->cls_ipnif = inp;
454 inp->inf_isintf = (caddr_t)clp;
457 * Tell arp about new interface
466 * Process IP Network Interface Deactivation
468 * Called whenever an IP network interface becomes inactive.
470 * Called from a critical section.
473 * inp pointer to IP network interface
476 * 0 command successful
477 * errno command failed - reason indicated
481 spanscls_ipdact(struct ip_nif *inp)
483 struct spanscls *clp;
486 * Get cls instance and make sure it's been activated
488 clp = (struct spanscls *)inp->inf_isintf;
489 if ((clp == NULL) || (clp->cls_ipnif == NULL))
493 * Let arp know about this
495 spansarp_ipdact(clp);
498 * Clear IP interface pointer
500 clp->cls_ipnif = NULL;
506 * Output IP Broadcast Packet
508 * Called whenever an IP broadcast packet is sent to this interface.
511 * inp pointer to IP network interface
512 * m pointer to packet buffer chain
515 * 0 packet sent successfully
516 * errno send failed - reason indicated
520 spanscls_bcast_output(struct ip_nif *inp, KBuffer *m)
523 struct spanscls *clp;
524 struct spanscls_hdr *chp;
528 * Get cls instance and make sure it's been activated
530 clp = (struct spanscls *)inp->inf_isintf;
531 if ((clp == NULL) || (clp->cls_ipnif == NULL)) {
537 * Make sure that we know our addresses
539 spp = clp->cls_spans;
540 if (spp->sp_addr.address_format != T_ATM_SPANS_ADDR) {
546 * See if there's room to add CLS header to front of packet.
548 KB_HEADROOM(m, space);
549 if (space < sizeof(struct spanscls_hdr)) {
553 * We have to allocate another buffer and tack it
554 * onto the front of the packet
556 KB_ALLOCPKT(n, sizeof(struct spanscls_hdr),
557 KB_F_NOWAIT, KB_T_HEADER);
562 KB_TAILALIGN(n, sizeof(struct spanscls_hdr));
567 * Header fits, just adjust buffer controls
569 KB_HEADADJ(m, sizeof(struct spanscls_hdr));
573 * Now, build the CLS header
575 KB_DATASTART(m, chp, struct spanscls_hdr *);
576 spans_addr_copy(&spans_bcastaddr, &chp->ch_dst);
577 spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
578 *(u_int *)&chp->ch_proto = *(u_int *)&spanscls_hdr.ch_proto;
579 *(u_int *)&chp->ch_dsap = *(u_int *)&spanscls_hdr.ch_dsap;
580 *(u_short *)&chp->ch_oui[1] = *(u_short *)&spanscls_hdr.ch_oui[1];
581 chp->ch_pid = htons(ETHERTYPE_IP);
585 spanscls_pdu_print(clp, m, "output");
589 * Finally, send the pdu via the CLS service
591 err = atm_cm_cpcs_data(clp->cls_conn, m);
602 * Process VCC Input Data
604 * All input packets received from CLS VCC lower layers are processed here.
607 * tok connection token (pointer to CLS VCC control block)
608 * m pointer to input packet buffer chain
615 spanscls_cpcs_data(void *tok, KBuffer *m)
617 struct spanscls *clp = tok;
618 struct spans *spp = clp->cls_spans;
619 struct spanscls_hdr *chp;
623 * Make sure we're ready
625 if ((clp->cls_state != CLS_OPEN) || (spp->sp_state != SPANS_ACTIVE)) {
632 spanscls_pdu_print(clp, m, "input");
636 * Get CLS header into buffer
638 if (KB_LEN(m) < sizeof(struct spanscls_hdr)) {
639 KB_PULLUP(m, sizeof(struct spanscls_hdr), m);
643 KB_DATASTART(m, chp, struct spanscls_hdr *);
646 * Verify packet information
648 if ((*(u_int *)&chp->ch_proto != *(u_int *)&spanscls_hdr.ch_proto) ||
649 (*(u_int *)&chp->ch_dsap != *(u_int *)&spanscls_hdr.ch_dsap) ||
650 (*(u_short *)&chp->ch_oui[1] !=
651 *(u_short *)&spanscls_hdr.ch_oui[1])) {
654 * Check for bridged PDU
656 if (bcmp((char *)&chp->ch_proto, (char *)spanscls_bridged,
657 sizeof(spanscls_bridged))) {
658 log(LOG_ERR, "spanscls_input: bad format\n");
660 spanscls_pdu_print(clp, m, "input error");
669 * Make sure packet is for us
671 if (spans_addr_cmp(&chp->ch_dst, spp->sp_addr.address) &&
672 spans_addr_cmp(&chp->ch_dst, &spans_bcastaddr)) {
678 * Do protocol processing
680 switch (ntohs(chp->ch_pid)) {
686 KB_HEADADJ(m, -sizeof(struct spanscls_hdr));
687 KB_PLENADJ(m, -sizeof(struct spanscls_hdr));
690 * Packet is ready for input to IP
692 if ((inp = clp->cls_ipnif) != NULL)
693 (*inp->inf_ipinput)(inp, m);
699 spansarp_input(clp, m);
703 log(LOG_ERR, "spanscls_input: unknown protocol 0x%x\n",
712 * Close a SPANS CLS VCC
714 * This function will close a SPANS CLS VCC.
717 * clp pointer to CLS instance
718 * cause pointer to cause code
725 spanscls_closevc(struct spanscls *clp, struct t_atm_cause *cause)
733 err = atm_cm_release(clp->cls_conn, cause);
735 log(LOG_ERR, "spanscls_closevc: release err=%d\n", err);
737 clp->cls_conn = NULL;
740 clp->cls_state = CLS_CLOSED;
745 * Process CLS VCC Connected Notification
748 * toku user's connection token (spanscls protocol block)
755 spanscls_connected(void *toku)
758 * We should never get one of these
760 log(LOG_ERR, "spanscls: unexpected connected event\n");
765 * Process CLS VCC Cleared Notification
768 * toku user's connection token (spanscls protocol block)
769 * cause pointer to cause code
776 spanscls_cleared(void *toku, struct t_atm_cause *cause)
778 struct spanscls *clp = (struct spanscls *)toku;
781 * CLS VCC has been closed, so clean up our side
783 clp->cls_conn = NULL;
784 spanscls_closevc(clp, cause);
789 * Get Connection's Application/Owner Name
792 * tok spanscls connection token
795 * addr pointer to string containing our name
799 spanscls_getname(void *tok)
806 * Print a SPANS CLS PDU
809 * clp pointer to cls instance
810 * m pointer to pdu buffer chain
811 * msg pointer to message string
818 spanscls_pdu_print(struct spanscls *clp, KBuffer *m, char *msg)
822 ksnprintf(buf, sizeof(buf), "spanscls %s:\n", msg);
823 atm_pdu_print(m, buf);