Module Name:    src
Committed By:   pooka
Date:           Wed Mar 13 21:13:45 UTC 2013

Modified Files:
        src/sys/rump/net/lib/libvirtif: Makefile if_virt.c
Added Files:
        src/sys/rump/net/lib/libvirtif: rumpcomp_user.c rumpcomp_user.h

Log Message:
Push the bits accessing the networking backend into hypercalls.
This allows a few highly desirable things to happen:

1) Linux support, which is included in this commit (thanks to wanq for
   sending me the magic bits for accessing /dev/net/tun)
2) Reusing the kernel-side of the interface for devices such as
   hardware packet processors which interact directly with user vm spaces
   (not included in the commit).


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/rump/net/lib/libvirtif/Makefile
cvs rdiff -u -r1.27 -r1.28 src/sys/rump/net/lib/libvirtif/if_virt.c
cvs rdiff -u -r0 -r1.1 src/sys/rump/net/lib/libvirtif/rumpcomp_user.c \
    src/sys/rump/net/lib/libvirtif/rumpcomp_user.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/rump/net/lib/libvirtif/Makefile
diff -u src/sys/rump/net/lib/libvirtif/Makefile:1.3 src/sys/rump/net/lib/libvirtif/Makefile:1.4
--- src/sys/rump/net/lib/libvirtif/Makefile:1.3	Thu May 28 00:02:17 2009
+++ src/sys/rump/net/lib/libvirtif/Makefile	Wed Mar 13 21:13:45 2013
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.3 2009/05/28 00:02:17 pooka Exp $
+#	$NetBSD: Makefile,v 1.4 2013/03/13 21:13:45 pooka Exp $
 #
 
 LIB=	rumpnet_virtif
@@ -6,7 +6,9 @@ LIB=	rumpnet_virtif
 SRCS=	if_virt.c
 SRCS+=	component.c
 
-CPPFLAGS+=	-I${.CURDIR}/../../../librump/rumpkern
+CPPFLAGS+=	-I${.CURDIR}/../../../librump/rumpkern -I${.CURDIR}
+
+RUMPCOMP_USER=	#defined
 
 .include <bsd.lib.mk>
 .include <bsd.klinks.mk>

Index: src/sys/rump/net/lib/libvirtif/if_virt.c
diff -u src/sys/rump/net/lib/libvirtif/if_virt.c:1.27 src/sys/rump/net/lib/libvirtif/if_virt.c:1.28
--- src/sys/rump/net/lib/libvirtif/if_virt.c:1.27	Fri Sep 14 16:29:22 2012
+++ src/sys/rump/net/lib/libvirtif/if_virt.c	Wed Mar 13 21:13:45 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_virt.c,v 1.27 2012/09/14 16:29:22 pooka Exp $	*/
+/*	$NetBSD: if_virt.c,v 1.28 2013/03/13 21:13:45 pooka Exp $	*/
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 1.27 2012/09/14 16:29:22 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 1.28 2013/03/13 21:13:45 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/condvar.h>
@@ -49,11 +49,12 @@ __KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 
 #include <netinet/in_var.h>
 
 #include <rump/rump.h>
-#include <rump/rumpuser.h>
 
 #include "rump_private.h"
 #include "rump_net_private.h"
 
