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 $
30 * SPANS Signalling Manager
31 * ---------------------------
33 * SPANS-related subroutines.
37 #include <netproto/atm/kern_include.h>
39 #include "spans_xdr.h"
40 #include "spans_var.h"
45 * Called when a user wants to open a VC. This function will construct
46 * a VCCB, create the stack requested by the user, and, if we are
47 * opening an SVC, start the SPANS signalling message exchange. The
48 * user will have to wait for a notify event to be sure the SVC is fully
51 * Must be called from a critical section.
54 * spp pointer to SPANS protocol instance
55 * acp pointer to PVC's connection parameters
58 * 0 VCC creation successful
59 * errno VCC setup failed - reason indicated
63 spans_open_vcc(struct spans *spp, Atm_connvc *cvp)
65 struct atm_pif *pip = spp->sp_pif;
66 struct spans_vccb *svp;
69 int err, pvc, vpi, vci;
71 ATM_DEBUG2("spans_open_vcc: spp=%p, cvp=%p\n", spp, cvp);
74 * Validate user parameters. AAL and encapsulation are
75 * checked by the connection manager.
79 * Check called party address(es)
81 if (cvp->cvc_attr.called.tag != T_ATM_PRESENT ||
82 cvp->cvc_attr.called.addr.address_format ==
84 cvp->cvc_attr.called.subaddr.address_format !=
88 switch (cvp->cvc_attr.called.addr.address_format) {
91 * Make sure VPI/VCI is valid
94 pvp = (Atm_addr_pvc *)cvp->cvc_attr.called.addr.address;
95 vpi = ATM_PVC_GET_VPI(pvp);
96 vci = ATM_PVC_GET_VCI(pvp);
97 if ((vpi > pip->pif_maxvpi) ||
99 (vci > pip->pif_maxvci)) {
104 * Make sure VPI/VCI is not already in use
106 if (spans_find_vpvc(spp, vpi, vci, 0)) {
109 ATM_DEBUG2("spans_open_vcc: VPI.VCI=%d.%d\n",
113 case T_ATM_SPANS_ADDR:
118 * Check signalling state
120 if (spp->sp_state != SPANS_ACTIVE) {
125 *Check destination address length
127 if (cvp->cvc_attr.called.addr.address_length !=
128 sizeof(spans_addr)) {
138 * Check that this is for the same interface SPANS uses
140 if (!cvp->cvc_attr.nif ||
141 cvp->cvc_attr.nif->nif_pif != spp->sp_pif) {
148 if (!spans_get_spans_aal(cvp->cvc_attr.aal.type, &aal)) {
154 * Check encapsulation
156 /* XXX -- How do we check encapsulation? */
157 if (cvp->ac_encaps != ATM_ENC_NULL) {
163 * Allocate control block for VCC
165 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
174 svp->sv_type = VCC_PVC | VCC_IN | VCC_OUT;
177 svp->sv_sstate = (spp->sp_state == SPANS_ACTIVE ?
178 SPANS_VC_ACTIVE : SPANS_VC_ACT_DOWN);
179 svp->sv_ustate = VCCU_OPEN;
181 svp->sv_type = VCC_SVC | VCC_OUT;
182 spans_addr_copy(cvp->cvc_attr.called.addr.address,
183 &svp->sv_conn.con_dst);
184 spans_addr_copy(spp->sp_addr.address,
185 &svp->sv_conn.con_src);
186 svp->sv_conn.con_dsap = SPANS_SAP_IP;
187 svp->sv_conn.con_ssap = spans_ephemeral_sap(spp);
188 svp->sv_sstate = SPANS_VC_POPEN;
189 svp->sv_ustate = VCCU_POPEN;
191 svp->sv_proto = ATM_SIG_SPANS;
192 svp->sv_pif = spp->sp_pif;
193 svp->sv_nif = cvp->cvc_attr.nif;
194 svp->sv_connvc = cvp;
195 svp->sv_spans_aal = aal;
196 svp->sv_tstamp = time_second;
199 * Put VCCB on SPANS queue
201 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
204 * Link VCCB to VCC connection block
206 cvp->cvc_vcc = (struct vccb *) svp;
209 * Start the SPANS message exchange if this is an SVC
213 svp->sv_spans_qos.rsc_peak = 1;
214 svp->sv_spans_qos.rsc_mean = 1;
215 svp->sv_spans_qos.rsc_burst = 1;
216 err = spans_send_open_req(spp, svp);
219 * On error, delete the VCCB
221 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
224 atm_free((caddr_t)svp);
228 * VCCB is opening--set the retransmit timer
230 SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
241 * Called when a user wants to close a VCC. This function will clean
242 * up the VCCB and, for an SVC, send a close request.
244 * Must be called from a critical section.
247 * spp pointer to SPANS protocol instance
248 * svp pointer to VCCB for the VCC to be closed
251 * 0 VCC is now closed
252 * errno error encountered
255 spans_close_vcc(struct spans *spp, struct spans_vccb *svp, int force)
259 ATM_DEBUG2("spans_close_vcc: svp=%p, state=%d\n", svp,
263 * Check that this is for the same interface SPANS uses
265 if (svp->sv_pif != spp->sp_pif) {
270 * Kill any possible timer
272 SPANS_VC_CANCEL((struct vccb *) svp);
275 * Mark the close time.
277 svp->sv_tstamp = time_second;
280 * Process based on the connection type
282 if (svp->sv_type & VCC_PVC) {
283 svp->sv_sstate = SPANS_VC_FREE;
284 svp->sv_ustate = VCCU_CLOSED;
285 } else if (svp->sv_type & VCC_SVC) {
289 svp->sv_ustate = VCCU_CLOSED;
292 * Send the appropriate SPANS close message
294 switch (svp->sv_sstate) {
295 case SPANS_VC_R_POPEN:
296 err = spans_send_open_rsp(spp, svp, SPANS_FAIL);
297 svp->sv_sstate = SPANS_VC_FREE;
303 err = spans_send_close_req(spp, svp);
305 svp->sv_sstate = SPANS_VC_FREE;
307 svp->sv_sstate = SPANS_VC_CLOSE;
308 SPANS_VC_TIMER((struct vccb *) svp,
314 svp->sv_sstate = SPANS_VC_FREE;
321 * Wait for user to free resources
330 * Called when the signalling manager wants to close a VCC immediately.
331 * This function will clean up the VCCB and notify the owner.
333 * Must be called from a critical section.
336 * spp pointer to SPANS protocol instance
337 * svp pointer to VCCB for the VCC to be closed
340 * 0 VCC is now closed
341 * errno error encountered
344 spans_clear_vcc(struct spans *spp, struct spans_vccb *svp)
348 ATM_DEBUG2("spans_clear_vcc: svp=%p, state=%d\n", svp,
352 * Check that this is for the same interface SPANS uses
354 if (svp->sv_pif != spp->sp_pif) {
359 * Kill any possible timer
361 SPANS_VC_CANCEL((struct vccb *) svp);
364 * Mark the close time
366 svp->sv_tstamp = time_second;
369 * Mark the VCCB closed
371 outstate = svp->sv_sstate;
372 svp->sv_sstate = SPANS_VC_FREE;
373 svp->sv_ustate = VCCU_CLOSED;
376 * Notify the user if old state indicates.
379 case SPANS_VC_ACTIVE:
380 case SPANS_VC_ACT_DOWN:
385 /* XXX -- set cause */
386 atm_cm_cleared(svp->sv_connvc);
389 case SPANS_VC_R_POPEN:
395 * Wait for user to free resources
402 * Reset the switch state
404 * Called when the switch or host at the far end of the ATM link has
405 * gone away. This can be deteched either by a number of SPANS_STAT_REQ
406 * messages going unanswered or by the host epoch changing in a SPANS
407 * SPANS_STAT_IND or SPANS_STAT_REQ message.
410 * spp pointer to SPANS protocol instance
417 spans_switch_reset(struct spans *spp, int cause)
419 struct vccb *vcp, *vnext;
421 ATM_DEBUG2("spans_switch_reset: spp=%p, cause=%d\n",
427 log(LOG_INFO, "spans: signalling %s on interface %s%d\n",
428 (cause == SPANS_UNI_DOWN ? "down" : "up"),
429 spp->sp_pif->pif_name,
430 spp->sp_pif->pif_unit);
433 * Terminate all of our VCCs
436 for (vcp = Q_HEAD(spp->sp_vccq, struct vccb); vcp;
441 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
443 if (vcp->vc_type & VCC_SVC) {
445 * Close the SVC and notify the owner
447 outstate = vcp->vc_sstate;
448 SPANS_VC_CANCEL(vcp);
449 vcp->vc_ustate = VCCU_CLOSED;
450 vcp->vc_sstate = SPANS_VC_FREE;
451 if (outstate == SPANS_VC_OPEN ||
452 outstate == SPANS_VC_POPEN) {
453 /* XXX -- set cause */
454 atm_cm_cleared(vcp->vc_connvc);
456 } else if (vcp->vc_type & VCC_PVC) {
462 vcp->vc_sstate = SPANS_VC_ACT_DOWN;
465 vcp->vc_sstate = SPANS_VC_ACTIVE;
469 log(LOG_ERR, "spans: invalid VCC type: vccb=%p, type=%d\n",