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 $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS signalling message processing.
38 #include <netatm/kern_include.h>
41 #include "spans_xdr.h"
42 #include <netatm/spans/spans_var.h>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/spans/spans_msg.c,v 1.5 1999/08/28 00:48:50 peter Exp $");
51 void xdrmbuf_init __P((XDR *, KBuffer *, enum xdr_op));
56 static void spans_host_link __P((struct spans *, long));
57 static void spans_status_ind __P((struct spans *, spans_msg *));
58 static void spans_status_rsp __P((struct spans *, spans_msg *));
59 static void spans_open_req __P((struct spans *, spans_msg *));
60 static void spans_open_rsp __P((struct spans *, spans_msg *));
61 static void spans_close_req __P((struct spans *, spans_msg *));
62 static void spans_close_rsp __P((struct spans *, spans_msg *));
63 static void spans_multi_req __P((struct spans *, spans_msg *));
64 static void spans_add_req __P((struct spans *, spans_msg *));
65 static void spans_join_req __P((struct spans *, spans_msg *));
66 static void spans_leave_req __P((struct spans *, spans_msg *));
67 static void spans_vcir_ind __P((struct spans *, spans_msg *));
68 static void spans_query_req __P((struct spans *, spans_msg *));
72 * Called to set status when a status message comes in from a host
73 * connected back-to-back with us. Check the epoch and, if it has
74 * changed, set the appropriate state and save updated state
78 * spp pointer to SPANS protocol instance block
79 * host_epoch epoch of host at far end of link
83 * errno error encountered
87 spans_host_link(spp, host_epoch)
91 struct atm_pif *pip = spp->sp_pif;
94 * There's a host at the other end of the link. If its
95 * epoch has changed, clean up our state and save the
98 if (spp->sp_s_epoch != host_epoch) {
99 spp->sp_s_epoch = host_epoch;
100 spans_switch_reset(spp, SPANS_UNI_UP);
101 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
102 spp->sp_addr.address_length = sizeof(spans_addr);
103 KM_COPY(&pip->pif_macaddr.ma_data[2],
104 &spp->sp_addr.address[4],
107 "spans: using SPANS address of %s on interface %s%d\n",
108 spans_addr_print((spans_addr *)spp->sp_addr.address),
115 * Send a SPANS signalling message
117 * Called to send a SPANS message. This routine gets a buffer, performs
118 * XDR processing, and hands the message to the AAL for transmission.
121 * spp pointer to SPANS protocol instance block
122 * msg pointer to status message
126 * errno error encountered
130 spans_send_msg(spp, msg)
139 ATM_DEBUG2("spans_send_msg: msg=%p, type=%d\n", msg,
141 if (msg->sm_type != SPANS_STAT_REQ &&
142 msg->sm_type != SPANS_STAT_IND &&
143 msg->sm_type != SPANS_STAT_RSP) {
144 printf("spans_send_msg: sending ");
145 spans_print_msg(msg);
150 * If the signalling channel has been closed, don't do anything
153 return(ECONNABORTED);
158 KB_ALLOCPKT(m, sizeof(spans_msg), KB_F_NOWAIT, KB_T_DATA);
160 /* No buffer available */
165 * Convert message to network order
167 KB_LEN(m) = KB_BFRLEN(m);
168 xdrmbuf_init(&xdrs, m, XDR_ENCODE);
169 if (!xdr_spans_msg(&xdrs, msg)) {
170 log(LOG_ERR, "spans_send_msg: XDR encode failed\n");
171 KB_LEN(m) = XDR_GETPOS(&xdrs);
172 spans_dump_buffer(m);
176 KB_LEN(m) = XDR_GETPOS(&xdrs);
181 err = atm_cm_cpcs_data(spp->sp_conn, m);
190 * Send an open request
192 * Build and send an open request.
195 * spp pointer to SPANS protocol instance block
196 * svp pointer to VCCB for which the request is being sent
203 spans_send_open_req(spp, svp)
205 struct spans_vccb *svp;
210 ATM_DEBUG1("spans_send_open_req: svp=%p\n", svp);
213 * Get memory for a request message
215 req = (spans_msg *)atm_allocate(&spans_msgpool);
222 * Fill in the request
224 req->sm_vers = SPANS_VERS_1_0;
225 req->sm_type = SPANS_OPEN_REQ;
226 req->sm_open_req.opreq_conn = svp->sv_conn;
227 req->sm_open_req.opreq_aal = svp->sv_spans_aal;
228 req->sm_open_req.opreq_desrsrc = svp->sv_spans_qos;
229 req->sm_open_req.opreq_minrsrc.rsc_peak = 0;
230 req->sm_open_req.opreq_minrsrc.rsc_mean = 0;
231 req->sm_open_req.opreq_minrsrc.rsc_burst = 0;
232 req->sm_open_req.opreq_vpvc.vpf_valid = FALSE;
237 err = spans_send_msg(spp, req);
246 * Send an open response
248 * Build and send a response to an open request or open indication.
251 * spp pointer to SPANS protocol instance block
252 * svp pointer to VCCB for which the response is being sent
253 * result result code to include in the response
260 spans_send_open_rsp(spp, svp, result)
262 struct spans_vccb *svp;
268 ATM_DEBUG2("spans_send_open_rsp: svp=%p, result=%d\n", svp,
272 * Get memory for a response message
274 rsp = (spans_msg *)atm_allocate(&spans_msgpool);
279 * Fill in the response
281 rsp->sm_vers = SPANS_VERS_1_0;
282 rsp->sm_type = SPANS_OPEN_RSP;
283 rsp->sm_open_rsp.oprsp_conn = svp->sv_conn;
284 rsp->sm_open_rsp.oprsp_result = result;
285 rsp->sm_open_rsp.oprsp_rsrc = svp->sv_spans_qos;
286 rsp->sm_open_rsp.oprsp_vpvc =
287 SPANS_PACK_VPIVCI(svp->sv_vpi, svp->sv_vci);
292 rc = spans_send_msg(spp, rsp);
300 * Send a close request
302 * Called to send a close request.
305 * spp pointer to SPANS protocol instance block
306 * svp pointer to VCCB for which the close is being sent
313 spans_send_close_req(spp, svp)
315 struct spans_vccb *svp;
320 ATM_DEBUG1("spans_send_close_req: svp=%p\n", svp);
323 * Get memory for a close request
325 req = (spans_msg *)atm_allocate(&spans_msgpool);
332 * Fill in the request
334 req->sm_vers = SPANS_VERS_1_0;
335 if (svp->sv_type & VCC_OUT) {
336 req->sm_type = SPANS_CLOSE_REQ;
337 } else if (svp->sv_type & VCC_IN) {
338 req->sm_type = SPANS_RCLOSE_REQ;
342 "spans_send_close_req: invalid VCCB type 0x%x\n",
346 req->sm_close_req.clreq_conn = svp->sv_conn;
349 * Send the close request
351 err = spans_send_msg(spp, req);
363 * Process a status indication or status request
365 * Called when a status indication or status request is received.
366 * Processing will be based on the current SPANS state.
369 * spp pointer to SPANS protocol instance block
370 * msg pointer to the status message
377 spans_status_ind(spp, msg)
382 struct atm_pif *pip = spp->sp_pif;
385 * Reset the probe count.
387 spp->sp_probe_ct = 0;
389 switch (spp->sp_state) {
392 * Interface just came up, update signalling state
394 spp->sp_state = SPANS_ACTIVE;
401 log(LOG_ERR, "spans: received status msg in state %d\n",
406 * Process the message
408 switch (msg->sm_type) {
412 * Handle a request from a host at the other end of
415 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
421 * There's a switch at the other end of the link. If
422 * its epoch has changed, reset the SPANS state and save
423 * the new information.
425 if (spp->sp_s_epoch !=
426 msg->sm_stat_ind.stind_sw_epoch) {
427 spans_switch_reset(spp, SPANS_UNI_UP);
429 msg->sm_stat_ind.stind_sw_epoch;
430 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
431 spp->sp_addr.address_length =
433 spans_addr_copy(&msg->sm_stat_ind.stind_es_addr,
434 spp->sp_addr.address);
436 "spans: received SPANS address %s from switch for interface %s%d\n",
437 spans_addr_print((spans_addr *)spp->sp_addr.address),
444 ATM_DEBUG1("spans_status_ind: Invalid message type %d\n",
450 * Respond to the status request or indication with a
453 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
456 rsp_msg->sm_vers = SPANS_VERS_1_0;
457 rsp_msg->sm_type = SPANS_STAT_RSP;
458 rsp_msg->sm_stat_rsp.strsp_es_epoch = spp->sp_h_epoch;
459 spans_addr_copy(spp->sp_addr.address,
460 &rsp_msg->sm_stat_rsp.strsp_es_addr);
461 spans_send_msg(spp, rsp_msg);
468 * Process a status response
470 * Called when a status response is received.
471 * Processing will be based on the current SPANS state.
474 * spp pointer to SPANS protocol instance block
475 * msg pointer to the status response message
482 spans_status_rsp(spp, msg)
488 * Reset the probe count.
490 spp->sp_probe_ct = 0;
492 switch (spp->sp_state) {
495 * Interface just came up, update signalling state
497 spp->sp_state = SPANS_ACTIVE;
504 log(LOG_ERR, "spans: received status msg in state %d\n",
509 * Process the message
511 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
516 * Process an open indication or open request
518 * Called when an open indication or open request is received.
519 * Processing will be based on the state of the requested connection.
522 * spp pointer to SPANS protocol instance block
523 * msg pointer to the open message
530 spans_open_req(spp, msg)
534 spans_result result = SPANS_OK;
536 struct spans_vccb *svp = NULL;
539 int err = 0, vpi, vci;
541 Atm_attributes call_attrs;
543 ATM_DEBUG2("spans_open_req: spp=%p, msg=%p\n", spp, msg);
546 * See if the connection is new
548 if ((svp = spans_find_conn(spp, &msg->sm_open_req.opreq_conn)) != NULL) {
550 * We already have a VCCB that matches the connection in
553 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
554 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
555 if (msg->sm_open_req.opreq_aal == svp->sv_spans_aal &&
556 (!msg->sm_open_req.opreq_vpvc.vpf_valid ||
557 (vpi == svp->sv_vpi &&
558 vci == svp->sv_vci))) {
560 * VCCB already exists, process depending on
563 switch (svp->sv_sstate) {
564 case SPANS_VC_R_POPEN:
565 /* I'm still thinking about it */
568 /* Retransmit the open_rsp */
573 ATM_DEBUG0("spans_open_req: bad VCCB state\n");
579 * VCCB is for same connection, but other
580 * parameters don't match
582 ATM_DEBUG0("spans_open_req: VCCB confusion\n");
590 * Verify that the request is for our ATM addres
592 if (spans_addr_cmp(spp->sp_addr.address,
593 &msg->sm_open_req.opreq_conn.con_dst)) {
594 ATM_DEBUG0("spans_open_req: bad destination\n");
595 result = SPANS_BADDEST;
600 * See if we recognize the specified AAL
602 if (!spans_get_local_aal(msg->sm_open_req.opreq_aal, &aal)) {
603 ATM_DEBUG0("spans_open_req: bad AAL\n");
609 * Should verify that we can handle requested connection QOS
613 * Select a VPI/VCI for the new connection
615 if (msg->sm_open_req.opreq_vpvc.vpf_valid) {
617 * Requestor asked for a certain VPI/VCI. Make sure we
618 * aren't already using the pair that was asked for.
620 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
621 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
622 if (spans_find_vpvc(spp, vci, vpi, VCC_IN)) {
623 ATM_DEBUG0("spans_open_req: VPI, VCI busy\n");
624 result = SPANS_NOVPVC;
627 vpvc = msg->sm_open_req.opreq_vpvc.vpf_vpvc;
630 * Allocate a VPI/VCI for this end of the VCC
632 vpvc = spans_alloc_vpvc(spp);
634 ATM_DEBUG0("spans_open_req: no VPI, VCI available\n");
635 result = SPANS_NOVPVC;
641 * Get a new VCCB for the connection
643 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
645 ATM_DEBUG0("spans_open_req: VCCB pool empty\n");
646 result = SPANS_NORSC;
651 * Find the physical interface structure
656 * Fill in the VCCB fields that we can at this point
658 svp->sv_type = VCC_SVC | VCC_IN;
659 svp->sv_proto = ATM_SIG_SPANS;
660 svp->sv_sstate = SPANS_VC_R_POPEN;
661 svp->sv_ustate = VCCU_POPEN;
663 svp->sv_nif = pip->pif_nif;
664 svp->sv_conn = msg->sm_open_req.opreq_conn;
665 svp->sv_spans_qos = msg->sm_open_req.opreq_desrsrc;
666 svp->sv_spans_aal = msg->sm_open_req.opreq_aal;
667 svp->sv_tstamp = time_second;
669 svp->sv_vpi = SPANS_EXTRACT_VPI(vpvc);
670 svp->sv_vci = SPANS_EXTRACT_VCI(vpvc);
673 * Put the VCCB on the SPANS queue
675 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
678 * Set up the ATM attributes block
680 KM_ZERO(&call_attrs, sizeof(call_attrs));
681 call_attrs.nif = svp->sv_nif;
682 call_attrs.api = CMAPI_CPCS;
684 call_attrs.aal.tag = T_ATM_PRESENT;
685 call_attrs.aal.type = aal;
688 call_attrs.aal.v.aal4.forward_max_SDU_size =
690 call_attrs.aal.v.aal4.backward_max_SDU_size =
692 call_attrs.aal.v.aal4.SSCS_type =
694 call_attrs.aal.v.aal4.mid_low = 0;
695 call_attrs.aal.v.aal4.mid_high = 1023;
698 call_attrs.aal.v.aal5.forward_max_SDU_size =
700 call_attrs.aal.v.aal5.backward_max_SDU_size =
702 call_attrs.aal.v.aal5.SSCS_type =
707 call_attrs.traffic.tag = T_ATM_PRESENT;
708 call_attrs.traffic.v.forward.PCR_high_priority = T_ATM_ABSENT;
709 call_attrs.traffic.v.forward.PCR_all_traffic =
710 msg->sm_open_req.opreq_desrsrc.rsc_peak *
712 call_attrs.traffic.v.forward.SCR_high_priority = T_ATM_ABSENT;
713 call_attrs.traffic.v.forward.SCR_all_traffic = T_ATM_ABSENT;
714 call_attrs.traffic.v.forward.MBS_high_priority = T_ATM_ABSENT;
715 call_attrs.traffic.v.forward.MBS_all_traffic = T_ATM_ABSENT;
716 call_attrs.traffic.v.forward.tagging = T_NO;
717 call_attrs.traffic.v.backward.PCR_high_priority = T_ATM_ABSENT;
718 call_attrs.traffic.v.backward.PCR_all_traffic =
719 call_attrs.traffic.v.forward.PCR_all_traffic;
720 call_attrs.traffic.v.backward.SCR_high_priority = T_ATM_ABSENT;
721 call_attrs.traffic.v.backward.SCR_all_traffic = T_ATM_ABSENT;
722 call_attrs.traffic.v.backward.MBS_high_priority = T_ATM_ABSENT;
723 call_attrs.traffic.v.backward.MBS_all_traffic = T_ATM_ABSENT;
724 call_attrs.traffic.v.backward.tagging = T_NO;
725 call_attrs.traffic.v.best_effort = T_YES;
727 call_attrs.bearer.tag = T_ATM_PRESENT;
728 call_attrs.bearer.v.bearer_class = T_ATM_CLASS_X;
729 call_attrs.bearer.v.traffic_type = T_ATM_NULL;
730 call_attrs.bearer.v.timing_requirements = T_ATM_NULL;
731 call_attrs.bearer.v.clipping_susceptibility = T_NO;
732 call_attrs.bearer.v.connection_configuration = T_ATM_1_TO_1;
735 call_attrs.bhli.tag = T_ATM_ABSENT;
736 call_attrs.blli.tag_l2 = T_ATM_ABSENT;
737 call_attrs.blli.tag_l3 = T_ATM_ABSENT;
738 call_attrs.llc.tag = T_ATM_ABSENT;
740 call_attrs.called.tag = T_ATM_PRESENT;
741 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_dst,
742 call_attrs.called.addr.address);
743 call_attrs.called.addr.address_format = T_ATM_SPANS_ADDR;
744 call_attrs.called.addr.address_length = sizeof(spans_addr);
745 call_attrs.called.subaddr.address_format = T_ATM_ABSENT;
746 call_attrs.called.subaddr.address_length = 0;
748 call_attrs.calling.tag = T_ATM_PRESENT;
749 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_src,
750 call_attrs.calling.addr.address);
751 call_attrs.calling.addr.address_format = T_ATM_SPANS_ADDR;
752 call_attrs.calling.addr.address_length = sizeof(spans_addr);
753 call_attrs.calling.subaddr.address_format = T_ATM_ABSENT;
754 call_attrs.calling.subaddr.address_length = 0;
756 call_attrs.qos.tag = T_ATM_PRESENT;
757 call_attrs.qos.v.coding_standard = T_ATM_NETWORK_CODING;
758 call_attrs.qos.v.forward.qos_class = T_ATM_QOS_CLASS_0;
759 call_attrs.qos.v.backward.qos_class = T_ATM_QOS_CLASS_0;
761 call_attrs.transit.tag = T_ATM_ABSENT;
762 call_attrs.cause.tag = T_ATM_ABSENT;
765 * Notify the connection manager that it has a new channel
767 err = atm_cm_incoming((struct vccb *)svp, &call_attrs);
769 ATM_DEBUG0("spans_open_req: atm_cm_incoming returned error\n");
775 * Wait for the connection recipient to issue an accept
781 * Clean up the VCCB and the atm_conn block if we got them
784 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
790 * Some problem was detected with the request. Send a SPANS
791 * message rejecting the connection.
793 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
798 * Fill out the response
800 rsp_msg->sm_vers = SPANS_VERS_1_0;
801 rsp_msg->sm_type = SPANS_OPEN_RSP;
802 rsp_msg->sm_open_rsp.oprsp_conn = msg->sm_open_req.opreq_conn;
803 rsp_msg->sm_open_rsp.oprsp_result = result;
804 rsp_msg->sm_open_rsp.oprsp_vpvc = 0;
807 * Send the Open Response
809 spans_send_msg(spp, rsp_msg);
815 * Process an open response or open confirmation
817 * Called when an open response or open confirmation is received.
818 * Processing will be based on the state of the requested connection and
819 * the status returned.
822 * spp pointer to SPANS protocol instance block
823 * msg pointer to the open response or confirmation message
830 spans_open_rsp(spp, msg)
834 struct spans_vccb *svp;
836 ATM_DEBUG2("spans_open_rsp: spp=%p, msg=%p\n", spp, msg);
839 * Locate the VCCB for the connection
841 svp = spans_find_conn(spp, &msg->sm_open_rsp.oprsp_conn);
846 * Check the connection state
848 if ((svp->sv_sstate != SPANS_VC_POPEN &&
849 svp->sv_sstate != SPANS_VC_R_POPEN) ||
850 svp->sv_ustate != VCCU_POPEN) {
852 "spans_open_rsp: invalid VCCB state, sstate=%d, ustate=%d\n",
853 svp->sv_sstate, svp->sv_ustate);
858 * Cancel the retransmission timer
860 SPANS_VC_CANCEL((struct vccb *) svp);
865 switch (msg->sm_open_rsp.oprsp_result) {
869 * Save the assigned VPI and VCI
871 svp->sv_vpi = SPANS_EXTRACT_VPI(msg->sm_open_rsp.oprsp_vpvc);
872 svp->sv_vci = SPANS_EXTRACT_VCI(msg->sm_open_rsp.oprsp_vpvc);
875 * Update the VCC state and notify the VCC owner
877 svp->sv_sstate = SPANS_VC_OPEN;
878 svp->sv_ustate = VCCU_OPEN;
879 svp->sv_tstamp = time_second;
880 atm_cm_connected(svp->sv_connvc);
888 * Close out the VCCB and notify the user
890 svp->sv_sstate = SPANS_VC_FREE;
891 svp->sv_ustate = VCCU_CLOSED;
892 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
893 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
895 svp->sv_connvc->cvc_attr.cause.v.location =
897 svp->sv_connvc->cvc_attr.cause.v.cause_value =
898 T_ATM_CAUSE_CALL_REJECTED;
899 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
900 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
901 atm_cm_cleared(svp->sv_connvc);
905 log(LOG_ERR, "spans: unknown result %d in open rsp\n",
906 msg->sm_open_rsp.oprsp_result);
913 * Process a close request from the network
915 * Called when a close request, close indication, rclose request, or
916 * rclose indication is received. Processing will be based on the
917 * state of the connection.
920 * spp pointer to SPANS protocol instance block
921 * msg pointer to the close request message
928 spans_close_req(spp, msg)
932 struct spans_vccb *svp;
938 ATM_DEBUG2("spans_close_req: spp=%p, msg=%p\n", spp, msg);
941 * Locate the VCCB for the connection
943 svp = spans_find_conn(spp, &msg->sm_close_req.clreq_conn);
945 result = SPANS_BADDEST;
950 * Check the connection type
952 if (!(svp->sv_type & VCC_SVC)) {
958 * Check the connection state
960 switch (svp->sv_sstate) {
962 case SPANS_VC_R_POPEN:
965 * VCC is open or opening--continue
972 * We're already closing--give a response, since this
973 * is probably a retransmission
983 * Cancel the retransmission timer
985 SPANS_VC_CANCEL((struct vccb *) svp);
988 * Close out the VCCB and notify the user
990 outstate = svp->sv_sstate;
991 svp->sv_ustate = VCCU_CLOSED;
992 svp->sv_sstate = SPANS_VC_FREE;
993 cvp = svp->sv_connvc;
995 case SPANS_VC_R_POPEN:
996 spans_free((struct vccb *)svp);
1001 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
1002 cvp->cvc_attr.cause.v.coding_standard =
1004 cvp->cvc_attr.cause.v.location = T_ATM_LOC_USER;
1005 cvp->cvc_attr.cause.v.cause_value =
1006 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1007 KM_ZERO(cvp->cvc_attr.cause.v.diagnostics,
1008 sizeof(cvp->cvc_attr.cause.v.diagnostics));
1009 atm_cm_cleared(svp->sv_connvc);
1017 * Respond to the SPANS_CLOSE_IND with a SPANS_CLOSE_RSP
1019 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
1020 if (rsp_msg == NULL)
1022 rsp_msg->sm_vers = SPANS_VERS_1_0;
1023 if (msg->sm_type == SPANS_RCLOSE_REQ ||
1024 msg->sm_type == SPANS_RCLOSE_IND) {
1025 rsp_msg->sm_type = SPANS_RCLOSE_RSP;
1027 rsp_msg->sm_type = SPANS_CLOSE_RSP;
1029 rsp_msg->sm_close_rsp.clrsp_conn = msg->sm_close_req.clreq_conn;
1030 rsp_msg->sm_close_rsp.clrsp_result = result;
1031 spans_send_msg(spp, rsp_msg);
1037 * Process a close response or close confirmation
1039 * Called when an close response or close confirmation is received.
1040 * Processing will be based on the state of the requested connection and
1041 * the returned status.
1044 * spp pointer to SPANS protocol instance block
1045 * msg pointer to the close response or confirmation message
1052 spans_close_rsp(spp, msg)
1056 struct spans_vccb *svp;
1058 ATM_DEBUG2("spans_close_rsp: spp=%p, msg=%p\n", spp, msg);
1061 * Locate the VCCB for the connection
1063 svp = spans_find_conn(spp, &msg->sm_close_rsp.clrsp_conn);
1069 * Check the VCCB state
1071 if (svp->sv_sstate != SPANS_VC_CLOSE) {
1076 * Cancel the retransmission timer
1078 SPANS_VC_CANCEL((struct vccb *) svp);
1081 * Check the response from the remote end
1083 switch (msg->sm_close_rsp.clrsp_result) {
1087 * Mark the VCCB as closed and notify the owner
1089 svp->sv_sstate = SPANS_VC_FREE;
1090 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1091 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1093 svp->sv_connvc->cvc_attr.cause.v.location =
1095 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1096 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1097 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1098 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1099 atm_cm_cleared(svp->sv_connvc);
1107 * Mark the VCCB as closed and notify the owner
1109 svp->sv_sstate = SPANS_VC_FREE;
1110 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1111 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1113 svp->sv_connvc->cvc_attr.cause.v.location =
1115 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1116 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
1117 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1118 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1119 atm_cm_cleared(svp->sv_connvc);
1123 log(LOG_ERR, "spans: unknown result %d in close rsp\n",
1124 msg->sm_close_rsp.clrsp_result);
1131 * Process a multi request or multi indication
1133 * Called when a multi response or multi confirmation is received. We
1134 * don't support multicast channels, so we just reject the request.
1137 * spp pointer to SPANS protocol instance block
1138 * msg pointer to the multi request or indication message
1145 spans_multi_req(spp, msg)
1152 * Get memory for a SPANS_MULTI_RSP message.
1154 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1155 if (rsp_msg == NULL)
1159 * Fill out the response.
1161 rsp_msg->sm_vers = SPANS_VERS_1_0;
1162 rsp_msg->sm_type = SPANS_MULTI_RSP;
1163 rsp_msg->sm_multi_rsp.mursp_conn = msg->sm_multi_req.mureq_conn;
1164 rsp_msg->sm_multi_rsp.mursp_result = SPANS_FAIL;
1165 rsp_msg->sm_multi_rsp.mursp_rsrc = msg->sm_multi_req.mureq_desrsrc;
1166 rsp_msg->sm_multi_rsp.mursp_vpvc = 0;
1169 * Send the response and free the message.
1171 (void) spans_send_msg(spp, rsp_msg);
1177 * Process an add request or add indication
1179 * Called when an add response or add confirmation is received. We
1180 * don't support multicast channels, so we just reject the request.
1183 * spp pointer to SPANS protocol instance block
1184 * msg pointer to the add request or indication message
1191 spans_add_req(spp, msg)
1198 * Get memory for a SPANS_ADD_RSP message.
1200 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1201 if (rsp_msg == NULL)
1205 * Fill out the response.
1207 rsp_msg->sm_vers = SPANS_VERS_1_0;
1208 rsp_msg->sm_type = SPANS_ADD_RSP;
1209 rsp_msg->sm_add_rsp.adrsp_conn = msg->sm_add_req.adreq_desconn;
1210 rsp_msg->sm_add_rsp.adrsp_result = SPANS_FAIL;
1211 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_peak = 0;
1212 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_mean = 0;
1213 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_burst = 0;
1216 * Send the response and free the message.
1218 (void) spans_send_msg(spp, rsp_msg);
1224 * Process a join request
1226 * Called when an join request is received. We don't support group
1227 * addresses, so we just reject the request.
1230 * spp pointer to SPANS protocol instance block
1231 * msg pointer to the join request message
1238 spans_join_req(spp, msg)
1245 * Get memory for a SPANS_JOIN_CNF message.
1247 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1248 if (rsp_msg == NULL)
1252 * Fill out the response.
1254 rsp_msg->sm_vers = SPANS_VERS_1_0;
1255 rsp_msg->sm_type = SPANS_JOIN_CNF;
1256 spans_addr_copy(&msg->sm_join_req.jnreq_addr,
1257 &rsp_msg->sm_join_cnf.jncnf_addr);
1258 rsp_msg->sm_join_cnf.jncnf_result = SPANS_FAIL;
1261 * Send the response and free the message.
1263 (void) spans_send_msg(spp, rsp_msg);
1269 * Process a leave request
1271 * Called when an leave request is received. We don't support group
1272 * addresses, so we just reject the request.
1275 * spp pointer to SPANS protocol instance block
1276 * msg pointer to the leave request message
1283 spans_leave_req(spp, msg)
1290 * Get memory for a SPANS_LEAVE_CNF message.
1292 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1293 if (rsp_msg == NULL)
1297 * Fill out the response.
1299 rsp_msg->sm_vers = SPANS_VERS_1_0;
1300 rsp_msg->sm_type = SPANS_LEAVE_CNF;
1301 spans_addr_copy(&msg->sm_leave_req.lvreq_addr,
1302 &rsp_msg->sm_leave_cnf.lvcnf_addr);
1303 rsp_msg->sm_leave_cnf.lvcnf_result = SPANS_FAIL;
1306 * Send the response and free the message.
1308 (void) spans_send_msg(spp, rsp_msg);
1314 * Process a VCI range indication
1316 * Called when a VCI range indication is received. Adjust the VCI
1317 * bounds if they have changed.
1320 * spp pointer to SPANS protocol instance block
1321 * msg pointer to the VCI range indication message
1328 spans_vcir_ind(spp, msg)
1333 * Adjust the limits if they have changed
1335 if (msg->sm_vcir_ind.vrind_min != spp->sp_min_vci) {
1337 (msg->sm_vcir_ind.vrind_min <
1340 msg->sm_vcir_ind.vrind_min);
1342 if (msg->sm_vcir_ind.vrind_max != spp->sp_max_vci) {
1344 (msg->sm_vcir_ind.vrind_max >
1347 msg->sm_vcir_ind.vrind_max);
1353 * Process a query request
1355 * Called when a query request is received. Respond with the
1356 * appropriate query response.
1359 * spp pointer to SPANS protocol instance block
1360 * msg pointer to the VCI range indication message
1367 spans_query_req(spp, msg)
1371 struct spans_vccb *svp = NULL;
1374 ATM_DEBUG1("spans_query_req: msg=%p\n", msg);
1377 * Ignore an end-to-end query
1379 if (msg->sm_query_req.qyreq_type == SPANS_QUERY_END_TO_END) {
1384 * Get memory for a SPANS_QUERY_RSP message.
1386 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1387 if (rsp_msg == NULL)
1391 * Fill out the response.
1393 rsp_msg->sm_vers = SPANS_VERS_1_0;
1394 rsp_msg->sm_type = SPANS_QUERY_RSP;
1395 rsp_msg->sm_query_rsp.qyrsp_conn = msg->sm_query_req.qyreq_conn;
1396 rsp_msg->sm_query_rsp.qyrsp_type = msg->sm_query_req.qyreq_type;
1397 rsp_msg->sm_query_rsp.qyrsp_data = 0;
1400 * Get the state of the requested connection
1402 svp = spans_find_conn(spp, &msg->sm_query_req.qyreq_conn);
1404 switch(svp->sv_sstate) {
1407 rsp_msg->sm_query_rsp.qyrsp_state =
1411 rsp_msg->sm_query_rsp.qyrsp_state =
1414 case SPANS_VC_POPEN:
1415 case SPANS_VC_R_POPEN:
1416 rsp_msg->sm_query_rsp.qyrsp_state =
1417 SPANS_CONN_OPEN_PEND;
1419 case SPANS_VC_CLOSE:
1420 case SPANS_VC_ABORT:
1421 rsp_msg->sm_query_rsp.qyrsp_state =
1422 SPANS_CONN_CLOSE_PEND;
1424 case SPANS_VC_ACTIVE:
1425 case SPANS_VC_ACT_DOWN:
1427 * VCCB is for a PVC (shouldn't happen)
1434 * No VCCB found--connection doesn't exist
1436 rsp_msg->sm_query_rsp.qyrsp_state = SPANS_CONN_CLOSED;
1440 * Send the response and free the message.
1442 (void) spans_send_msg(spp, rsp_msg);
1448 * Process a SPANS signalling message
1450 * Called when a SPANS message is received. The message is converted
1451 * into internal format with XDR and decoded by calling the appropriate
1452 * mesage handling routine. Unrecognized and unexpected messages are
1456 * spp pointer to SPANS protocol instance block
1457 * m pointer to a buffer chain containing the SPANS message
1464 spans_rcv_msg(spp, m)
1472 * Get storage for the message
1474 msg = (spans_msg *)atm_allocate(&spans_msgpool);
1480 * Convert the message from network order to internal format
1482 xdrmbuf_init(&xdrs, m, XDR_DECODE);
1483 if (!xdr_spans_msg(&xdrs, msg)) {
1484 log(LOG_ERR, "spans_rcv_msg: XDR decode failed\n");
1485 spans_dump_buffer(m);
1491 * Debug--print some information about the message
1493 if (msg->sm_type != SPANS_STAT_REQ &&
1494 msg->sm_type != SPANS_STAT_IND &&
1495 msg->sm_type != SPANS_STAT_RSP) {
1496 printf("spans_rcv_msg: got ");
1497 spans_print_msg(msg);
1502 * Verify the message sm_vers
1504 if (msg->sm_vers != SPANS_VERS_1_0) {
1505 log(LOG_ERR, "spans: invalid message version 0x%x\n",
1510 * Ignore the message if SPANS isn't up yet
1512 if (spp->sp_state != SPANS_ACTIVE &&
1513 (spp->sp_state != SPANS_PROBE ||
1514 (msg->sm_type != SPANS_STAT_REQ &&
1515 msg->sm_type != SPANS_STAT_RSP &&
1516 msg->sm_type != SPANS_STAT_IND))) {
1521 * Process the message based on its type
1523 switch(msg->sm_type) {
1524 case SPANS_STAT_REQ:
1525 spans_status_ind(spp, msg);
1527 case SPANS_STAT_IND:
1528 spans_status_ind(spp, msg);
1530 case SPANS_STAT_RSP:
1531 spans_status_rsp(spp, msg);
1533 case SPANS_OPEN_REQ:
1534 spans_open_req(spp, msg);
1536 case SPANS_OPEN_IND:
1537 spans_open_req(spp, msg);
1539 case SPANS_OPEN_RSP:
1540 spans_open_rsp(spp, msg);
1542 case SPANS_OPEN_CNF:
1543 spans_open_rsp(spp, msg);
1545 case SPANS_CLOSE_REQ:
1546 spans_close_req(spp, msg);
1548 case SPANS_CLOSE_IND:
1549 spans_close_req(spp, msg);
1551 case SPANS_CLOSE_RSP:
1552 spans_close_rsp(spp, msg);
1554 case SPANS_CLOSE_CNF:
1555 spans_close_rsp(spp, msg);
1557 case SPANS_RCLOSE_REQ:
1558 spans_close_req(spp, msg);
1560 case SPANS_RCLOSE_IND:
1561 spans_close_req(spp, msg);
1563 case SPANS_RCLOSE_RSP:
1564 spans_close_rsp(spp, msg);
1566 case SPANS_RCLOSE_CNF:
1567 spans_close_rsp(spp, msg);
1569 case SPANS_MULTI_REQ:
1570 spans_multi_req(spp, msg);
1572 case SPANS_MULTI_IND:
1573 spans_multi_req(spp, msg);
1575 case SPANS_MULTI_RSP:
1577 "spans: unexpected message (multi_rsp)\n");
1579 case SPANS_MULTI_CNF:
1581 "spans: unexpected message (multi_conf)\n");
1584 spans_add_req(spp, msg);
1587 spans_add_req(spp, msg);
1591 "spans: unexpected message (add_rsp)\n");
1594 log(LOG_ERR, "spans: unexpected message (add_conf)\n");
1596 case SPANS_JOIN_REQ:
1597 spans_join_req(spp, msg);
1599 case SPANS_JOIN_CNF:
1600 log(LOG_ERR, "spans: unexpected message (join_conf)\n");
1602 case SPANS_LEAVE_REQ:
1603 spans_leave_req(spp, msg);
1605 case SPANS_LEAVE_CNF:
1607 "spans: unexpected message (leave_conf)\n");
1609 case SPANS_VCIR_IND:
1610 spans_vcir_ind(spp, msg);
1612 case SPANS_QUERY_REQ:
1613 spans_query_req(spp, msg);
1615 case SPANS_QUERY_RSP:
1617 "spans: unexpected message (query_rsp)\n");
1620 log(LOG_ERR, "spans: unknown SPANS message type %d\n",
1626 * Free the incoming message (both buffer and internal format) if