Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 May 2015 16:41:35 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r283655 - projects/ifnet/sys/net
Message-ID:  <201505281641.t4SGfZIk024794@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Thu May 28 16:41:34 2015
New Revision: 283655
URL: https://svnweb.freebsd.org/changeset/base/283655

Log:
  Convert tap(4) to new ifnet KPI.  Not tested yet, and some rough edges
  still left.
  
  In collaboration with:	Tiwei Bie <btw mail.ustc.edu.cn>
  Sponsored by:		Netflix
  Sponsored by:		Nginx, Inc.

Deleted:
  projects/ifnet/sys/net/if_tapvar.h
Modified:
  projects/ifnet/sys/net/if_tap.c

Modified: projects/ifnet/sys/net/if_tap.c
==============================================================================
--- projects/ifnet/sys/net/if_tap.c	Thu May 28 16:39:22 2015	(r283654)
+++ projects/ifnet/sys/net/if_tap.c	Thu May 28 16:41:34 2015	(r283655)
@@ -36,13 +36,11 @@
  */
 
 #include "opt_compat.h"
-#include "opt_inet.h"
 
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/filio.h>
-#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
@@ -60,22 +58,17 @@
 #include <sys/uio.h>
 #include <sys/queue.h>
 
-#include <net/bpf.h>
 #include <net/ethernet.h>
 #include <net/if.h>
-#include <net/if_var.h>
 #include <net/if_clone.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <net/route.h>
-#include <net/vnet.h>
-
-#include <netinet/in.h>
-
-#include <net/if_tapvar.h>
 #include <net/if_tap.h>
+#include <net/vnet.h>
 
+/*
+ * XXXGL: to avoid inclusion of if_var.h define if_purgeaddrs.
+ * This should be fixed by destroying interface clone on close(2).
+ */
+void if_purgeaddrs(if_t);
 
 #define CDEV_NAME	"tap"
 #define TAPDEBUG	if (tapdebug) printf
