aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_clone.c
diff options
context:
space:
mode:
authorHiroki Sato <hrs@FreeBSD.org>2015-03-02 20:00:03 +0000
committerHiroki Sato <hrs@FreeBSD.org>2015-03-02 20:00:03 +0000
commitc92a456b5537ceb711011c014e68ae0201ab4290 (patch)
tree05d3b415604775b6412825773fe5cf4c187c313b /sys/net/if_clone.c
parent2d427c524dfc4813a829ba8a2167e351722c5e24 (diff)
downloadsrc-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.c43
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###.
*