diff --git a/sys/net/if.c b/sys/net/if.c --- a/sys/net/if.c +++ b/sys/net/if.c @@ -285,8 +285,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, 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 @@ if_attach(struct ifnet *ifp) { - if_attach_internal(ifp, 0, NULL); + if_attach_internal(ifp, false); } /* @@ -830,7 +830,7 @@ } 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_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 @@ 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 @@ * 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 @@ 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 @@ 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 @@ * 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 @@ */ 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) diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h --- a/sys/net/if_clone.h +++ b/sys/net/if_clone.h @@ -76,8 +76,7 @@ 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 *); diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -525,49 +525,48 @@ 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