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_subr.c,v 1.4 1999/08/28 00:48:52 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_subr.c,v 1.6 2006/01/14 13:36:39 swildner Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS-related subroutines.
38 #include <netproto/atm/kern_include.h>
40 #include "spans_xdr.h"
41 #include "spans_var.h"
46 * Called when a user wants to open a VC. This function will construct
47 * a VCCB, create the stack requested by the user, and, if we are
48 * opening an SVC, start the SPANS signalling message exchange. The
49 * user will have to wait for a notify event to be sure the SVC is fully
52 * Must be called from a critical section.
55 * spp pointer to SPANS protocol instance
56 * acp pointer to PVC's connection parameters
59 * 0 VCC creation successful
60 * errno VCC setup failed - reason indicated
64 spans_open_vcc(struct spans
*spp
, Atm_connvc
*cvp
)
66 struct atm_pif
*pip
= spp
->sp_pif
;
67 struct spans_vccb
*svp
;
70 int err
, pvc
, vpi
, vci
;
72 ATM_DEBUG2("spans_open_vcc: spp=%p, cvp=%p\n", spp
, cvp
);
75 * Validate user parameters. AAL and encapsulation are
76 * checked by the connection manager.
80 * Check called party address(es)
82 if (cvp
->cvc_attr
.called
.tag
!= T_ATM_PRESENT
||
83 cvp
->cvc_attr
.called
.addr
.address_format
==
85 cvp
->cvc_attr
.called
.subaddr
.address_format
!=
89 switch (cvp
->cvc_attr
.called
.addr
.address_format
) {
92 * Make sure VPI/VCI is valid
95 pvp
= (Atm_addr_pvc
*)cvp
->cvc_attr
.called
.addr
.address
;
96 vpi
= ATM_PVC_GET_VPI(pvp
);
97 vci
= ATM_PVC_GET_VCI(pvp
);
98 if ((vpi
> pip
->pif_maxvpi
) ||
100 (vci
> pip
->pif_maxvci
)) {
105 * Make sure VPI/VCI is not already in use
107 if (spans_find_vpvc(spp
, vpi
, vci
, 0)) {
110 ATM_DEBUG2("spans_open_vcc: VPI.VCI=%d.%d\n",
114 case T_ATM_SPANS_ADDR
:
119 * Check signalling state
121 if (spp
->sp_state
!= SPANS_ACTIVE
) {
126 *Check destination address length
128 if (cvp
->cvc_attr
.called
.addr
.address_length
!=
129 sizeof(spans_addr
)) {
139 * Check that this is for the same interface SPANS uses
141 if (!cvp
->cvc_attr
.nif
||
142 cvp
->cvc_attr
.nif
->nif_pif
!= spp
->sp_pif
) {
149 if (!spans_get_spans_aal(cvp
->cvc_attr
.aal
.type
, &aal
)) {
155 * Check encapsulation
157 /* XXX -- How do we check encapsulation? */
158 if (cvp
->ac_encaps
!= ATM_ENC_NULL
) {
164 * Allocate control block for VCC
166 svp
= (struct spans_vccb
*)atm_allocate(&spans_vcpool
);
175 svp
->sv_type
= VCC_PVC
| VCC_IN
| VCC_OUT
;
178 svp
->sv_sstate
= (spp
->sp_state
== SPANS_ACTIVE
?
179 SPANS_VC_ACTIVE
: SPANS_VC_ACT_DOWN
);
180 svp
->sv_ustate
= VCCU_OPEN
;
182 svp
->sv_type
= VCC_SVC
| VCC_OUT
;
183 spans_addr_copy(cvp
->cvc_attr
.called
.addr
.address
,
184 &svp
->sv_conn
.con_dst
);
185 spans_addr_copy(spp
->sp_addr
.address
,
186 &svp
->sv_conn
.con_src
);
187 svp
->sv_conn
.con_dsap
= SPANS_SAP_IP
;
188 svp
->sv_conn
.con_ssap
= spans_ephemeral_sap(spp
);
189 svp
->sv_sstate
= SPANS_VC_POPEN
;
190 svp
->sv_ustate
= VCCU_POPEN
;
192 svp
->sv_proto
= ATM_SIG_SPANS
;
193 svp
->sv_pif
= spp
->sp_pif
;
194 svp
->sv_nif
= cvp
->cvc_attr
.nif
;
195 svp
->sv_connvc
= cvp
;
196 svp
->sv_spans_aal
= aal
;
197 svp
->sv_tstamp
= time_second
;
200 * Put VCCB on SPANS queue
202 ENQUEUE(svp
, struct spans_vccb
, sv_sigelem
, spp
->sp_vccq
);
205 * Link VCCB to VCC connection block
207 cvp
->cvc_vcc
= (struct vccb
*) svp
;
210 * Start the SPANS message exchange if this is an SVC
214 svp
->sv_spans_qos
.rsc_peak
= 1;
215 svp
->sv_spans_qos
.rsc_mean
= 1;
216 svp
->sv_spans_qos
.rsc_burst
= 1;
217 err
= spans_send_open_req(spp
, svp
);
220 * On error, delete the VCCB
222 DEQUEUE(svp
, struct spans_vccb
, sv_sigelem
,
225 atm_free((caddr_t
)svp
);
229 * VCCB is opening--set the retransmit timer
231 SPANS_VC_TIMER((struct vccb
*) svp
, SV_TIMEOUT
);
242 * Called when a user wants to close a VCC. This function will clean
243 * up the VCCB and, for an SVC, send a close request.
245 * Must be called from a critical section.
248 * spp pointer to SPANS protocol instance
249 * svp pointer to VCCB for the VCC to be closed
252 * 0 VCC is now closed
253 * errno error encountered
256 spans_close_vcc(struct spans
*spp
, struct spans_vccb
*svp
, int force
)
260 ATM_DEBUG2("spans_close_vcc: svp=%p, state=%d\n", svp
,
264 * Check that this is for the same interface SPANS uses
266 if (svp
->sv_pif
!= spp
->sp_pif
) {
271 * Kill any possible timer
273 SPANS_VC_CANCEL((struct vccb
*) svp
);
276 * Mark the close time.
278 svp
->sv_tstamp
= time_second
;
281 * Process based on the connection type
283 if (svp
->sv_type
& VCC_PVC
) {
284 svp
->sv_sstate
= SPANS_VC_FREE
;
285 svp
->sv_ustate
= VCCU_CLOSED
;
286 } else if (svp
->sv_type
& VCC_SVC
) {
290 svp
->sv_ustate
= VCCU_CLOSED
;
293 * Send the appropriate SPANS close message
295 switch (svp
->sv_sstate
) {
296 case SPANS_VC_R_POPEN
:
297 err
= spans_send_open_rsp(spp
, svp
, SPANS_FAIL
);
298 svp
->sv_sstate
= SPANS_VC_FREE
;
304 err
= spans_send_close_req(spp
, svp
);
306 svp
->sv_sstate
= SPANS_VC_FREE
;
308 svp
->sv_sstate
= SPANS_VC_CLOSE
;
309 SPANS_VC_TIMER((struct vccb
*) svp
,
315 svp
->sv_sstate
= SPANS_VC_FREE
;
322 * Wait for user to free resources
331 * Called when the signalling manager wants to close a VCC immediately.
332 * This function will clean up the VCCB and notify the owner.
334 * Must be called from a critical section.
337 * spp pointer to SPANS protocol instance
338 * svp pointer to VCCB for the VCC to be closed
341 * 0 VCC is now closed
342 * errno error encountered
345 spans_clear_vcc(struct spans
*spp
, struct spans_vccb
*svp
)
349 ATM_DEBUG2("spans_clear_vcc: svp=%p, state=%d\n", svp
,
353 * Check that this is for the same interface SPANS uses
355 if (svp
->sv_pif
!= spp
->sp_pif
) {
360 * Kill any possible timer
362 SPANS_VC_CANCEL((struct vccb
*) svp
);
365 * Mark the close time
367 svp
->sv_tstamp
= time_second
;
370 * Mark the VCCB closed
372 outstate
= svp
->sv_sstate
;
373 svp
->sv_sstate
= SPANS_VC_FREE
;
374 svp
->sv_ustate
= VCCU_CLOSED
;
377 * Notify the user if old state indicates.
380 case SPANS_VC_ACTIVE
:
381 case SPANS_VC_ACT_DOWN
:
386 /* XXX -- set cause */
387 atm_cm_cleared(svp
->sv_connvc
);
390 case SPANS_VC_R_POPEN
:
396 * Wait for user to free resources
403 * Reset the switch state
405 * Called when the switch or host at the far end of the ATM link has
406 * gone away. This can be deteched either by a number of SPANS_STAT_REQ
407 * messages going unanswered or by the host epoch changing in a SPANS
408 * SPANS_STAT_IND or SPANS_STAT_REQ message.
411 * spp pointer to SPANS protocol instance
418 spans_switch_reset(struct spans
*spp
, int cause
)
420 struct vccb
*vcp
, *vnext
;
422 ATM_DEBUG2("spans_switch_reset: spp=%p, cause=%d\n",
428 log(LOG_INFO
, "spans: signalling %s on interface %s%d\n",
429 (cause
== SPANS_UNI_DOWN
? "down" : "up"),
430 spp
->sp_pif
->pif_name
,
431 spp
->sp_pif
->pif_unit
);
434 * Terminate all of our VCCs
437 for (vcp
= Q_HEAD(spp
->sp_vccq
, struct vccb
); vcp
;
442 vnext
= Q_NEXT(vcp
, struct vccb
, vc_sigelem
);
444 if (vcp
->vc_type
& VCC_SVC
) {
446 * Close the SVC and notify the owner
448 outstate
= vcp
->vc_sstate
;
449 SPANS_VC_CANCEL((struct vccb
*) vcp
);
450 vcp
->vc_ustate
= VCCU_CLOSED
;
451 vcp
->vc_sstate
= SPANS_VC_FREE
;
452 if (outstate
== SPANS_VC_OPEN
||
453 outstate
== SPANS_VC_POPEN
) {
454 /* XXX -- set cause */
455 atm_cm_cleared(vcp
->vc_connvc
);
457 } else if (vcp
->vc_type
& VCC_PVC
) {
463 vcp
->vc_sstate
= SPANS_VC_ACT_DOWN
;
466 vcp
->vc_sstate
= SPANS_VC_ACTIVE
;
470 log(LOG_ERR
, "spans: invalid VCC type: vccb=%p, type=%d\n",