+#include "rumpcomp_user.h"
+
 /*
  * Virtual interface for userspace purposes.  Uses tap(4) to
  * interface with the kernel and just simply shovels data
@@ -69,7 +70,7 @@ static void	virtif_stop(struct ifnet *, 
 
 struct virtif_sc {
 	struct ethercom sc_ec;
-	int sc_tapfd;
+	struct virtif_user *sc_viu;
 	bool sc_dying;
 	struct lwp *sc_l_snd, *sc_l_rcv;
 	kmutex_t sc_mtx;
@@ -88,27 +89,23 @@ int
 rump_virtif_create(int num)
 {
 	struct virtif_sc *sc;
+	struct virtif_user *viu;
 	struct ifnet *ifp;
 	uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0x0a, 0x00, 0x0b, 0x0e, 0x01 };
-	char tapdev[16];
-	int fd, error = 0;
+	int error = 0;
 
 	if (num >= 0x100)
 		return E2BIG;
 
-	snprintf(tapdev, sizeof(tapdev), "/dev/tap%d", num);
-	fd = rumpuser_open(tapdev, RUMPUSER_OPEN_RDWR, &error);
-	if (fd == -1) {
-		printf("virtif_create: can't open /dev/tap%d: %d\n",
-		    num, error);
-		return error;
-	}
+	if ((viu = rumpcomp_virtif_create(num)) == NULL)
+		return ENXIO;
+
 	enaddr[2] = cprng_fast32() & 0xff;
 	enaddr[5] = num;
 
 	sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
 	sc->sc_dying = false;
-	sc->sc_tapfd = fd;
+	sc->sc_viu = viu;
 
 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&sc->sc_cv, "virtsnd");
@@ -168,6 +165,8 @@ virtif_unclone(struct ifnet *ifp)
 	cv_broadcast(&sc->sc_cv);
 	mutex_exit(&sc->sc_mtx);
 
+	rumpcomp_virtif_dying(sc->sc_viu);
+
 	virtif_stop(ifp, 1);
 	if_down(ifp);
 
@@ -180,7 +179,7 @@ virtif_unclone(struct ifnet *ifp)
 		sc->sc_l_rcv = NULL;
 	}
 
-	rumpuser_close(sc->sc_tapfd, NULL);
+	rumpcomp_virtif_destroy(sc->sc_viu);
 
 	mutex_destroy(&sc->sc_mtx);
 	cv_destroy(&sc->sc_cv);
@@ -220,7 +219,6 @@ virtif_ioctl(struct ifnet *ifp, u_long c
 	return rv;
 }
 
-/* just send everything in-context */
 static void
 virtif_start(struct ifnet *ifp)
 {
@@ -252,35 +250,21 @@ virtif_receiver(void *arg)
 	struct virtif_sc *sc = ifp->if_softc;
 	struct mbuf *m;
 	size_t plen = ETHER_MAX_LEN_JUMBO+1;
-	struct pollfd pfd;
 	ssize_t n;
-	int error, rv;
-
-	pfd.fd = sc->sc_tapfd;
-	pfd.events = POLLIN;
 
 	for (;;) {
 		m = m_gethdr(M_WAIT, MT_DATA);
 		MEXTMALLOC(m, plen, M_WAIT);
 
  again:
-		/* poll, but periodically check if we should die */
-		rv = rumpuser_poll(&pfd, 1, POLLTIMO_MS, &error);
 		if (sc->sc_dying) {
 			m_freem(m);
 			break;
 		}
-		if (rv == 0)
-			goto again;
-
-		n = rumpuser_read(sc->sc_tapfd, mtod(m, void *), plen, &error);
-		KASSERT(n < ETHER_MAX_LEN_JUMBO);
-		if (__predict_false(n < 0)) {
-			if (n == -1 && error == EAGAIN) {
-				goto again;
-			}
-
-			printf("%s: read from /dev/tap failed. host is down?\n",
+		
+		n = rumpcomp_virtif_recv(sc->sc_viu, mtod(m, void *), plen);
+		if (n < 0) {
+			printf("%s: read hypercall failed. host if down?\n",
 			    ifp->if_xname);
 			mutex_enter(&sc->sc_mtx);
 			/* could check if need go, done soon anyway */
@@ -314,8 +298,8 @@ virtif_sender(void *arg)
 	struct ifnet *ifp = arg;
 	struct virtif_sc *sc = ifp->if_softc;
 	struct mbuf *m, *m0;
-	struct rumpuser_iovec io[LB_SH];
-	int i, error;
+	struct iovec io[LB_SH];
+	int i;
 
 	mutex_enter(&sc->sc_mtx);
 	KERNEL_LOCK(1, NULL);
@@ -341,11 +325,9 @@ virtif_sender(void *arg)
 		if (i == LB_SH)
 			panic("lazy bum");
 		bpf_mtap(ifp, m0);
-		KERNEL_UNLOCK_LAST(curlwp);
 
-		rumpuser_writev(sc->sc_tapfd, io, i, &error);
+		rumpcomp_virtif_send(sc->sc_viu, io, i);
 
-		KERNEL_LOCK(1, NULL);
 		m_freem(m0);
 		mutex_enter(&sc->sc_mtx);
 	}

Added files:

Index: src/sys/rump/net/lib/libvirtif/rumpcomp_user.c
diff -u /dev/null src/sys/rump/net/lib/libvirtif/rumpcomp_user.c:1.1
--- /dev/null	Wed Mar 13 21:13:45 2013
+++ src/sys/rump/net/lib/libvirtif/rumpcomp_user.c	Wed Mar 13 21:13:45 2013
@@ -0,0 +1,180 @@
+/*	$NetBSD: rumpcomp_user.c,v 1.1 2013/03/13 21:13:45 pooka Exp $	*/
+
+/*
+ * Copyright (c) 2013 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __linux__
+#include <net/if.h>
+#include <linux/if_tun.h>
+#endif
+
+#include <rump/rumpuser_component.h>
+
+struct virtif_user {
+	int viu_fd;
+	int viu_dying;
+};
+
+static int
+opentapdev(int devnum)
+{
+	int fd = -1;
+
+#if defined(__NetBSD__) || defined(__DragonFly__)
+	char tapdev[64];
+
+	snprintf(tapdev, sizeof(tapdev), "/dev/tap%d", devnum);
+	fd = open(tapdev, O_RDWR);
+	if (fd == -1) {
+		fprintf(stderr, "rumpcomp_virtif_create: can't open %s: "
+		    "%s\n", tapdev, strerror(errno));
+	}
+
+#elif defined(__linux__)
+	struct ifreq ifr;
+	char devname[16];
+
+	fd = open("/dev/net/tun", O_RDWR);
+	if (fd == -1) {
+		fprintf(stderr, "rumpcomp_virtif_create: can't open %s: "
+		    "%s\n", "/dev/net/tun", strerror(errno));
+		return -1;
+	}
+
+	snprintf(devname, sizeof(devname), "tun%d", devnum);
+	memset(&ifr, 0, sizeof(ifr));
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+	strncpy(ifr.ifr_name, devname, sizeof(ifr.ifr_name)-1);
+
+	if (ioctl(fd, TUNSETIFF, &ifr) == -1) {
+		close(fd);
+		fd = -1;
+	}
+
+#else
+	fprintf(stderr, "virtif not supported on this platform\n");
+#endif
+
+	return fd;
+}
+
+struct virtif_user *
+rumpcomp_virtif_create(int devnum)
+{
+	struct virtif_user *viu;
+	void *cookie;
+
+	cookie = rumpuser_component_unschedule();
+
+	viu = malloc(sizeof(*viu));
+	viu->viu_fd = opentapdev(devnum);
+	viu->viu_dying = 0;
+
+ out:
+	if (viu->viu_fd == -1) {
+		free(viu);
+		viu = NULL;
+	}
+
+	rumpuser_component_schedule(cookie);
+	return viu;
+}
+
+void
+rumpcomp_virtif_send(struct virtif_user *viu,
+	struct iovec *iov, size_t iovlen)
+{
+	void *cookie = rumpuser_component_unschedule();
+
+	/* no need to check for return value; packets may be dropped */
+	writev(viu->viu_fd, iov, iovlen);
+
+	rumpuser_component_schedule(cookie);
+}
+
+/* how often to check for interface going south */
+#define POLLTIMO_MS 10
+size_t
+rumpcomp_virtif_recv(struct virtif_user *viu, void *data, size_t dlen)
+{
+	void *cookie = rumpuser_component_unschedule();
+	struct pollfd pfd;
+	ssize_t nn = 0;
+	int rv;
+
+	pfd.fd = viu->viu_fd;
+	pfd.events = POLLIN;
+
+	for (;;) {
+		if (viu->viu_dying)
+			break;
+
+		rv = poll(&pfd, 1, POLLTIMO_MS);
+		if (rv == 0)
+			continue;
+		if (rv == -1)
+			break;
+
+		nn = read(viu->viu_fd, data, dlen);
+		if (nn == -1 && errno == EAGAIN)
+			continue;
+
+		break;
+	}
+
+	rumpuser_component_schedule(cookie);
+	return nn;
+}
+#undef POLLTIMO_MS
+
+void
+rumpcomp_virtif_dying(struct virtif_user *viu)
+{
+
+	/* no locking necessary.  it'll be seen eventually */
+	viu->viu_dying = 1;
+}
+
+void
+rumpcomp_virtif_destroy(struct virtif_user *viu)
+{
+	void *cookie = rumpuser_component_unschedule();
+
+	close(viu->viu_fd);
+	free(viu);
+
+	rumpuser_component_schedule(cookie);
+}
Index: src/sys/rump/net/lib/libvirtif/rumpcomp_user.h
diff -u /dev/null src/sys/rump/net/lib/libvirtif/rumpcomp_user.h:1.1
--- /dev/null	Wed Mar 13 21:13:45 2013
+++ src/sys/rump/net/lib/libvirtif/rumpcomp_user.h	Wed Mar 13 21:13:45 2013
@@ -0,0 +1,35 @@
+/*	$NetBSD: rumpcomp_user.h,v 1.1 2013/03/13 21:13:45 pooka Exp $	*/
+
+/*
+ * Copyright (c) 2013 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+struct virtif_user;
+
+struct virtif_user *rumpcomp_virtif_create(int);
+void rumpcomp_virtif_dying(struct virtif_user *);
+void rumpcomp_virtif_destroy(struct virtif_user *);
+
+void	rumpcomp_virtif_send(struct virtif_user *, struct iovec *, size_t);
+ssize_t	rumpcomp_virtif_recv(struct virtif_user *, void *data, size_t);

Reply via email to