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.
This commit is contained in:
parent
66c8095956
commit
3c3136b1dd
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user