@@ -94,15 +87,14 @@ static void		tapclone(void *, struct ucr
 static void		tapcreate(struct cdev *);
 
 /* network interface */
-static void		tapifstart(struct ifnet *);
-static int		tapifioctl(struct ifnet *, u_long, caddr_t);
-static void		tapifinit(void *);
+static int		tapifioctl(if_t, u_long, void *, struct thread *);
+static int		tapiftransmit(if_t, struct mbuf *);
 
 static int		tap_clone_create(struct if_clone *, int, caddr_t);
-static void		tap_clone_destroy(struct ifnet *);
+static void		tap_clone_destroy(if_t);
 static struct if_clone *tap_cloner;
 static int		vmnet_clone_create(struct if_clone *, int, caddr_t);
-static void		vmnet_clone_destroy(struct ifnet *);
+static void		vmnet_clone_destroy(if_t);
 static struct if_clone *vmnet_cloner;
 
 /* character device */
@@ -146,6 +138,53 @@ static struct cdevsw	tap_cdevsw = {
 	.d_kqfilter =	tapkqfilter,
 };
 
+static struct ifdriver tap_ifdrv = {
+	.ifdrv_ops = {
+		.ifop_ioctl = tapifioctl,
+		.ifop_transmit = tapiftransmit,
+	},
+	.ifdrv_name = tapname,
+	.ifdrv_type = IFT_ETHER,
+};
+
+static struct ifdriver vmnet_ifdrv = {
+	.ifdrv_ops = {
+		.ifop_ioctl = tapifioctl,
+		.ifop_transmit = tapiftransmit,
+	},
+	.ifdrv_name = vmnetname,
+	.ifdrv_type = IFT_ETHER,
+};
+
+/*
+ * Tap interface software context.
+ * tap_mtx locks tap_flags, tap_pid. tap_next locked with global tapmtx.
+ * Other fields locked by owning subsystems.
+ */
+struct tap_softc {
+	struct mtx	tap_mtx;		/* per-softc mutex */
+	struct cdev	*tap_dev;
+	if_t		tap_ifp;
+	struct mbufq	tap_queue;
+	uint32_t	tap_ifflags;
+	uint32_t	tap_mtu;
+	uint64_t	tap_baudrate;
+	uint16_t	tap_flags;		/* misc flags */
+#define	TAP_OPEN	(1 << 0)
+#define	TAP_INITED	(1 << 1)
+#define	TAP_RWAIT	(1 << 2)
+#define	TAP_ASYNC	(1 << 3)
+#define TAP_READY       (TAP_OPEN|TAP_INITED)
+#define	TAP_VMNET	(1 << 4)
+
+	uint8_t 	ether_addr[ETHER_ADDR_LEN];	/* remote address */
+	pid_t		tap_pid;		/* PID of process to open */
+	struct sigio	*tap_sigio;		/* information for async I/O */
+	struct selinfo	tap_rsel;		/* read select */
+
+	SLIST_ENTRY(tap_softc)	tap_next;	/* next device in chain */
+};
+
 /*
  * All global variables in if_tap.c are locked with tapmtx, with the
  * exception of tapdebug, which is accessed unlocked; tapclones is
@@ -214,15 +253,14 @@ vmnet_clone_create(struct if_clone *ifc,
 static void
 tap_destroy(struct tap_softc *tp)
 {
-	struct ifnet *ifp = tp->tap_ifp;
+	if_t ifp = tp->tap_ifp;
 
 	CURVNET_SET(ifp->if_vnet);
 	destroy_dev(tp->tap_dev);
 	seldrain(&tp->tap_rsel);
 	knlist_clear(&tp->tap_rsel.si_note, 0);
 	knlist_destroy(&tp->tap_rsel.si_note);
-	ether_ifdetach(ifp);
-	if_free(ifp);
+	if_detach(ifp);
 
 	mtx_destroy(&tp->tap_mtx);
 	free(tp, M_TAP);
@@ -230,9 +268,11 @@ tap_destroy(struct tap_softc *tp)
 }
 
 static void
-tap_clone_destroy(struct ifnet *ifp)
+tap_clone_destroy(if_t ifp)
 {
-	struct tap_softc *tp = ifp->if_softc;
+	struct tap_softc *tp;
+
+	tp = if_getsoftc(ifp, IF_DRIVER_SOFTC);
 
 	mtx_lock(&tapmtx);
 	SLIST_REMOVE(&taphead, tp, tap_softc, tap_next);
@@ -242,7 +282,7 @@ tap_clone_destroy(struct ifnet *ifp)
 
 /* vmnet devices are tap devices in disguise */
 static void
-vmnet_clone_destroy(struct ifnet *ifp)
+vmnet_clone_destroy(if_t ifp)
 {
 	tap_clone_destroy(ifp);
 }
@@ -257,7 +297,7 @@ tapmodevent(module_t mod, int type, void
 {
 	static eventhandler_tag	 eh_tag = NULL;
 	struct tap_softc	*tp = NULL;
-	struct ifnet		*ifp = NULL;
+	if_t			 ifp = NULL;
 
 	switch (type) {
 	case MOD_LOAD:
@@ -310,7 +350,7 @@ tapmodevent(module_t mod, int type, void
 
 			ifp = tp->tap_ifp;
 
-			TAPDEBUG("detaching %s\n", ifp->if_xname);
+			TAPDEBUG("detaching %s\n", if_name(ifp));
 
 			tap_destroy(tp);
 			mtx_lock(&tapmtx);
@@ -327,8 +367,7 @@ tapmodevent(module_t mod, int type, void
 	}
 
 	return (0);
-} /* tapmodevent */
-
+}
 
 /*
  * DEVFS handler
@@ -336,7 +375,8 @@ tapmodevent(module_t mod, int type, void
  * We need to support two kind of devices - tap and vmnet
  */
 static void
-tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
+tapclone(void *arg, struct ucred *cred, char *name, int namelen,
+    struct cdev **dev)
 {
 	char		devname[SPECNAMELEN + 1];
 	int		i, unit, append_unit;
@@ -390,8 +430,7 @@ tapclone(void *arg, struct ucred *cred, 
 
 	if_clone_create(name, namelen, NULL);
 	CURVNET_RESTORE();
-} /* tapclone */
-
+}
 
 /*
  * tapcreate
@@ -401,17 +440,25 @@ tapclone(void *arg, struct ucred *cred, 
 static void
 tapcreate(struct cdev *dev)
 {
-	struct ifnet		*ifp = NULL;
+	struct if_attach_args	 ifat = {
+		.ifat_version = IF_ATTACH_VERSION,
+		.ifat_mtu = ETHERMTU,
+		.ifat_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST,
+		.ifat_capabilities = IFCAP_LINKSTATE,
+		.ifat_capenable = IFCAP_LINKSTATE,
+	};
+	if_t			 ifp = NULL;
 	struct tap_softc	*tp = NULL;
 	unsigned short		 macaddr_hi;
 	uint32_t		 macaddr_mid;
 	int			 unit;
 	const char		*name = NULL;
-	u_char			eaddr[6];
+	u_char			 eaddr[6];
 
 	/* allocate driver storage and create device */
 	tp = malloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
 	mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF);
+	mbufq_init(&tp->tap_queue, IFQ_MAXLEN);
 	mtx_lock(&tapmtx);
 	SLIST_INSERT_HEAD(&taphead, tp, tap_next);
 	mtx_unlock(&tapmtx);
@@ -421,9 +468,12 @@ tapcreate(struct cdev *dev)
 	/* select device: tap or vmnet */
 	if (unit & VMNET_DEV_MASK) {
 		name = vmnetname;
+		ifat.ifat_drv = &vmnet_ifdrv;
 		tp->tap_flags |= TAP_VMNET;
-	} else
+	} else {
 		name = tapname;
+		ifat.ifat_drv = &tap_ifdrv;
+	}
 
 	unit &= TAPMAXUNIT;
 
@@ -437,25 +487,16 @@ tapcreate(struct cdev *dev)
 	eaddr[5] = (u_char)unit;
 
 	/* fill the rest and attach interface */
-	ifp = tp->tap_ifp = if_alloc(IFT_ETHER);
+	ifat.ifat_softc = tp;
+	ifat.ifat_dunit = unit;
+	ifat.ifat_lla = eaddr;
+	ifp = tp->tap_ifp = if_attach(&ifat);
 	if (ifp == NULL)
-		panic("%s%d: can not if_alloc()", name, unit);
-	ifp->if_softc = tp;
-	if_initname(ifp, name, 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);
-	ifp->if_capabilities |= IFCAP_LINKSTATE;
-	ifp->if_capenable |= IFCAP_LINKSTATE;
+		panic("%s%d: can not if_attach()", name, unit);
 
 	dev->si_drv1 = tp;
 	tp->tap_dev = dev;
 
-	ether_ifattach(ifp, eaddr);
-
 	mtx_lock(&tp->tap_mtx);
 	tp->tap_flags |= TAP_INITED;
 	mtx_unlock(&tp->tap_mtx);
@@ -463,9 +504,8 @@ tapcreate(struct cdev *dev)
 	knlist_init_mtx(&tp->tap_rsel.si_note, &tp->tap_mtx);
 
 	TAPDEBUG("interface %s is created. minor = %#x\n", 
-		ifp->if_xname, dev2unit(dev));
-} /* tapcreate */
-
+	    if_name(ifp), dev2unit(dev));
+}
 
 /*
  * tapopen
@@ -476,7 +516,7 @@ static int
 tapopen(struct cdev *dev, int flag, int mode, struct thread *td)
 {
 	struct tap_softc	*tp = NULL;
-	struct ifnet		*ifp = NULL;
+	if_t			 ifp = NULL;
 	int			 error;
 
 	if (tapuopen == 0) {
@@ -501,18 +541,21 @@ tapopen(struct cdev *dev, int flag, int 
 	tp->tap_flags |= TAP_OPEN;
 	ifp = tp->tap_ifp;
 
-	ifp->if_drv_flags |= IFF_DRV_RUNNING;
-	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-	if (tapuponopen)
-		ifp->if_flags |= IFF_UP;
 	if_link_state_change(ifp, LINK_STATE_UP);
 	mtx_unlock(&tp->tap_mtx);
 
-	TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, dev2unit(dev));
+	if (tapuponopen) {
+		struct ifreq ifr;
 
-	return (0);
-} /* tapopen */
+		if_drvioctl(ifp, SIOCGIFFLAGS, &ifr, td);
+		ifr.ifr_flags |= IFF_UP;
+		if_drvioctl(ifp, SIOCSIFFLAGS, &ifr, td);
+	}
 
