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.7 2006/12/22 23:57:54 swildner Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS signalling message processing.
38 #include <netproto/atm/kern_include.h>
40 #include "spans_xdr.h"
41 #include "spans_var.h"
46 void xdrmbuf_init (XDR *, KBuffer *, enum xdr_op);
51 static void spans_host_link (struct spans *, long);
52 static void spans_status_ind (struct spans *, spans_msg *);
53 static void spans_status_rsp (struct spans *, spans_msg *);
54 static void spans_open_req (struct spans *, spans_msg *);
55 static void spans_open_rsp (struct spans *, spans_msg *);
56 static void spans_close_req (struct spans *, spans_msg *);
57 static void spans_close_rsp (struct spans *, spans_msg *);
58 static void spans_multi_req (struct spans *, spans_msg *);
59 static void spans_add_req (struct spans *, spans_msg *);
60 static void spans_join_req (struct spans *, spans_msg *);
61 static void spans_leave_req (struct spans *, spans_msg *);
62 static void spans_vcir_ind (struct spans *, spans_msg *);
63 static void spans_query_req (struct spans *, spans_msg *);
67 * Called to set status when a status message comes in from a host
68 * connected back-to-back with us. Check the epoch and, if it has
69 * changed, set the appropriate state and save updated state
73 * spp pointer to SPANS protocol instance block
74 * host_epoch epoch of host at far end of link
78 * errno error encountered
82 spans_host_link(struct spans *spp, long host_epoch)
84 struct atm_pif *pip = spp->sp_pif;
87 * There's a host at the other end of the link. If its
88 * epoch has changed, clean up our state and save the
91 if (spp->sp_s_epoch != host_epoch) {
92 spp->sp_s_epoch = host_epoch;
93 spans_switch_reset(spp, SPANS_UNI_UP);
94 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
95 spp->sp_addr.address_length = sizeof(spans_addr);
96 KM_COPY(&pip->pif_macaddr.ma_data[2],
97 &spp->sp_addr.address[4],
100 "spans: using SPANS address of %s on interface %s%d\n",
101 spans_addr_print((spans_addr *)spp->sp_addr.address),
108 * Send a SPANS signalling message
110 * Called to send a SPANS message. This routine gets a buffer, performs
111 * XDR processing, and hands the message to the AAL for transmission.
114 * spp pointer to SPANS protocol instance block
115 * msg pointer to status message
119 * errno error encountered
123 spans_send_msg(struct spans *spp, spans_msg *msg)
130 ATM_DEBUG2("spans_send_msg: msg=%p, type=%d\n", msg,
132 if (msg->sm_type != SPANS_STAT_REQ &&
133 msg->sm_type != SPANS_STAT_IND &&
134 msg->sm_type != SPANS_STAT_RSP) {
135 kprintf("spans_send_msg: sending ");
136 spans_print_msg(msg);
141 * If the signalling channel has been closed, don't do anything
144 return(ECONNABORTED);
149 KB_ALLOCPKT(m, sizeof(spans_msg), KB_F_NOWAIT, KB_T_DATA);
151 /* No buffer available */
156 * Convert message to network order
158 KB_LEN(m) = KB_BFRLEN(m);
159 xdrmbuf_init(&xdrs, m, XDR_ENCODE);
160 if (!xdr_spans_msg(&xdrs, msg)) {
161 log(LOG_ERR, "spans_send_msg: XDR encode failed\n");
162 KB_LEN(m) = XDR_GETPOS(&xdrs);
163 spans_dump_buffer(m);
167 KB_LEN(m) = XDR_GETPOS(&xdrs);
172 err = atm_cm_cpcs_data(spp->sp_conn, m);
181 * Send an open request
183 * Build and send an open request.
186 * spp pointer to SPANS protocol instance block
187 * svp pointer to VCCB for which the request is being sent
194 spans_send_open_req(struct spans *spp, struct spans_vccb *svp)
199 ATM_DEBUG1("spans_send_open_req: svp=%p\n", svp);
202 * Get memory for a request message
204 req = (spans_msg *)atm_allocate(&spans_msgpool);
211 * Fill in the request
213 req->sm_vers = SPANS_VERS_1_0;
214 req->sm_type = SPANS_OPEN_REQ;
215 req->sm_open_req.opreq_conn = svp->sv_conn;
216 req->sm_open_req.opreq_aal = svp->sv_spans_aal;
217 req->sm_open_req.opreq_desrsrc = svp->sv_spans_qos;
218 req->sm_open_req.opreq_minrsrc.rsc_peak = 0;
219 req->sm_open_req.opreq_minrsrc.rsc_mean = 0;
220 req->sm_open_req.opreq_minrsrc.rsc_burst = 0;
221 req->sm_open_req.opreq_vpvc.vpf_valid = FALSE;
226 err = spans_send_msg(spp, req);
235 * Send an open response
237 * Build and send a response to an open request or open indication.
240 * spp pointer to SPANS protocol instance block
241 * svp pointer to VCCB for which the response is being sent
242 * result result code to include in the response
249 spans_send_open_rsp(struct spans *spp, struct spans_vccb *svp,
255 ATM_DEBUG2("spans_send_open_rsp: svp=%p, result=%d\n", svp,
259 * Get memory for a response message
261 rsp = (spans_msg *)atm_allocate(&spans_msgpool);
266 * Fill in the response
268 rsp->sm_vers = SPANS_VERS_1_0;
269 rsp->sm_type = SPANS_OPEN_RSP;
270 rsp->sm_open_rsp.oprsp_conn = svp->sv_conn;
271 rsp->sm_open_rsp.oprsp_result = result;
272 rsp->sm_open_rsp.oprsp_rsrc = svp->sv_spans_qos;
273 rsp->sm_open_rsp.oprsp_vpvc =
274 SPANS_PACK_VPIVCI(svp->sv_vpi, svp->sv_vci);
279 rc = spans_send_msg(spp, rsp);
287 * Send a close request
289 * Called to send a close request.
292 * spp pointer to SPANS protocol instance block
293 * svp pointer to VCCB for which the close is being sent
300 spans_send_close_req(struct spans *spp, struct spans_vccb *svp)
305 ATM_DEBUG1("spans_send_close_req: svp=%p\n", svp);
308 * Get memory for a close request
310 req = (spans_msg *)atm_allocate(&spans_msgpool);
317 * Fill in the request
319 req->sm_vers = SPANS_VERS_1_0;
320 if (svp->sv_type & VCC_OUT) {
321 req->sm_type = SPANS_CLOSE_REQ;
322 } else if (svp->sv_type & VCC_IN) {
323 req->sm_type = SPANS_RCLOSE_REQ;
327 "spans_send_close_req: invalid VCCB type 0x%x\n",
331 req->sm_close_req.clreq_conn = svp->sv_conn;
334 * Send the close request
336 err = spans_send_msg(spp, req);
348 * Process a status indication or status request
350 * Called when a status indication or status request is received.
351 * Processing will be based on the current SPANS state.
354 * spp pointer to SPANS protocol instance block
355 * msg pointer to the status message
362 spans_status_ind(struct spans *spp, spans_msg *msg)
365 struct atm_pif *pip = spp->sp_pif;
368 * Reset the probe count.
370 spp->sp_probe_ct = 0;
372 switch (spp->sp_state) {
375 * Interface just came up, update signalling state
377 spp->sp_state = SPANS_ACTIVE;
384 log(LOG_ERR, "spans: received status msg in state %d\n",
389 * Process the message
391 switch (msg->sm_type) {
395 * Handle a request from a host at the other end of
398 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
404 * There's a switch at the other end of the link. If
405 * its epoch has changed, reset the SPANS state and save
406 * the new information.
408 if (spp->sp_s_epoch !=
409 msg->sm_stat_ind.stind_sw_epoch) {
410 spans_switch_reset(spp, SPANS_UNI_UP);
412 msg->sm_stat_ind.stind_sw_epoch;
413 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
414 spp->sp_addr.address_length =
416 spans_addr_copy(&msg->sm_stat_ind.stind_es_addr,
417 spp->sp_addr.address);
419 "spans: received SPANS address %s from switch for interface %s%d\n",
420 spans_addr_print((spans_addr *)spp->sp_addr.address),
427 ATM_DEBUG1("spans_status_ind: Invalid message type %d\n",
433 * Respond to the status request or indication with a
436 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
439 rsp_msg->sm_vers = SPANS_VERS_1_0;
440 rsp_msg->sm_type = SPANS_STAT_RSP;
441 rsp_msg->sm_stat_rsp.strsp_es_epoch = spp->sp_h_epoch;
442 spans_addr_copy(spp->sp_addr.address,
443 &rsp_msg->sm_stat_rsp.strsp_es_addr);
444 spans_send_msg(spp, rsp_msg);
451 * Process a status response
453 * Called when a status response is received.
454 * Processing will be based on the current SPANS state.
457 * spp pointer to SPANS protocol instance block
458 * msg pointer to the status response message
465 spans_status_rsp(struct spans *spp, spans_msg *msg)
469 * Reset the probe count.
471 spp->sp_probe_ct = 0;
473 switch (spp->sp_state) {
476 * Interface just came up, update signalling state
478 spp->sp_state = SPANS_ACTIVE;
485 log(LOG_ERR, "spans: received status msg in state %d\n",
490 * Process the message
492 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
497 * Process an open indication or open request
499 * Called when an open indication or open request is received.
500 * Processing will be based on the state of the requested connection.
503 * spp pointer to SPANS protocol instance block
504 * msg pointer to the open message
511 spans_open_req(struct spans *spp, spans_msg *msg)
513 spans_result result = SPANS_OK;
515 struct spans_vccb *svp = NULL;
518 int err = 0, vpi, vci;
520 Atm_attributes call_attrs;
522 ATM_DEBUG2("spans_open_req: spp=%p, msg=%p\n", spp, msg);
525 * See if the connection is new
527 if ((svp = spans_find_conn(spp, &msg->sm_open_req.opreq_conn)) != NULL) {
529 * We already have a VCCB that matches the connection in
532 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
533 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
534 if (msg->sm_open_req.opreq_aal == svp->sv_spans_aal &&
535 (!msg->sm_open_req.opreq_vpvc.vpf_valid ||
536 (vpi == svp->sv_vpi &&
537 vci == svp->sv_vci))) {
539 * VCCB already exists, process depending on
542 switch (svp->sv_sstate) {
543 case SPANS_VC_R_POPEN:
544 /* I'm still thinking about it */
547 /* Retransmit the open_rsp */
552 ATM_DEBUG0("spans_open_req: bad VCCB state\n");
558 * VCCB is for same connection, but other
559 * parameters don't match
561 ATM_DEBUG0("spans_open_req: VCCB confusion\n");
569 * Verify that the request is for our ATM addres
571 if (spans_addr_cmp(spp->sp_addr.address,
572 &msg->sm_open_req.opreq_conn.con_dst)) {
573 ATM_DEBUG0("spans_open_req: bad destination\n");
574 result = SPANS_BADDEST;
579 * See if we recognize the specified AAL
581 if (!spans_get_local_aal(msg->sm_open_req.opreq_aal, &aal)) {
582 ATM_DEBUG0("spans_open_req: bad AAL\n");
588 * Should verify that we can handle requested connection QOS
592 * Select a VPI/VCI for the new connection
594 if (msg->sm_open_req.opreq_vpvc.vpf_valid) {
596 * Requestor asked for a certain VPI/VCI. Make sure we
597 * aren't already using the pair that was asked for.
599 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
600 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
601 if (spans_find_vpvc(spp, vci, vpi, VCC_IN)) {
602 ATM_DEBUG0("spans_open_req: VPI, VCI busy\n");
603 result = SPANS_NOVPVC;
606 vpvc = msg->sm_open_req.opreq_vpvc.vpf_vpvc;
609 * Allocate a VPI/VCI for this end of the VCC
611 vpvc = spans_alloc_vpvc(spp);
613 ATM_DEBUG0("spans_open_req: no VPI, VCI available\n");
614 result = SPANS_NOVPVC;
620 * Get a new VCCB for the connection
622 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
624 ATM_DEBUG0("spans_open_req: VCCB pool empty\n");
625 result = SPANS_NORSC;
630 * Find the physical interface structure
635 * Fill in the VCCB fields that we can at this point
637 svp->sv_type = VCC_SVC | VCC_IN;
638 svp->sv_proto = ATM_SIG_SPANS;
639 svp->sv_sstate = SPANS_VC_R_POPEN;
640 svp->sv_ustate = VCCU_POPEN;
642 svp->sv_nif = pip->pif_nif;
643 svp->sv_conn = msg->sm_open_req.opreq_conn;
644 svp->sv_spans_qos = msg->sm_open_req.opreq_desrsrc;
645 svp->sv_spans_aal = msg->sm_open_req.opreq_aal;
646 svp->sv_tstamp = time_second;
648 svp->sv_vpi = SPANS_EXTRACT_VPI(vpvc);
649 svp->sv_vci = SPANS_EXTRACT_VCI(vpvc);
652 * Put the VCCB on the SPANS queue
654 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
657 * Set up the ATM attributes block
659 KM_ZERO(&call_attrs, sizeof(call_attrs));
660 call_attrs.nif = svp->sv_nif;
661 call_attrs.api = CMAPI_CPCS;
663 call_attrs.aal.tag = T_ATM_PRESENT;
664 call_attrs.aal.type = aal;
667 call_attrs.aal.v.aal4.forward_max_SDU_size =
669 call_attrs.aal.v.aal4.backward_max_SDU_size =
671 call_attrs.aal.v.aal4.SSCS_type =
673 call_attrs.aal.v.aal4.mid_low = 0;
674 call_attrs.aal.v.aal4.mid_high = 1023;
677 call_attrs.aal.v.aal5.forward_max_SDU_size =
679 call_attrs.aal.v.aal5.backward_max_SDU_size =
681 call_attrs.aal.v.aal5.SSCS_type =
686 call_attrs.traffic.tag = T_ATM_PRESENT;
687 call_attrs.traffic.v.forward.PCR_high_priority = T_ATM_ABSENT;
688 call_attrs.traffic.v.forward.PCR_all_traffic =
689 msg->sm_open_req.opreq_desrsrc.rsc_peak *
691 call_attrs.traffic.v.forward.SCR_high_priority = T_ATM_ABSENT;
692 call_attrs.traffic.v.forward.SCR_all_traffic = T_ATM_ABSENT;
693 call_attrs.traffic.v.forward.MBS_high_priority = T_ATM_ABSENT;
694 call_attrs.traffic.v.forward.MBS_all_traffic = T_ATM_ABSENT;
695 call_attrs.traffic.v.forward.tagging = T_NO;
696 call_attrs.traffic.v.backward.PCR_high_priority = T_ATM_ABSENT;
697 call_attrs.traffic.v.backward.PCR_all_traffic =
698 call_attrs.traffic.v.forward.PCR_all_traffic;
699 call_attrs.traffic.v.backward.SCR_high_priority = T_ATM_ABSENT;
700 call_attrs.traffic.v.backward.SCR_all_traffic = T_ATM_ABSENT;
701 call_attrs.traffic.v.backward.MBS_high_priority = T_ATM_ABSENT;
702 call_attrs.traffic.v.backward.MBS_all_traffic = T_ATM_ABSENT;
703 call_attrs.traffic.v.backward.tagging = T_NO;
704 call_attrs.traffic.v.best_effort = T_YES;
706 call_attrs.bearer.tag = T_ATM_PRESENT;
707 call_attrs.bearer.v.bearer_class = T_ATM_CLASS_X;
708 call_attrs.bearer.v.traffic_type = T_ATM_NULL;
709 call_attrs.bearer.v.timing_requirements = T_ATM_NULL;
710 call_attrs.bearer.v.clipping_susceptibility = T_NO;
711 call_attrs.bearer.v.connection_configuration = T_ATM_1_TO_1;
714 call_attrs.bhli.tag = T_ATM_ABSENT;
715 call_attrs.blli.tag_l2 = T_ATM_ABSENT;
716 call_attrs.blli.tag_l3 = T_ATM_ABSENT;
717 call_attrs.llc.tag = T_ATM_ABSENT;
719 call_attrs.called.tag = T_ATM_PRESENT;
720 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_dst,
721 call_attrs.called.addr.address);
722 call_attrs.called.addr.address_format = T_ATM_SPANS_ADDR;
723 call_attrs.called.addr.address_length = sizeof(spans_addr);
724 call_attrs.called.subaddr.address_format = T_ATM_ABSENT;
725 call_attrs.called.subaddr.address_length = 0;
727 call_attrs.calling.tag = T_ATM_PRESENT;
728 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_src,
729 call_attrs.calling.addr.address);
730 call_attrs.calling.addr.address_format = T_ATM_SPANS_ADDR;
731 call_attrs.calling.addr.address_length = sizeof(spans_addr);
732 call_attrs.calling.subaddr.address_format = T_ATM_ABSENT;
733 call_attrs.calling.subaddr.address_length = 0;
735 call_attrs.qos.tag = T_ATM_PRESENT;
736 call_attrs.qos.v.coding_standard = T_ATM_NETWORK_CODING;
737 call_attrs.qos.v.forward.qos_class = T_ATM_QOS_CLASS_0;
738 call_attrs.qos.v.backward.qos_class = T_ATM_QOS_CLASS_0;
740 call_attrs.transit.tag = T_ATM_ABSENT;
741 call_attrs.cause.tag = T_ATM_ABSENT;
744 * Notify the connection manager that it has a new channel
746 err = atm_cm_incoming((struct vccb *)svp, &call_attrs);
748 ATM_DEBUG0("spans_open_req: atm_cm_incoming returned error\n");
754 * Wait for the connection recipient to issue an accept
760 * Clean up the VCCB and the atm_conn block if we got them
763 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
769 * Some problem was detected with the request. Send a SPANS
770 * message rejecting the connection.
772 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
777 * Fill out the response
779 rsp_msg->sm_vers = SPANS_VERS_1_0;
780 rsp_msg->sm_type = SPANS_OPEN_RSP;
781 rsp_msg->sm_open_rsp.oprsp_conn = msg->sm_open_req.opreq_conn;
782 rsp_msg->sm_open_rsp.oprsp_result = result;
783 rsp_msg->sm_open_rsp.oprsp_vpvc = 0;
786 * Send the Open Response
788 spans_send_msg(spp, rsp_msg);
794 * Process an open response or open confirmation
796 * Called when an open response or open confirmation is received.
797 * Processing will be based on the state of the requested connection and
798 * the status returned.
801 * spp pointer to SPANS protocol instance block
802 * msg pointer to the open response or confirmation message
809 spans_open_rsp(struct spans *spp, spans_msg *msg)
811 struct spans_vccb *svp;
813 ATM_DEBUG2("spans_open_rsp: spp=%p, msg=%p\n", spp, msg);
816 * Locate the VCCB for the connection
818 svp = spans_find_conn(spp, &msg->sm_open_rsp.oprsp_conn);
823 * Check the connection state
825 if ((svp->sv_sstate != SPANS_VC_POPEN &&
826 svp->sv_sstate != SPANS_VC_R_POPEN) ||
827 svp->sv_ustate != VCCU_POPEN) {
829 "spans_open_rsp: invalid VCCB state, sstate=%d, ustate=%d\n",
830 svp->sv_sstate, svp->sv_ustate);
835 * Cancel the retransmission timer
837 SPANS_VC_CANCEL((struct vccb *) svp);
842 switch (msg->sm_open_rsp.oprsp_result) {
846 * Save the assigned VPI and VCI
848 svp->sv_vpi = SPANS_EXTRACT_VPI(msg->sm_open_rsp.oprsp_vpvc);
849 svp->sv_vci = SPANS_EXTRACT_VCI(msg->sm_open_rsp.oprsp_vpvc);
852 * Update the VCC state and notify the VCC owner
854 svp->sv_sstate = SPANS_VC_OPEN;
855 svp->sv_ustate = VCCU_OPEN;
856 svp->sv_tstamp = time_second;
857 atm_cm_connected(svp->sv_connvc);
865 * Close out the VCCB and notify the user
867 svp->sv_sstate = SPANS_VC_FREE;
868 svp->sv_ustate = VCCU_CLOSED;
869 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
870 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
872 svp->sv_connvc->cvc_attr.cause.v.location =
874 svp->sv_connvc->cvc_attr.cause.v.cause_value =
875 T_ATM_CAUSE_CALL_REJECTED;
876 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
877 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
878 atm_cm_cleared(svp->sv_connvc);
882 log(LOG_ERR, "spans: unknown result %d in open rsp\n",
883 msg->sm_open_rsp.oprsp_result);
890 * Process a close request from the network
892 * Called when a close request, close indication, rclose request, or
893 * rclose indication is received. Processing will be based on the
894 * state of the connection.
897 * spp pointer to SPANS protocol instance block
898 * msg pointer to the close request message
905 spans_close_req(struct spans *spp, spans_msg *msg)
907 struct spans_vccb *svp;
913 ATM_DEBUG2("spans_close_req: spp=%p, msg=%p\n", spp, msg);
916 * Locate the VCCB for the connection
918 svp = spans_find_conn(spp, &msg->sm_close_req.clreq_conn);
920 result = SPANS_BADDEST;
925 * Check the connection type
927 if (!(svp->sv_type & VCC_SVC)) {
933 * Check the connection state
935 switch (svp->sv_sstate) {
937 case SPANS_VC_R_POPEN:
940 * VCC is open or opening--continue
947 * We're already closing--give a response, since this
948 * is probably a retransmission
958 * Cancel the retransmission timer
960 SPANS_VC_CANCEL((struct vccb *) svp);
963 * Close out the VCCB and notify the user
965 outstate = svp->sv_sstate;
966 svp->sv_ustate = VCCU_CLOSED;
967 svp->sv_sstate = SPANS_VC_FREE;
968 cvp = svp->sv_connvc;
970 case SPANS_VC_R_POPEN:
971 spans_free((struct vccb *)svp);
976 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
977 cvp->cvc_attr.cause.v.coding_standard =
979 cvp->cvc_attr.cause.v.location = T_ATM_LOC_USER;
980 cvp->cvc_attr.cause.v.cause_value =
981 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
982 KM_ZERO(cvp->cvc_attr.cause.v.diagnostics,
983 sizeof(cvp->cvc_attr.cause.v.diagnostics));
984 atm_cm_cleared(svp->sv_connvc);
992 * Respond to the SPANS_CLOSE_IND with a SPANS_CLOSE_RSP
994 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
997 rsp_msg->sm_vers = SPANS_VERS_1_0;
998 if (msg->sm_type == SPANS_RCLOSE_REQ ||
999 msg->sm_type == SPANS_RCLOSE_IND) {
1000 rsp_msg->sm_type = SPANS_RCLOSE_RSP;
1002 rsp_msg->sm_type = SPANS_CLOSE_RSP;
1004 rsp_msg->sm_close_rsp.clrsp_conn = msg->sm_close_req.clreq_conn;
1005 rsp_msg->sm_close_rsp.clrsp_result = result;
1006 spans_send_msg(spp, rsp_msg);
1012 * Process a close response or close confirmation
1014 * Called when an close response or close confirmation is received.
1015 * Processing will be based on the state of the requested connection and
1016 * the returned status.
1019 * spp pointer to SPANS protocol instance block
1020 * msg pointer to the close response or confirmation message
1027 spans_close_rsp(struct spans *spp, spans_msg *msg)
1029 struct spans_vccb *svp;
1031 ATM_DEBUG2("spans_close_rsp: spp=%p, msg=%p\n", spp, msg);
1034 * Locate the VCCB for the connection
1036 svp = spans_find_conn(spp, &msg->sm_close_rsp.clrsp_conn);
1042 * Check the VCCB state
1044 if (svp->sv_sstate != SPANS_VC_CLOSE) {
1049 * Cancel the retransmission timer
1051 SPANS_VC_CANCEL((struct vccb *) svp);
1054 * Check the response from the remote end
1056 switch (msg->sm_close_rsp.clrsp_result) {
1060 * Mark the VCCB as closed and notify the owner
1062 svp->sv_sstate = SPANS_VC_FREE;
1063 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1064 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1066 svp->sv_connvc->cvc_attr.cause.v.location =
1068 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1069 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1070 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1071 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1072 atm_cm_cleared(svp->sv_connvc);
1080 * Mark the VCCB as closed and notify the owner
1082 svp->sv_sstate = SPANS_VC_FREE;
1083 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1084 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1086 svp->sv_connvc->cvc_attr.cause.v.location =
1088 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1089 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
1090 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1091 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1092 atm_cm_cleared(svp->sv_connvc);
1096 log(LOG_ERR, "spans: unknown result %d in close rsp\n",
1097 msg->sm_close_rsp.clrsp_result);
1104 * Process a multi request or multi indication
1106 * Called when a multi response or multi confirmation is received. We
1107 * don't support multicast channels, so we just reject the request.
1110 * spp pointer to SPANS protocol instance block
1111 * msg pointer to the multi request or indication message
1118 spans_multi_req(struct spans *spp, spans_msg *msg)
1123 * Get memory for a SPANS_MULTI_RSP message.
1125 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1126 if (rsp_msg == NULL)
1130 * Fill out the response.
1132 rsp_msg->sm_vers = SPANS_VERS_1_0;
1133 rsp_msg->sm_type = SPANS_MULTI_RSP;
1134 rsp_msg->sm_multi_rsp.mursp_conn = msg->sm_multi_req.mureq_conn;
1135 rsp_msg->sm_multi_rsp.mursp_result = SPANS_FAIL;
1136 rsp_msg->sm_multi_rsp.mursp_rsrc = msg->sm_multi_req.mureq_desrsrc;
1137 rsp_msg->sm_multi_rsp.mursp_vpvc = 0;
1140 * Send the response and free the message.
1142 spans_send_msg(spp, rsp_msg);
1148 * Process an add request or add indication
1150 * Called when an add response or add confirmation is received. We
1151 * don't support multicast channels, so we just reject the request.
1154 * spp pointer to SPANS protocol instance block
1155 * msg pointer to the add request or indication message
1162 spans_add_req(struct spans *spp, spans_msg *msg)
1167 * Get memory for a SPANS_ADD_RSP message.
1169 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1170 if (rsp_msg == NULL)
1174 * Fill out the response.
1176 rsp_msg->sm_vers = SPANS_VERS_1_0;
1177 rsp_msg->sm_type = SPANS_ADD_RSP;
1178 rsp_msg->sm_add_rsp.adrsp_conn = msg->sm_add_req.adreq_desconn;
1179 rsp_msg->sm_add_rsp.adrsp_result = SPANS_FAIL;
1180 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_peak = 0;
1181 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_mean = 0;
1182 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_burst = 0;
1185 * Send the response and free the message.
1187 spans_send_msg(spp, rsp_msg);
1193 * Process a join request
1195 * Called when an join request is received. We don't support group
1196 * addresses, so we just reject the request.
1199 * spp pointer to SPANS protocol instance block
1200 * msg pointer to the join request message
1207 spans_join_req(struct spans *spp, spans_msg *msg)
1212 * Get memory for a SPANS_JOIN_CNF message.
1214 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1215 if (rsp_msg == NULL)
1219 * Fill out the response.
1221 rsp_msg->sm_vers = SPANS_VERS_1_0;
1222 rsp_msg->sm_type = SPANS_JOIN_CNF;
1223 spans_addr_copy(&msg->sm_join_req.jnreq_addr,
1224 &rsp_msg->sm_join_cnf.jncnf_addr);
1225 rsp_msg->sm_join_cnf.jncnf_result = SPANS_FAIL;
1228 * Send the response and free the message.
1230 spans_send_msg(spp, rsp_msg);
1236 * Process a leave request
1238 * Called when an leave request is received. We don't support group
1239 * addresses, so we just reject the request.
1242 * spp pointer to SPANS protocol instance block
1243 * msg pointer to the leave request message
1250 spans_leave_req(struct spans *spp, spans_msg *msg)
1255 * Get memory for a SPANS_LEAVE_CNF message.
1257 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1258 if (rsp_msg == NULL)
1262 * Fill out the response.
1264 rsp_msg->sm_vers = SPANS_VERS_1_0;
1265 rsp_msg->sm_type = SPANS_LEAVE_CNF;
1266 spans_addr_copy(&msg->sm_leave_req.lvreq_addr,
1267 &rsp_msg->sm_leave_cnf.lvcnf_addr);
1268 rsp_msg->sm_leave_cnf.lvcnf_result = SPANS_FAIL;
1271 * Send the response and free the message.
1273 spans_send_msg(spp, rsp_msg);
1279 * Process a VCI range indication
1281 * Called when a VCI range indication is received. Adjust the VCI
1282 * bounds if they have changed.
1285 * spp pointer to SPANS protocol instance block
1286 * msg pointer to the VCI range indication message
1293 spans_vcir_ind(struct spans *spp, spans_msg *msg)
1296 * Adjust the limits if they have changed
1298 if (msg->sm_vcir_ind.vrind_min != spp->sp_min_vci) {
1300 (msg->sm_vcir_ind.vrind_min <
1303 msg->sm_vcir_ind.vrind_min);
1305 if (msg->sm_vcir_ind.vrind_max != spp->sp_max_vci) {
1307 (msg->sm_vcir_ind.vrind_max >
1310 msg->sm_vcir_ind.vrind_max);
1316 * Process a query request
1318 * Called when a query request is received. Respond with the
1319 * appropriate query response.
1322 * spp pointer to SPANS protocol instance block
1323 * msg pointer to the VCI range indication message
1330 spans_query_req(struct spans *spp, spans_msg *msg)
1332 struct spans_vccb *svp = NULL;
1335 ATM_DEBUG1("spans_query_req: msg=%p\n", msg);
1338 * Ignore an end-to-end query
1340 if (msg->sm_query_req.qyreq_type == SPANS_QUERY_END_TO_END) {
1345 * Get memory for a SPANS_QUERY_RSP message.
1347 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1348 if (rsp_msg == NULL)
1352 * Fill out the response.
1354 rsp_msg->sm_vers = SPANS_VERS_1_0;
1355 rsp_msg->sm_type = SPANS_QUERY_RSP;
1356 rsp_msg->sm_query_rsp.qyrsp_conn = msg->sm_query_req.qyreq_conn;
1357 rsp_msg->sm_query_rsp.qyrsp_type = msg->sm_query_req.qyreq_type;
1358 rsp_msg->sm_query_rsp.qyrsp_data = 0;
1361 * Get the state of the requested connection
1363 svp = spans_find_conn(spp, &msg->sm_query_req.qyreq_conn);
1365 switch(svp->sv_sstate) {
1368 rsp_msg->sm_query_rsp.qyrsp_state =
1372 rsp_msg->sm_query_rsp.qyrsp_state =
1375 case SPANS_VC_POPEN:
1376 case SPANS_VC_R_POPEN:
1377 rsp_msg->sm_query_rsp.qyrsp_state =
1378 SPANS_CONN_OPEN_PEND;
1380 case SPANS_VC_CLOSE:
1381 case SPANS_VC_ABORT:
1382 rsp_msg->sm_query_rsp.qyrsp_state =
1383 SPANS_CONN_CLOSE_PEND;
1385 case SPANS_VC_ACTIVE:
1386 case SPANS_VC_ACT_DOWN:
1388 * VCCB is for a PVC (shouldn't happen)
1395 * No VCCB found--connection doesn't exist
1397 rsp_msg->sm_query_rsp.qyrsp_state = SPANS_CONN_CLOSED;
1401 * Send the response and free the message.
1403 spans_send_msg(spp, rsp_msg);
1409 * Process a SPANS signalling message
1411 * Called when a SPANS message is received. The message is converted
1412 * into internal format with XDR and decoded by calling the appropriate
1413 * mesage handling routine. Unrecognized and unexpected messages are
1417 * spp pointer to SPANS protocol instance block
1418 * m pointer to a buffer chain containing the SPANS message
1425 spans_rcv_msg(struct spans *spp, KBuffer *m)
1431 * Get storage for the message
1433 msg = (spans_msg *)atm_allocate(&spans_msgpool);
1439 * Convert the message from network order to internal format
1441 xdrmbuf_init(&xdrs, m, XDR_DECODE);
1442 if (!xdr_spans_msg(&xdrs, msg)) {
1443 log(LOG_ERR, "spans_rcv_msg: XDR decode failed\n");
1444 spans_dump_buffer(m);
1450 * Debug--print some information about the message
1452 if (msg->sm_type != SPANS_STAT_REQ &&
1453 msg->sm_type != SPANS_STAT_IND &&
1454 msg->sm_type != SPANS_STAT_RSP) {
1455 kprintf("spans_rcv_msg: got ");
1456 spans_print_msg(msg);
1461 * Verify the message sm_vers
1463 if (msg->sm_vers != SPANS_VERS_1_0) {
1464 log(LOG_ERR, "spans: invalid message version 0x%x\n",
1469 * Ignore the message if SPANS isn't up yet
1471 if (spp->sp_state != SPANS_ACTIVE &&
1472 (spp->sp_state != SPANS_PROBE ||
1473 (msg->sm_type != SPANS_STAT_REQ &&
1474 msg->sm_type != SPANS_STAT_RSP &&
1475 msg->sm_type != SPANS_STAT_IND))) {
1480 * Process the message based on its type
1482 switch(msg->sm_type) {
1483 case SPANS_STAT_REQ:
1484 spans_status_ind(spp, msg);
1486 case SPANS_STAT_IND:
1487 spans_status_ind(spp, msg);
1489 case SPANS_STAT_RSP:
1490 spans_status_rsp(spp, msg);
1492 case SPANS_OPEN_REQ:
1493 spans_open_req(spp, msg);
1495 case SPANS_OPEN_IND:
1496 spans_open_req(spp, msg);
1498 case SPANS_OPEN_RSP:
1499 spans_open_rsp(spp, msg);
1501 case SPANS_OPEN_CNF:
1502 spans_open_rsp(spp, msg);
1504 case SPANS_CLOSE_REQ:
1505 spans_close_req(spp, msg);
1507 case SPANS_CLOSE_IND:
1508 spans_close_req(spp, msg);
1510 case SPANS_CLOSE_RSP:
1511 spans_close_rsp(spp, msg);
1513 case SPANS_CLOSE_CNF:
1514 spans_close_rsp(spp, msg);
1516 case SPANS_RCLOSE_REQ:
1517 spans_close_req(spp, msg);
1519 case SPANS_RCLOSE_IND:
1520 spans_close_req(spp, msg);
1522 case SPANS_RCLOSE_RSP:
1523 spans_close_rsp(spp, msg);
1525 case SPANS_RCLOSE_CNF:
1526 spans_close_rsp(spp, msg);
1528 case SPANS_MULTI_REQ:
1529 spans_multi_req(spp, msg);
1531 case SPANS_MULTI_IND:
1532 spans_multi_req(spp, msg);
1534 case SPANS_MULTI_RSP:
1536 "spans: unexpected message (multi_rsp)\n");
1538 case SPANS_MULTI_CNF:
1540 "spans: unexpected message (multi_conf)\n");
1543 spans_add_req(spp, msg);
1546 spans_add_req(spp, msg);
1550 "spans: unexpected message (add_rsp)\n");
1553 log(LOG_ERR, "spans: unexpected message (add_conf)\n");
1555 case SPANS_JOIN_REQ:
1556 spans_join_req(spp, msg);
1558 case SPANS_JOIN_CNF:
1559 log(LOG_ERR, "spans: unexpected message (join_conf)\n");
1561 case SPANS_LEAVE_REQ:
1562 spans_leave_req(spp, msg);
1564 case SPANS_LEAVE_CNF:
1566 "spans: unexpected message (leave_conf)\n");
1568 case SPANS_VCIR_IND:
1569 spans_vcir_ind(spp, msg);
1571 case SPANS_QUERY_REQ:
1572 spans_query_req(spp, msg);
1574 case SPANS_QUERY_RSP:
1576 "spans: unexpected message (query_rsp)\n");
1579 log(LOG_ERR, "spans: unknown SPANS message type %d\n",
1585 * Free the incoming message (both buffer and internal format) if