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 */