+	TAPDEBUG("%s is open. minor = %#x\n", if_name(ifp), dev2unit(dev));
+
+	return (0);
+}
 
 /*
  * tapclose
@@ -522,36 +565,30 @@ tapopen(struct cdev *dev, int flag, int 
 static int
 tapclose(struct cdev *dev, int foo, int bar, struct thread *td)
 {
-	struct ifaddr		*ifa;
 	struct tap_softc	*tp = dev->si_drv1;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 
 	/* junk all pending output */
 	mtx_lock(&tp->tap_mtx);
 	CURVNET_SET(ifp->if_vnet);
-	IF_DRAIN(&ifp->if_snd);
+	if_link_state_change(ifp, LINK_STATE_DOWN);
+	mbufq_drain(&tp->tap_queue);
 
 	/*
 	 * Do not bring the interface down, and do not anything with
 	 * interface, if we are in VMnet mode. Just close the device.
 	 */
 	if (((tp->tap_flags & TAP_VMNET) == 0) &&
-	    (ifp->if_flags & (IFF_UP | IFF_LINK0)) == IFF_UP) {
+	    (tp->tap_ifflags & (IFF_UP | IFF_LINK0)) == IFF_UP) {
+		struct ifreq ifr;
+
 		mtx_unlock(&tp->tap_mtx);
-		if_down(ifp);
+		if_drvioctl(ifp, SIOCGIFFLAGS, &ifr, td);
+		ifr.ifr_flags &= ~IFF_UP;
+		if_drvioctl(ifp, SIOCSIFFLAGS, &ifr, td);
+		if_purgeaddrs(ifp);
 		mtx_lock(&tp->tap_mtx);
-		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-			mtx_unlock(&tp->tap_mtx);
-			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
-				rtinit(ifa, (int)RTM_DELETE, 0);
-			}
-			if_purgeaddrs(ifp);
-			mtx_lock(&tp->tap_mtx);
-		}
 	}
