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,
224 cvp->cvc_vcc = (struct vccb *)0;
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",