summaryrefslogtreecommitdiffstats
path: root/sys/net/if_epair.c
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2014-10-10 06:45:13 +0000
committerhrs <hrs@FreeBSD.org>2014-10-10 06:45:13 +0000
commit1805c9c20a4f714ee1456e879bba08088f1cb4dd (patch)
treeb56f03608f4e55074162d6c6eb94b328bd9e720a /sys/net/if_epair.c
parentc4ad6de85563108a0d0c3c40bdabdc276acef508 (diff)
downloadFreeBSD-src-1805c9c20a4f714ee1456e879bba08088f1cb4dd.zip
FreeBSD-src-1805c9c20a4f714ee1456e879bba08088f1cb4dd.tar.gz
Virtualize if_epair(4). An if_xname check for both "a" and "b" interfaces
is added to return EEXIST when only "b" interface exists---this can happen when epair<N>b is moved to a vnet jail and then "ifconfig epair<N> create" is invoked there.
Diffstat (limited to 'sys/net/if_epair.c')
-rw-r--r--sys/net/if_epair.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index 13d7e0b..e9a8ed5 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -101,7 +101,7 @@ static int epair_clone_destroy(struct if_clone *, struct ifnet *);
static const char epairname[] = "epair";
-/* Netisr realted definitions and sysctl. */
+/* Netisr related definitions and sysctl. */
static struct netisr_handler epair_nh = {
.nh_name = epairname,
.nh_proto = NETISR_EPAIR,
@@ -172,7 +172,8 @@ STAILQ_HEAD(eid_list, epair_ifp_drain);
static MALLOC_DEFINE(M_EPAIR, epairname,
"Pair of virtual cross-over connected Ethernet-like interfaces");
-static struct if_clone *epair_cloner;
+static VNET_DEFINE(struct if_clone *, epair_cloner);
+#define V_epair_cloner VNET(epair_cloner)
/*
* DPCPU area and functions.
@@ -760,10 +761,17 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifc_free_unit(ifc, unit);
return (ENOSPC);
}
- *dp = 'a';
+ *dp = 'b';
/* Must not change dp so we can replace 'a' by 'b' later. */
*(dp+1) = '\0';
+ /* Check if 'a' and 'b' interfaces already exist. */
+ if (ifunit(name) != NULL)
+ return (EEXIST);
+ *dp = 'a';
+ if (ifunit(name) != NULL)
+ return (EEXIST);
+
/* Allocate memory for both [ab] interfaces */
sca = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO);
EPAIR_REFCOUNT_INIT(&sca->refcount, 1);
@@ -944,6 +952,25 @@ epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
return (0);
}
+static void
+vnet_epair_init(const void *unused __unused)
+{
+
+ V_epair_cloner = if_clone_advanced(epairname, 0,
+ epair_clone_match, epair_clone_create, epair_clone_destroy);
+}
+VNET_SYSINIT(vnet_epair_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_epair_init, NULL);
+
+static void
+vnet_epair_uninit(const void *unused __unused)
+{
+
+ if_clone_detach(V_epair_cloner);
+}
+VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_epair_uninit, NULL);
+
static int
epair_modevent(module_t mod, int type, void *data)
{
@@ -957,13 +984,10 @@ epair_modevent(module_t mod, int type, void *data)
if (TUNABLE_INT_FETCH("net.link.epair.netisr_maxqlen", &qlimit))
epair_nh.nh_qlimit = qlimit;
netisr_register(&epair_nh);
- epair_cloner = if_clone_advanced(epairname, 0,
- epair_clone_match, epair_clone_create, epair_clone_destroy);
if (bootverbose)
printf("%s initialized.\n", epairname);
break;
case MOD_UNLOAD:
- if_clone_detach(epair_cloner);
netisr_unregister(&epair_nh);
epair_dpcpu_detach();
if (bootverbose)
OpenPOWER on IntegriCloud