-
-	if_link_state_change(ifp, LINK_STATE_DOWN);
 	CURVNET_RESTORE();
 
 	funsetown(&tp->tap_sigio);
@@ -562,35 +599,10 @@ tapclose(struct cdev *dev, int foo, int 
 	tp->tap_pid = 0;
 	mtx_unlock(&tp->tap_mtx);
 
-	TAPDEBUG("%s is closed. minor = %#x\n", 
-		ifp->if_xname, dev2unit(dev));
+	TAPDEBUG("%s is closed. minor = %#x\n", if_name(ifp), dev2unit(dev));
 
 	return (0);
-} /* tapclose */
-
-
-/*
- * tapifinit
- *
- * network interface initialization function
- */
-static void
-tapifinit(void *xtp)
-{
-	struct tap_softc	*tp = (struct tap_softc *)xtp;
-	struct ifnet		*ifp = tp->tap_ifp;
-
-	TAPDEBUG("initializing %s\n", ifp->if_xname);
-
-	mtx_lock(&tp->tap_mtx);
-	ifp->if_drv_flags |= IFF_DRV_RUNNING;
-	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-	mtx_unlock(&tp->tap_mtx);
-
-	/* attempt to start output */
-	tapifstart(ifp);
-} /* tapifinit */
-
+}
 
 /*
  * tapifioctl
@@ -598,71 +610,78 @@ tapifinit(void *xtp)
  * Process an ioctl request on network interface
  */
 static int
-tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+tapifioctl(if_t ifp, u_long cmd, void *data, struct thread *td)
 {
-	struct tap_softc	*tp = ifp->if_softc;
+	struct tap_softc	*tp;
 	struct ifreq		*ifr = (struct ifreq *)data;
 	struct ifstat		*ifs = NULL;
 	struct ifmediareq	*ifmr = NULL;
 	int			 dummy, error = 0;
 
+	tp = if_getsoftc(ifp, IF_DRIVER_SOFTC);
+
 	switch (cmd) {
-		case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
-		case SIOCADDMULTI:
-		case SIOCDELMULTI:
-			break;
+	case SIOCSIFFLAGS:
+		tp->tap_ifflags = ifr->ifr_flags;
+		break;
 
-		case SIOCGIFMEDIA:
-			ifmr = (struct ifmediareq *)data;
-			dummy = ifmr->ifm_count;
-			ifmr->ifm_count = 1;
-			ifmr->ifm_status = IFM_AVALID;
-			ifmr->ifm_active = IFM_ETHER;
-			if (tp->tap_flags & TAP_OPEN)
-				ifmr->ifm_status |= IFM_ACTIVE;
-			ifmr->ifm_current = ifmr->ifm_active;
-			if (dummy >= 1) {
-				int media = IFM_ETHER;
-				error = copyout(&media, ifmr->ifm_ulist,
-				    sizeof(int));
-			}
-			break;
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+		break;
 
-		case SIOCSIFMTU:
-			ifp->if_mtu = ifr->ifr_mtu;
-			break;
+	case SIOCGIFMEDIA:
+		ifmr = (struct ifmediareq *)data;
+		dummy = ifmr->ifm_count;
+		ifmr->ifm_count = 1;
+		ifmr->ifm_status = IFM_AVALID;
+		ifmr->ifm_active = IFM_ETHER;
+		if (tp->tap_flags & TAP_OPEN)
+			ifmr->ifm_status |= IFM_ACTIVE;
+		ifmr->ifm_current = ifmr->ifm_active;
+		if (dummy >= 1) {
+			int media = IFM_ETHER;
+			error = copyout(&media, ifmr->ifm_ulist,
+			    sizeof(int));
+		}
+		break;
 
-		case SIOCGIFSTATUS:
-			ifs = (struct ifstat *)data;
-			mtx_lock(&tp->tap_mtx);
-			if (tp->tap_pid != 0)
-				snprintf(ifs->ascii, sizeof(ifs->ascii),
-					"\tOpened by PID %d\n", tp->tap_pid);
-			else
-				ifs->ascii[0] = '\0';
-			mtx_unlock(&tp->tap_mtx);
-			break;
+	case SIOCSIFMTU:
+		tp->tap_mtu = ifr->ifr_mtu;
+		break;
 
-		default:
-			error = ether_ioctl(ifp, cmd, data);
-			break;
+	case SIOCGIFSTATUS:
+		ifs = (struct ifstat *)data;
+		mtx_lock(&tp->tap_mtx);
+		if (tp->tap_pid != 0)
+			snprintf(ifs->ascii, sizeof(ifs->ascii),
+				"\tOpened by PID %d\n", tp->tap_pid);
+		else
+			ifs->ascii[0] = '\0';
+		mtx_unlock(&tp->tap_mtx);
+		break;
+
+	default:
+		error = EOPNOTSUPP;
+		break;
 	}
 
 	return (error);
-} /* tapifioctl */
-
+}
 
 /*
- * tapifstart
+ * tapiftransmit
  *
  * queue packets from higher level ready to put out
  */
