diff options
author | hrs <hrs@FreeBSD.org> | 2014-10-10 06:45:13 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2014-10-10 06:45:13 +0000 |
commit | 1805c9c20a4f714ee1456e879bba08088f1cb4dd (patch) | |
tree | b56f03608f4e55074162d6c6eb94b328bd9e720a | |
parent | c4ad6de85563108a0d0c3c40bdabdc276acef508 (diff) | |
download | FreeBSD-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.
-rw-r--r-- | sys/net/if_epair.c | 36 |
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) |