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/sigpvc/sigpvc_if.c,v 1.7 2000/01/17 20:49:46 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/sigpvc/sigpvc_if.c,v 1.11 2006/12/20 18:14:43 dillon Exp $
31 * PVC-only Signalling Manager
32 * ---------------------------
34 * External interfaces to SigPVC manager. Includes support for
35 * running as a loadable kernel module.
39 #ifndef ATM_SIGPVC_MODULE
43 #include <netproto/atm/kern_include.h>
45 #include "sigpvc_var.h"
50 struct sp_info sigpvc_vcpool
= {
51 "sigpvc vcc pool", /* si_name */
52 sizeof(struct sigpvc_vccb
), /* si_blksiz */
60 static int sigpvc_start (void);
61 static int sigpvc_stop (void);
62 static int sigpvc_attach (struct sigmgr
*, struct atm_pif
*);
63 static int sigpvc_detach (struct atm_pif
*);
64 static int sigpvc_setup (Atm_connvc
*, int *);
65 static int sigpvc_release (struct vccb
*, int *);
66 static int sigpvc_free (struct vccb
*);
67 static int sigpvc_ioctl (int, caddr_t
, caddr_t
);
72 static int sigpvc_registered
= 0;
73 static struct sigmgr sigpvc_mgr
= {
87 static struct attr_cause sigpvc_cause
= {
92 T_ATM_CAUSE_UNSPECIFIED_NORMAL
,
99 * Initialize sigpvc processing
101 * This will be called during module loading. We'll just register
102 * the sigpvc protocol descriptor and wait for a SigPVC ATM interface
109 * 0 startup was successful
110 * errno startup failed - reason indicated
119 * Verify software version
121 if (atm_version
!= ATM_VERSION
) {
122 log(LOG_ERR
, "version mismatch: sigpvc=%d.%d kernel=%d.%d\n",
123 ATM_VERS_MAJ(ATM_VERSION
), ATM_VERS_MIN(ATM_VERSION
),
124 ATM_VERS_MAJ(atm_version
), ATM_VERS_MIN(atm_version
));
129 * Register ourselves with system
131 err
= atm_sigmgr_register(&sigpvc_mgr
);
133 sigpvc_registered
= 1;
140 * Halt sigpvc processing
142 * This should be called just prior to unloading the module from
143 * memory. All sigpvc interfaces must be deregistered before the
144 * protocol can be shutdown.
150 * 0 shutdown was successful
151 * errno shutdown failed - reason indicated
162 * Is protocol even setup?
164 if (sigpvc_registered
) {
167 * Any protocol instances still registered??
169 if (sigpvc_mgr
.sm_prinst
) {
171 /* Yes, can't stop now */
177 * De-register from system
179 err
= atm_sigmgr_deregister(&sigpvc_mgr
);
180 sigpvc_registered
= 0;
183 * Free up our vccb storage pool
185 atm_release_pool(&sigpvc_vcpool
);
196 * Attach a SigPVC-controlled interface
198 * Each ATM physical interface must be attached with the signalling manager for
199 * the interface's signalling protocol (via the atm_sigmgr_attach function).
200 * This function will handle the attachment for SigPVC-controlled interfaces.
201 * A new sigpvc protocol instance will be created and then we'll just sit
202 * around waiting for connection requests.
204 * Function must be called from a critical section.
207 * smp pointer to sigpvc signalling manager control block
208 * pip pointer to atm physical interface control block
211 * 0 attach successful
212 * errno attach failed - reason indicated
216 sigpvc_attach(struct sigmgr
*smp
, struct atm_pif
*pip
)
219 struct sigpvc
*pvp
= NULL
;
222 * Allocate sigpvc protocol instance control block
224 pvp
= KM_ALLOC(sizeof(struct sigpvc
), M_DEVBUF
, M_INTWAIT
| M_NULLOK
);
229 KM_ZERO(pvp
, sizeof(struct sigpvc
));
232 * Link instance into manager's chain
234 LINK2TAIL((struct siginst
*)pvp
, struct siginst
,
235 smp
->sm_prinst
, si_next
);
238 * Finally, set state and link in interface
241 pvp
->pv_state
= SIGPVC_ACTIVE
;
242 pip
->pif_sigmgr
= smp
;
243 pip
->pif_siginst
= (struct siginst
*)pvp
;
247 * Reset our work if attach fails
250 pip
->pif_sigmgr
= NULL
;
251 pip
->pif_siginst
= NULL
;
253 UNLINK((struct siginst
*)pvp
, struct siginst
,
254 smp
->sm_prinst
, si_next
);
255 KM_FREE(pvp
, sizeof(struct sigpvc
), M_DEVBUF
);
264 * Detach a SigPVC-controlled interface
266 * Each ATM physical interface may be detached from its signalling manager
267 * (via the atm_sigmgr_detach function). This function will handle the
268 * detachment for all SigPVC-controlled interfaces. All circuits will be
269 * immediately terminated.
271 * Function must be called from a critical section.
274 * pip pointer to atm physical interface control block
277 * 0 detach successful
278 * errno detach failed - reason indicated
282 sigpvc_detach(struct atm_pif
*pip
)
285 struct vccb
*vcp
, *vnext
;
288 * Get SigPVC protocol instance
290 pvp
= (struct sigpvc
*)pip
->pif_siginst
;
293 * Terminate all of our VCCs
295 for (vcp
= Q_HEAD(pvp
->pv_vccq
, struct vccb
); vcp
; vcp
= vnext
){
298 vnext
= Q_NEXT(vcp
, struct vccb
, vc_sigelem
);
301 * Close VCC and notify owner
303 oustate
= vcp
->vc_ustate
;
304 sigpvc_close_vcc(vcp
);
305 if (oustate
== VCCU_OPEN
) {
306 vcp
->vc_connvc
->cvc_attr
.cause
= sigpvc_cause
;
307 atm_cm_cleared(vcp
->vc_connvc
);
312 * If there are no vcc's queued, then get rid of the protocol
315 if (Q_HEAD(pvp
->pv_vccq
, struct vccb
) == NULL
) {
316 struct sigmgr
*smp
= pip
->pif_sigmgr
;
318 pip
->pif_sigmgr
= NULL
;
319 pip
->pif_siginst
= NULL
;
320 UNLINK((struct siginst
*)pvp
, struct siginst
, smp
->sm_prinst
,
322 KM_FREE(pvp
, sizeof(struct sigpvc
), M_DEVBUF
);
326 * Otherwise, set new state indicating detach in progress.
327 * The protocol instance will be freed during sigpvc_free
328 * processing for the last queued vcc.
330 pvp
->pv_state
= SIGPVC_DETACH
;
338 * Open a SigPVC ATM Connection
340 * All service user requests to open a VC connection (via atm_open_connection)
341 * over an ATM interface attached to the SigPVC signalling manager are handled
342 * here. Only PVC requests are allowed.
344 * Function will be called from a critical section.
347 * cvp pointer to CM's connection VCC
348 * errp location to store an error code if CALL_FAILED is returned
351 * CALL_PROCEEDING - connection establishment is in progress
352 * CALL_FAILED - connection establishment failed
353 * CALL_CONNECTED - connection has been successfully established
357 sigpvc_setup(Atm_connvc
*cvp
, int *errp
)
360 (struct sigpvc
*)cvp
->cvc_attr
.nif
->nif_pif
->pif_siginst
;
364 * See what signalling has to say
366 switch (pvp
->pv_state
) {
378 * Open requested type of connection
380 switch (cvp
->cvc_attr
.called
.addr
.address_format
) {
386 ret
= sigpvc_create_pvc(pvp
, cvp
, errp
);
390 *errp
= EPROTONOSUPPORT
;
400 * Close a SigPVC ATM Connection
402 * All service user requests to terminate a previously open VC connection
403 * (via the atm_close_connection function), which is running over an interface
404 * attached to the SigPVC signalling manager, are handled here.
406 * Function will be called from a critical section.
409 * vcp pointer to connection's VC control block
410 * errp location to store an error code if CALL_FAILED is returned
413 * CALL_PROCEEDING - connection termination is in progress
414 * CALL_FAILED - connection termination failed
415 * CALL_CLEARED - connection has been successfully terminated
419 sigpvc_release(struct vccb
*vcp
, int *errp
)
423 * Make sure VCC is open
425 if ((vcp
->vc_sstate
== VCCS_NULL
) || (vcp
->vc_sstate
== VCCS_FREE
) ||
426 (vcp
->vc_ustate
== VCCU_NULL
) || (vcp
->vc_ustate
== VCCU_CLOSED
)) {
428 return (CALL_FAILED
);
432 * Not much else to do except close the vccb
434 sigpvc_close_vcc(vcp
);
436 return (CALL_CLEARED
);
441 * Free SigPVC ATM Connection Resources
443 * All service user requests to free the resources of a closed VCC connection
444 * (via the atm_free_connection function), which is running over an interface
445 * attached to the SigPVC signalling manager, are handled here.
447 * Function will be called from a critical section.
450 * vcp pointer to connection's VCC control block
453 * 0 connection free was successful
454 * errno connection free failed - reason indicated
458 sigpvc_free(struct vccb
*vcp
)
460 struct atm_pif
*pip
= vcp
->vc_pif
;
461 struct sigpvc
*pvp
= (struct sigpvc
*)pip
->pif_siginst
;
464 * Make sure VCC has been closed
466 if ((vcp
->vc_ustate
!= VCCU_CLOSED
) || (vcp
->vc_sstate
!= VCCS_FREE
))
470 * Remove vccb from protocol queue
472 DEQUEUE(vcp
, struct vccb
, vc_sigelem
, pvp
->pv_vccq
);
477 vcp
->vc_ustate
= VCCU_NULL
;
478 vcp
->vc_sstate
= VCCS_NULL
;
479 atm_free((caddr_t
)vcp
);
482 * If we're detaching and this was the last vcc queued,
483 * get rid of the protocol instance
485 if ((pvp
->pv_state
== SIGPVC_DETACH
) &&
486 (Q_HEAD(pvp
->pv_vccq
, struct vccb
) == NULL
)) {
487 struct sigmgr
*smp
= pip
->pif_sigmgr
;
489 pip
->pif_sigmgr
= NULL
;
490 pip
->pif_siginst
= NULL
;
491 UNLINK((struct siginst
*)pvp
, struct siginst
, smp
->sm_prinst
,
493 KM_FREE(pvp
, sizeof(struct sigpvc
), M_DEVBUF
);
501 * Process Signalling Manager PF_ATM ioctls
503 * Function will be called from a critical section.
506 * code PF_ATM sub-operation code
507 * data pointer to code specific parameter data area
508 * arg1 pointer to code specific argument
512 * errno error processing request - reason indicated
516 sigpvc_ioctl(int code
, caddr_t data
, caddr_t arg1
)
518 struct atmdelreq
*adp
;
519 struct atminfreq
*aip
;
520 struct air_vcc_rsp avr
;
526 int i
, space
, err
= 0;
535 adp
= (struct atmdelreq
*)data
;
536 pvp
= (struct sigpvc
*)arg1
;
541 vpi
= adp
->adr_pvc_vpi
;
542 vci
= adp
->adr_pvc_vci
;
543 for (vcp
= Q_HEAD(pvp
->pv_vccq
, struct vccb
); vcp
;
544 vcp
= Q_NEXT(vcp
, struct vccb
, vc_sigelem
)) {
545 if ((vcp
->vc_vpi
== vpi
) && (vcp
->vc_vci
== vci
))
552 * Schedule VCC termination
554 err
= atm_cm_abort(vcp
->vc_connvc
, &sigpvc_cause
.v
);
566 * Get VCC information
568 aip
= (struct atminfreq
*)data
;
569 pvp
= (struct sigpvc
*)arg1
;
571 cp
= aip
->air_buf_addr
;
572 space
= aip
->air_buf_len
;
575 * Get info for all VCCs on interface
577 for (vcp
= Q_HEAD(pvp
->pv_vccq
, struct vccb
); vcp
;
578 vcp
= Q_NEXT(vcp
, struct vccb
, vc_sigelem
)) {
580 * Make sure there's room in user buffer
582 if (space
< sizeof(avr
)) {
588 * Fill in info to be returned
590 ksnprintf(avr
.avp_intf
, sizeof(avr
.avp_intf
),
592 pvp
->pv_pif
->pif_name
, pvp
->pv_pif
->pif_unit
);
593 avr
.avp_vpi
= vcp
->vc_vpi
;
594 avr
.avp_vci
= vcp
->vc_vci
;
595 avr
.avp_type
= vcp
->vc_type
;
596 avr
.avp_sig_proto
= ATM_SIG_PVC
;
597 avr
.avp_aal
= vcp
->vc_connvc
->cvc_attr
.aal
.type
;
598 cop
= vcp
->vc_connvc
->cvc_conn
;
600 avr
.avp_encaps
= cop
->co_mpx
;
603 KM_ZERO(avr
.avp_owners
, sizeof(avr
.avp_owners
));
604 for (i
= 0; cop
&& i
< sizeof(avr
.avp_owners
);
606 i
+= T_ATM_APP_NAME_LEN
+1) {
607 strncpy(&avr
.avp_owners
[i
],
608 cop
->co_endpt
->ep_getname(cop
->co_toku
),
611 avr
.avp_state
= vcp
->vc_sstate
;
612 avr
.avp_daddr
.address_format
= T_ATM_ABSENT
;
613 avr
.avp_dsubaddr
.address_format
= T_ATM_ABSENT
;
614 avr
.avp_ipdus
= vcp
->vc_ipdus
;
615 avr
.avp_opdus
= vcp
->vc_opdus
;
616 avr
.avp_ibytes
= vcp
->vc_ibytes
;
617 avr
.avp_obytes
= vcp
->vc_obytes
;
618 avr
.avp_ierrors
= vcp
->vc_ierrors
;
619 avr
.avp_oerrors
= vcp
->vc_oerrors
;
620 avr
.avp_tstamp
= vcp
->vc_tstamp
;
623 * Copy data to user buffer and update buffer info
625 if ((err
= copyout((caddr_t
)&avr
, cp
, sizeof(avr
))) != 0)
628 space
-= sizeof(avr
);
632 * Update buffer pointer/count
634 aip
->air_buf_addr
= cp
;
635 aip
->air_buf_len
= space
;
641 * Get ARP table/server information
643 /* We don't maintain any ARP information */
654 #ifdef ATM_SIGPVC_MODULE
656 *******************************************************************
658 * Loadable Module Support
660 *******************************************************************
662 static int sigpvc_doload (void);
663 static int sigpvc_dounload (void);
666 * Generic module load processing
668 * This function is called by an OS-specific function when this
669 * module is being loaded.
675 * 0 load was successful
676 * errno load failed - reason indicated
687 err
= sigpvc_start();
689 /* Problems, clean up */
697 * Generic module unload processing
699 * This function is called by an OS-specific function when this
700 * module is being unloaded.
706 * 0 unload was successful
707 * errno unload failed - reason indicated
711 sigpvc_dounload(void)
716 * OK, try to clean up our mess
723 #include <sys/exec.h>
724 #include <sys/sysent.h>
728 * Loadable miscellaneous module description
734 * Loadable module support "load" entry point
736 * This is the routine called by the lkm driver whenever the
737 * modload(1) command is issued for this module.
740 * lkmtp pointer to lkm drivers's structure
741 * cmd lkm command code
744 * 0 command was successful
745 * errno command failed - reason indicated
749 sigpvc_load(struct lkm_table
*lkmtp
, int cmd
)
751 return(sigpvc_doload());
756 * Loadable module support "unload" entry point
758 * This is the routine called by the lkm driver whenever the
759 * modunload(1) command is issued for this module.
762 * lkmtp pointer to lkm drivers's structure
763 * cmd lkm command code
766 * 0 command was successful
767 * errno command failed - reason indicated
771 sigpvc_unload(struct lkm_table
*lkmtp
, int cmd
)
773 return(sigpvc_dounload());
778 * Loadable module support entry point
780 * This is the routine called by the lkm driver for all loadable module
781 * functions for this driver. This routine name must be specified
782 * on the modload(1) command. This routine will be called whenever the
783 * modload(1), modunload(1) or modstat(1) commands are issued for this
787 * lkmtp pointer to lkm drivers's structure
788 * cmd lkm command code
792 * 0 command was successful
793 * errno command failed - reason indicated
797 sigpvc_mod(struct lkm_table
*lkmtp
, int cmd
, int ver
)
799 MOD_DISPATCH(sigpvc
, lkmtp
, cmd
, ver
,
800 sigpvc_load
, sigpvc_unload
, lkm_nullcmd
);
803 #else /* !ATM_SIGPVC_MODULE */
806 *******************************************************************
808 * Kernel Compiled Module Support
810 *******************************************************************
812 static void sigpvc_doload (void *);
814 SYSINIT(atmsigpvc
, SI_SUB_PROTO_END
, SI_ORDER_ANY
, sigpvc_doload
, NULL
)
817 * Kernel initialization
827 sigpvc_doload(void *arg
)
834 err
= sigpvc_start();
836 /* Problems, clean up */
839 log(LOG_ERR
, "ATM SIGPVC unable to initialize (%d)!!\n", err
);
843 #endif /* ATM_SIGPVC_MODULE */