-static void
-tapifstart(struct ifnet *ifp)
+static int
+tapiftransmit(if_t ifp, struct mbuf *m)
 {
-	struct tap_softc	*tp = ifp->if_softc;
+	struct tap_softc *tp;
+	int error;
 
-	TAPDEBUG("%s starting\n", ifp->if_xname);
+	TAPDEBUG("%s starting\n", if_name(ifp));
+
+	tp = if_getsoftc(ifp, IF_DRIVER_SOFTC);
 
 	/*
 	 * do not junk pending output if we are in VMnet mode.
@@ -672,48 +691,35 @@ tapifstart(struct ifnet *ifp)
 	mtx_lock(&tp->tap_mtx);
 	if (((tp->tap_flags & TAP_VMNET) == 0) &&
 	    ((tp->tap_flags & TAP_READY) != TAP_READY)) {
-		struct mbuf *m;
-
 		/* Unlocked read. */
-		TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, 
+		TAPDEBUG("%s not ready, tap_flags = 0x%x\n", if_name(ifp),
 		    tp->tap_flags);
-
-		for (;;) {
-			IF_DEQUEUE(&ifp->if_snd, m);
-			if (m != NULL) {
-				m_freem(m);
-				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-			} else
-				break;
-		}
+		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 		mtx_unlock(&tp->tap_mtx);
-
-		return;
+		return (0);
 	}
 
-	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-
-	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
-		if (tp->tap_flags & TAP_RWAIT) {
-			tp->tap_flags &= ~TAP_RWAIT;
-			wakeup(tp);
-		}
+	if ((error = mbufq_enqueue(&tp->tap_queue, m)) != 0)
+		return (error);
 
-		if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
-			mtx_unlock(&tp->tap_mtx);
-			pgsigio(&tp->tap_sigio, SIGIO, 0);
-			mtx_lock(&tp->tap_mtx);
-		}
+	if (tp->tap_flags & TAP_RWAIT) {
+		tp->tap_flags &= ~TAP_RWAIT;
+		wakeup(tp);
+	}
 
-		selwakeuppri(&tp->tap_rsel, PZERO+1);
-		KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
-		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); /* obytes are counted in ether_output */
+	if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
+		mtx_unlock(&tp->tap_mtx);
+		pgsigio(&tp->tap_sigio, SIGIO, 0);
+		mtx_lock(&tp->tap_mtx);
 	}
 
-	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+	selwakeuppri(&tp->tap_rsel, PZERO+1);
+	KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
+
 	mtx_unlock(&tp->tap_mtx);
-} /* tapifstart */
 
+	return (0);
+}
 
 /*
  * tapioctl
@@ -721,12 +727,13 @@ tapifstart(struct ifnet *ifp)
  * the cdevsw interface is now pretty minimal
  */
 static int
-tapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
+tapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
+    struct thread *td)
 {
 	struct tap_softc	*tp = dev->si_drv1;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 	struct tapinfo		*tapp = NULL;
-	int			 f;
+	int			 error = 0;
 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
     defined(COMPAT_FREEBSD4)
 	int			 ival;
@@ -734,20 +741,24 @@ tapioctl(struct cdev *dev, u_long cmd, c
 
 	switch (cmd) {
 		case TAPSIFINFO:
+		{
+			struct ifreq ifr;
+
 			tapp = (struct tapinfo *)data;
-			mtx_lock(&tp->tap_mtx);
-			ifp->if_mtu = tapp->mtu;
-			ifp->if_type = tapp->type;
-			ifp->if_baudrate = tapp->baudrate;
-			mtx_unlock(&tp->tap_mtx);
+			ifr.ifr_mtu = tapp->mtu;
+			error = if_drvioctl(ifp, SIOCSIFMTU, &ifr, td);
+			if (error)
+				break;
+			tp->tap_baudrate = tapp->baudrate;
+			if_setbaudrate(ifp, tapp->baudrate);
 			break;
-
+		}
 		case TAPGIFINFO:
 			tapp = (struct tapinfo *)data;
 			mtx_lock(&tp->tap_mtx);
-			tapp->mtu = ifp->if_mtu;
-			tapp->type = ifp->if_type;
-			tapp->baudrate = ifp->if_baudrate;
+			tapp->mtu = tp->tap_mtu;
+			tapp->type = IFT_ETHER;
+			tapp->baudrate = tp->tap_baudrate;
 			mtx_unlock(&tp->tap_mtx);
 			break;
 
@@ -759,12 +770,13 @@ tapioctl(struct cdev *dev, u_long cmd, c
 			*(int *)data = tapdebug;
 			break;
 
-		case TAPGIFNAME: {
+		case TAPGIFNAME:
+		{
 			struct ifreq	*ifr = (struct ifreq *) data;
 
-			strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
-			} break;
-
+			strlcpy(ifr->ifr_name, if_name(ifp), IFNAMSIZ);
+			break;
+		}
 		case FIONBIO:
 			break;
 
@@ -777,20 +789,16 @@ tapioctl(struct cdev *dev, u_long cmd, c
 			mtx_unlock(&tp->tap_mtx);
 			break;
 
-		case FIONREAD:
-			if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
-				struct mbuf *mb;
-
-				IFQ_LOCK(&ifp->if_snd);
-				IFQ_POLL_NOLOCK(&ifp->if_snd, mb);
-				for (*(int *)data = 0; mb != NULL;
-				     mb = mb->m_next)
-					*(int *)data += mb->m_len;
-				IFQ_UNLOCK(&ifp->if_snd);
-			} else
+		case FIONREAD: {
+			struct mbuf *m;
+
+			m = mbufq_first(&tp->tap_queue);
+			if (m != NULL)
+				*(int *)data = m->m_pkthdr.len;
+			else
 				*(int *)data = 0;
 			break;
-
+		}
 		case FIOSETOWN:
 			return (fsetown(*(int *)data, &tp->tap_sigio));
 
@@ -817,16 +825,20 @@ tapioctl(struct cdev *dev, u_long cmd, c
 			/* FALLTHROUGH */
 #endif
 		case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */
+		{
+			struct ifreq ifr;
+			int f;
+
 			f = *(int *)data;
 			f &= 0x0fff;
 			f &= ~IFF_CANTCHANGE;
 			f |= IFF_UP;
 
-			mtx_lock(&tp->tap_mtx);
-			ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
-			mtx_unlock(&tp->tap_mtx);
+			if_drvioctl(ifp, SIOCGIFFLAGS, &ifr, td);
+			ifr.ifr_flags = f | (ifr.ifr_flags & IFF_CANTCHANGE);
+			error = if_drvioctl(ifp, SIOCSIFFLAGS, &ifr, td);
 			break;
-
+		}
 		case SIOCGIFADDR:	/* get MAC address of the remote side */
 			mtx_lock(&tp->tap_mtx);
 			bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
@@ -842,9 +854,9 @@ tapioctl(struct cdev *dev, u_long cmd, c
 		default:
 			return (ENOTTY);
 	}
-	return (0);
-} /* tapioctl */
 
+	return (error);
+}
 
 /*
  * tapread
@@ -856,11 +868,11 @@ static int
 tapread(struct cdev *dev, struct uio *uio, int flag)
 {
 	struct tap_softc	*tp = dev->si_drv1;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 	struct mbuf		*m = NULL;
 	int			 error = 0, len;
 
-	TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, dev2unit(dev));
+	TAPDEBUG("%s reading, minor = %#x\n", if_name(ifp), dev2unit(dev));
 
 	mtx_lock(&tp->tap_mtx);
 	if ((tp->tap_flags & TAP_READY) != TAP_READY) {
@@ -868,7 +880,7 @@ tapread(struct cdev *dev, struct uio *ui
 
 		/* Unlocked read. */
 		TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n",
-			ifp->if_xname, dev2unit(dev), tp->tap_flags);
+		    if_name(ifp), dev2unit(dev), tp->tap_flags);
 
 		return (EHOSTDOWN);
 	}
