A cloned tap device patch (for a person to test KQEMU 1.4.0pre1 for QEMU 0.10.1)
Naoya Sugioka
naoya.sugioka at gmail.com
Tue May 5 17:35:55 PDT 2009
Hello,
As some of you already know, I wrote a kqemu patch for DragonFly, but
I found very simple problem to use it.
I cannot create tap0 cloned interface by ifconfig comamnd now, so I
made a patch.
Attachment is a suggested patch to create tap cloned tap device (only
tap device) only applicapable with HEAD.
I 'd like to post this patch to share with community and get a feedback from.
I'm start using this to use QEMU/KQEMU as a virtual server of
DragonFly/FreeBSD. Unfortuantelly, I saw
DMA address error when using wirh Linux guest though...
thank you,
-Naoya
diff --git a/sys/net/tap/if_tap.c b/sys/net/tap/if_tap.c
index f4bd6ca..e50ae4b 100644
--- a/sys/net/tap/if_tap.c
+++ b/sys/net/tap/if_tap.c
@@ -65,6 +65,7 @@
#include <net/if.h>
#include <net/ifq_var.h>
#include <net/if_arp.h>
+#include <net/if_clone.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -87,6 +88,11 @@ static int tapmodevent (module_t, int, void *);
/* device */
static void tapcreate (cdev_t);
+/* clone */
+static int tap_clone_create(struct if_clone *, int);
+static void tap_clone_destroy(struct ifnet *);
+
+
/* network interface */
static void tapifstart (struct ifnet *);
static int tapifioctl (struct ifnet *, u_long, caddr_t,
@@ -117,10 +123,24 @@ static struct dev_ops tap_ops = {
static int taprefcnt = 0; /* module ref. counter */
static int taplastunit = -1; /* max. open unit number */
static int tapdebug = 0; /* debug flag */
+static int tapuopen = 0; /* all user open() */
+static int tapuponopen = 0; /* IFF_UP */
MALLOC_DECLARE(M_TAP);
MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
+struct if_clone tap_cloner = IF_CLONE_INITIALIZER("tap",
+ tap_clone_create,
+ tap_clone_destroy, 0, IF_MAXUNIT);
SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
+SYSCTL_DECL(_net_link);
+SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
+ "Ethernet tunnel software network interface");
+SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
+ "Allow user to open /dev/tap (based on node permissions)");
+SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
+ "Bring interface up when /dev/tap is opened");
+SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
+
DEV_MODULE(if_tap, tapmodevent, NULL);
/*
@@ -131,55 +151,28 @@ DEV_MODULE(if_tap, tapmodevent, NULL);
static int
tapmodevent(module_t mod, int type, void *data)
{
- static int attached = 0;
- struct ifnet *ifp = NULL;
- int unit;
-
+ struct tap_softc* tp;
switch (type) {
case MOD_LOAD:
- if (attached)
+ if (!SLIST_EMPTY(&tap_listhead))
return (EEXIST);
dev_ops_add(&tap_ops, 0, 0);
- attached = 1;
+ SLIST_INIT(&tap_listhead);
+ if_clone_attach(&tap_cloner);
+
break;
case MOD_UNLOAD:
if (taprefcnt > 0)
return (EBUSY);
+ if_clone_detach(&tap_cloner);
dev_ops_remove(&tap_ops, 0, 0);
- /* XXX: maintain tap ifs in a local list */
- unit = 0;
- while (unit <= taplastunit) {
- TAILQ_FOREACH(ifp, &ifnet, if_link) {
- if ((strcmp(ifp->if_dname, TAP) == 0) ||
- (strcmp(ifp->if_dname, VMNET) == 0)) {
- if (ifp->if_dunit == unit)
- break;
- }
- }
-
- if (ifp != NULL) {
- struct tap_softc *tp = ifp->if_softc;
-
- TAPDEBUG(ifp, "detached. minor = %#x, " \
- "taplastunit = %d\n",
- minor(tp->tap_dev), taplastunit);
-
- ifnet_serialize_all(ifp);
- tapifstop(tp, 1);
- ifnet_deserialize_all(ifp);
-
- ether_ifdetach(ifp);
- destroy_dev(tp->tap_dev);
- kfree(tp, M_TAP);
- } else {
- unit++;
- }
- }
- attached = 0;
+ /* maintain tap ifs in a local list */
+ SLIST_FOREACH(tp, &tap_listhead, tap_entries)
+ tap_clone_destroy(&tp->tap_if);
break;
default:
@@ -250,9 +243,64 @@ tapcreate(cdev_t dev)
tp->tap_flags |= TAP_INITED;
tp->tap_devq.ifq_maxlen = ifqmaxlen;
+ SLIST_INSERT_HEAD(&tap_listhead, tp, tap_entries);
+
TAPDEBUG(ifp, "created. minor = %#x\n", minor(tp->tap_dev));
} /* tapcreate */
+/*
+ * tap_clone_create:
+ *
+ * Create a new tap instance.
+ */
+static int
+tap_clone_create(struct if_clone *ifc, int unit)
+{
+ struct ifnet *ifp = NULL;
+ struct tap_softc *tp = NULL;
+ uint8_t ether_addr[ETHER_ADDR_LEN];
+
+ MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
+
+ tp->tap_dev = make_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL,
+ 0600, "%s%d", ifc->ifc_name, unit);
+ tp->tap_dev->si_drv1 = tp;
+ reference_dev(tp->tap_dev); /* so we can destroy it later */
+
+ /* generate fake MAC address: 00 bd xx xx xx unit_no */
+ ether_addr[0] = 0x00;
+ ether_addr[1] = 0xbd;
+ bcopy(&ticks, ðer_addr[2], 3);
+ ether_addr[5] = (u_char)unit;
+
+ ifp = &tp->tap_if;
+ ifp->if_softc = tp;
+
+ if_initname(ifp, ifc->ifc_name, unit);
+ if (unit > taplastunit)
+ taplastunit = unit;
+
+ ifp->if_init = tapifinit;
+ ifp->if_start = tapifstart;
+ ifp->if_ioctl = tapifioctl;
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
+ ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
+ ifq_set_ready(&ifp->if_snd);
+
+ ether_ifattach(ifp, ether_addr, NULL);
+
+ tp->tap_flags |= TAP_INITED;
+ tp->tap_devq.ifq_maxlen = ifqmaxlen;
+
+ SLIST_INSERT_HEAD(&tap_listhead, tp, tap_entries);
+
+ TAPDEBUG(ifp, "clone created. minor = %#x tap_flags = 0x%x\n",
+ minor(tp->tap_dev), tp->tap_flags);
+
+ return (0);
+}
+
/*
* tapopen
@@ -262,15 +310,17 @@ tapcreate(cdev_t dev)
static int
tapopen(struct dev_open_args *ap)
{
- cdev_t dev = ap->a_head.a_dev;
+ cdev_t dev = NULL;
struct tap_softc *tp = NULL;
struct ifnet *ifp = NULL;
int error;
- if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0)
+ if (tapuopen == 0 &&
+ (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0)
return (error);
get_mplock();
+ dev = ap->a_head.a_dev;
tp = dev->si_drv1;
if (tp == NULL) {
tapcreate(dev);
@@ -296,6 +346,10 @@ tapopen(struct dev_open_args *ap)
fsetown(curthread->td_proc->p_pid, &tp->tap_sigtd);
tp->tap_flags |= TAP_OPEN;
taprefcnt ++;
+ ifp = &tp->tap_if;
+
+ if (tapuponopen)
+ ifp->if_flags |= IFF_UP;
TAPDEBUG(ifp, "opened. minor = %#x, refcnt = %d, taplastunit = %d\n",
minor(tp->tap_dev), taprefcnt, taplastunit);
@@ -366,6 +420,35 @@ tapclose(struct dev_close_args *ap)
return (0);
}
+/*
+ * tap_clone_destroy:
+ *
+ * Destroy a tap instance.
+ */
+static void
+tap_clone_destroy(struct ifnet *ifp)
+{
+ struct tap_softc *tp = ifp->if_softc;
+
+ TAPDEBUG(ifp, "clone destroyed. minor = %#x, refcnt = %d, taplastunit = %d\n",
+ minor(tp->tap_dev), taprefcnt, taplastunit);
+ /*
+ * Do we really need this?
+ */
+ IF_DRAIN(&ifp->if_snd);
+
+ ifnet_serialize_all(ifp);
+ tapifstop(tp, 1);
+ ifnet_deserialize_all(ifp);
+
+ ether_ifdetach(ifp);
+ SLIST_REMOVE(&tap_listhead, tp, tap_softc, tap_entries);
+
+ destroy_dev(tp->tap_dev);
+ kfree(tp, M_TAP);
+
+ taplastunit--;
+}
/*
* tapifinit
@@ -380,7 +463,8 @@ tapifinit(void *xtp)
struct tap_softc *tp = xtp;
struct ifnet *ifp = &tp->tap_if;
- TAPDEBUG(ifp, "initializing, minor = %#x\n", minor(tp->tap_dev));
+ TAPDEBUG(ifp, "initializing, minor = %#x tap_flags = 0x%x\n",
+ minor(tp->tap_dev), tp->tap_flags);
ASSERT_IFNET_SERIALIZED_ALL(ifp);
@@ -745,7 +829,7 @@ tapwrite(struct dev_write_args *ap)
struct mbuf *top = NULL, **mp = NULL, *m = NULL;
int error = 0, tlen, mlen;
- TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev));
+// TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev));
if (uio->uio_resid == 0)
return (0);
@@ -844,7 +928,8 @@ tappoll(struct dev_poll_args *ap)
if (ap->a_events & (POLLOUT | POLLWRNORM))
revents |= (ap->a_events & (POLLOUT | POLLWRNORM));
ap->a_events = revents;
- return(0);
+
+ return revents;
}
/*
diff --git a/sys/net/tap/if_tapvar.h b/sys/net/tap/if_tapvar.h
index 2cd173e..cc712d5 100644
--- a/sys/net/tap/if_tapvar.h
+++ b/sys/net/tap/if_tapvar.h
@@ -61,6 +61,10 @@ struct tap_softc {
struct sigio *tap_sigio; /* information for async I/O */
struct selinfo tap_rsel; /* read select */
struct ifqueue tap_devq;
+
+ SLIST_ENTRY(tap_softc) tap_entries;
};
+SLIST_HEAD(,tap_softc) tap_listhead;
+
#endif /* !_NET_IF_TAPVAR_H_ */
More information about the Submit
mailing list