fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / spans / spans_subr.c
blob1eb62f42089e7067be19b7167463a676dea5d422
1 /*
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"
44 * Open a SPANS VCC
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
50 * open.
52 * Must be called from a critical section.
54 * Arguments:
55 * spp pointer to SPANS protocol instance
56 * acp pointer to PVC's connection parameters
58 * Returns:
59 * 0 VCC creation successful
60 * errno VCC setup failed - reason indicated
63 int
64 spans_open_vcc(struct spans *spp, Atm_connvc *cvp)
66 struct atm_pif *pip = spp->sp_pif;
67 struct spans_vccb *svp;
68 Atm_addr_pvc *pvp;
69 spans_aal aal;
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 ==
84 T_ATM_ABSENT ||
85 cvp->cvc_attr.called.subaddr.address_format !=
86 T_ATM_ABSENT) {
87 return(EINVAL);
89 switch (cvp->cvc_attr.called.addr.address_format) {
90 case T_ATM_PVC_ADDR:
92 * Make sure VPI/VCI is valid
94 pvc = 1;
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) ||
99 (vci == 0) ||
100 (vci > pip->pif_maxvci)) {
101 return(ERANGE);
105 * Make sure VPI/VCI is not already in use
107 if (spans_find_vpvc(spp, vpi, vci, 0)) {
108 return(EADDRINUSE);
110 ATM_DEBUG2("spans_open_vcc: VPI.VCI=%d.%d\n",
111 vpi, vci);
112 break;
114 case T_ATM_SPANS_ADDR:
115 pvc = 0;
116 vpi = vci = 0;
119 * Check signalling state
121 if (spp->sp_state != SPANS_ACTIVE) {
122 return(ENETDOWN);
126 *Check destination address length
128 if (cvp->cvc_attr.called.addr.address_length !=
129 sizeof(spans_addr)) {
130 return(EINVAL);
132 break;
134 default:
135 return(EINVAL);
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) {
143 return(EINVAL);
147 * Check AAL
149 if (!spans_get_spans_aal(cvp->cvc_attr.aal.type, &aal)) {
150 return(EINVAL);
153 #ifdef NOTDEF
155 * Check encapsulation
157 /* XXX -- How do we check encapsulation? */
158 if (cvp->ac_encaps != ATM_ENC_NULL) {
159 return(EINVAL);
161 #endif
164 * Allocate control block for VCC
166 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
167 if (svp == NULL) {
168 return(ENOMEM);
172 * Fill in VCCB
174 if (pvc) {
175 svp->sv_type = VCC_PVC | VCC_IN | VCC_OUT;
176 svp->sv_vpi = vpi;
177 svp->sv_vci = vci;
178 svp->sv_sstate = (spp->sp_state == SPANS_ACTIVE ?
179 SPANS_VC_ACTIVE : SPANS_VC_ACT_DOWN);
180 svp->sv_ustate = VCCU_OPEN;
181 } else {
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
212 if (!pvc) {
213 svp->sv_retry = 0;
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);
218 if (err) {
220 * On error, delete the VCCB
222 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
223 spp->sp_vccq);
224 cvp->cvc_vcc = NULL;
225 atm_free((caddr_t)svp);
226 return(err);
227 } else {
229 * VCCB is opening--set the retransmit timer
231 SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
235 return(0);
240 * Close a SPANS VCC
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.
247 * Arguments:
248 * spp pointer to SPANS protocol instance
249 * svp pointer to VCCB for the VCC to be closed
251 * Returns:
252 * 0 VCC is now closed
253 * errno error encountered
256 spans_close_vcc(struct spans *spp, struct spans_vccb *svp, int force)
258 int err = 0;
260 ATM_DEBUG2("spans_close_vcc: svp=%p, state=%d\n", svp,
261 svp->sv_sstate);
264 * Check that this is for the same interface SPANS uses
266 if (svp->sv_pif != spp->sp_pif) {
267 return (EINVAL);
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) {
288 * Update VCCB states
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;
299 break;
300 case SPANS_VC_OPEN:
301 case SPANS_VC_POPEN:
302 case SPANS_VC_ABORT:
303 svp->sv_retry = 0;
304 err = spans_send_close_req(spp, svp);
305 if (force) {
306 svp->sv_sstate = SPANS_VC_FREE;
307 } else {
308 svp->sv_sstate = SPANS_VC_CLOSE;
309 SPANS_VC_TIMER((struct vccb *) svp,
310 SV_TIMEOUT);
312 break;
313 case SPANS_VC_CLOSE:
314 if (force) {
315 svp->sv_sstate = SPANS_VC_FREE;
317 break;
322 * Wait for user to free resources
324 return(err);
329 * Clear a SPANS VCC
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.
336 * Arguments:
337 * spp pointer to SPANS protocol instance
338 * svp pointer to VCCB for the VCC to be closed
340 * Returns:
341 * 0 VCC is now closed
342 * errno error encountered
345 spans_clear_vcc(struct spans *spp, struct spans_vccb *svp)
347 u_char outstate;
349 ATM_DEBUG2("spans_clear_vcc: svp=%p, state=%d\n", svp,
350 svp->sv_sstate);
353 * Check that this is for the same interface SPANS uses
355 if (svp->sv_pif != spp->sp_pif) {
356 return (EINVAL);
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.
379 switch (outstate) {
380 case SPANS_VC_ACTIVE:
381 case SPANS_VC_ACT_DOWN:
382 case SPANS_VC_POPEN:
383 case SPANS_VC_OPEN:
384 case SPANS_VC_CLOSE:
385 case SPANS_VC_ABORT:
386 /* XXX -- set cause */
387 atm_cm_cleared(svp->sv_connvc);
388 break;
389 case SPANS_VC_NULL:
390 case SPANS_VC_R_POPEN:
391 case SPANS_VC_FREE:
392 break;
396 * Wait for user to free resources
398 return(0);
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.
410 * Arguments:
411 * spp pointer to SPANS protocol instance
413 * Returns:
414 * none
417 void
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",
423 spp, cause);
426 * Log the event
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
436 crit_enter();
437 for (vcp = Q_HEAD(spp->sp_vccq, struct vccb); vcp;
438 vcp = vnext) {
440 u_char outstate;
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) {
459 * Note new state
461 switch(cause) {
462 case SPANS_UNI_DOWN:
463 vcp->vc_sstate = SPANS_VC_ACT_DOWN;
464 break;
465 case SPANS_UNI_UP:
466 vcp->vc_sstate = SPANS_VC_ACTIVE;
467 break;
469 } else {
470 log(LOG_ERR, "spans: invalid VCC type: vccb=%p, type=%d\n",
471 vcp, vcp->vc_type);
474 crit_exit();