@@ -876,28 +888,23 @@ tapread(struct cdev *dev, struct uio *ui
 	tp->tap_flags &= ~TAP_RWAIT;
 
 	/* sleep until we get a packet */
-	do {
-		IF_DEQUEUE(&ifp->if_snd, m);
-
-		if (m == NULL) {
-			if (flag & O_NONBLOCK) {
-				mtx_unlock(&tp->tap_mtx);
-				return (EWOULDBLOCK);
-			}
-
-			tp->tap_flags |= TAP_RWAIT;
-			error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1),
-			    "taprd", 0);
-			if (error) {
-				mtx_unlock(&tp->tap_mtx);
-				return (error);
-			}
+	while ((m = mbufq_dequeue(&tp->tap_queue)) != NULL) {
+		if (flag & O_NONBLOCK) {
+			mtx_unlock(&tp->tap_mtx);
+			return (EWOULDBLOCK);
 		}
-	} while (m == NULL);
+		tp->tap_flags |= TAP_RWAIT;
+		error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1),
+		    "taprd", 0);
+		if (error) {
+			mtx_unlock(&tp->tap_mtx);
+			return (error);
+		}
+	}
 	mtx_unlock(&tp->tap_mtx);
 
 	/* feed packet to bpf */
-	BPF_MTAP(ifp, m);
+	if_mtap(ifp, m, NULL, 0);
 
 	/* xfer packet to user space */
 	while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) {
@@ -906,18 +913,21 @@ tapread(struct cdev *dev, struct uio *ui
 			break;
 
 		error = uiomove(mtod(m, void *), len, uio);
+		if (error == 0 && (m->m_flags & M_PKTHDR) != 0)
+			if_inc_txcounters(ifp, m);
+		else
+			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 		m = m_free(m);
 	}
 
 	if (m != NULL) {
-		TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname, 
-			dev2unit(dev));
+		TAPDEBUG("%s dropping mbuf, minor = %#x\n", if_name(ifp),
+		    dev2unit(dev));
 		m_freem(m);
 	}
 
 	return (error);
-} /* tapread */
-
+}
 
 /*
  * tapwrite
@@ -929,18 +939,17 @@ tapwrite(struct cdev *dev, struct uio *u
 {
 	struct ether_header	*eh;
 	struct tap_softc	*tp = dev->si_drv1;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 	struct mbuf		*m;
 
-	TAPDEBUG("%s writing, minor = %#x\n", 
-		ifp->if_xname, dev2unit(dev));
+	TAPDEBUG("%s writing, minor = %#x\n", if_name(ifp), dev2unit(dev));
 
 	if (uio->uio_resid == 0)
 		return (0);
 
 	if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
 		TAPDEBUG("%s invalid packet len = %zd, minor = %#x\n",
-			ifp->if_xname, uio->uio_resid, dev2unit(dev));
+		    if_name(ifp), uio->uio_resid, dev2unit(dev));
 
 		return (EIO);
 	}
@@ -963,7 +972,7 @@ tapwrite(struct cdev *dev, struct uio *u
 	}
 	eh = mtod(m, struct ether_header *);
 
-	if (eh && (ifp->if_flags & IFF_PROMISC) == 0 &&
+	if (eh && (tp->tap_ifflags & IFF_PROMISC) == 0 &&
 	    !ETHER_IS_MULTICAST(eh->ether_dhost) &&
 	    bcmp(eh->ether_dhost, if_lladdr(ifp), ETHER_ADDR_LEN) != 0) {
 		m_freem(m);
@@ -972,13 +981,12 @@ tapwrite(struct cdev *dev, struct uio *u
 
 	/* Pass packet up to parent. */
 	CURVNET_SET(ifp->if_vnet);
