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:
Hiroki Sato 2014-10-10 06:45:13 +00:00
parent 66c8095956
commit 3c3136b1dd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272889

View File

@ -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)