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>
41 #include "spans_xdr.h"
42 #include "spans_var.h"
47 void xdrmbuf_init (XDR *, KBuffer *, enum xdr_op);
52 static void spans_host_link (struct spans *, long);
53 static void spans_status_ind (struct spans *, spans_msg *);
54 static void spans_status_rsp (struct spans *, spans_msg *);
55 static void spans_open_req (struct spans *, spans_msg *);
56 static void spans_open_rsp (struct spans *, spans_msg *);
57 static void spans_close_req (struct spans *, spans_msg *);
58 static void spans_close_rsp (struct spans *, spans_msg *);
59 static void spans_multi_req (struct spans *, spans_msg *);
60 static void spans_add_req (struct spans *, spans_msg *);
61 static void spans_join_req (struct spans *, spans_msg *);
62 static void spans_leave_req (struct spans *, spans_msg *);
63 static void spans_vcir_ind (struct spans *, spans_msg *);
64 static void spans_query_req (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(struct spans *spp, long host_epoch)
85 struct atm_pif *pip = spp->sp_pif;
88 * There's a host at the other end of the link. If its
89 * epoch has changed, clean up our state and save the
92 if (spp->sp_s_epoch != host_epoch) {
93 spp->sp_s_epoch = host_epoch;
94 spans_switch_reset(spp, SPANS_UNI_UP);
95 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
96 spp->sp_addr.address_length = sizeof(spans_addr);
97 KM_COPY(&pip->pif_macaddr.ma_data[2],
98 &spp->sp_addr.address[4],
101 "spans: using SPANS address of %s on interface %s%d\n",
102 spans_addr_print((spans_addr *)spp->sp_addr.address),
109 * Send a SPANS signalling message
111 * Called to send a SPANS message. This routine gets a buffer, performs
112 * XDR processing, and hands the message to the AAL for transmission.
115 * spp pointer to SPANS protocol instance block
116 * msg pointer to status message
120 * errno error encountered
124 spans_send_msg(struct spans *spp, spans_msg *msg)
131 ATM_DEBUG2("spans_send_msg: msg=%p, type=%d\n", msg,
133 if (msg->sm_type != SPANS_STAT_REQ &&
134 msg->sm_type != SPANS_STAT_IND &&
135 msg->sm_type != SPANS_STAT_RSP) {
136 kprintf("spans_send_msg: sending ");
137 spans_print_msg(msg);
142 * If the signalling channel has been closed, don't do anything
145 return(ECONNABORTED);
150 KB_ALLOCPKT(m, sizeof(spans_msg), KB_F_NOWAIT, KB_T_DATA);
152 /* No buffer available */
157 * Convert message to network order
159 KB_LEN(m) = KB_BFRLEN(m);
160 xdrmbuf_init(&xdrs, m, XDR_ENCODE);
161 if (!xdr_spans_msg(&xdrs, msg)) {
162 log(LOG_ERR, "spans_send_msg: XDR encode failed\n");
163 KB_LEN(m) = XDR_GETPOS(&xdrs);
164 spans_dump_buffer(m);
168 KB_LEN(m) = XDR_GETPOS(&xdrs);
173 err = atm_cm_cpcs_data(spp->sp_conn, m);
182 * Send an open request
184 * Build and send an open request.
187 * spp pointer to SPANS protocol instance block
188 * svp pointer to VCCB for which the request is being sent
195 spans_send_open_req(struct spans *spp, struct spans_vccb *svp)
200 ATM_DEBUG1("spans_send_open_req: svp=%p\n", svp);
203 * Get memory for a request message
205 req = (spans_msg *)atm_allocate(&spans_msgpool);
212 * Fill in the request
214 req->sm_vers = SPANS_VERS_1_0;
215 req->sm_type = SPANS_OPEN_REQ;
216 req->sm_open_req.opreq_conn = svp->sv_conn;
217 req->sm_open_req.opreq_aal = svp->sv_spans_aal;
218 req->sm_open_req.opreq_desrsrc = svp->sv_spans_qos;
219 req->sm_open_req.opreq_minrsrc.rsc_peak = 0;
220 req->sm_open_req.opreq_minrsrc.rsc_mean = 0;
221 req->sm_open_req.opreq_minrsrc.rsc_burst = 0;
222 req->sm_open_req.opreq_vpvc.vpf_valid = FALSE;
227 err = spans_send_msg(spp, req);
236 * Send an open response
238 * Build and send a response to an open request or open indication.
241 * spp pointer to SPANS protocol instance block
242 * svp pointer to VCCB for which the response is being sent
243 * result result code to include in the response
250 spans_send_open_rsp(struct spans *spp, struct spans_vccb *svp,
256 ATM_DEBUG2("spans_send_open_rsp: svp=%p, result=%d\n", svp,
260 * Get memory for a response message
262 rsp = (spans_msg *)atm_allocate(&spans_msgpool);
267 * Fill in the response
269 rsp->sm_vers = SPANS_VERS_1_0;
270 rsp->sm_type = SPANS_OPEN_RSP;
271 rsp->sm_open_rsp.oprsp_conn = svp->sv_conn;
272 rsp->sm_open_rsp.oprsp_result = result;
273 rsp->sm_open_rsp.oprsp_rsrc = svp->sv_spans_qos;
274 rsp->sm_open_rsp.oprsp_vpvc =
275 SPANS_PACK_VPIVCI(svp->sv_vpi, svp->sv_vci);
280 rc = spans_send_msg(spp, rsp);
288 * Send a close request
290 * Called to send a close request.
293 * spp pointer to SPANS protocol instance block
294 * svp pointer to VCCB for which the close is being sent
301 spans_send_close_req(struct spans *spp, struct spans_vccb *svp)
306 ATM_DEBUG1("spans_send_close_req: svp=%p\n", svp);
309 * Get memory for a close request
311 req = (spans_msg *)atm_allocate(&spans_msgpool);
318 * Fill in the request
320 req->sm_vers = SPANS_VERS_1_0;
321 if (svp->sv_type & VCC_OUT) {
322 req->sm_type = SPANS_CLOSE_REQ;
323 } else if (svp->sv_type & VCC_IN) {
324 req->sm_type = SPANS_RCLOSE_REQ;
328 "spans_send_close_req: invalid VCCB type 0x%x\n",
332 req->sm_close_req.clreq_conn = svp->sv_conn;
335 * Send the close request
337 err = spans_send_msg(spp, req);
349 * Process a status indication or status request
351 * Called when a status indication or status request is received.
352 * Processing will be based on the current SPANS state.
355 * spp pointer to SPANS protocol instance block
356 * msg pointer to the status message
363 spans_status_ind(struct spans *spp, spans_msg *msg)
366 struct atm_pif *pip = spp->sp_pif;
369 * Reset the probe count.
371 spp->sp_probe_ct = 0;
373 switch (spp->sp_state) {
376 * Interface just came up, update signalling state
378 spp->sp_state = SPANS_ACTIVE;
385 log(LOG_ERR, "spans: received status msg in state %d\n",
390 * Process the message
392 switch (msg->sm_type) {
396 * Handle a request from a host at the other end of
399 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
405 * There's a switch at the other end of the link. If
406 * its epoch has changed, reset the SPANS state and save
407 * the new information.
409 if (spp->sp_s_epoch !=
410 msg->sm_stat_ind.stind_sw_epoch) {
411 spans_switch_reset(spp, SPANS_UNI_UP);
413 msg->sm_stat_ind.stind_sw_epoch;
414 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
415 spp->sp_addr.address_length =
417 spans_addr_copy(&msg->sm_stat_ind.stind_es_addr,
418 spp->sp_addr.address);
420 "spans: received SPANS address %s from switch for interface %s%d\n",
421 spans_addr_print((spans_addr *)spp->sp_addr.address),
428 ATM_DEBUG1("spans_status_ind: Invalid message type %d\n",
434 * Respond to the status request or indication with a
437 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
440 rsp_msg->sm_vers = SPANS_VERS_1_0;
441 rsp_msg->sm_type = SPANS_STAT_RSP;
442 rsp_msg->sm_stat_rsp.strsp_es_epoch = spp->sp_h_epoch;
443 spans_addr_copy(spp->sp_addr.address,
444 &rsp_msg->sm_stat_rsp.strsp_es_addr);
445 spans_send_msg(spp, rsp_msg);
452 * Process a status response
454 * Called when a status response is received.
455 * Processing will be based on the current SPANS state.
458 * spp pointer to SPANS protocol instance block
459 * msg pointer to the status response message
466 spans_status_rsp(struct spans *spp, spans_msg *msg)
470 * Reset the probe count.
472 spp->sp_probe_ct = 0;
474 switch (spp->sp_state) {
477 * Interface just came up, update signalling state
479 spp->sp_state = SPANS_ACTIVE;
486 log(LOG_ERR, "spans: received status msg in state %d\n",
491 * Process the message
493 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
498 * Process an open indication or open request
500 * Called when an open indication or open request is received.
501 * Processing will be based on the state of the requested connection.
504 * spp pointer to SPANS protocol instance block
505 * msg pointer to the open message
512 spans_open_req(struct spans *spp, spans_msg *msg)
514 spans_result result = SPANS_OK;
516 struct spans_vccb *svp = NULL;
519 int err = 0, vpi, vci;
521 Atm_attributes call_attrs;
523 ATM_DEBUG2("spans_open_req: spp=%p, msg=%p\n", spp, msg);
526 * See if the connection is new
528 if ((svp = spans_find_conn(spp, &msg->sm_open_req.opreq_conn)) != NULL) {
530 * We already have a VCCB that matches the connection in
533 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
534 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
535 if (msg->sm_open_req.opreq_aal == svp->sv_spans_aal &&
536 (!msg->sm_open_req.opreq_vpvc.vpf_valid ||
537 (vpi == svp->sv_vpi &&
538 vci == svp->sv_vci))) {
540 * VCCB already exists, process depending on
543 switch (svp->sv_sstate) {
544 case SPANS_VC_R_POPEN:
545 /* I'm still thinking about it */
548 /* Retransmit the open_rsp */
553 ATM_DEBUG0("spans_open_req: bad VCCB state\n");
559 * VCCB is for same connection, but other
560 * parameters don't match
562 ATM_DEBUG0("spans_open_req: VCCB confusion\n");
570 * Verify that the request is for our ATM addres
572 if (spans_addr_cmp(spp->sp_addr.address,
573 &msg->sm_open_req.opreq_conn.con_dst)) {
574 ATM_DEBUG0("spans_open_req: bad destination\n");
575 result = SPANS_BADDEST;
580 * See if we recognize the specified AAL
582 if (!spans_get_local_aal(msg->sm_open_req.opreq_aal, &aal)) {
583 ATM_DEBUG0("spans_open_req: bad AAL\n");
589 * Should verify that we can handle requested connection QOS
593 * Select a VPI/VCI for the new connection
595 if (msg->sm_open_req.opreq_vpvc.vpf_valid) {
597 * Requestor asked for a certain VPI/VCI. Make sure we
598 * aren't already using the pair that was asked for.
600 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
601 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
602 if (spans_find_vpvc(spp, vci, vpi, VCC_IN)) {
603 ATM_DEBUG0("spans_open_req: VPI, VCI busy\n");
604 result = SPANS_NOVPVC;
607 vpvc = msg->sm_open_req.opreq_vpvc.vpf_vpvc;
610 * Allocate a VPI/VCI for this end of the VCC
612 vpvc = spans_alloc_vpvc(spp);
614 ATM_DEBUG0("spans_open_req: no VPI, VCI available\n");
615 result = SPANS_NOVPVC;
621 * Get a new VCCB for the connection
623 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
625 ATM_DEBUG0("spans_open_req: VCCB pool empty\n");
626 result = SPANS_NORSC;
631 * Find the physical interface structure
636 * Fill in the VCCB fields that we can at this point
638 svp->sv_type = VCC_SVC | VCC_IN;
639 svp->sv_proto = ATM_SIG_SPANS;
640 svp->sv_sstate = SPANS_VC_R_POPEN;
641 svp->sv_ustate = VCCU_POPEN;
643 svp->sv_nif = pip->pif_nif;
644 svp->sv_conn = msg->sm_open_req.opreq_conn;
645 svp->sv_spans_qos = msg->sm_open_req.opreq_desrsrc;
646 svp->sv_spans_aal = msg->sm_open_req.opreq_aal;
647 svp->sv_tstamp = time_second;
649 svp->sv_vpi = SPANS_EXTRACT_VPI(vpvc);
650 svp->sv_vci = SPANS_EXTRACT_VCI(vpvc);
653 * Put the VCCB on the SPANS queue
655 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
658 * Set up the ATM attributes block
660 KM_ZERO(&call_attrs, sizeof(call_attrs));
661 call_attrs.nif = svp->sv_nif;
662 call_attrs.api = CMAPI_CPCS;
664 call_attrs.aal.tag = T_ATM_PRESENT;
665 call_attrs.aal.type = aal;
668 call_attrs.aal.v.aal4.forward_max_SDU_size =
670 call_attrs.aal.v.aal4.backward_max_SDU_size =
672 call_attrs.aal.v.aal4.SSCS_type =
674 call_attrs.aal.v.aal4.mid_low = 0;
675 call_attrs.aal.v.aal4.mid_high = 1023;
678 call_attrs.aal.v.aal5.forward_max_SDU_size =
680 call_attrs.aal.v.aal5.backward_max_SDU_size =
682 call_attrs.aal.v.aal5.SSCS_type =
687 call_attrs.traffic.tag = T_ATM_PRESENT;
688 call_attrs.traffic.v.forward.PCR_high_priority = T_ATM_ABSENT;
689 call_attrs.traffic.v.forward.PCR_all_traffic =
690 msg->sm_open_req.opreq_desrsrc.rsc_peak *
692 call_attrs.traffic.v.forward.SCR_high_priority = T_ATM_ABSENT;
693 call_attrs.traffic.v.forward.SCR_all_traffic = T_ATM_ABSENT;
694 call_attrs.traffic.v.forward.MBS_high_priority = T_ATM_ABSENT;
695 call_attrs.traffic.v.forward.MBS_all_traffic = T_ATM_ABSENT;
696 call_attrs.traffic.v.forward.tagging = T_NO;
697 call_attrs.traffic.v.backward.PCR_high_priority = T_ATM_ABSENT;
698 call_attrs.traffic.v.backward.PCR_all_traffic =
699 call_attrs.traffic.v.forward.PCR_all_traffic;
700 call_attrs.traffic.v.backward.SCR_high_priority = T_ATM_ABSENT;
701 call_attrs.traffic.v.backward.SCR_all_traffic = T_ATM_ABSENT;
702 call_attrs.traffic.v.backward.MBS_high_priority = T_ATM_ABSENT;
703 call_attrs.traffic.v.backward.MBS_all_traffic = T_ATM_ABSENT;
704 call_attrs.traffic.v.backward.tagging = T_NO;
705 call_attrs.traffic.v.best_effort = T_YES;
707 call_attrs.bearer.tag = T_ATM_PRESENT;
708 call_attrs.bearer.v.bearer_class = T_ATM_CLASS_X;
709 call_attrs.bearer.v.traffic_type = T_ATM_NULL;
710 call_attrs.bearer.v.timing_requirements = T_ATM_NULL;
711 call_attrs.bearer.v.clipping_susceptibility = T_NO;
712 call_attrs.bearer.v.connection_configuration = T_ATM_1_TO_1;
715 call_attrs.bhli.tag = T_ATM_ABSENT;
716 call_attrs.blli.tag_l2 = T_ATM_ABSENT;
717 call_attrs.blli.tag_l3 = T_ATM_ABSENT;
718 call_attrs.llc.tag = T_ATM_ABSENT;
720 call_attrs.called.tag = T_ATM_PRESENT;
721 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_dst,
722 call_attrs.called.addr.address);
723 call_attrs.called.addr.address_format = T_ATM_SPANS_ADDR;
724 call_attrs.called.addr.address_length = sizeof(spans_addr);
725 call_attrs.called.subaddr.address_format = T_ATM_ABSENT;
726 call_attrs.called.subaddr.address_length = 0;
728 call_attrs.calling.tag = T_ATM_PRESENT;
729 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_src,
730 call_attrs.calling.addr.address);
731 call_attrs.calling.addr.address_format = T_ATM_SPANS_ADDR;
732 call_attrs.calling.addr.address_length = sizeof(spans_addr);
733 call_attrs.calling.subaddr.address_format = T_ATM_ABSENT;
734 call_attrs.calling.subaddr.address_length = 0;
736 call_attrs.qos.tag = T_ATM_PRESENT;
737 call_attrs.qos.v.coding_standard = T_ATM_NETWORK_CODING;
738 call_attrs.qos.v.forward.qos_class = T_ATM_QOS_CLASS_0;
739 call_attrs.qos.v.backward.qos_class = T_ATM_QOS_CLASS_0;
741 call_attrs.transit.tag = T_ATM_ABSENT;
742 call_attrs.cause.tag = T_ATM_ABSENT;
745 * Notify the connection manager that it has a new channel
747 err = atm_cm_incoming((struct vccb *)svp, &call_attrs);
749 ATM_DEBUG0("spans_open_req: atm_cm_incoming returned error\n");
755 * Wait for the connection recipient to issue an accept
761 * Clean up the VCCB and the atm_conn block if we got them
764 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
770 * Some problem was detected with the request. Send a SPANS
771 * message rejecting the connection.
773 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
778 * Fill out the response
780 rsp_msg->sm_vers = SPANS_VERS_1_0;
781 rsp_msg->sm_type = SPANS_OPEN_RSP;
782 rsp_msg->sm_open_rsp.oprsp_conn = msg->sm_open_req.opreq_conn;
783 rsp_msg->sm_open_rsp.oprsp_result = result;
784 rsp_msg->sm_open_rsp.oprsp_vpvc = 0;
787 * Send the Open Response
789 spans_send_msg(spp, rsp_msg);
795 * Process an open response or open confirmation
797 * Called when an open response or open confirmation is received.
798 * Processing will be based on the state of the requested connection and
799 * the status returned.
802 * spp pointer to SPANS protocol instance block
803 * msg pointer to the open response or confirmation message
810 spans_open_rsp(struct spans *spp, spans_msg *msg)
812 struct spans_vccb *svp;
814 ATM_DEBUG2("spans_open_rsp: spp=%p, msg=%p\n", spp, msg);
817 * Locate the VCCB for the connection
819 svp = spans_find_conn(spp, &msg->sm_open_rsp.oprsp_conn);
824 * Check the connection state
826 if ((svp->sv_sstate != SPANS_VC_POPEN &&
827 svp->sv_sstate != SPANS_VC_R_POPEN) ||
828 svp->sv_ustate != VCCU_POPEN) {
830 "spans_open_rsp: invalid VCCB state, sstate=%d, ustate=%d\n",
831 svp->sv_sstate, svp->sv_ustate);
836 * Cancel the retransmission timer
838 SPANS_VC_CANCEL((struct vccb *) svp);
843 switch (msg->sm_open_rsp.oprsp_result) {
847 * Save the assigned VPI and VCI
849 svp->sv_vpi = SPANS_EXTRACT_VPI(msg->sm_open_rsp.oprsp_vpvc);
850 svp->sv_vci = SPANS_EXTRACT_VCI(msg->sm_open_rsp.oprsp_vpvc);
853 * Update the VCC state and notify the VCC owner
855 svp->sv_sstate = SPANS_VC_OPEN;
856 svp->sv_ustate = VCCU_OPEN;
857 svp->sv_tstamp = time_second;
858 atm_cm_connected(svp->sv_connvc);
866 * Close out the VCCB and notify the user
868 svp->sv_sstate = SPANS_VC_FREE;
869 svp->sv_ustate = VCCU_CLOSED;
870 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
871 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
873 svp->sv_connvc->cvc_attr.cause.v.location =
875 svp->sv_connvc->cvc_attr.cause.v.cause_value =
876 T_ATM_CAUSE_CALL_REJECTED;
877 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
878 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
879 atm_cm_cleared(svp->sv_connvc);
883 log(LOG_ERR, "spans: unknown result %d in open rsp\n",
884 msg->sm_open_rsp.oprsp_result);
891 * Process a close request from the network
893 * Called when a close request, close indication, rclose request, or
894 * rclose indication is received. Processing will be based on the
895 * state of the connection.
898 * spp pointer to SPANS protocol instance block
899 * msg pointer to the close request message
906 spans_close_req(struct spans *spp, spans_msg *msg)
908 struct spans_vccb *svp;
914 ATM_DEBUG2("spans_close_req: spp=%p, msg=%p\n", spp, msg);
917 * Locate the VCCB for the connection
919 svp = spans_find_conn(spp, &msg->sm_close_req.clreq_conn);
921 result = SPANS_BADDEST;
926 * Check the connection type
928 if (!(svp->sv_type & VCC_SVC)) {
934 * Check the connection state
936 switch (svp->sv_sstate) {
938 case SPANS_VC_R_POPEN:
941 * VCC is open or opening--continue
948 * We're already closing--give a response, since this
949 * is probably a retransmission
959 * Cancel the retransmission timer
961 SPANS_VC_CANCEL((struct vccb *) svp);
964 * Close out the VCCB and notify the user
966 outstate = svp->sv_sstate;
967 svp->sv_ustate = VCCU_CLOSED;
968 svp->sv_sstate = SPANS_VC_FREE;
969 cvp = svp->sv_connvc;
971 case SPANS_VC_R_POPEN:
972 spans_free((struct vccb *)svp);
977 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
978 cvp->cvc_attr.cause.v.coding_standard =
980 cvp->cvc_attr.cause.v.location = T_ATM_LOC_USER;
981 cvp->cvc_attr.cause.v.cause_value =
982 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
983 KM_ZERO(cvp->cvc_attr.cause.v.diagnostics,
984 sizeof(cvp->cvc_attr.cause.v.diagnostics));
985 atm_cm_cleared(svp->sv_connvc);
993 * Respond to the SPANS_CLOSE_IND with a SPANS_CLOSE_RSP
995 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
998 rsp_msg->sm_vers = SPANS_VERS_1_0;
999 if (msg->sm_type == SPANS_RCLOSE_REQ ||
1000 msg->sm_type == SPANS_RCLOSE_IND) {
1001 rsp_msg->sm_type = SPANS_RCLOSE_RSP;
1003 rsp_msg->sm_type = SPANS_CLOSE_RSP;
1005 rsp_msg->sm_close_rsp.clrsp_conn = msg->sm_close_req.clreq_conn;
1006 rsp_msg->sm_close_rsp.clrsp_result = result;
1007 spans_send_msg(spp, rsp_msg);
1013 * Process a close response or close confirmation
1015 * Called when an close response or close confirmation is received.
1016 * Processing will be based on the state of the requested connection and
1017 * the returned status.
1020 * spp pointer to SPANS protocol instance block
1021 * msg pointer to the close response or confirmation message
1028 spans_close_rsp(struct spans *spp, spans_msg *msg)
1030 struct spans_vccb *svp;
1032 ATM_DEBUG2("spans_close_rsp: spp=%p, msg=%p\n", spp, msg);
1035 * Locate the VCCB for the connection
1037 svp = spans_find_conn(spp, &msg->sm_close_rsp.clrsp_conn);
1043 * Check the VCCB state
1045 if (svp->sv_sstate != SPANS_VC_CLOSE) {
1050 * Cancel the retransmission timer
1052 SPANS_VC_CANCEL((struct vccb *) svp);
1055 * Check the response from the remote end
1057 switch (msg->sm_close_rsp.clrsp_result) {
1061 * Mark the VCCB as closed and notify the owner
1063 svp->sv_sstate = SPANS_VC_FREE;
1064 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1065 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1067 svp->sv_connvc->cvc_attr.cause.v.location =
1069 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1070 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1071 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1072 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1073 atm_cm_cleared(svp->sv_connvc);
1081 * Mark the VCCB as closed and notify the owner
1083 svp->sv_sstate = SPANS_VC_FREE;
1084 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1085 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1087 svp->sv_connvc->cvc_attr.cause.v.location =
1089 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1090 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
1091 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1092 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1093 atm_cm_cleared(svp->sv_connvc);
1097 log(LOG_ERR, "spans: unknown result %d in close rsp\n",
1098 msg->sm_close_rsp.clrsp_result);
1105 * Process a multi request or multi indication
1107 * Called when a multi response or multi confirmation is received. We
1108 * don't support multicast channels, so we just reject the request.
1111 * spp pointer to SPANS protocol instance block
1112 * msg pointer to the multi request or indication message
1119 spans_multi_req(struct spans *spp, spans_msg *msg)
1124 * Get memory for a SPANS_MULTI_RSP message.
1126 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1127 if (rsp_msg == NULL)
1131 * Fill out the response.
1133 rsp_msg->sm_vers = SPANS_VERS_1_0;
1134 rsp_msg->sm_type = SPANS_MULTI_RSP;
1135 rsp_msg->sm_multi_rsp.mursp_conn = msg->sm_multi_req.mureq_conn;
1136 rsp_msg->sm_multi_rsp.mursp_result = SPANS_FAIL;
1137 rsp_msg->sm_multi_rsp.mursp_rsrc = msg->sm_multi_req.mureq_desrsrc;
1138 rsp_msg->sm_multi_rsp.mursp_vpvc = 0;
1141 * Send the response and free the message.
1143 spans_send_msg(spp, rsp_msg);
1149 * Process an add request or add indication
1151 * Called when an add response or add confirmation is received. We
1152 * don't support multicast channels, so we just reject the request.
1155 * spp pointer to SPANS protocol instance block
1156 * msg pointer to the add request or indication message
1163 spans_add_req(struct spans *spp, spans_msg *msg)
1168 * Get memory for a SPANS_ADD_RSP message.
1170 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1171 if (rsp_msg == NULL)
1175 * Fill out the response.
1177 rsp_msg->sm_vers = SPANS_VERS_1_0;
1178 rsp_msg->sm_type = SPANS_ADD_RSP;
1179 rsp_msg->sm_add_rsp.adrsp_conn = msg->sm_add_req.adreq_desconn;
1180 rsp_msg->sm_add_rsp.adrsp_result = SPANS_FAIL;
1181 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_peak = 0;
1182 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_mean = 0;
1183 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_burst = 0;
1186 * Send the response and free the message.
1188 spans_send_msg(spp, rsp_msg);
1194 * Process a join request
1196 * Called when an join request is received. We don't support group
1197 * addresses, so we just reject the request.
1200 * spp pointer to SPANS protocol instance block
1201 * msg pointer to the join request message
1208 spans_join_req(struct spans *spp, spans_msg *msg)
1213 * Get memory for a SPANS_JOIN_CNF message.
1215 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1216 if (rsp_msg == NULL)
1220 * Fill out the response.
1222 rsp_msg->sm_vers = SPANS_VERS_1_0;
1223 rsp_msg->sm_type = SPANS_JOIN_CNF;
1224 spans_addr_copy(&msg->sm_join_req.jnreq_addr,
1225 &rsp_msg->sm_join_cnf.jncnf_addr);
1226 rsp_msg->sm_join_cnf.jncnf_result = SPANS_FAIL;
1229 * Send the response and free the message.
1231 spans_send_msg(spp, rsp_msg);
1237 * Process a leave request
1239 * Called when an leave request is received. We don't support group
1240 * addresses, so we just reject the request.
1243 * spp pointer to SPANS protocol instance block
1244 * msg pointer to the leave request message
1251 spans_leave_req(struct spans *spp, spans_msg *msg)
1256 * Get memory for a SPANS_LEAVE_CNF message.
1258 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1259 if (rsp_msg == NULL)
1263 * Fill out the response.
1265 rsp_msg->sm_vers = SPANS_VERS_1_0;
1266 rsp_msg->sm_type = SPANS_LEAVE_CNF;
1267 spans_addr_copy(&msg->sm_leave_req.lvreq_addr,
1268 &rsp_msg->sm_leave_cnf.lvcnf_addr);
1269 rsp_msg->sm_leave_cnf.lvcnf_result = SPANS_FAIL;
1272 * Send the response and free the message.
1274 spans_send_msg(spp, rsp_msg);
1280 * Process a VCI range indication
1282 * Called when a VCI range indication is received. Adjust the VCI
1283 * bounds if they have changed.
1286 * spp pointer to SPANS protocol instance block
1287 * msg pointer to the VCI range indication message
1294 spans_vcir_ind(struct spans *spp, spans_msg *msg)
1297 * Adjust the limits if they have changed
1299 if (msg->sm_vcir_ind.vrind_min != spp->sp_min_vci) {
1301 (msg->sm_vcir_ind.vrind_min <
1304 msg->sm_vcir_ind.vrind_min);
1306 if (msg->sm_vcir_ind.vrind_max != spp->sp_max_vci) {
1308 (msg->sm_vcir_ind.vrind_max >
1311 msg->sm_vcir_ind.vrind_max);
1317 * Process a query request
1319 * Called when a query request is received. Respond with the
1320 * appropriate query response.
1323 * spp pointer to SPANS protocol instance block
1324 * msg pointer to the VCI range indication message
1331 spans_query_req(struct spans *spp, spans_msg *msg)
1333 struct spans_vccb *svp = NULL;
1336 ATM_DEBUG1("spans_query_req: msg=%p\n", msg);
1339 * Ignore an end-to-end query
1341 if (msg->sm_query_req.qyreq_type == SPANS_QUERY_END_TO_END) {
1346 * Get memory for a SPANS_QUERY_RSP message.
1348 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1349 if (rsp_msg == NULL)
1353 * Fill out the response.
1355 rsp_msg->sm_vers = SPANS_VERS_1_0;
1356 rsp_msg->sm_type = SPANS_QUERY_RSP;
1357 rsp_msg->sm_query_rsp.qyrsp_conn = msg->sm_query_req.qyreq_conn;
1358 rsp_msg->sm_query_rsp.qyrsp_type = msg->sm_query_req.qyreq_type;
1359 rsp_msg->sm_query_rsp.qyrsp_data = 0;
1362 * Get the state of the requested connection
1364 svp = spans_find_conn(spp, &msg->sm_query_req.qyreq_conn);
1366 switch(svp->sv_sstate) {
1369 rsp_msg->sm_query_rsp.qyrsp_state =
1373 rsp_msg->sm_query_rsp.qyrsp_state =
1376 case SPANS_VC_POPEN:
1377 case SPANS_VC_R_POPEN:
1378 rsp_msg->sm_query_rsp.qyrsp_state =
1379 SPANS_CONN_OPEN_PEND;
1381 case SPANS_VC_CLOSE:
1382 case SPANS_VC_ABORT:
1383 rsp_msg->sm_query_rsp.qyrsp_state =
1384 SPANS_CONN_CLOSE_PEND;
1386 case SPANS_VC_ACTIVE:
1387 case SPANS_VC_ACT_DOWN:
1389 * VCCB is for a PVC (shouldn't happen)
1396 * No VCCB found--connection doesn't exist
1398 rsp_msg->sm_query_rsp.qyrsp_state = SPANS_CONN_CLOSED;
1402 * Send the response and free the message.
1404 spans_send_msg(spp, rsp_msg);
1410 * Process a SPANS signalling message
1412 * Called when a SPANS message is received. The message is converted
1413 * into internal format with XDR and decoded by calling the appropriate
1414 * mesage handling routine. Unrecognized and unexpected messages are
1418 * spp pointer to SPANS protocol instance block
1419 * m pointer to a buffer chain containing the SPANS message
1426 spans_rcv_msg(struct spans *spp, KBuffer *m)
1432 * Get storage for the message
1434 msg = (spans_msg *)atm_allocate(&spans_msgpool);
1440 * Convert the message from network order to internal format
1442 xdrmbuf_init(&xdrs, m, XDR_DECODE);
1443 if (!xdr_spans_msg(&xdrs, msg)) {
1444 log(LOG_ERR, "spans_rcv_msg: XDR decode failed\n");
1445 spans_dump_buffer(m);
1451 * Debug--print some information about the message
1453 if (msg->sm_type != SPANS_STAT_REQ &&
1454 msg->sm_type != SPANS_STAT_IND &&
1455 msg->sm_type != SPANS_STAT_RSP) {
1456 kprintf("spans_rcv_msg: got ");
1457 spans_print_msg(msg);
1462 * Verify the message sm_vers
1464 if (msg->sm_vers != SPANS_VERS_1_0) {
1465 log(LOG_ERR, "spans: invalid message version 0x%x\n",
1470 * Ignore the message if SPANS isn't up yet
1472 if (spp->sp_state != SPANS_ACTIVE &&
1473 (spp->sp_state != SPANS_PROBE ||
1474 (msg->sm_type != SPANS_STAT_REQ &&
1475 msg->sm_type != SPANS_STAT_RSP &&
1476 msg->sm_type != SPANS_STAT_IND))) {
1481 * Process the message based on its type
1483 switch(msg->sm_type) {
1484 case SPANS_STAT_REQ:
1485 spans_status_ind(spp, msg);
1487 case SPANS_STAT_IND:
1488 spans_status_ind(spp, msg);
1490 case SPANS_STAT_RSP:
1491 spans_status_rsp(spp, msg);
1493 case SPANS_OPEN_REQ:
1494 spans_open_req(spp, msg);
1496 case SPANS_OPEN_IND:
1497 spans_open_req(spp, msg);
1499 case SPANS_OPEN_RSP:
1500 spans_open_rsp(spp, msg);
1502 case SPANS_OPEN_CNF:
1503 spans_open_rsp(spp, msg);
1505 case SPANS_CLOSE_REQ:
1506 spans_close_req(spp, msg);
1508 case SPANS_CLOSE_IND:
1509 spans_close_req(spp, msg);
1511 case SPANS_CLOSE_RSP:
1512 spans_close_rsp(spp, msg);
1514 case SPANS_CLOSE_CNF:
1515 spans_close_rsp(spp, msg);
1517 case SPANS_RCLOSE_REQ:
1518 spans_close_req(spp, msg);
1520 case SPANS_RCLOSE_IND:
1521 spans_close_req(spp, msg);
1523 case SPANS_RCLOSE_RSP:
1524 spans_close_rsp(spp, msg);
1526 case SPANS_RCLOSE_CNF:
1527 spans_close_rsp(spp, msg);
1529 case SPANS_MULTI_REQ:
1530 spans_multi_req(spp, msg);
1532 case SPANS_MULTI_IND:
1533 spans_multi_req(spp, msg);
1535 case SPANS_MULTI_RSP:
1537 "spans: unexpected message (multi_rsp)\n");
1539 case SPANS_MULTI_CNF:
1541 "spans: unexpected message (multi_conf)\n");
1544 spans_add_req(spp, msg);
1547 spans_add_req(spp, msg);
1551 "spans: unexpected message (add_rsp)\n");
1554 log(LOG_ERR, "spans: unexpected message (add_conf)\n");
1556 case SPANS_JOIN_REQ:
1557 spans_join_req(spp, msg);
1559 case SPANS_JOIN_CNF:
1560 log(LOG_ERR, "spans: unexpected message (join_conf)\n");
1562 case SPANS_LEAVE_REQ:
1563 spans_leave_req(spp, msg);
1565 case SPANS_LEAVE_CNF:
1567 "spans: unexpected message (leave_conf)\n");
1569 case SPANS_VCIR_IND:
1570 spans_vcir_ind(spp, msg);
1572 case SPANS_QUERY_REQ:
1573 spans_query_req(spp, msg);
1575 case SPANS_QUERY_RSP:
1577 "spans: unexpected message (query_rsp)\n");
1580 log(LOG_ERR, "spans: unknown SPANS message type %d\n",
1586 * Free the incoming message (both buffer and internal format) if