summaryrefslogtreecommitdiffstats
path: root/sys/net/if_tap.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-02-21 20:29:52 +0000
committerphk <phk@FreeBSD.org>2004-02-21 20:29:52 +0000
commit32b7c9a433930842533064d829ba214aadf6a67d (patch)
treec97716bebd5c7c784bf841850192a5addeaf0347 /sys/net/if_tap.c
parentdf397dedeab80f98300da9e5999d17a57c01b19f (diff)
downloadFreeBSD-src-32b7c9a433930842533064d829ba214aadf6a67d.zip
FreeBSD-src-32b7c9a433930842533064d829ba214aadf6a67d.tar.gz
Device megapatch 2/6:
This commit adds a couple of functions for pseudodrivers to use for implementing cloning in a manner we will be able to lock down (shortly). Basically what happens is that pseudo drivers get a way to ask for "give me the dev_t with this unit number" or alternatively "give me a dev_t with the lowest guaranteed free unit number" (there is unfortunately a lot of non-POLA in the exact numeric value of this number, just live with it for now) Managing the unit number space this way removes the need to use rman(9) to do so in the drivers this greatly simplifies the code in the drivers because even using rman(9) they still needed to manage their dev_t's anyway. I have taken the if_tun, if_tap, snp and nmdm drivers through the mill, partly because they (ab)used makedev(), but mostly because together they represent three different problems for device-cloning: if_tun and snp is the plain case: just give me a device. if_tap has two kinds of devices, with a flag for device type. nmdm has paired devices (ala pty) can you can clone either of them.
Diffstat (limited to 'sys/net/if_tap.c')
-rw-r--r--sys/net/if_tap.c164
1 files changed, 35 insertions, 129 deletions
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c
index 82ae3b9..f83243b 100644
--- a/sys/net/if_tap.c
+++ b/sys/net/if_tap.c
@@ -54,8 +54,6 @@
#include <sys/ttycom.h>
#include <sys/uio.h>
#include <sys/vnode.h>
-#include <machine/bus.h> /* XXX: Shouldn't really be required! */
-#include <sys/rman.h>
#include <sys/queue.h>
#include <net/bpf.h>
@@ -71,14 +69,12 @@
#define CDEV_NAME "tap"
-#define CDEV_MAJOR 149
#define TAPDEBUG if (tapdebug) printf
#define TAP "tap"
#define VMNET "vmnet"
#define TAPMAXUNIT 0x7fff
-#define VMNET_DEV_MASK 0x00800000
- /* 0x007f00ff */
+#define VMNET_DEV_MASK CLONE_FLAG0
/* module */
static int tapmodevent(module_t, int, void *);
@@ -108,15 +104,12 @@ static struct cdevsw tap_cdevsw = {
.d_ioctl = tapioctl,
.d_poll = tappoll,
.d_name = CDEV_NAME,
- .d_maj = CDEV_MAJOR,
+ .d_flags = D_PSEUDO,
};
static int tapdebug = 0; /* debug flag */
static SLIST_HEAD(, tap_softc) taphead; /* first device */
-static udev_t tapbasedev = NOUDEV; /* base device */
-static struct rman tapdevunits[2]; /* device units */
-#define tapunits tapdevunits
-#define vmnetunits (tapdevunits + 1)
+static struct clonedevs *tapclones;
MALLOC_DECLARE(M_TAP);
MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
@@ -137,63 +130,27 @@ tapmodevent(mod, type, data)
static eventhandler_tag eh_tag = NULL;
struct tap_softc *tp = NULL;
struct ifnet *ifp = NULL;
- int error, s;
+ int s;
switch (type) {
case MOD_LOAD:
- /* initialize resources */
- tapunits->rm_type = RMAN_ARRAY;
- tapunits->rm_descr = "open tap units";
- vmnetunits->rm_type = RMAN_ARRAY;
- vmnetunits->rm_descr = "open vmnet units";
-
- error = rman_init(tapunits);
- if (error != 0)
- goto bail;
-
- error = rman_init(vmnetunits);
- if (error != 0)
- goto bail1;
-
- error = rman_manage_region(tapunits, 0, TAPMAXUNIT);
- if (error != 0)
- goto bail2;
-
- error = rman_manage_region(vmnetunits, 0, TAPMAXUNIT);
- if (error != 0)
- goto bail2;
/* intitialize device */
SLIST_INIT(&taphead);
eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
- if (eh_tag == NULL) {
- error = ENOMEM;
- goto bail2;
- }
-
-
+ if (eh_tag == NULL)
+ return (ENOMEM);
return (0);
-bail2:
- rman_fini(vmnetunits);
-bail1:
- rman_fini(tapunits);
-bail:
- return (error);
case MOD_UNLOAD:
SLIST_FOREACH(tp, &taphead, tap_next)
- if (tp->tap_unit != NULL)
+ if (tp->tap_flags & TAP_OPEN)
return (EBUSY);
EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
- error = rman_fini(tapunits);
- KASSERT((error == 0), ("Could not fini tap units"));
- error = rman_fini(vmnetunits);
- KASSERT((error == 0), ("Could not fini vmnet units"));
-
while ((tp = SLIST_FIRST(&taphead)) != NULL) {
SLIST_REMOVE_HEAD(&taphead, tap_next);
@@ -204,18 +161,14 @@ bail:
KASSERT(!(tp->tap_flags & TAP_OPEN),
("%s flags is out of sync", ifp->if_xname));
- /* XXX makedev check? nah.. not right now :) */
-
+ destroy_dev(tp->tap_dev);
s = splimp();
ether_ifdetach(ifp);
splx(s);
free(tp, M_TAP);
}
-
- if (tapbasedev != NOUDEV)
- destroy_dev(udev2dev(tapbasedev, 0));
-
+ clone_cleanup(&tapclones);
break;
@@ -239,65 +192,35 @@ tapclone(arg, name, namelen, dev)
int namelen;
dev_t *dev;
{
- int unit, minor = 0 /* XXX avoid warning */ , error;
+ u_int extra;
+ int i, unit;
char *device_name = name;
- struct resource *r = NULL;
if (*dev != NODEV)
return;
- if (strcmp(device_name, TAP) == 0) {
- /* get first free tap unit */
- r = rman_reserve_resource(tapunits, 0, TAPMAXUNIT, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- unit = rman_get_start(r);
- minor = unit2minor(unit);
- }
- else if (strcmp(device_name, VMNET) == 0) {
- /* get first free vmnet unit */
- r = rman_reserve_resource(vmnetunits, 0, TAPMAXUNIT, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- unit = rman_get_start(r);
- minor = unit2minor(unit) | VMNET_DEV_MASK;
+ device_name = TAP;
+ extra = 0;
+ if (strcmp(name, TAP) == 0) {
+ unit = -1;
+ } else if (strcmp(name, VMNET) == 0) {
+ device_name = VMNET;
+ extra = VMNET_DEV_MASK;
+ unit = -1;
+ } else if (dev_stdclone(name, NULL, device_name, &unit) != 1) {
+ device_name = VMNET;
+ extra = VMNET_DEV_MASK;
+ if (dev_stdclone(name, NULL, device_name, &unit) != 1)
+ return;
}
- if (r != NULL) { /* need cloning */
- TAPDEBUG("%s%d is available. minor = %#x\n",
- device_name, unit, minor);
-
- error = rman_release_resource(r);
- KASSERT((error == 0), ("Could not release tap/vmnet unit"));
-
- /* check if device for the unit has been created */
- *dev = makedev(CDEV_MAJOR, minor);
- if ((*dev)->si_flags & SI_NAMED) {
- TAPDEBUG("%s%d device exists. minor = %#x\n",
- device_name, unit, minor);
- return; /* device has been created */
- }
- } else { /* try to match name/unit, first try tap then vmnet */
- device_name = TAP;
- if (dev_stdclone(name, NULL, device_name, &unit) != 1) {
- device_name = VMNET;
-
- if (dev_stdclone(name, NULL, device_name, &unit) != 1)
- return;
-
- minor = unit2minor(unit) | VMNET_DEV_MASK;
- } else
- minor = unit2minor(unit);
- }
-
- TAPDEBUG("make_dev(%s%d). minor = %#x\n", device_name, unit, minor);
-
- *dev = make_dev(&tap_cdevsw, minor, UID_ROOT, GID_WHEEL, 0600, "%s%d",
- device_name, unit);
-
- if (tapbasedev == NOUDEV)
- tapbasedev = (*dev)->si_udev;
- else {
- (*dev)->si_flags |= SI_CHEAPCLONE;
- dev_depends(udev2dev(tapbasedev, 0), *dev);
+ /* find any existing device, or allocate new unit number */
+ i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
+ if (i) {
+ *dev = make_dev(&tap_cdevsw, unit2minor(unit) | extra,
+ UID_ROOT, GID_WHEEL, 0600, "%s%d", device_name, unit);
+ if (*dev != NULL)
+ (*dev)->si_flags |= SI_CHEAPCLONE;
}
} /* tapclone */
@@ -317,6 +240,8 @@ tapcreate(dev)
int unit, s;
char *name = NULL;
+ dev->si_flags &= ~SI_CHEAPCLONE;
+
/* allocate driver storage and create device */
MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
SLIST_INSERT_HEAD(&taphead, tp, tap_next);
@@ -354,6 +279,7 @@ tapcreate(dev)
ifp->if_snd.ifq_maxlen = ifqmaxlen;
dev->si_drv1 = tp;
+ tp->tap_dev = dev;
s = splimp();
ether_ifattach(ifp, tp->arpcom.ac_enaddr);
@@ -380,24 +306,12 @@ tapopen(dev, flag, mode, td)
{
struct tap_softc *tp = NULL;
int unit, error;
- struct resource *r = NULL;
if ((error = suser(td)) != 0)
return (error);
unit = dev2unit(dev) & TAPMAXUNIT;
- if (minor(dev) & VMNET_DEV_MASK)
- r = rman_reserve_resource(vmnetunits, unit, unit, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- else
- r = rman_reserve_resource(tapunits, unit, unit, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
-
- if (r == NULL)
- return (EBUSY);
-
- dev->si_flags &= ~SI_CHEAPCLONE;
tp = dev->si_drv1;
if (tp == NULL) {
@@ -410,7 +324,6 @@ tapopen(dev, flag, mode, td)
bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr));
- tp->tap_unit = r;
tp->tap_pid = td->td_proc->p_pid;
tp->tap_flags |= TAP_OPEN;
@@ -433,12 +346,9 @@ tapclose(dev, foo, bar, td)
int bar;
struct thread *td;
{
- int s, error;
struct tap_softc *tp = dev->si_drv1;
struct ifnet *ifp = &tp->tap_if;
-
- KASSERT((tp->tap_unit != NULL),
- ("%s is not open", ifp->if_xname));
+ int s;
/* junk all pending output */
IF_DRAIN(&ifp->if_snd);
@@ -479,10 +389,6 @@ tapclose(dev, foo, bar, td)
tp->tap_flags &= ~TAP_OPEN;
tp->tap_pid = 0;
- error = rman_release_resource(tp->tap_unit);
- KASSERT((error == 0),
- ("%s could not release unit", ifp->if_xname));
- tp->tap_unit = NULL;
TAPDEBUG("%s is closed. minor = %#x\n",
ifp->if_xname, minor(dev));
OpenPOWER on IntegriCloud