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