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 $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS-related subroutines.
38 #include <netatm/kern_include.h>
40 #include "spans_xdr.h"
41 #include <netatm/spans/spans_var.h>
44 __RCSID("@(#) $FreeBSD: src/sys/netatm/spans/spans_subr.c,v 1.4 1999/08/28 00:48:52 peter Exp $");
51 * Called when a user wants to open a VC. This function will construct
52 * a VCCB, create the stack requested by the user, and, if we are
53 * opening an SVC, start the SPANS signalling message exchange. The
54 * user will have to wait for a notify event to be sure the SVC is fully
57 * Must be called at splnet.
60 * spp pointer to SPANS protocol instance
61 * acp pointer to PVC's connection parameters
64 * 0 VCC creation successful
65 * errno VCC setup failed - reason indicated
69 spans_open_vcc(spp, cvp)
74 struct atm_pif *pip = spp->sp_pif;
75 struct spans_vccb *svp;
78 int err, pvc, vpi, vci;
80 ATM_DEBUG2("spans_open_vcc: spp=%p, cvp=%p\n", spp, cvp);
83 * Validate user parameters. AAL and encapsulation are
84 * checked by the connection manager.
88 * Check called party address(es)
90 if (cvp->cvc_attr.called.tag != T_ATM_PRESENT ||
91 cvp->cvc_attr.called.addr.address_format ==
93 cvp->cvc_attr.called.subaddr.address_format !=
97 switch (cvp->cvc_attr.called.addr.address_format) {
100 * Make sure VPI/VCI is valid
103 pvp = (Atm_addr_pvc *)cvp->cvc_attr.called.addr.address;
104 vpi = ATM_PVC_GET_VPI(pvp);
105 vci = ATM_PVC_GET_VCI(pvp);
106 if ((vpi > pip->pif_maxvpi) ||
108 (vci > pip->pif_maxvci)) {
113 * Make sure VPI/VCI is not already in use
115 if (spans_find_vpvc(spp, vpi, vci, 0)) {
118 ATM_DEBUG2("spans_open_vcc: VPI.VCI=%d.%d\n",
122 case T_ATM_SPANS_ADDR:
127 * Check signalling state
129 if (spp->sp_state != SPANS_ACTIVE) {
134 *Check destination address length
136 if (cvp->cvc_attr.called.addr.address_length !=
137 sizeof(spans_addr)) {
147 * Check that this is for the same interface SPANS uses
149 if (!cvp->cvc_attr.nif ||
150 cvp->cvc_attr.nif->nif_pif != spp->sp_pif) {
157 if (!spans_get_spans_aal(cvp->cvc_attr.aal.type, &aal)) {
163 * Check encapsulation
165 /* XXX -- How do we check encapsulation? */
166 if (cvp->ac_encaps != ATM_ENC_NULL) {
172 * Allocate control block for VCC
174 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
183 svp->sv_type = VCC_PVC | VCC_IN | VCC_OUT;
186 svp->sv_sstate = (spp->sp_state == SPANS_ACTIVE ?
187 SPANS_VC_ACTIVE : SPANS_VC_ACT_DOWN);
188 svp->sv_ustate = VCCU_OPEN;
190 svp->sv_type = VCC_SVC | VCC_OUT;
191 spans_addr_copy(cvp->cvc_attr.called.addr.address,
192 &svp->sv_conn.con_dst);
193 spans_addr_copy(spp->sp_addr.address,
194 &svp->sv_conn.con_src);
195 svp->sv_conn.con_dsap = SPANS_SAP_IP;
196 svp->sv_conn.con_ssap = spans_ephemeral_sap(spp);
197 svp->sv_sstate = SPANS_VC_POPEN;
198 svp->sv_ustate = VCCU_POPEN;
200 svp->sv_proto = ATM_SIG_SPANS;
201 svp->sv_pif = spp->sp_pif;
202 svp->sv_nif = cvp->cvc_attr.nif;
203 svp->sv_connvc = cvp;
204 svp->sv_spans_aal = aal;
205 svp->sv_tstamp = time_second;
208 * Put VCCB on SPANS queue
210 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
213 * Link VCCB to VCC connection block
215 cvp->cvc_vcc = (struct vccb *) svp;
218 * Start the SPANS message exchange if this is an SVC
222 svp->sv_spans_qos.rsc_peak = 1;
223 svp->sv_spans_qos.rsc_mean = 1;
224 svp->sv_spans_qos.rsc_burst = 1;
225 err = spans_send_open_req(spp, svp);
228 * On error, delete the VCCB
230 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
232 cvp->cvc_vcc = (struct vccb *)0;
233 atm_free((caddr_t)svp);
237 * VCCB is opening--set the retransmit timer
239 SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
250 * Called when a user wants to close a VCC. This function will clean
251 * up the VCCB and, for an SVC, send a close request.
253 * Must be called at splnet.
256 * spp pointer to SPANS protocol instance
257 * svp pointer to VCCB for the VCC to be closed
260 * 0 VCC is now closed
261 * errno error encountered
264 spans_close_vcc(spp, svp, force)
266 struct spans_vccb *svp;
272 ATM_DEBUG2("spans_close_vcc: svp=%p, state=%d\n", svp,
276 * Check that this is for the same interface SPANS uses
278 if (svp->sv_pif != spp->sp_pif) {
283 * Kill any possible timer
285 SPANS_VC_CANCEL((struct vccb *) svp);
288 * Mark the close time.
290 svp->sv_tstamp = time_second;
293 * Process based on the connection type
295 if (svp->sv_type & VCC_PVC) {
296 svp->sv_sstate = SPANS_VC_FREE;
297 svp->sv_ustate = VCCU_CLOSED;
298 } else if (svp->sv_type & VCC_SVC) {
302 svp->sv_ustate = VCCU_CLOSED;
305 * Send the appropriate SPANS close message
307 switch (svp->sv_sstate) {
308 case SPANS_VC_R_POPEN:
309 err = spans_send_open_rsp(spp, svp, SPANS_FAIL);
310 svp->sv_sstate = SPANS_VC_FREE;
316 err = spans_send_close_req(spp, svp);
318 svp->sv_sstate = SPANS_VC_FREE;
320 svp->sv_sstate = SPANS_VC_CLOSE;
321 SPANS_VC_TIMER((struct vccb *) svp,
327 svp->sv_sstate = SPANS_VC_FREE;
334 * Wait for user to free resources
343 * Called when the signalling manager wants to close a VCC immediately.
344 * This function will clean up the VCCB and notify the owner.
346 * Must be called at splnet.
349 * spp pointer to SPANS protocol instance
350 * svp pointer to VCCB for the VCC to be closed
353 * 0 VCC is now closed
354 * errno error encountered
357 spans_clear_vcc(spp, svp)
359 struct spans_vccb *svp;
364 ATM_DEBUG2("spans_clear_vcc: svp=%p, state=%d\n", svp,
368 * Check that this is for the same interface SPANS uses
370 if (svp->sv_pif != spp->sp_pif) {
375 * Kill any possible timer
377 SPANS_VC_CANCEL((struct vccb *) svp);
380 * Mark the close time
382 svp->sv_tstamp = time_second;
385 * Mark the VCCB closed
387 outstate = svp->sv_sstate;
388 svp->sv_sstate = SPANS_VC_FREE;
389 svp->sv_ustate = VCCU_CLOSED;
392 * Notify the user if old state indicates.
395 case SPANS_VC_ACTIVE:
396 case SPANS_VC_ACT_DOWN:
401 /* XXX -- set cause */
402 atm_cm_cleared(svp->sv_connvc);
405 case SPANS_VC_R_POPEN:
411 * Wait for user to free resources
418 * Reset the switch state
420 * Called when the switch or host at the far end of the ATM link has
421 * gone away. This can be deteched either by a number of SPANS_STAT_REQ
422 * messages going unanswered or by the host epoch changing in a SPANS
423 * SPANS_STAT_IND or SPANS_STAT_REQ message.
426 * spp pointer to SPANS protocol instance
433 spans_switch_reset(spp, cause)
439 struct vccb *vcp, *vnext;
441 ATM_DEBUG2("spans_switch_reset: spp=%p, cause=%d\n",
447 log(LOG_INFO, "spans: signalling %s on interface %s%d\n",
448 (cause == SPANS_UNI_DOWN ? "down" : "up"),
449 spp->sp_pif->pif_name,
450 spp->sp_pif->pif_unit);
453 * Terminate all of our VCCs
456 for (vcp = Q_HEAD(spp->sp_vccq, struct vccb); vcp;
461 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
463 if (vcp->vc_type & VCC_SVC) {
465 * Close the SVC and notify the owner
467 outstate = vcp->vc_sstate;
468 SPANS_VC_CANCEL((struct vccb *) vcp);
469 vcp->vc_ustate = VCCU_CLOSED;
470 vcp->vc_sstate = SPANS_VC_FREE;
471 if (outstate == SPANS_VC_OPEN ||
472 outstate == SPANS_VC_POPEN) {
473 /* XXX -- set cause */
474 atm_cm_cleared(vcp->vc_connvc);
476 } else if (vcp->vc_type & VCC_PVC) {
482 vcp->vc_sstate = SPANS_VC_ACT_DOWN;
485 vcp->vc_sstate = SPANS_VC_ACTIVE;
489 log(LOG_ERR, "spans: invalid VCC type: vccb=%p, type=%d\n",