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.3 2003/08/07 21:17:35 dillon Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS-related subroutines.
38 #include <netatm/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 at splnet.
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(spp, cvp)
69 struct atm_pif *pip = spp->sp_pif;
70 struct spans_vccb *svp;
73 int err, pvc, vpi, vci;
75 ATM_DEBUG2("spans_open_vcc: spp=%p, cvp=%p\n", spp, cvp);
78 * Validate user parameters. AAL and encapsulation are
79 * checked by the connection manager.
83 * Check called party address(es)
85 if (cvp->cvc_attr.called.tag != T_ATM_PRESENT ||
86 cvp->cvc_attr.called.addr.address_format ==
88 cvp->cvc_attr.called.subaddr.address_format !=
92 switch (cvp->cvc_attr.called.addr.address_format) {
95 * Make sure VPI/VCI is valid
98 pvp = (Atm_addr_pvc *)cvp->cvc_attr.called.addr.address;
99 vpi = ATM_PVC_GET_VPI(pvp);
100 vci = ATM_PVC_GET_VCI(pvp);
101 if ((vpi > pip->pif_maxvpi) ||
103 (vci > pip->pif_maxvci)) {
108 * Make sure VPI/VCI is not already in use
110 if (spans_find_vpvc(spp, vpi, vci, 0)) {
113 ATM_DEBUG2("spans_open_vcc: VPI.VCI=%d.%d\n",
117 case T_ATM_SPANS_ADDR:
122 * Check signalling state
124 if (spp->sp_state != SPANS_ACTIVE) {
129 *Check destination address length
131 if (cvp->cvc_attr.called.addr.address_length !=
132 sizeof(spans_addr)) {
142 * Check that this is for the same interface SPANS uses
144 if (!cvp->cvc_attr.nif ||
145 cvp->cvc_attr.nif->nif_pif != spp->sp_pif) {
152 if (!spans_get_spans_aal(cvp->cvc_attr.aal.type, &aal)) {
158 * Check encapsulation
160 /* XXX -- How do we check encapsulation? */
161 if (cvp->ac_encaps != ATM_ENC_NULL) {
167 * Allocate control block for VCC
169 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
178 svp->sv_type = VCC_PVC | VCC_IN | VCC_OUT;
181 svp->sv_sstate = (spp->sp_state == SPANS_ACTIVE ?
182 SPANS_VC_ACTIVE : SPANS_VC_ACT_DOWN);
183 svp->sv_ustate = VCCU_OPEN;
185 svp->sv_type = VCC_SVC | VCC_OUT;
186 spans_addr_copy(cvp->cvc_attr.called.addr.address,
187 &svp->sv_conn.con_dst);
188 spans_addr_copy(spp->sp_addr.address,
189 &svp->sv_conn.con_src);
190 svp->sv_conn.con_dsap = SPANS_SAP_IP;
191 svp->sv_conn.con_ssap = spans_ephemeral_sap(spp);
192 svp->sv_sstate = SPANS_VC_POPEN;
193 svp->sv_ustate = VCCU_POPEN;
195 svp->sv_proto = ATM_SIG_SPANS;
196 svp->sv_pif = spp->sp_pif;
197 svp->sv_nif = cvp->cvc_attr.nif;
198 svp->sv_connvc = cvp;
199 svp->sv_spans_aal = aal;
200 svp->sv_tstamp = time_second;
203 * Put VCCB on SPANS queue
205 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
208 * Link VCCB to VCC connection block
210 cvp->cvc_vcc = (struct vccb *) svp;
213 * Start the SPANS message exchange if this is an SVC
217 svp->sv_spans_qos.rsc_peak = 1;
218 svp->sv_spans_qos.rsc_mean = 1;
219 svp->sv_spans_qos.rsc_burst = 1;
220 err = spans_send_open_req(spp, svp);
223 * On error, delete the VCCB
225 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
227 cvp->cvc_vcc = (struct vccb *)0;
228 atm_free((caddr_t)svp);
232 * VCCB is opening--set the retransmit timer
234 SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
245 * Called when a user wants to close a VCC. This function will clean
246 * up the VCCB and, for an SVC, send a close request.
248 * Must be called at splnet.
251 * spp pointer to SPANS protocol instance
252 * svp pointer to VCCB for the VCC to be closed
255 * 0 VCC is now closed
256 * errno error encountered
259 spans_close_vcc(spp, svp, force)
261 struct spans_vccb *svp;
267 ATM_DEBUG2("spans_close_vcc: svp=%p, state=%d\n", svp,
271 * Check that this is for the same interface SPANS uses
273 if (svp->sv_pif != spp->sp_pif) {
278 * Kill any possible timer
280 SPANS_VC_CANCEL((struct vccb *) svp);
283 * Mark the close time.
285 svp->sv_tstamp = time_second;
288 * Process based on the connection type
290 if (svp->sv_type & VCC_PVC) {
291 svp->sv_sstate = SPANS_VC_FREE;
292 svp->sv_ustate = VCCU_CLOSED;
293 } else if (svp->sv_type & VCC_SVC) {
297 svp->sv_ustate = VCCU_CLOSED;
300 * Send the appropriate SPANS close message
302 switch (svp->sv_sstate) {
303 case SPANS_VC_R_POPEN:
304 err = spans_send_open_rsp(spp, svp, SPANS_FAIL);
305 svp->sv_sstate = SPANS_VC_FREE;
311 err = spans_send_close_req(spp, svp);
313 svp->sv_sstate = SPANS_VC_FREE;
315 svp->sv_sstate = SPANS_VC_CLOSE;
316 SPANS_VC_TIMER((struct vccb *) svp,
322 svp->sv_sstate = SPANS_VC_FREE;
329 * Wait for user to free resources
338 * Called when the signalling manager wants to close a VCC immediately.
339 * This function will clean up the VCCB and notify the owner.
341 * Must be called at splnet.
344 * spp pointer to SPANS protocol instance
345 * svp pointer to VCCB for the VCC to be closed
348 * 0 VCC is now closed
349 * errno error encountered
352 spans_clear_vcc(spp, svp)
354 struct spans_vccb *svp;
359 ATM_DEBUG2("spans_clear_vcc: svp=%p, state=%d\n", svp,
363 * Check that this is for the same interface SPANS uses
365 if (svp->sv_pif != spp->sp_pif) {
370 * Kill any possible timer
372 SPANS_VC_CANCEL((struct vccb *) svp);
375 * Mark the close time
377 svp->sv_tstamp = time_second;
380 * Mark the VCCB closed
382 outstate = svp->sv_sstate;
383 svp->sv_sstate = SPANS_VC_FREE;
384 svp->sv_ustate = VCCU_CLOSED;
387 * Notify the user if old state indicates.
390 case SPANS_VC_ACTIVE:
391 case SPANS_VC_ACT_DOWN:
396 /* XXX -- set cause */
397 atm_cm_cleared(svp->sv_connvc);
400 case SPANS_VC_R_POPEN:
406 * Wait for user to free resources
413 * Reset the switch state
415 * Called when the switch or host at the far end of the ATM link has
416 * gone away. This can be deteched either by a number of SPANS_STAT_REQ
417 * messages going unanswered or by the host epoch changing in a SPANS
418 * SPANS_STAT_IND or SPANS_STAT_REQ message.
421 * spp pointer to SPANS protocol instance
428 spans_switch_reset(spp, cause)
434 struct vccb *vcp, *vnext;
436 ATM_DEBUG2("spans_switch_reset: spp=%p, cause=%d\n",
442 log(LOG_INFO, "spans: signalling %s on interface %s%d\n",
443 (cause == SPANS_UNI_DOWN ? "down" : "up"),
444 spp->sp_pif->pif_name,
445 spp->sp_pif->pif_unit);
448 * Terminate all of our VCCs
451 for (vcp = Q_HEAD(spp->sp_vccq, struct vccb); vcp;
456 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
458 if (vcp->vc_type & VCC_SVC) {
460 * Close the SVC and notify the owner
462 outstate = vcp->vc_sstate;
463 SPANS_VC_CANCEL((struct vccb *) vcp);
464 vcp->vc_ustate = VCCU_CLOSED;
465 vcp->vc_sstate = SPANS_VC_FREE;
466 if (outstate == SPANS_VC_OPEN ||
467 outstate == SPANS_VC_POPEN) {
468 /* XXX -- set cause */
469 atm_cm_cleared(vcp->vc_connvc);
471 } else if (vcp->vc_type & VCC_PVC) {
477 vcp->vc_sstate = SPANS_VC_ACT_DOWN;
480 vcp->vc_sstate = SPANS_VC_ACTIVE;
484 log(LOG_ERR, "spans: invalid VCC type: vccb=%p, type=%d\n",