Page MenuHomeFreeBSD

D1859.id4076.diff
No OneTemporary

D1859.id4076.diff

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

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)

Event Timeline