if_vmove: improve restoration in cloner's ifgroup membership
* Do a single call into if_clone.c instead of two. The cloner can't disappear since the interface sits on its list. * Make restoration smarter - check that cloner with same name exists in the new vnet. Differential revision: https://reviews.freebsd.org/D33941
This commit is contained in:
parent
4a178afb4a
commit
54712fc423
34
sys/net/if.c
34
sys/net/if.c
@ -285,8 +285,8 @@ static void do_link_state_change(void *, int);
|
||||
static int if_getgroup(struct ifgroupreq *, struct ifnet *);
|
||||
static int if_getgroupmembers(struct ifgroupreq *);
|
||||
static void if_delgroups(struct ifnet *);
|
||||
static void if_attach_internal(struct ifnet *, int, struct if_clone *);
|
||||
static int if_detach_internal(struct ifnet *, int, struct if_clone **);
|
||||
static void if_attach_internal(struct ifnet *, bool);
|
||||
static int if_detach_internal(struct ifnet *, bool);
|
||||
static void if_siocaddmulti(void *, int);
|
||||
static void if_link_ifnet(struct ifnet *);
|
||||
static bool if_unlink_ifnet(struct ifnet *, bool);
|
||||
@ -775,7 +775,7 @@ void
|
||||
if_attach(struct ifnet *ifp)
|
||||
{
|
||||
|
||||
if_attach_internal(ifp, 0, NULL);
|
||||
if_attach_internal(ifp, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -830,7 +830,7 @@ if_hw_tsomax_update(if_t ifp, struct ifnet_hw_tsomax *pmax)
|
||||
}
|
||||
|
||||
static void
|
||||
if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
|
||||
if_attach_internal(struct ifnet *ifp, bool vmove)
|
||||
{
|
||||
unsigned socksize, ifasize;
|
||||
int namelen, masklen;
|
||||
@ -847,9 +847,11 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
|
||||
|
||||
if_addgroup(ifp, IFG_ALL);
|
||||
|
||||
/* Restore group membership for cloned interfaces. */
|
||||
if (vmove && ifc != NULL)
|
||||
if_clone_addgroup(ifp, ifc);
|
||||
#ifdef VIMAGE
|
||||
/* Restore group membership for cloned interface. */
|
||||
if (vmove)
|
||||
if_clone_restoregroup(ifp);
|
||||
#endif
|
||||
|
||||
getmicrotime(&ifp->if_lastchange);
|
||||
ifp->if_epoch = time_uptime;
|
||||
@ -1097,7 +1099,7 @@ if_detach(struct ifnet *ifp)
|
||||
found = if_unlink_ifnet(ifp, false);
|
||||
if (found) {
|
||||
sx_xlock(&ifnet_detach_sxlock);
|
||||
if_detach_internal(ifp, 0, NULL);
|
||||
if_detach_internal(ifp, false);
|
||||
sx_xunlock(&ifnet_detach_sxlock);
|
||||
}
|
||||
CURVNET_RESTORE();
|
||||
@ -1114,7 +1116,7 @@ if_detach(struct ifnet *ifp)
|
||||
* the cloned interfaces are destoyed as first thing of teardown.
|
||||
*/
|
||||
static int
|
||||
if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
|
||||
if_detach_internal(struct ifnet *ifp, bool vmove)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int i;
|
||||
@ -1149,15 +1151,6 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
|
||||
taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
|
||||
taskqueue_drain(taskqueue_swi, &ifp->if_addmultitask);
|
||||
|
||||
/*
|
||||
* Check if this is a cloned interface or not. Must do even if
|
||||
* shutting down as a if_vmove_reclaim() would move the ifp and
|
||||
* the if_clone_addgroup() will have a corrupted string overwise
|
||||
* from a gibberish pointer.
|
||||
*/
|
||||
if (vmove && ifcp != NULL)
|
||||
*ifcp = if_clone_findifc(ifp);
|
||||
|
||||
if_down(ifp);
|
||||
|
||||
#ifdef VIMAGE
|
||||
@ -1271,7 +1264,6 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
|
||||
static int
|
||||
if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
|
||||
{
|
||||
struct if_clone *ifc;
|
||||
#ifdef DEV_BPF
|
||||
u_int bif_dlt, bif_hdrlen;
|
||||
#endif
|
||||
@ -1291,7 +1283,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
|
||||
* mark as dead etc. so that the ifnet can be reattached later.
|
||||
* If we cannot find it, we lost the race to someone else.
|
||||
*/
|
||||
rc = if_detach_internal(ifp, 1, &ifc);
|
||||
rc = if_detach_internal(ifp, true);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
|
||||
@ -1318,7 +1310,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
|
||||
*/
|
||||
CURVNET_SET_QUIET(new_vnet);
|
||||
ifindex_alloc(ifp);
|
||||
if_attach_internal(ifp, 1, ifc);
|
||||
if_attach_internal(ifp, true);
|
||||
|
||||
#ifdef DEV_BPF
|
||||
if (ifp->if_bpf == NULL)
|
||||
|
@ -525,49 +525,48 @@ if_clone_list(struct if_clonereq *ifcr)
|
||||
return (err);
|
||||
}
|
||||
|
||||
#ifdef VIMAGE
|
||||
/*
|
||||
* if_clone_findifc() looks up ifnet from the current
|
||||
* cloner list, and returns ifc if found. Note that ifc_refcnt
|
||||
* is incremented.
|
||||
* if_clone_restoregroup() is used in context of if_vmove().
|
||||
*
|
||||
* Since if_detach_internal() has removed the interface from ALL groups, we
|
||||
* need to "restore" interface membership in the cloner's group. Note that
|
||||
* interface belongs to cloner in its home vnet, so we first find the original
|
||||
* cloner, and then we confirm that cloner with the same name exists in the
|
||||
* current vnet.
|
||||
*/
|
||||
struct if_clone *
|
||||
if_clone_findifc(struct ifnet *ifp)
|
||||
void
|
||||
if_clone_restoregroup(struct ifnet *ifp)
|
||||
{
|
||||
struct if_clone *ifc, *ifc0;
|
||||
struct if_clone *ifc;
|
||||
struct ifnet *ifcifp;
|
||||
char ifc_name[IFCLOSIZ] = { [0] = '\0' };
|
||||
|
||||
ifc0 = NULL;
|
||||
CURVNET_SET_QUIET(ifp->if_home_vnet);
|
||||
IF_CLONERS_LOCK();
|
||||
LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
|
||||
IF_CLONE_LOCK(ifc);
|
||||
LIST_FOREACH(ifcifp, &ifc->ifc_iflist, if_clones) {
|
||||
if (ifp == ifcifp) {
|
||||
ifc0 = ifc;
|
||||
IF_CLONE_ADDREF_LOCKED(ifc);
|
||||
strncpy(ifc_name, ifc->ifc_name, IFCLOSIZ-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
IF_CLONE_UNLOCK(ifc);
|
||||
if (ifc0 != NULL)
|
||||
if (ifc_name[0] != '\0')
|
||||
break;
|
||||
}
|
||||
CURVNET_RESTORE();
|
||||
LIST_FOREACH(ifc, &V_if_cloners, ifc_list)
|
||||
if (strcmp(ifc->ifc_name, ifc_name) == 0 &&
|
||||
((ifc->ifc_flags & IFC_NOGROUP) == 0))
|
||||
break;
|
||||
IF_CLONERS_UNLOCK();
|
||||
|
||||
return (ifc0);
|
||||
}
|
||||
|
||||
/*
|
||||
* if_clone_addgroup() decrements ifc_refcnt because it is called after
|
||||
* if_clone_findifc().
|
||||
*/
|
||||
void
|
||||
if_clone_addgroup(struct ifnet *ifp, struct if_clone *ifc)
|
||||
{
|
||||
if ((ifc->ifc_flags & IFC_NOGROUP) == 0) {
|
||||
if_addgroup(ifp, ifc->ifc_name);
|
||||
IF_CLONE_REMREF(ifc);
|
||||
}
|
||||
if (ifc != NULL)
|
||||
if_addgroup(ifp, ifc_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A utility function to extract unit numbers from interface names of
|
||||
|
@ -76,8 +76,7 @@ void vnet_if_clone_init(void);
|
||||
int if_clone_create(char *, size_t, caddr_t);
|
||||
int if_clone_destroy(const char *);
|
||||
int if_clone_list(struct if_clonereq *);
|
||||
struct if_clone *if_clone_findifc(struct ifnet *);
|
||||
void if_clone_addgroup(struct ifnet *, struct if_clone *);
|
||||
void if_clone_restoregroup(struct ifnet *);
|
||||
|
||||
/* The below interfaces are used only by epair(4). */
|
||||
void if_clone_addif(struct if_clone *, struct ifnet *);
|
||||
|
Loading…
Reference in New Issue
Block a user