Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Feb 2012 18:50:49 +0700 (NOVT)
From:      Eugene Grosbein <eugen@grosbein.net>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/165174: [patch] [tap] allow tap(4) to keep its address on close
Message-ID:  <201202151150.q1FBon3U006603@eg.sd.rdtc.ru>
Resent-Message-ID: <201202151200.q1FC0Lin010013@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         165174
>Category:       kern
>Synopsis:       [patch] [tap] allow tap(4) to keep its address on close
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 15 12:00:20 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 8.2-STABLE i386
>Organization:
RDTC JSC
>Environment:
System: FreeBSD eg.sd.rdtc.ru 8.2-STABLE FreeBSD 8.2-STABLE #37: Wed Feb 15 14:22:03 NOVT 2012 root@eg.sd.rdtc.ru:/usr/local/obj/usr/local/src/sys/EG i386

>Description:

	I routinely start, run and close several VirtualBox-controlled
	virtual machines within FreeBSD. These machines use tap(4)-based
	networking. tap interfaces are configured in /etc/rc.conf
	just like all other interfaces:

cloned_interfaces="tap0 tap1 tap2"
ifconfig_tap0="inet 192.168.254.1/29"
ifconfig_tap1="inet 192.168.254.17/28"
ifconfig_tap2="inet 192.168.254.9/29"

	Each machine uses its own tapX. VirtualBox runs as non-root user
	with help of /etc/sysctl.conf:

net.link.tap.user_open=1
net.link.tap.up_on_open=1

	This works for first start of each VM only as tap(4) driver
	removes interface addresses of tapX on close. Very inconvinient.

>How-To-Repeat:

	Create tap0 with ifconfig, run an application working with tap0,
	restart the application and its networking fails.

>Fix:

	The following patch introduces new per-interface sysctls
	that may be used to keep addresses of tap interfaces
	and interfaces itself up on close:

net.link.tap.0.keep_up=1
net.link.tap.1.keep_up=1
net.link.tap.2.keep_up=1

	Default value is 0 and corresponds to current behaviour.

	The patch updates manual page too.

--- sys/net/if_tapvar.h.orig	2012-02-15 13:35:31.000000000 +0700
+++ sys/net/if_tapvar.h	2012-02-15 14:06:40.000000000 +0700
@@ -41,6 +41,8 @@
 #ifndef _NET_IF_TAPVAR_H_
 #define _NET_IF_TAPVAR_H_
 
+#include <sys/sysctl.h>
+
 /*
  * tap_mtx locks tap_flags, tap_pid.  tap_next locked with global tapmtx.
  * Other fields locked by owning subsystems.
@@ -64,6 +66,9 @@ struct tap_softc {
 	SLIST_ENTRY(tap_softc)	tap_next;	/* next device in chain      */
 	struct cdev *tap_dev;
 	struct mtx	 tap_mtx;		/* per-softc mutex */
+
+	struct sysctl_ctx_list	ctx;		/* sysctl variables */
+	int		 keep_up;
 };
 
 #endif /* !_NET_IF_TAPVAR_H_ */
--- sys/net/if_tap.c.orig	2012-02-15 13:24:10.000000000 +0700
+++ sys/net/if_tap.c	2012-02-15 16:28:15.000000000 +0700
@@ -229,6 +229,7 @@ tap_clone_destroy(struct ifnet *ifp)
 {
 	struct tap_softc *tp = ifp->if_softc;
 
+	sysctl_ctx_free(&tp->ctx);
 	mtx_lock(&tapmtx);
 	SLIST_REMOVE(&taphead, tp, tap_softc, tap_next);
 	mtx_unlock(&tapmtx);
@@ -399,6 +400,8 @@ tapcreate(struct cdev *dev)
 	int			 unit;
 	char			*name = NULL;
 	u_char			eaddr[6];
+	char			 num[14];	/* sufficient for 32 bits */
+	struct sysctl_oid	*oid;
 
 	dev->si_flags &= ~SI_CHEAPCLONE;
 
@@ -433,6 +436,16 @@ tapcreate(struct cdev *dev)
 	ifp = tp->tap_ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL)
 		panic("%s%d: can not if_alloc()", name, unit);
+		
+	sysctl_ctx_init(&tp->ctx);
+	snprintf(num, sizeof(num), "%u", unit);
+	tp->keep_up = 0;
+	oid = SYSCTL_ADD_NODE(&tp->ctx, &SYSCTL_NODE_CHILDREN(_net_link, tap),
+		OID_AUTO, num, CTLFLAG_RD, NULL, "");
+	SYSCTL_ADD_INT(&tp->ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+		"keep_up", CTLTYPE_INT|CTLFLAG_RW, &tp->keep_up, tp->keep_up,
+		"Keep interface up on close");
+
 	ifp->if_softc = tp;
 	if_initname(ifp, name, unit);
 	ifp->if_init = tapifinit;
@@ -528,7 +541,8 @@ tapclose(struct cdev *dev, int foo, int 
 	 * interface, if we are in VMnet mode. just close the device.
 	 */
 
-	if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) {
+	if (!tp->keep_up &&
+	    ((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) {
 		mtx_unlock(&tp->tap_mtx);
 		if_down(ifp);
 		mtx_lock(&tp->tap_mtx);
--- share/man/man4/tap.4.orig	2012-02-15 14:37:59.000000000 +0700
+++ share/man/man4/tap.4	2012-02-15 16:25:50.000000000 +0700
@@ -268,7 +268,9 @@
 .Dq ifconfig tap Ns Sy N No down )
 unless the device is a
 .Em VMnet
-device.
+device (but see
+.Sx SYSCTL VARIABLES
+section below).
 All queued frames are thrown away.
 If the interface is up when the data
 device is not open, output frames are thrown away rather than
@@ -316,6 +318,14 @@
 VMware
 .Dv SIOCSIFFLAGS .
 .El
+.Sh SYSCTL VARIABLES
+In addition to global sysctl variables described above, there are
+per-interface variables:
+.Bl -tag -width indent
+.It Va net.link.tap.X.keep_up: No 0
+Set this variable to 1 and interface tapX will stay up
+and keep its address on close regardless of mode.
+.El
 .Sh SEE ALSO
 .Xr inet 4 ,
 .Xr intro 4
>Release-Note:
>Audit-Trail:
>Unformatted:



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