Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163941221
D1859.id4076.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D1859.id4076.diff
View Options
Index: head/sys/net/if.c
===================================================================
--- head/sys/net/if.c
+++ head/sys/net/if.c
@@ -172,8 +172,8 @@
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);
-static void if_detach_internal(struct ifnet *, int);
+static void if_attach_internal(struct ifnet *, int, struct if_clone *);
+static void if_detach_internal(struct ifnet *, int, struct if_clone **);
#ifdef INET6
/*
@@ -558,6 +558,15 @@
* tasks, given that we are moving from one vnet to another an ifnet which
* has already been fully initialized.
*
+ * Note that if_detach_internal() removes group membership unconditionally
+ * even when vmove flag is set, and if_attach_internal() adds only IFG_ALL.
+ * Thus, when if_vmove() is applied to a cloned interface, group membership
+ * is lost while a cloned one always joins a group whose name is
+ * ifc->ifc_name. To recover this after if_detach_internal() and
+ * if_attach_internal(), the cloner should be specified to
+ * if_attach_internal() via ifc. If it is non-NULL, if_attach_internal()
+ * attempts to join a group whose name is ifc->ifc_name.
+ *
* XXX:
* - The decision to return void and thus require this function to
* succeed is questionable.
@@ -568,7 +577,7 @@
if_attach(struct ifnet *ifp)
{
- if_attach_internal(ifp, 0);
+ if_attach_internal(ifp, 0, NULL);
}
/*
@@ -623,7 +632,7 @@
}
static void
-if_attach_internal(struct ifnet *ifp, int vmove)
+if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
{
unsigned socksize, ifasize;
int namelen, masklen;
@@ -642,6 +651,10 @@
if_addgroup(ifp, IFG_ALL);
+ /* Restore group membership for cloned interfaces. */
+ if (vmove && ifc != NULL)
+ if_clone_addgroup(ifp, ifc);
+
getmicrotime(&ifp->if_lastchange);
ifp->if_epoch = time_uptime;
@@ -860,12 +873,12 @@
{
CURVNET_SET_QUIET(ifp->if_vnet);
- if_detach_internal(ifp, 0);
+ if_detach_internal(ifp, 0, NULL);
CURVNET_RESTORE();
}
static void
-if_detach_internal(struct ifnet *ifp, int vmove)
+if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
{
struct ifaddr *ifa;
struct radix_node_head *rnh;
@@ -894,6 +907,10 @@
return; /* XXX this should panic as well? */
}
+ /* Check if this is a cloned interface or not. */
+ if (vmove && ifcp != NULL)
+ *ifcp = if_clone_findifc(ifp);
+
/*
* Remove/wait for pending events.
*/
@@ -999,12 +1016,13 @@
void
if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
{
+ struct if_clone *ifc;
/*
* Detach from current vnet, but preserve LLADDR info, do not
* mark as dead etc. so that the ifnet can be reattached later.
*/
- if_detach_internal(ifp, 1);
+ if_detach_internal(ifp, 1, &ifc);
/*
* Unlink the ifnet from ifindex_table[] in current vnet, and shrink
@@ -1034,7 +1052,7 @@
ifnet_setbyindex_locked(ifp->if_index, ifp);
IFNET_WUNLOCK();
- if_attach_internal(ifp, 1);
+ if_attach_internal(ifp, 1, ifc);
CURVNET_RESTORE();
}
Index: head/sys/net/if_clone.h
===================================================================
--- head/sys/net/if_clone.h
+++ head/sys/net/if_clone.h
@@ -69,6 +69,8 @@
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 *);
/* The below interface used only by epair(4). */
int if_clone_destroyif(struct if_clone *, struct ifnet *);
Index: head/sys/net/if_clone.c
===================================================================
--- head/sys/net/if_clone.c
+++ head/sys/net/if_clone.c
@@ -518,6 +518,49 @@
}
/*
+ * 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###.
*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 28, 8:32 AM (3 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35606250
Default Alt Text
D1859.id4076.diff (4 KB)
Attached To
Mode
D1859: Fix group membership of a cloned interface before and after if_vmove()
Attached
Detach File
Event Timeline
Log In to Comment