diff options
author | Hiroki Sato <hrs@FreeBSD.org> | 2015-03-02 20:00:03 +0000 |
---|---|---|
committer | Hiroki Sato <hrs@FreeBSD.org> | 2015-03-02 20:00:03 +0000 |
commit | c92a456b5537ceb711011c014e68ae0201ab4290 (patch) | |
tree | 05d3b415604775b6412825773fe5cf4c187c313b /sys/net/if_clone.c | |
parent | 2d427c524dfc4813a829ba8a2167e351722c5e24 (diff) | |
download | src-c92a456b5537ceb711011c014e68ae0201ab4290.tar.gz src-c92a456b5537ceb711011c014e68ae0201ab4290.zip |
Fix group membership of cloned interfaces when one is moved by
if_vmove().
In if_vmove(), if_detach_internal() and if_attach_internal() were
called in series to detach and reattach the interface. When
detaching, if_delgroup() was called and the interface leaves all of
the group membership. And then upon attachment, if_addgroup(ifp,
IFG_ALL) was called and it joined only "all" group again.
This had a problem. Normally, a cloned interface automatically joins
a group whose name is ifc_name of the cloner in addition to "all"
upon creation. However, if_vmove() removed the membership and did
not restore upon attachment.
Differential Revision: https://reviews.freebsd.org/D1859
Notes
Notes:
svn path=/head/; revision=279538
Diffstat (limited to 'sys/net/if_clone.c')
-rw-r--r-- | sys/net/if_clone.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index 09f8d2a613bf..dc71bfc04f1e 100644 --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -518,6 +518,49 @@ done: } /* + * if_clone_findifc() looks up ifnet from the current + * cloner list, and returns ifc if found. Note that ifc_refcnt + * is incremented. + */ +struct if_clone * +if_clone_findifc(struct ifnet *ifp) +{ + struct if_clone *ifc, *ifc0; + struct ifnet *ifcifp; + + ifc0 = NULL; + 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); + break; + } + } + IF_CLONE_UNLOCK(ifc); + if (ifc0 != NULL) + 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_addgroup(ifp, ifc->ifc_name); + IF_CLONE_REMREF(ifc); +} + +/* * A utility function to extract unit numbers from interface names of * the form name###. * |