-	(*ifp->if_input)(ifp, m);
+	if_input(ifp, m);
 	CURVNET_RESTORE();
 	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); /* ibytes are counted in parent */
 
 	return (0);
-} /* tapwrite */
-
+}
 
 /*
  * tappoll
@@ -991,35 +999,33 @@ static int
 tappoll(struct cdev *dev, int events, struct thread *td)
 {
 	struct tap_softc	*tp = dev->si_drv1;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 	int			 revents = 0;
 
-	TAPDEBUG("%s polling, minor = %#x\n", 
-		ifp->if_xname, dev2unit(dev));
+	TAPDEBUG("%s polling, minor = %#x\n", if_name(ifp), dev2unit(dev));
 
+	mtx_lock(&tp->tap_mtx);
 	if (events & (POLLIN | POLLRDNORM)) {
-		IFQ_LOCK(&ifp->if_snd);
-		if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
+		if (mbufq_len(&tp->tap_queue) > 0) {
 			TAPDEBUG("%s have data in queue. len = %d, " \
-				"minor = %#x\n", ifp->if_xname,
-				ifp->if_snd.ifq_len, dev2unit(dev));
+			    "minor = %#x\n", if_name(ifp),
+			    mbufq_len(&tp->tap_queue), dev2unit(dev));
 
 			revents |= (events & (POLLIN | POLLRDNORM));
 		} else {
 			TAPDEBUG("%s waiting for data, minor = %#x\n",
-				ifp->if_xname, dev2unit(dev));
+			    if_name(ifp), dev2unit(dev));
 
 			selrecord(td, &tp->tap_rsel);
 		}
-		IFQ_UNLOCK(&ifp->if_snd);
 	}
+	mtx_unlock(&tp->tap_mtx);
 
 	if (events & (POLLOUT | POLLWRNORM))
 		revents |= (events & (POLLOUT | POLLWRNORM));
 
 	return (revents);
-} /* tappoll */
-
+}
 
 /*
  * tap_kqfilter
@@ -1030,24 +1036,24 @@ static int
 tapkqfilter(struct cdev *dev, struct knote *kn)
 {
 	struct tap_softc	*tp = dev->si_drv1;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 
 	switch (kn->kn_filter) {
 	case EVFILT_READ:
 		TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n",
-			ifp->if_xname, dev2unit(dev));
+		    if_name(ifp), dev2unit(dev));
 		kn->kn_fop = &tap_read_filterops;
 		break;
 
 	case EVFILT_WRITE:
 		TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n",
-			ifp->if_xname, dev2unit(dev));
+		    if_name(ifp), dev2unit(dev));
 		kn->kn_fop = &tap_write_filterops;
 		break;
 
 	default:
 		TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n",
-			ifp->if_xname, dev2unit(dev));
+		    if_name(ifp), dev2unit(dev));
 		return (EINVAL);
 		/* NOT REACHED */
 	}
@@ -1056,8 +1062,7 @@ tapkqfilter(struct cdev *dev, struct kno
 	knlist_add(&tp->tap_rsel.si_note, kn, 0);
 
 	return (0);
-} /* tapkqfilter */
-
+}
 
 /*
  * tap_kqread
@@ -1070,21 +1075,22 @@ tapkqread(struct knote *kn, long hint)
 	int			 ret;
 	struct tap_softc	*tp = kn->kn_hook;
 	struct cdev		*dev = tp->tap_dev;
-	struct ifnet		*ifp = tp->tap_ifp;
+	if_t			 ifp = tp->tap_ifp;
 
-	if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) {
+	mtx_lock(&tp->tap_mtx);
+	if ((kn->kn_data = mbufq_len(&tp->tap_queue)) > 0) {
 		TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n",
-			ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev));
+		    if_name(ifp), mbufq_len(&tp->tap_queue), dev2unit(dev));
 		ret = 1;
 	} else {
 		TAPDEBUG("%s waiting for data, minor = %#x\n",
-			ifp->if_xname, dev2unit(dev));
+		    if_name(ifp), dev2unit(dev));
 		ret = 0;
 	}
+	mtx_unlock(&tp->tap_mtx);
 
 	return (ret);
-} /* tapkqread */
-
+}
 
 /*
  * tap_kqwrite
@@ -1095,13 +1101,10 @@ static int
 tapkqwrite(struct knote *kn, long hint)
 {
 	struct tap_softc	*tp = kn->kn_hook;
-	struct ifnet		*ifp = tp->tap_ifp;
-
-	kn->kn_data = ifp->if_mtu;
 

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505281641.t4SGfZIk024794>