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_msg.c,v 1.5 1999/08/28 00:48:50 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_msg.c,v 1.3 2003/08/07 21:17:35 dillon Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS signalling message processing.
38 #include <netatm/kern_include.h>
41 #include "spans_xdr.h"
42 #include "spans_var.h"
47 void xdrmbuf_init __P((XDR *, KBuffer *, enum xdr_op));
52 static void spans_host_link __P((struct spans *, long));
53 static void spans_status_ind __P((struct spans *, spans_msg *));
54 static void spans_status_rsp __P((struct spans *, spans_msg *));
55 static void spans_open_req __P((struct spans *, spans_msg *));
56 static void spans_open_rsp __P((struct spans *, spans_msg *));
57 static void spans_close_req __P((struct spans *, spans_msg *));
58 static void spans_close_rsp __P((struct spans *, spans_msg *));
59 static void spans_multi_req __P((struct spans *, spans_msg *));
60 static void spans_add_req __P((struct spans *, spans_msg *));
61 static void spans_join_req __P((struct spans *, spans_msg *));
62 static void spans_leave_req __P((struct spans *, spans_msg *));
63 static void spans_vcir_ind __P((struct spans *, spans_msg *));
64 static void spans_query_req __P((struct spans *, spans_msg *));
68 * Called to set status when a status message comes in from a host
69 * connected back-to-back with us. Check the epoch and, if it has
70 * changed, set the appropriate state and save updated state
74 * spp pointer to SPANS protocol instance block
75 * host_epoch epoch of host at far end of link
79 * errno error encountered
83 spans_host_link(spp, host_epoch)
87 struct atm_pif *pip = spp->sp_pif;
90 * There's a host at the other end of the link. If its
91 * epoch has changed, clean up our state and save the
94 if (spp->sp_s_epoch != host_epoch) {
95 spp->sp_s_epoch = host_epoch;
96 spans_switch_reset(spp, SPANS_UNI_UP);
97 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
98 spp->sp_addr.address_length = sizeof(spans_addr);
99 KM_COPY(&pip->pif_macaddr.ma_data[2],
100 &spp->sp_addr.address[4],
103 "spans: using SPANS address of %s on interface %s%d\n",
104 spans_addr_print((spans_addr *)spp->sp_addr.address),
111 * Send a SPANS signalling message
113 * Called to send a SPANS message. This routine gets a buffer, performs
114 * XDR processing, and hands the message to the AAL for transmission.
117 * spp pointer to SPANS protocol instance block
118 * msg pointer to status message
122 * errno error encountered
126 spans_send_msg(spp, msg)
135 ATM_DEBUG2("spans_send_msg: msg=%p, type=%d\n", msg,
137 if (msg->sm_type != SPANS_STAT_REQ &&
138 msg->sm_type != SPANS_STAT_IND &&
139 msg->sm_type != SPANS_STAT_RSP) {
140 printf("spans_send_msg: sending ");
141 spans_print_msg(msg);
146 * If the signalling channel has been closed, don't do anything
149 return(ECONNABORTED);
154 KB_ALLOCPKT(m, sizeof(spans_msg), KB_F_NOWAIT, KB_T_DATA);
156 /* No buffer available */
161 * Convert message to network order
163 KB_LEN(m) = KB_BFRLEN(m);
164 xdrmbuf_init(&xdrs, m, XDR_ENCODE);
165 if (!xdr_spans_msg(&xdrs, msg)) {
166 log(LOG_ERR, "spans_send_msg: XDR encode failed\n");
167 KB_LEN(m) = XDR_GETPOS(&xdrs);
168 spans_dump_buffer(m);
172 KB_LEN(m) = XDR_GETPOS(&xdrs);
177 err = atm_cm_cpcs_data(spp->sp_conn, m);
186 * Send an open request
188 * Build and send an open request.
191 * spp pointer to SPANS protocol instance block
192 * svp pointer to VCCB for which the request is being sent
199 spans_send_open_req(spp, svp)
201 struct spans_vccb *svp;
206 ATM_DEBUG1("spans_send_open_req: svp=%p\n", svp);
209 * Get memory for a request message
211 req = (spans_msg *)atm_allocate(&spans_msgpool);
218 * Fill in the request
220 req->sm_vers = SPANS_VERS_1_0;
221 req->sm_type = SPANS_OPEN_REQ;
222 req->sm_open_req.opreq_conn = svp->sv_conn;
223 req->sm_open_req.opreq_aal = svp->sv_spans_aal;
224 req->sm_open_req.opreq_desrsrc = svp->sv_spans_qos;
225 req->sm_open_req.opreq_minrsrc.rsc_peak = 0;
226 req->sm_open_req.opreq_minrsrc.rsc_mean = 0;
227 req->sm_open_req.opreq_minrsrc.rsc_burst = 0;
228 req->sm_open_req.opreq_vpvc.vpf_valid = FALSE;
233 err = spans_send_msg(spp, req);
242 * Send an open response
244 * Build and send a response to an open request or open indication.
247 * spp pointer to SPANS protocol instance block
248 * svp pointer to VCCB for which the response is being sent
249 * result result code to include in the response
256 spans_send_open_rsp(spp, svp, result)
258 struct spans_vccb *svp;
264 ATM_DEBUG2("spans_send_open_rsp: svp=%p, result=%d\n", svp,
268 * Get memory for a response message
270 rsp = (spans_msg *)atm_allocate(&spans_msgpool);
275 * Fill in the response
277 rsp->sm_vers = SPANS_VERS_1_0;
278 rsp->sm_type = SPANS_OPEN_RSP;
279 rsp->sm_open_rsp.oprsp_conn = svp->sv_conn;
280 rsp->sm_open_rsp.oprsp_result = result;
281 rsp->sm_open_rsp.oprsp_rsrc = svp->sv_spans_qos;
282 rsp->sm_open_rsp.oprsp_vpvc =
283 SPANS_PACK_VPIVCI(svp->sv_vpi, svp->sv_vci);
288 rc = spans_send_msg(spp, rsp);
296 * Send a close request
298 * Called to send a close request.
301 * spp pointer to SPANS protocol instance block
302 * svp pointer to VCCB for which the close is being sent
309 spans_send_close_req(spp, svp)
311 struct spans_vccb *svp;
316 ATM_DEBUG1("spans_send_close_req: svp=%p\n", svp);
319 * Get memory for a close request
321 req = (spans_msg *)atm_allocate(&spans_msgpool);
328 * Fill in the request
330 req->sm_vers = SPANS_VERS_1_0;
331 if (svp->sv_type & VCC_OUT) {
332 req->sm_type = SPANS_CLOSE_REQ;
333 } else if (svp->sv_type & VCC_IN) {
334 req->sm_type = SPANS_RCLOSE_REQ;
338 "spans_send_close_req: invalid VCCB type 0x%x\n",
342 req->sm_close_req.clreq_conn = svp->sv_conn;
345 * Send the close request
347 err = spans_send_msg(spp, req);
359 * Process a status indication or status request
361 * Called when a status indication or status request is received.
362 * Processing will be based on the current SPANS state.
365 * spp pointer to SPANS protocol instance block
366 * msg pointer to the status message
373 spans_status_ind(spp, msg)
378 struct atm_pif *pip = spp->sp_pif;
381 * Reset the probe count.
383 spp->sp_probe_ct = 0;
385 switch (spp->sp_state) {
388 * Interface just came up, update signalling state
390 spp->sp_state = SPANS_ACTIVE;
397 log(LOG_ERR, "spans: received status msg in state %d\n",
402 * Process the message
404 switch (msg->sm_type) {
408 * Handle a request from a host at the other end of
411 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
417 * There's a switch at the other end of the link. If
418 * its epoch has changed, reset the SPANS state and save
419 * the new information.
421 if (spp->sp_s_epoch !=
422 msg->sm_stat_ind.stind_sw_epoch) {
423 spans_switch_reset(spp, SPANS_UNI_UP);
425 msg->sm_stat_ind.stind_sw_epoch;
426 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
427 spp->sp_addr.address_length =
429 spans_addr_copy(&msg->sm_stat_ind.stind_es_addr,
430 spp->sp_addr.address);
432 "spans: received SPANS address %s from switch for interface %s%d\n",
433 spans_addr_print((spans_addr *)spp->sp_addr.address),
440 ATM_DEBUG1("spans_status_ind: Invalid message type %d\n",
446 * Respond to the status request or indication with a
449 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
452 rsp_msg->sm_vers = SPANS_VERS_1_0;
453 rsp_msg->sm_type = SPANS_STAT_RSP;
454 rsp_msg->sm_stat_rsp.strsp_es_epoch = spp->sp_h_epoch;
455 spans_addr_copy(spp->sp_addr.address,
456 &rsp_msg->sm_stat_rsp.strsp_es_addr);
457 spans_send_msg(spp, rsp_msg);
464 * Process a status response
466 * Called when a status response is received.
467 * Processing will be based on the current SPANS state.
470 * spp pointer to SPANS protocol instance block
471 * msg pointer to the status response message
478 spans_status_rsp(spp, msg)
484 * Reset the probe count.
486 spp->sp_probe_ct = 0;
488 switch (spp->sp_state) {
491 * Interface just came up, update signalling state
493 spp->sp_state = SPANS_ACTIVE;
500 log(LOG_ERR, "spans: received status msg in state %d\n",
505 * Process the message
507 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
512 * Process an open indication or open request
514 * Called when an open indication or open request is received.
515 * Processing will be based on the state of the requested connection.
518 * spp pointer to SPANS protocol instance block
519 * msg pointer to the open message
526 spans_open_req(spp, msg)
530 spans_result result = SPANS_OK;
532 struct spans_vccb *svp = NULL;
535 int err = 0, vpi, vci;
537 Atm_attributes call_attrs;
539 ATM_DEBUG2("spans_open_req: spp=%p, msg=%p\n", spp, msg);
542 * See if the connection is new
544 if ((svp = spans_find_conn(spp, &msg->sm_open_req.opreq_conn)) != NULL) {
546 * We already have a VCCB that matches the connection in
549 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
550 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
551 if (msg->sm_open_req.opreq_aal == svp->sv_spans_aal &&
552 (!msg->sm_open_req.opreq_vpvc.vpf_valid ||
553 (vpi == svp->sv_vpi &&
554 vci == svp->sv_vci))) {
556 * VCCB already exists, process depending on
559 switch (svp->sv_sstate) {
560 case SPANS_VC_R_POPEN:
561 /* I'm still thinking about it */
564 /* Retransmit the open_rsp */
569 ATM_DEBUG0("spans_open_req: bad VCCB state\n");
575 * VCCB is for same connection, but other
576 * parameters don't match
578 ATM_DEBUG0("spans_open_req: VCCB confusion\n");
586 * Verify that the request is for our ATM addres
588 if (spans_addr_cmp(spp->sp_addr.address,
589 &msg->sm_open_req.opreq_conn.con_dst)) {
590 ATM_DEBUG0("spans_open_req: bad destination\n");
591 result = SPANS_BADDEST;
596 * See if we recognize the specified AAL
598 if (!spans_get_local_aal(msg->sm_open_req.opreq_aal, &aal)) {
599 ATM_DEBUG0("spans_open_req: bad AAL\n");
605 * Should verify that we can handle requested connection QOS
609 * Select a VPI/VCI for the new connection
611 if (msg->sm_open_req.opreq_vpvc.vpf_valid) {
613 * Requestor asked for a certain VPI/VCI. Make sure we
614 * aren't already using the pair that was asked for.
616 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
617 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
618 if (spans_find_vpvc(spp, vci, vpi, VCC_IN)) {
619 ATM_DEBUG0("spans_open_req: VPI, VCI busy\n");
620 result = SPANS_NOVPVC;
623 vpvc = msg->sm_open_req.opreq_vpvc.vpf_vpvc;
626 * Allocate a VPI/VCI for this end of the VCC
628 vpvc = spans_alloc_vpvc(spp);
630 ATM_DEBUG0("spans_open_req: no VPI, VCI available\n");
631 result = SPANS_NOVPVC;
637 * Get a new VCCB for the connection
639 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
641 ATM_DEBUG0("spans_open_req: VCCB pool empty\n");
642 result = SPANS_NORSC;
647 * Find the physical interface structure
652 * Fill in the VCCB fields that we can at this point
654 svp->sv_type = VCC_SVC | VCC_IN;
655 svp->sv_proto = ATM_SIG_SPANS;
656 svp->sv_sstate = SPANS_VC_R_POPEN;
657 svp->sv_ustate = VCCU_POPEN;
659 svp->sv_nif = pip->pif_nif;
660 svp->sv_conn = msg->sm_open_req.opreq_conn;
661 svp->sv_spans_qos = msg->sm_open_req.opreq_desrsrc;
662 svp->sv_spans_aal = msg->sm_open_req.opreq_aal;
663 svp->sv_tstamp = time_second;
665 svp->sv_vpi = SPANS_EXTRACT_VPI(vpvc);
666 svp->sv_vci = SPANS_EXTRACT_VCI(vpvc);
669 * Put the VCCB on the SPANS queue
671 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
674 * Set up the ATM attributes block
676 KM_ZERO(&call_attrs, sizeof(call_attrs));
677 call_attrs.nif = svp->sv_nif;
678 call_attrs.api = CMAPI_CPCS;
680 call_attrs.aal.tag = T_ATM_PRESENT;
681 call_attrs.aal.type = aal;
684 call_attrs.aal.v.aal4.forward_max_SDU_size =
686 call_attrs.aal.v.aal4.backward_max_SDU_size =
688 call_attrs.aal.v.aal4.SSCS_type =
690 call_attrs.aal.v.aal4.mid_low = 0;
691 call_attrs.aal.v.aal4.mid_high = 1023;
694 call_attrs.aal.v.aal5.forward_max_SDU_size =
696 call_attrs.aal.v.aal5.backward_max_SDU_size =
698 call_attrs.aal.v.aal5.SSCS_type =
703 call_attrs.traffic.tag = T_ATM_PRESENT;
704 call_attrs.traffic.v.forward.PCR_high_priority = T_ATM_ABSENT;
705 call_attrs.traffic.v.forward.PCR_all_traffic =
706 msg->sm_open_req.opreq_desrsrc.rsc_peak *
708 call_attrs.traffic.v.forward.SCR_high_priority = T_ATM_ABSENT;
709 call_attrs.traffic.v.forward.SCR_all_traffic = T_ATM_ABSENT;
710 call_attrs.traffic.v.forward.MBS_high_priority = T_ATM_ABSENT;
711 call_attrs.traffic.v.forward.MBS_all_traffic = T_ATM_ABSENT;
712 call_attrs.traffic.v.forward.tagging = T_NO;
713 call_attrs.traffic.v.backward.PCR_high_priority = T_ATM_ABSENT;
714 call_attrs.traffic.v.backward.PCR_all_traffic =
715 call_attrs.traffic.v.forward.PCR_all_traffic;
716 call_attrs.traffic.v.backward.SCR_high_priority = T_ATM_ABSENT;
717 call_attrs.traffic.v.backward.SCR_all_traffic = T_ATM_ABSENT;
718 call_attrs.traffic.v.backward.MBS_high_priority = T_ATM_ABSENT;
719 call_attrs.traffic.v.backward.MBS_all_traffic = T_ATM_ABSENT;
720 call_attrs.traffic.v.backward.tagging = T_NO;
721 call_attrs.traffic.v.best_effort = T_YES;
723 call_attrs.bearer.tag = T_ATM_PRESENT;
724 call_attrs.bearer.v.bearer_class = T_ATM_CLASS_X;
725 call_attrs.bearer.v.traffic_type = T_ATM_NULL;
726 call_attrs.bearer.v.timing_requirements = T_ATM_NULL;
727 call_attrs.bearer.v.clipping_susceptibility = T_NO;
728 call_attrs.bearer.v.connection_configuration = T_ATM_1_TO_1;
731 call_attrs.bhli.tag = T_ATM_ABSENT;
732 call_attrs.blli.tag_l2 = T_ATM_ABSENT;
733 call_attrs.blli.tag_l3 = T_ATM_ABSENT;
734 call_attrs.llc.tag = T_ATM_ABSENT;
736 call_attrs.called.tag = T_ATM_PRESENT;
737 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_dst,
738 call_attrs.called.addr.address);
739 call_attrs.called.addr.address_format = T_ATM_SPANS_ADDR;
740 call_attrs.called.addr.address_length = sizeof(spans_addr);
741 call_attrs.called.subaddr.address_format = T_ATM_ABSENT;
742 call_attrs.called.subaddr.address_length = 0;
744 call_attrs.calling.tag = T_ATM_PRESENT;
745 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_src,
746 call_attrs.calling.addr.address);
747 call_attrs.calling.addr.address_format = T_ATM_SPANS_ADDR;
748 call_attrs.calling.addr.address_length = sizeof(spans_addr);
749 call_attrs.calling.subaddr.address_format = T_ATM_ABSENT;
750 call_attrs.calling.subaddr.address_length = 0;
752 call_attrs.qos.tag = T_ATM_PRESENT;
753 call_attrs.qos.v.coding_standard = T_ATM_NETWORK_CODING;
754 call_attrs.qos.v.forward.qos_class = T_ATM_QOS_CLASS_0;
755 call_attrs.qos.v.backward.qos_class = T_ATM_QOS_CLASS_0;
757 call_attrs.transit.tag = T_ATM_ABSENT;
758 call_attrs.cause.tag = T_ATM_ABSENT;
761 * Notify the connection manager that it has a new channel
763 err = atm_cm_incoming((struct vccb *)svp, &call_attrs);
765 ATM_DEBUG0("spans_open_req: atm_cm_incoming returned error\n");
771 * Wait for the connection recipient to issue an accept
777 * Clean up the VCCB and the atm_conn block if we got them
780 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
786 * Some problem was detected with the request. Send a SPANS
787 * message rejecting the connection.
789 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
794 * Fill out the response
796 rsp_msg->sm_vers = SPANS_VERS_1_0;
797 rsp_msg->sm_type = SPANS_OPEN_RSP;
798 rsp_msg->sm_open_rsp.oprsp_conn = msg->sm_open_req.opreq_conn;
799 rsp_msg->sm_open_rsp.oprsp_result = result;
800 rsp_msg->sm_open_rsp.oprsp_vpvc = 0;
803 * Send the Open Response
805 spans_send_msg(spp, rsp_msg);
811 * Process an open response or open confirmation
813 * Called when an open response or open confirmation is received.
814 * Processing will be based on the state of the requested connection and
815 * the status returned.
818 * spp pointer to SPANS protocol instance block
819 * msg pointer to the open response or confirmation message
826 spans_open_rsp(spp, msg)
830 struct spans_vccb *svp;
832 ATM_DEBUG2("spans_open_rsp: spp=%p, msg=%p\n", spp, msg);
835 * Locate the VCCB for the connection
837 svp = spans_find_conn(spp, &msg->sm_open_rsp.oprsp_conn);
842 * Check the connection state
844 if ((svp->sv_sstate != SPANS_VC_POPEN &&
845 svp->sv_sstate != SPANS_VC_R_POPEN) ||
846 svp->sv_ustate != VCCU_POPEN) {
848 "spans_open_rsp: invalid VCCB state, sstate=%d, ustate=%d\n",
849 svp->sv_sstate, svp->sv_ustate);
854 * Cancel the retransmission timer
856 SPANS_VC_CANCEL((struct vccb *) svp);
861 switch (msg->sm_open_rsp.oprsp_result) {
865 * Save the assigned VPI and VCI
867 svp->sv_vpi = SPANS_EXTRACT_VPI(msg->sm_open_rsp.oprsp_vpvc);
868 svp->sv_vci = SPANS_EXTRACT_VCI(msg->sm_open_rsp.oprsp_vpvc);
871 * Update the VCC state and notify the VCC owner
873 svp->sv_sstate = SPANS_VC_OPEN;
874 svp->sv_ustate = VCCU_OPEN;
875 svp->sv_tstamp = time_second;
876 atm_cm_connected(svp->sv_connvc);
884 * Close out the VCCB and notify the user
886 svp->sv_sstate = SPANS_VC_FREE;
887 svp->sv_ustate = VCCU_CLOSED;
888 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
889 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
891 svp->sv_connvc->cvc_attr.cause.v.location =
893 svp->sv_connvc->cvc_attr.cause.v.cause_value =
894 T_ATM_CAUSE_CALL_REJECTED;
895 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
896 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
897 atm_cm_cleared(svp->sv_connvc);
901 log(LOG_ERR, "spans: unknown result %d in open rsp\n",
902 msg->sm_open_rsp.oprsp_result);
909 * Process a close request from the network
911 * Called when a close request, close indication, rclose request, or
912 * rclose indication is received. Processing will be based on the
913 * state of the connection.
916 * spp pointer to SPANS protocol instance block
917 * msg pointer to the close request message
924 spans_close_req(spp, msg)
928 struct spans_vccb *svp;
934 ATM_DEBUG2("spans_close_req: spp=%p, msg=%p\n", spp, msg);
937 * Locate the VCCB for the connection
939 svp = spans_find_conn(spp, &msg->sm_close_req.clreq_conn);
941 result = SPANS_BADDEST;
946 * Check the connection type
948 if (!(svp->sv_type & VCC_SVC)) {
954 * Check the connection state
956 switch (svp->sv_sstate) {
958 case SPANS_VC_R_POPEN:
961 * VCC is open or opening--continue
968 * We're already closing--give a response, since this
969 * is probably a retransmission
979 * Cancel the retransmission timer
981 SPANS_VC_CANCEL((struct vccb *) svp);
984 * Close out the VCCB and notify the user
986 outstate = svp->sv_sstate;
987 svp->sv_ustate = VCCU_CLOSED;
988 svp->sv_sstate = SPANS_VC_FREE;
989 cvp = svp->sv_connvc;
991 case SPANS_VC_R_POPEN:
992 spans_free((struct vccb *)svp);
997 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
998 cvp->cvc_attr.cause.v.coding_standard =
1000 cvp->cvc_attr.cause.v.location = T_ATM_LOC_USER;
1001 cvp->cvc_attr.cause.v.cause_value =
1002 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1003 KM_ZERO(cvp->cvc_attr.cause.v.diagnostics,
1004 sizeof(cvp->cvc_attr.cause.v.diagnostics));
1005 atm_cm_cleared(svp->sv_connvc);
1013 * Respond to the SPANS_CLOSE_IND with a SPANS_CLOSE_RSP
1015 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
1016 if (rsp_msg == NULL)
1018 rsp_msg->sm_vers = SPANS_VERS_1_0;
1019 if (msg->sm_type == SPANS_RCLOSE_REQ ||
1020 msg->sm_type == SPANS_RCLOSE_IND) {
1021 rsp_msg->sm_type = SPANS_RCLOSE_RSP;
1023 rsp_msg->sm_type = SPANS_CLOSE_RSP;
1025 rsp_msg->sm_close_rsp.clrsp_conn = msg->sm_close_req.clreq_conn;
1026 rsp_msg->sm_close_rsp.clrsp_result = result;
1027 spans_send_msg(spp, rsp_msg);
1033 * Process a close response or close confirmation
1035 * Called when an close response or close confirmation is received.
1036 * Processing will be based on the state of the requested connection and
1037 * the returned status.
1040 * spp pointer to SPANS protocol instance block
1041 * msg pointer to the close response or confirmation message
1048 spans_close_rsp(spp, msg)
1052 struct spans_vccb *svp;
1054 ATM_DEBUG2("spans_close_rsp: spp=%p, msg=%p\n", spp, msg);
1057 * Locate the VCCB for the connection
1059 svp = spans_find_conn(spp, &msg->sm_close_rsp.clrsp_conn);
1065 * Check the VCCB state
1067 if (svp->sv_sstate != SPANS_VC_CLOSE) {
1072 * Cancel the retransmission timer
1074 SPANS_VC_CANCEL((struct vccb *) svp);
1077 * Check the response from the remote end
1079 switch (msg->sm_close_rsp.clrsp_result) {
1083 * Mark the VCCB as closed and notify the owner
1085 svp->sv_sstate = SPANS_VC_FREE;
1086 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1087 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1089 svp->sv_connvc->cvc_attr.cause.v.location =
1091 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1092 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1093 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1094 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1095 atm_cm_cleared(svp->sv_connvc);
1103 * Mark the VCCB as closed and notify the owner
1105 svp->sv_sstate = SPANS_VC_FREE;
1106 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1107 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1109 svp->sv_connvc->cvc_attr.cause.v.location =
1111 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1112 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
1113 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1114 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1115 atm_cm_cleared(svp->sv_connvc);
1119 log(LOG_ERR, "spans: unknown result %d in close rsp\n",
1120 msg->sm_close_rsp.clrsp_result);
1127 * Process a multi request or multi indication
1129 * Called when a multi response or multi confirmation is received. We
1130 * don't support multicast channels, so we just reject the request.
1133 * spp pointer to SPANS protocol instance block
1134 * msg pointer to the multi request or indication message
1141 spans_multi_req(spp, msg)
1148 * Get memory for a SPANS_MULTI_RSP message.
1150 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1151 if (rsp_msg == NULL)
1155 * Fill out the response.
1157 rsp_msg->sm_vers = SPANS_VERS_1_0;
1158 rsp_msg->sm_type = SPANS_MULTI_RSP;
1159 rsp_msg->sm_multi_rsp.mursp_conn = msg->sm_multi_req.mureq_conn;
1160 rsp_msg->sm_multi_rsp.mursp_result = SPANS_FAIL;
1161 rsp_msg->sm_multi_rsp.mursp_rsrc = msg->sm_multi_req.mureq_desrsrc;
1162 rsp_msg->sm_multi_rsp.mursp_vpvc = 0;
1165 * Send the response and free the message.
1167 (void) spans_send_msg(spp, rsp_msg);
1173 * Process an add request or add indication
1175 * Called when an add response or add confirmation is received. We
1176 * don't support multicast channels, so we just reject the request.
1179 * spp pointer to SPANS protocol instance block
1180 * msg pointer to the add request or indication message
1187 spans_add_req(spp, msg)
1194 * Get memory for a SPANS_ADD_RSP message.
1196 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1197 if (rsp_msg == NULL)
1201 * Fill out the response.
1203 rsp_msg->sm_vers = SPANS_VERS_1_0;
1204 rsp_msg->sm_type = SPANS_ADD_RSP;
1205 rsp_msg->sm_add_rsp.adrsp_conn = msg->sm_add_req.adreq_desconn;
1206 rsp_msg->sm_add_rsp.adrsp_result = SPANS_FAIL;
1207 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_peak = 0;
1208 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_mean = 0;
1209 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_burst = 0;
1212 * Send the response and free the message.
1214 (void) spans_send_msg(spp, rsp_msg);
1220 * Process a join request
1222 * Called when an join request is received. We don't support group
1223 * addresses, so we just reject the request.
1226 * spp pointer to SPANS protocol instance block
1227 * msg pointer to the join request message
1234 spans_join_req(spp, msg)
1241 * Get memory for a SPANS_JOIN_CNF message.
1243 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1244 if (rsp_msg == NULL)
1248 * Fill out the response.
1250 rsp_msg->sm_vers = SPANS_VERS_1_0;
1251 rsp_msg->sm_type = SPANS_JOIN_CNF;
1252 spans_addr_copy(&msg->sm_join_req.jnreq_addr,
1253 &rsp_msg->sm_join_cnf.jncnf_addr);
1254 rsp_msg->sm_join_cnf.jncnf_result = SPANS_FAIL;
1257 * Send the response and free the message.
1259 (void) spans_send_msg(spp, rsp_msg);
1265 * Process a leave request
1267 * Called when an leave request is received. We don't support group
1268 * addresses, so we just reject the request.
1271 * spp pointer to SPANS protocol instance block
1272 * msg pointer to the leave request message
1279 spans_leave_req(spp, msg)
1286 * Get memory for a SPANS_LEAVE_CNF message.
1288 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1289 if (rsp_msg == NULL)
1293 * Fill out the response.
1295 rsp_msg->sm_vers = SPANS_VERS_1_0;
1296 rsp_msg->sm_type = SPANS_LEAVE_CNF;
1297 spans_addr_copy(&msg->sm_leave_req.lvreq_addr,
1298 &rsp_msg->sm_leave_cnf.lvcnf_addr);
1299 rsp_msg->sm_leave_cnf.lvcnf_result = SPANS_FAIL;
1302 * Send the response and free the message.
1304 (void) spans_send_msg(spp, rsp_msg);
1310 * Process a VCI range indication
1312 * Called when a VCI range indication is received. Adjust the VCI
1313 * bounds if they have changed.
1316 * spp pointer to SPANS protocol instance block
1317 * msg pointer to the VCI range indication message
1324 spans_vcir_ind(spp, msg)
1329 * Adjust the limits if they have changed
1331 if (msg->sm_vcir_ind.vrind_min != spp->sp_min_vci) {
1333 (msg->sm_vcir_ind.vrind_min <
1336 msg->sm_vcir_ind.vrind_min);
1338 if (msg->sm_vcir_ind.vrind_max != spp->sp_max_vci) {
1340 (msg->sm_vcir_ind.vrind_max >
1343 msg->sm_vcir_ind.vrind_max);
1349 * Process a query request
1351 * Called when a query request is received. Respond with the
1352 * appropriate query response.
1355 * spp pointer to SPANS protocol instance block
1356 * msg pointer to the VCI range indication message
1363 spans_query_req(spp, msg)
1367 struct spans_vccb *svp = NULL;
1370 ATM_DEBUG1("spans_query_req: msg=%p\n", msg);
1373 * Ignore an end-to-end query
1375 if (msg->sm_query_req.qyreq_type == SPANS_QUERY_END_TO_END) {
1380 * Get memory for a SPANS_QUERY_RSP message.
1382 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1383 if (rsp_msg == NULL)
1387 * Fill out the response.
1389 rsp_msg->sm_vers = SPANS_VERS_1_0;
1390 rsp_msg->sm_type = SPANS_QUERY_RSP;
1391 rsp_msg->sm_query_rsp.qyrsp_conn = msg->sm_query_req.qyreq_conn;
1392 rsp_msg->sm_query_rsp.qyrsp_type = msg->sm_query_req.qyreq_type;
1393 rsp_msg->sm_query_rsp.qyrsp_data = 0;
1396 * Get the state of the requested connection
1398 svp = spans_find_conn(spp, &msg->sm_query_req.qyreq_conn);
1400 switch(svp->sv_sstate) {
1403 rsp_msg->sm_query_rsp.qyrsp_state =
1407 rsp_msg->sm_query_rsp.qyrsp_state =
1410 case SPANS_VC_POPEN:
1411 case SPANS_VC_R_POPEN:
1412 rsp_msg->sm_query_rsp.qyrsp_state =
1413 SPANS_CONN_OPEN_PEND;
1415 case SPANS_VC_CLOSE:
1416 case SPANS_VC_ABORT:
1417 rsp_msg->sm_query_rsp.qyrsp_state =
1418 SPANS_CONN_CLOSE_PEND;
1420 case SPANS_VC_ACTIVE:
1421 case SPANS_VC_ACT_DOWN:
1423 * VCCB is for a PVC (shouldn't happen)
1430 * No VCCB found--connection doesn't exist
1432 rsp_msg->sm_query_rsp.qyrsp_state = SPANS_CONN_CLOSED;
1436 * Send the response and free the message.
1438 (void) spans_send_msg(spp, rsp_msg);
1444 * Process a SPANS signalling message
1446 * Called when a SPANS message is received. The message is converted
1447 * into internal format with XDR and decoded by calling the appropriate
1448 * mesage handling routine. Unrecognized and unexpected messages are
1452 * spp pointer to SPANS protocol instance block
1453 * m pointer to a buffer chain containing the SPANS message
1460 spans_rcv_msg(spp, m)
1468 * Get storage for the message
1470 msg = (spans_msg *)atm_allocate(&spans_msgpool);
1476 * Convert the message from network order to internal format
1478 xdrmbuf_init(&xdrs, m, XDR_DECODE);
1479 if (!xdr_spans_msg(&xdrs, msg)) {
1480 log(LOG_ERR, "spans_rcv_msg: XDR decode failed\n");
1481 spans_dump_buffer(m);
1487 * Debug--print some information about the message
1489 if (msg->sm_type != SPANS_STAT_REQ &&
1490 msg->sm_type != SPANS_STAT_IND &&
1491 msg->sm_type != SPANS_STAT_RSP) {
1492 printf("spans_rcv_msg: got ");
1493 spans_print_msg(msg);
1498 * Verify the message sm_vers
1500 if (msg->sm_vers != SPANS_VERS_1_0) {
1501 log(LOG_ERR, "spans: invalid message version 0x%x\n",
1506 * Ignore the message if SPANS isn't up yet
1508 if (spp->sp_state != SPANS_ACTIVE &&
1509 (spp->sp_state != SPANS_PROBE ||
1510 (msg->sm_type != SPANS_STAT_REQ &&
1511 msg->sm_type != SPANS_STAT_RSP &&
1512 msg->sm_type != SPANS_STAT_IND))) {
1517 * Process the message based on its type
1519 switch(msg->sm_type) {
1520 case SPANS_STAT_REQ:
1521 spans_status_ind(spp, msg);
1523 case SPANS_STAT_IND:
1524 spans_status_ind(spp, msg);
1526 case SPANS_STAT_RSP:
1527 spans_status_rsp(spp, msg);
1529 case SPANS_OPEN_REQ:
1530 spans_open_req(spp, msg);
1532 case SPANS_OPEN_IND:
1533 spans_open_req(spp, msg);
1535 case SPANS_OPEN_RSP:
1536 spans_open_rsp(spp, msg);
1538 case SPANS_OPEN_CNF:
1539 spans_open_rsp(spp, msg);
1541 case SPANS_CLOSE_REQ:
1542 spans_close_req(spp, msg);
1544 case SPANS_CLOSE_IND:
1545 spans_close_req(spp, msg);
1547 case SPANS_CLOSE_RSP:
1548 spans_close_rsp(spp, msg);
1550 case SPANS_CLOSE_CNF:
1551 spans_close_rsp(spp, msg);
1553 case SPANS_RCLOSE_REQ:
1554 spans_close_req(spp, msg);
1556 case SPANS_RCLOSE_IND:
1557 spans_close_req(spp, msg);
1559 case SPANS_RCLOSE_RSP:
1560 spans_close_rsp(spp, msg);
1562 case SPANS_RCLOSE_CNF:
1563 spans_close_rsp(spp, msg);
1565 case SPANS_MULTI_REQ:
1566 spans_multi_req(spp, msg);
1568 case SPANS_MULTI_IND:
1569 spans_multi_req(spp, msg);
1571 case SPANS_MULTI_RSP:
1573 "spans: unexpected message (multi_rsp)\n");
1575 case SPANS_MULTI_CNF:
1577 "spans: unexpected message (multi_conf)\n");
1580 spans_add_req(spp, msg);
1583 spans_add_req(spp, msg);
1587 "spans: unexpected message (add_rsp)\n");
1590 log(LOG_ERR, "spans: unexpected message (add_conf)\n");
1592 case SPANS_JOIN_REQ:
1593 spans_join_req(spp, msg);
1595 case SPANS_JOIN_CNF:
1596 log(LOG_ERR, "spans: unexpected message (join_conf)\n");
1598 case SPANS_LEAVE_REQ:
1599 spans_leave_req(spp, msg);
1601 case SPANS_LEAVE_CNF:
1603 "spans: unexpected message (leave_conf)\n");
1605 case SPANS_VCIR_IND:
1606 spans_vcir_ind(spp, msg);
1608 case SPANS_QUERY_REQ:
1609 spans_query_req(spp, msg);
1611 case SPANS_QUERY_RSP:
1613 "spans: unexpected message (query_rsp)\n");
1616 log(LOG_ERR, "spans: unknown SPANS message type %d\n",
1622 * Free the incoming message (both buffer and internal format) if