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.3 2003/08/07 21:17:34 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 <netatm/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 __P((void));
61 static int sigpvc_stop __P((void));
62 static int sigpvc_attach __P((struct sigmgr *, struct atm_pif *));
63 static int sigpvc_detach __P((struct atm_pif *));
64 static int sigpvc_setup __P((Atm_connvc *, int *));
65 static int sigpvc_release __P((struct vccb *, int *));
66 static int sigpvc_free __P((struct vccb *));
67 static int sigpvc_ioctl __P((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
161 * Is protocol even setup?
163 if (sigpvc_registered) {
166 * Any protocol instances still registered??
168 if (sigpvc_mgr.sm_prinst) {
170 /* Yes, can't stop now */
176 * De-register from system
178 err = atm_sigmgr_deregister(&sigpvc_mgr);
179 sigpvc_registered = 0;
182 * Free up our vccb storage pool
184 atm_release_pool(&sigpvc_vcpool);
195 * Attach a SigPVC-controlled interface
197 * Each ATM physical interface must be attached with the signalling manager for
198 * the interface's signalling protocol (via the atm_sigmgr_attach function).
199 * This function will handle the attachment for SigPVC-controlled interfaces.
200 * A new sigpvc protocol instance will be created and then we'll just sit
201 * around waiting for connection requests.
203 * Function must be called at splnet.
206 * smp pointer to sigpvc signalling manager control block
207 * pip pointer to atm physical interface control block
210 * 0 attach successful
211 * errno attach failed - reason indicated
215 sigpvc_attach(smp, pip)
220 struct sigpvc *pvp = NULL;
223 * Allocate sigpvc protocol instance control block
225 pvp = (struct sigpvc *)
226 KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_NOWAIT);
231 KM_ZERO(pvp, sizeof(struct sigpvc));
234 * Link instance into manager's chain
236 LINK2TAIL((struct siginst *)pvp, struct siginst,
237 smp->sm_prinst, si_next);
240 * Finally, set state and link in interface
243 pvp->pv_state = SIGPVC_ACTIVE;
244 pip->pif_sigmgr = smp;
245 pip->pif_siginst = (struct siginst *)pvp;
249 * Reset our work if attach fails
252 pip->pif_sigmgr = NULL;
253 pip->pif_siginst = NULL;
255 UNLINK((struct siginst *)pvp, struct siginst,
256 smp->sm_prinst, si_next);
257 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
266 * Detach a SigPVC-controlled interface
268 * Each ATM physical interface may be detached from its signalling manager
269 * (via the atm_sigmgr_detach function). This function will handle the
270 * detachment for all SigPVC-controlled interfaces. All circuits will be
271 * immediately terminated.
273 * Function must be called at splnet.
276 * pip pointer to atm physical interface control block
279 * 0 detach successful
280 * errno detach failed - reason indicated
288 struct vccb *vcp, *vnext;
291 * Get SigPVC protocol instance
293 pvp = (struct sigpvc *)pip->pif_siginst;
296 * Terminate all of our VCCs
298 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
301 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
304 * Close VCC and notify owner
306 oustate = vcp->vc_ustate;
307 sigpvc_close_vcc(vcp);
308 if (oustate == VCCU_OPEN) {
309 vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
310 atm_cm_cleared(vcp->vc_connvc);
315 * If there are no vcc's queued, then get rid of the protocol
318 if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
319 struct sigmgr *smp = pip->pif_sigmgr;
321 pip->pif_sigmgr = NULL;
322 pip->pif_siginst = NULL;
323 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
325 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
329 * Otherwise, set new state indicating detach in progress.
330 * The protocol instance will be freed during sigpvc_free
331 * processing for the last queued vcc.
333 pvp->pv_state = SIGPVC_DETACH;
341 * Open a SigPVC ATM Connection
343 * All service user requests to open a VC connection (via atm_open_connection)
344 * over an ATM interface attached to the SigPVC signalling manager are handled
345 * here. Only PVC requests are allowed.
347 * Function will be called at splnet.
350 * cvp pointer to CM's connection VCC
351 * errp location to store an error code if CALL_FAILED is returned
354 * CALL_PROCEEDING - connection establishment is in progress
355 * CALL_FAILED - connection establishment failed
356 * CALL_CONNECTED - connection has been successfully established
360 sigpvc_setup(cvp, errp)
365 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
369 * See what signalling has to say
371 switch (pvp->pv_state) {
383 * Open requested type of connection
385 switch (cvp->cvc_attr.called.addr.address_format) {
391 ret = sigpvc_create_pvc(pvp, cvp, errp);
395 *errp = EPROTONOSUPPORT;
405 * Close a SigPVC ATM Connection
407 * All service user requests to terminate a previously open VC connection
408 * (via the atm_close_connection function), which is running over an interface
409 * attached to the SigPVC signalling manager, are handled here.
411 * Function will be called at splnet.
414 * vcp pointer to connection's VC control block
415 * errp location to store an error code if CALL_FAILED is returned
418 * CALL_PROCEEDING - connection termination is in progress
419 * CALL_FAILED - connection termination failed
420 * CALL_CLEARED - connection has been successfully terminated
424 sigpvc_release(vcp, errp)
430 * Make sure VCC is open
432 if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
433 (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
435 return (CALL_FAILED);
439 * Not much else to do except close the vccb
441 sigpvc_close_vcc(vcp);
443 return (CALL_CLEARED);
448 * Free SigPVC ATM Connection Resources
450 * All service user requests to free the resources of a closed VCC connection
451 * (via the atm_free_connection function), which is running over an interface
452 * attached to the SigPVC signalling manager, are handled here.
454 * Function will be called at splnet.
457 * vcp pointer to connection's VCC control block
460 * 0 connection free was successful
461 * errno connection free failed - reason indicated
468 struct atm_pif *pip = vcp->vc_pif;
469 struct sigpvc *pvp = (struct sigpvc *)pip->pif_siginst;
472 * Make sure VCC has been closed
474 if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
478 * Remove vccb from protocol queue
480 DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
485 vcp->vc_ustate = VCCU_NULL;
486 vcp->vc_sstate = VCCS_NULL;
487 atm_free((caddr_t)vcp);
490 * If we're detaching and this was the last vcc queued,
491 * get rid of the protocol instance
493 if ((pvp->pv_state == SIGPVC_DETACH) &&
494 (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
495 struct sigmgr *smp = pip->pif_sigmgr;
497 pip->pif_sigmgr = NULL;
498 pip->pif_siginst = NULL;
499 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
501 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
509 * Process Signalling Manager PF_ATM ioctls
511 * Function will be called at splnet.
514 * code PF_ATM sub-operation code
515 * data pointer to code specific parameter data area
516 * arg1 pointer to code specific argument
520 * errno error processing request - reason indicated
524 sigpvc_ioctl(code, data, arg1)
529 struct atmdelreq *adp;
530 struct atminfreq *aip;
531 struct air_vcc_rsp avr;
537 int i, space, err = 0;
546 adp = (struct atmdelreq *)data;
547 pvp = (struct sigpvc *)arg1;
552 vpi = adp->adr_pvc_vpi;
553 vci = adp->adr_pvc_vci;
554 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
555 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
556 if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
563 * Schedule VCC termination
565 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
577 * Get VCC information
579 aip = (struct atminfreq *)data;
580 pvp = (struct sigpvc *)arg1;
582 cp = aip->air_buf_addr;
583 space = aip->air_buf_len;
586 * Get info for all VCCs on interface
588 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
589 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
591 * Make sure there's room in user buffer
593 if (space < sizeof(avr)) {
599 * Fill in info to be returned
601 (void) snprintf(avr.avp_intf, sizeof(avr.avp_intf),
603 pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
604 avr.avp_vpi = vcp->vc_vpi;
605 avr.avp_vci = vcp->vc_vci;
606 avr.avp_type = vcp->vc_type;
607 avr.avp_sig_proto = ATM_SIG_PVC;
608 avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
609 cop = vcp->vc_connvc->cvc_conn;
611 avr.avp_encaps = cop->co_mpx;
614 KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
615 for (i = 0; cop && i < sizeof(avr.avp_owners);
617 i += T_ATM_APP_NAME_LEN+1) {
618 strncpy(&avr.avp_owners[i],
619 cop->co_endpt->ep_getname(cop->co_toku),
622 avr.avp_state = vcp->vc_sstate;
623 avr.avp_daddr.address_format = T_ATM_ABSENT;
624 avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
625 avr.avp_ipdus = vcp->vc_ipdus;
626 avr.avp_opdus = vcp->vc_opdus;
627 avr.avp_ibytes = vcp->vc_ibytes;
628 avr.avp_obytes = vcp->vc_obytes;
629 avr.avp_ierrors = vcp->vc_ierrors;
630 avr.avp_oerrors = vcp->vc_oerrors;
631 avr.avp_tstamp = vcp->vc_tstamp;
634 * Copy data to user buffer and update buffer info
636 if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
639 space -= sizeof(avr);
643 * Update buffer pointer/count
645 aip->air_buf_addr = cp;
646 aip->air_buf_len = space;
652 * Get ARP table/server information
654 /* We don't maintain any ARP information */
665 #ifdef ATM_SIGPVC_MODULE
667 *******************************************************************
669 * Loadable Module Support
671 *******************************************************************
673 static int sigpvc_doload __P((void));
674 static int sigpvc_dounload __P((void));
677 * Generic module load processing
679 * This function is called by an OS-specific function when this
680 * module is being loaded.
686 * 0 load was successful
687 * errno load failed - reason indicated
698 err = sigpvc_start();
700 /* Problems, clean up */
708 * Generic module unload processing
710 * This function is called by an OS-specific function when this
711 * module is being unloaded.
717 * 0 unload was successful
718 * errno unload failed - reason indicated
727 * OK, try to clean up our mess
737 * Loadable driver description
739 struct vdldrv sigpvc_drv = {
740 VDMAGIC_PSEUDO, /* Pseudo Driver */
741 "sigpvc_mod", /* name */
751 * Loadable module support entry point
753 * This is the routine called by the vd driver for all loadable module
754 * functions for this pseudo driver. This routine name must be specified
755 * on the modload(1) command. This routine will be called whenever the
756 * modload(1), modunload(1) or modstat(1) commands are issued for this
760 * cmd vd command code
761 * vdp pointer to vd driver's structure
762 * vdi pointer to command-specific vdioctl_* structure
763 * vds pointer to status structure (VDSTAT only)
766 * 0 command was successful
767 * errno command failed - reason indicated
771 sigpvc_mod(cmd, vdp, vdi, vds)
785 * We dont support any user configuration
787 err = sigpvc_doload();
789 /* Let vd driver know about us */
790 vdp->vdd_vdtab = (struct vdlinkage *)&sigpvc_drv;
797 err = sigpvc_dounload();
805 /* Not much to say at the moment */
810 log(LOG_ERR, "sigpvc_mod: Unknown vd command 0x%x\n", cmd);
820 #include <sys/exec.h>
821 #include <sys/sysent.h>
825 * Loadable miscellaneous module description
831 * Loadable module support "load" entry point
833 * This is the routine called by the lkm driver whenever the
834 * modload(1) command is issued for this module.
837 * lkmtp pointer to lkm drivers's structure
838 * cmd lkm command code
841 * 0 command was successful
842 * errno command failed - reason indicated
846 sigpvc_load(lkmtp, cmd)
847 struct lkm_table *lkmtp;
850 return(sigpvc_doload());
855 * Loadable module support "unload" entry point
857 * This is the routine called by the lkm driver whenever the
858 * modunload(1) command is issued for this module.
861 * lkmtp pointer to lkm drivers's structure
862 * cmd lkm command code
865 * 0 command was successful
866 * errno command failed - reason indicated
870 sigpvc_unload(lkmtp, cmd)
871 struct lkm_table *lkmtp;
874 return(sigpvc_dounload());
879 * Loadable module support entry point
881 * This is the routine called by the lkm driver for all loadable module
882 * functions for this driver. This routine name must be specified
883 * on the modload(1) command. This routine will be called whenever the
884 * modload(1), modunload(1) or modstat(1) commands are issued for this
888 * lkmtp pointer to lkm drivers's structure
889 * cmd lkm command code
893 * 0 command was successful
894 * errno command failed - reason indicated
898 sigpvc_mod(lkmtp, cmd, ver)
899 struct lkm_table *lkmtp;
903 MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
904 sigpvc_load, sigpvc_unload, lkm_nullcmd);
906 #endif /* __FreeBSD__ */
908 #else /* !ATM_SIGPVC_MODULE */
911 *******************************************************************
913 * Kernel Compiled Module Support
915 *******************************************************************
917 static void sigpvc_doload __P((void *));
919 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
922 * Kernel initialization
932 sigpvc_doload(void *arg)
939 err = sigpvc_start();
941 /* Problems, clean up */
944 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
948 #endif /* ATM_SIGPVC_MODULE */