kern/165174: [patch] [tap] allow tap(4) to keep its address on close
Eugene Grosbein
eugen at grosbein.net
Wed Feb 15 12:00:22 UTC 2012
>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 at 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:
More information about the freebsd-bugs
mailing list