From owner-svn-src-head@freebsd.org Tue Jun 21 13:48:54 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 45F03AC5898; Tue, 21 Jun 2016 13:48:54 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0F53314E6; Tue, 21 Jun 2016 13:48:53 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u5LDmraV081638; Tue, 21 Jun 2016 13:48:53 GMT (envelope-from bz@FreeBSD.org) Received: (from bz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u5LDmom9081605; Tue, 21 Jun 2016 13:48:50 GMT (envelope-from bz@FreeBSD.org) Message-Id: <201606211348.u5LDmom9081605@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bz set sender to bz@FreeBSD.org using -f From: "Bjoern A. Zeeb" Date: Tue, 21 Jun 2016 13:48:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r302054 - in head/sys: contrib/ipfilter/netinet dev/usb/net kern net netgraph netinet netinet6 netipsec netpfil/ipfw netpfil/pf X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Jun 2016 13:48:54 -0000 Author: bz Date: Tue Jun 21 13:48:49 2016 New Revision: 302054 URL: https://svnweb.freebsd.org/changeset/base/302054 Log: Get closer to a VIMAGE network stack teardown from top to bottom rather than removing the network interfaces first. This change is rather larger and convoluted as the ordering requirements cannot be separated. Move the pfil(9) framework to SI_SUB_PROTO_PFIL, move Firewalls and related modules to their own SI_SUB_PROTO_FIREWALL. Move initialization of "physical" interfaces to SI_SUB_DRIVERS, move virtual (cloned) interfaces to SI_SUB_PSEUDO. Move Multicast to SI_SUB_PROTO_MC. Re-work parts of multicast initialisation and teardown, not taking the huge amount of memory into account if used as a module yet. For interface teardown we try to do as many of them as we can on SI_SUB_INIT_IF, but for some this makes no sense, e.g., when tunnelling over a higher layer protocol such as IP. In that case the interface has to go along (or before) the higher layer protocol is shutdown. Kernel hhooks need to go last on teardown as they may be used at various higher layers and we cannot remove them before we cleaned up the higher layers. For interface teardown there are multiple paths: (a) a cloned interface is destroyed (inside a VIMAGE or in the base system), (b) any interface is moved from a virtual network stack to a different network stack ("vmove"), or (c) a virtual network stack is being shut down. All code paths go through if_detach_internal() where we, depending on the vmove flag or the vnet state, make a decision on how much to shut down; in case we are destroying a VNET the individual protocol layers will cleanup their own parts thus we cannot do so again for each interface as we end up with, e.g., double-frees, destroying locks twice or acquiring already destroyed locks. When calling into protocol cleanups we equally have to tell them whether they need to detach upper layer protocols ("ulp") or not (e.g., in6_ifdetach()). Provide or enahnce helper functions to do proper cleanup at a protocol rather than at an interface level. Approved by: re (hrs) Obtained from: projects/vnet Reviewed by: gnn, jhb Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D6747 Modified: head/sys/contrib/ipfilter/netinet/mlfk_ipl.c head/sys/dev/usb/net/usb_ethernet.c head/sys/kern/kern_hhook.c head/sys/net/if.c head/sys/net/if_bridge.c head/sys/net/if_disc.c head/sys/net/if_edsc.c head/sys/net/if_enc.c head/sys/net/if_epair.c head/sys/net/if_lagg.c head/sys/net/if_loop.c head/sys/net/if_vlan.c head/sys/net/pfil.c head/sys/net/route.c head/sys/net/vnet.c head/sys/net/vnet.h head/sys/netgraph/ng_eiface.c head/sys/netgraph/ng_iface.c head/sys/netinet/igmp.c head/sys/netinet/in.c head/sys/netinet/in_var.h head/sys/netinet/ip_id.c head/sys/netinet/ip_input.c head/sys/netinet/ip_mroute.c head/sys/netinet6/in6.c head/sys/netinet6/in6_ifattach.c head/sys/netinet6/in6_ifattach.h head/sys/netinet6/ip6_input.c head/sys/netinet6/ip6_mroute.c head/sys/netinet6/mld6.c head/sys/netinet6/nd6.c head/sys/netinet6/nd6.h head/sys/netipsec/ipsec.c head/sys/netipsec/xform_tcp.c head/sys/netpfil/ipfw/dn_sched.h head/sys/netpfil/ipfw/ip_dummynet.c head/sys/netpfil/ipfw/ip_fw2.c head/sys/netpfil/ipfw/ip_fw_nat.c head/sys/netpfil/pf/pf_ioctl.c Modified: head/sys/contrib/ipfilter/netinet/mlfk_ipl.c ============================================================================== --- head/sys/contrib/ipfilter/netinet/mlfk_ipl.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/contrib/ipfilter/netinet/mlfk_ipl.c Tue Jun 21 13:48:49 2016 (r302054) @@ -287,7 +287,7 @@ static moduledata_t ipfiltermod = { }; -DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); +DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY); #ifdef MODULE_VERSION MODULE_VERSION(ipfilter, 1); #endif Modified: head/sys/dev/usb/net/usb_ethernet.c ============================================================================== --- head/sys/dev/usb/net/usb_ethernet.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/dev/usb/net/usb_ethernet.c Tue Jun 21 13:48:49 2016 (r302054) @@ -641,5 +641,9 @@ uether_rxflush(struct usb_ether *ue) } } -DECLARE_MODULE(uether, uether_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +/* + * USB net drivers are run by DRIVER_MODULE() thus SI_SUB_DRIVERS, + * SI_ORDER_MIDDLE. Run uether after that. + */ +DECLARE_MODULE(uether, uether_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_VERSION(uether, 1); Modified: head/sys/kern/kern_hhook.c ============================================================================== --- head/sys/kern/kern_hhook.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/kern/kern_hhook.c Tue Jun 21 13:48:49 2016 (r302054) @@ -510,7 +510,7 @@ hhook_vnet_uninit(const void *unused __u /* * When a vnet is created and being initialised, init the V_hhook_vhead_list. */ -VNET_SYSINIT(hhook_vnet_init, SI_SUB_MBUF, SI_ORDER_FIRST, +VNET_SYSINIT(hhook_vnet_init, SI_SUB_INIT_IF, SI_ORDER_FIRST, hhook_vnet_init, NULL); /* @@ -518,5 +518,5 @@ VNET_SYSINIT(hhook_vnet_init, SI_SUB_MBU * points to clean up on vnet tear down, but in case the KPI is misused, * provide a function to clean up and free memory for a vnet being destroyed. */ -VNET_SYSUNINIT(hhook_vnet_uninit, SI_SUB_MBUF, SI_ORDER_ANY, +VNET_SYSUNINIT(hhook_vnet_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST, hhook_vnet_uninit, NULL); Modified: head/sys/net/if.c ============================================================================== --- head/sys/net/if.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if.c Tue Jun 21 13:48:49 2016 (r302054) @@ -914,6 +914,16 @@ if_detach(struct ifnet *ifp) CURVNET_RESTORE(); } +/* + * The vmove flag, if set, indicates that we are called from a callpath + * that is moving an interface to a different vnet instance. + * + * The shutdown flag, if set, indicates that we are called in the + * process of shutting down a vnet instance. Currently only the + * vnet_if_return SYSUNINIT function sets it. Note: we can be called + * on a vnet instance shutdown without this flag being set, e.g., when + * the cloned interfaces are destoyed as first thing of teardown. + */ static int if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) { @@ -921,8 +931,10 @@ if_detach_internal(struct ifnet *ifp, in int i; struct domain *dp; struct ifnet *iter; - int found = 0; + int found = 0, shutdown; + shutdown = (ifp->if_vnet->vnet_state > SI_SUB_VNET && + ifp->if_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; IFNET_WLOCK(); TAILQ_FOREACH(iter, &V_ifnet, if_link) if (iter == ifp) { @@ -930,10 +942,6 @@ if_detach_internal(struct ifnet *ifp, in found = 1; break; } -#ifdef VIMAGE - if (found) - curvnet->vnet_ifcnt--; -#endif IFNET_WUNLOCK(); if (!found) { /* @@ -951,19 +959,58 @@ if_detach_internal(struct ifnet *ifp, in #endif } - /* Check if this is a cloned interface or not. */ + /* + * At this point we know the interface still was on the ifnet list + * and we removed it so we are in a stable state. + */ +#ifdef VIMAGE + curvnet->vnet_ifcnt--; +#endif + + /* + * In any case (destroy or vmove) detach us from the groups + * and remove/wait for pending events on the taskq. + * XXX-BZ in theory an interface could still enqueue a taskq change? + */ + if_delgroups(ifp); + + taskqueue_drain(taskqueue_swi, &ifp->if_linktask); + + /* + * 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); + /* - * Remove/wait for pending events. + * On VNET shutdown abort here as the stack teardown will do all + * the work top-down for us. + */ + if (shutdown) { + /* + * In case of a vmove we are done here without error. + * If we would signal an error it would lead to the same + * abort as if we did not find the ifnet anymore. + * if_detach() calls us in void context and does not care + * about an early abort notification, so life is splendid :) + */ + goto finish_vnet_shutdown; + } + + /* + * At this point we are not tearing down a VNET and are either + * going to destroy or vmove the interface and have to cleanup + * accordingly. */ - taskqueue_drain(taskqueue_swi, &ifp->if_linktask); /* * Remove routes and flush queues. */ - if_down(ifp); #ifdef ALTQ if (ALTQ_IS_ENABLED(&ifp->if_snd)) altq_disable(&ifp->if_snd); @@ -1018,8 +1065,8 @@ if_detach_internal(struct ifnet *ifp, in } rt_flushifroutes(ifp); - if_delgroups(ifp); +finish_vnet_shutdown: /* * We cannot hold the lock over dom_ifdetach calls as they might * sleep, for example trying to drain a callout, thus open up the @@ -1048,7 +1095,7 @@ if_detach_internal(struct ifnet *ifp, in * unused if_index in target vnet and calls if_grow() if necessary, * and finally find an unused if_xname for the target vnet. */ -void +static void if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { struct if_clone *ifc; @@ -1115,6 +1162,7 @@ if_vmove_loan(struct thread *td, struct { struct prison *pr; struct ifnet *difp; + int shutdown; /* Try to find the prison within our visibility. */ sx_slock(&allprison_lock); @@ -1135,12 +1183,22 @@ if_vmove_loan(struct thread *td, struct /* XXX Lock interfaces to avoid races. */ CURVNET_SET_QUIET(pr->pr_vnet); difp = ifunit(ifname); - CURVNET_RESTORE(); if (difp != NULL) { + CURVNET_RESTORE(); prison_free(pr); return (EEXIST); } + /* Make sure the VNET is stable. */ + shutdown = (ifp->if_vnet->vnet_state > SI_SUB_VNET && + ifp->if_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; + if (shutdown) { + CURVNET_RESTORE(); + prison_free(pr); + return (EBUSY); + } + CURVNET_RESTORE(); + /* Move the interface into the child jail/vnet. */ if_vmove(ifp, pr->pr_vnet); @@ -1157,6 +1215,7 @@ if_vmove_reclaim(struct thread *td, char struct prison *pr; struct vnet *vnet_dst; struct ifnet *ifp; + int shutdown; /* Try to find the prison within our visibility. */ sx_slock(&allprison_lock); @@ -1184,6 +1243,15 @@ if_vmove_reclaim(struct thread *td, char return (EEXIST); } + /* Make sure the VNET is stable. */ + shutdown = (ifp->if_vnet->vnet_state > SI_SUB_VNET && + ifp->if_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; + if (shutdown) { + CURVNET_RESTORE(); + prison_free(pr); + return (EBUSY); + } + /* Get interface back from child jail/vnet. */ if_vmove(ifp, vnet_dst); CURVNET_RESTORE(); @@ -2642,8 +2710,22 @@ ifioctl(struct socket *so, u_long cmd, c struct ifreq *ifr; int error; int oif_flags; +#ifdef VIMAGE + int shutdown; +#endif CURVNET_SET(so->so_vnet); +#ifdef VIMAGE + /* Make sure the VNET is stable. */ + shutdown = (so->so_vnet->vnet_state > SI_SUB_VNET && + so->so_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; + if (shutdown) { + CURVNET_RESTORE(); + return (EBUSY); + } +#endif + + switch (cmd) { case SIOCGIFCONF: error = ifconf(cmd, data); Modified: head/sys/net/if_bridge.c ============================================================================== --- head/sys/net/if_bridge.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_bridge.c Tue Jun 21 13:48:49 2016 (r302054) @@ -541,7 +541,7 @@ vnet_bridge_uninit(const void *unused __ V_bridge_cloner = NULL; BRIDGE_LIST_LOCK_DESTROY(); } -VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_bridge_uninit, NULL); static int Modified: head/sys/net/if_disc.c ============================================================================== --- head/sys/net/if_disc.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_disc.c Tue Jun 21 13:48:49 2016 (r302054) @@ -137,7 +137,7 @@ vnet_disc_init(const void *unused __unus V_disc_cloner = if_clone_simple(discname, disc_clone_create, disc_clone_destroy, 0); } -VNET_SYSINIT(vnet_disc_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSINIT(vnet_disc_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_disc_init, NULL); static void @@ -146,7 +146,7 @@ vnet_disc_uninit(const void *unused __un if_clone_detach(V_disc_cloner); } -VNET_SYSUNINIT(vnet_disc_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_disc_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_disc_uninit, NULL); static int Modified: head/sys/net/if_edsc.c ============================================================================== --- head/sys/net/if_edsc.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_edsc.c Tue Jun 21 13:48:49 2016 (r302054) @@ -336,7 +336,7 @@ vnet_edsc_uninit(const void *unused __un */ if_clone_detach(V_edsc_cloner); } -VNET_SYSUNINIT(vnet_edsc_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_edsc_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_edsc_uninit, NULL); /* Modified: head/sys/net/if_enc.c ============================================================================== --- head/sys/net/if_enc.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_enc.c Tue Jun 21 13:48:49 2016 (r302054) @@ -136,7 +136,6 @@ enc_clone_destroy(struct ifnet *ifp) sc = ifp->if_softc; KASSERT(sc == V_enc_sc, ("sc != ifp->if_softc")); - enc_remove_hhooks(sc); bpfdetach(ifp); if_detach(ifp); if_free(ifp); @@ -170,10 +169,6 @@ enc_clone_create(struct if_clone *ifc, i ifp->if_softc = sc; if_attach(ifp); bpfattach(ifp, DLT_ENC, sizeof(struct enchdr)); - if (enc_add_hhooks(sc) != 0) { - enc_clone_destroy(ifp); - return (ENXIO); - } return (0); } @@ -369,18 +364,44 @@ vnet_enc_init(const void *unused __unuse V_enc_cloner = if_clone_simple(encname, enc_clone_create, enc_clone_destroy, 1); } -VNET_SYSINIT(vnet_enc_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSINIT(vnet_enc_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_enc_init, NULL); static void +vnet_enc_init_proto(void *unused __unused) +{ + KASSERT(V_enc_sc != NULL, ("%s: V_enc_sc is %p\n", __func__, V_enc_sc)); + + if (enc_add_hhooks(V_enc_sc) != 0) + enc_clone_destroy(V_enc_sc->sc_ifp); +} +VNET_SYSINIT(vnet_enc_init_proto, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, + vnet_enc_init_proto, NULL); + +static void vnet_enc_uninit(const void *unused __unused) { + KASSERT(V_enc_sc != NULL, ("%s: V_enc_sc is %p\n", __func__, V_enc_sc)); if_clone_detach(V_enc_cloner); } -VNET_SYSUNINIT(vnet_enc_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_enc_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_enc_uninit, NULL); +/* + * The hhook consumer needs to go before ip[6]_destroy are called on + * SI_ORDER_THIRD. + */ +static void +vnet_enc_uninit_hhook(const void *unused __unused) +{ + KASSERT(V_enc_sc != NULL, ("%s: V_enc_sc is %p\n", __func__, V_enc_sc)); + + enc_remove_hhooks(V_enc_sc); +} +VNET_SYSUNINIT(vnet_enc_uninit_hhook, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, + vnet_enc_uninit_hhook, NULL); + static int enc_modevent(module_t mod, int type, void *data) { @@ -401,4 +422,4 @@ static moduledata_t enc_mod = { 0 }; -DECLARE_MODULE(if_enc, enc_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); +DECLARE_MODULE(if_enc, enc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); Modified: head/sys/net/if_epair.c ============================================================================== --- head/sys/net/if_epair.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_epair.c Tue Jun 21 13:48:49 2016 (r302054) @@ -963,7 +963,7 @@ vnet_epair_init(const void *unused __unu netisr_register_vnet(&epair_nh); #endif } -VNET_SYSINIT(vnet_epair_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSINIT(vnet_epair_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_epair_init, NULL); static void @@ -975,7 +975,7 @@ vnet_epair_uninit(const void *unused __u #endif if_clone_detach(V_epair_cloner); } -VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_epair_uninit, NULL); static int @@ -1012,5 +1012,5 @@ static moduledata_t epair_mod = { 0 }; -DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE); MODULE_VERSION(if_epair, 1); Modified: head/sys/net/if_lagg.c ============================================================================== --- head/sys/net/if_lagg.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_lagg.c Tue Jun 21 13:48:49 2016 (r302054) @@ -271,7 +271,7 @@ vnet_lagg_uninit(const void *unused __un if_clone_detach(V_lagg_cloner); LAGG_LIST_LOCK_DESTROY(); } -VNET_SYSUNINIT(vnet_lagg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_lagg_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_lagg_uninit, NULL); static int Modified: head/sys/net/if_loop.c ============================================================================== --- head/sys/net/if_loop.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_loop.c Tue Jun 21 13:48:49 2016 (r302054) @@ -156,7 +156,7 @@ vnet_loif_init(const void *unused __unus 1); #endif } -VNET_SYSINIT(vnet_loif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSINIT(vnet_loif_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_loif_init, NULL); #ifdef VIMAGE @@ -167,7 +167,7 @@ vnet_loif_uninit(const void *unused __un if_clone_detach(V_lo_cloner); V_loif = NULL; } -VNET_SYSUNINIT(vnet_loif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_loif_uninit, SI_SUB_INIT_IF, SI_ORDER_SECOND, vnet_loif_uninit, NULL); #endif Modified: head/sys/net/if_vlan.c ============================================================================== --- head/sys/net/if_vlan.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/if_vlan.c Tue Jun 21 13:48:49 2016 (r302054) @@ -823,7 +823,7 @@ vnet_vlan_uninit(const void *unused __un if_clone_detach(V_vlan_cloner); } -VNET_SYSUNINIT(vnet_vlan_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, +VNET_SYSUNINIT(vnet_vlan_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST, vnet_vlan_uninit, NULL); #endif Modified: head/sys/net/pfil.c ============================================================================== --- head/sys/net/pfil.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/pfil.c Tue Jun 21 13:48:49 2016 (r302054) @@ -383,17 +383,14 @@ vnet_pfil_uninit(const void *unused __un PFIL_LOCK_DESTROY_REAL(&V_pfil_lock); } -/* Define startup order. */ -#define PFIL_SYSINIT_ORDER SI_SUB_PROTO_BEGIN -#define PFIL_MODEVENT_ORDER (SI_ORDER_FIRST) /* On boot slot in here. */ -#define PFIL_VNET_ORDER (PFIL_MODEVENT_ORDER + 2) /* Later still. */ - /* * Starting up. * * VNET_SYSINIT is called for each existing vnet and each new vnet. + * Make sure the pfil bits are first before any possible subsystem which + * might piggyback on the SI_SUB_PROTO_PFIL. */ -VNET_SYSINIT(vnet_pfil_init, PFIL_SYSINIT_ORDER, PFIL_VNET_ORDER, +VNET_SYSINIT(vnet_pfil_init, SI_SUB_PROTO_PFIL, SI_ORDER_FIRST, vnet_pfil_init, NULL); /* @@ -401,5 +398,5 @@ VNET_SYSINIT(vnet_pfil_init, PFIL_SYSINI * * VNET_SYSUNINIT is called for each exiting vnet as it exits. */ -VNET_SYSUNINIT(vnet_pfil_uninit, PFIL_SYSINIT_ORDER, PFIL_VNET_ORDER, +VNET_SYSUNINIT(vnet_pfil_uninit, SI_SUB_PROTO_PFIL, SI_ORDER_FIRST, vnet_pfil_uninit, NULL); Modified: head/sys/net/route.c ============================================================================== --- head/sys/net/route.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/route.c Tue Jun 21 13:48:49 2016 (r302054) @@ -334,7 +334,7 @@ vnet_route_uninit(const void *unused __u free(V_rt_tables, M_RTABLE); uma_zdestroy(V_rtzone); } -VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, +VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, vnet_route_uninit, 0); #endif Modified: head/sys/net/vnet.c ============================================================================== --- head/sys/net/vnet.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/vnet.c Tue Jun 21 13:48:49 2016 (r302054) @@ -331,8 +331,7 @@ vnet_init_done(void *unused __unused) curvnet = NULL; } - -SYSINIT(vnet_init_done, SI_SUB_VNET_DONE, SI_ORDER_FIRST, vnet_init_done, +SYSINIT(vnet_init_done, SI_SUB_VNET_DONE, SI_ORDER_ANY, vnet_init_done, NULL); /* Modified: head/sys/net/vnet.h ============================================================================== --- head/sys/net/vnet.h Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/net/vnet.h Tue Jun 21 13:48:49 2016 (r302054) @@ -111,8 +111,8 @@ vnet_##name##_init(const void *unused) \ { \ VNET_PCPUSTAT_ALLOC(name, M_WAITOK); \ } \ -VNET_SYSINIT(vnet_ ## name ## _init, SI_SUB_PROTO_IFATTACHDOMAIN, \ - SI_ORDER_ANY, vnet_ ## name ## _init, NULL) +VNET_SYSINIT(vnet_ ## name ## _init, SI_SUB_INIT_IF, \ + SI_ORDER_FIRST, vnet_ ## name ## _init, NULL) #define VNET_PCPUSTAT_SYSUNINIT(name) \ static void \ @@ -120,8 +120,8 @@ vnet_##name##_uninit(const void *unused) { \ VNET_PCPUSTAT_FREE(name); \ } \ -VNET_SYSUNINIT(vnet_ ## name ## _uninit, SI_SUB_PROTO_IFATTACHDOMAIN, \ - SI_ORDER_ANY, vnet_ ## name ## _uninit, NULL) +VNET_SYSUNINIT(vnet_ ## name ## _uninit, SI_SUB_INIT_IF, \ + SI_ORDER_FIRST, vnet_ ## name ## _uninit, NULL) #ifdef SYSCTL_OID #define SYSCTL_VNET_PCPUSTAT(parent, nbr, name, type, array, desc) \ Modified: head/sys/netgraph/ng_eiface.c ============================================================================== --- head/sys/netgraph/ng_eiface.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netgraph/ng_eiface.c Tue Jun 21 13:48:49 2016 (r302054) @@ -679,5 +679,5 @@ vnet_ng_eiface_uninit(const void *unused delete_unrhdr(V_ng_eiface_unit); } -VNET_SYSUNINIT(vnet_ng_eiface_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_ng_eiface_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_ng_eiface_uninit, NULL); Modified: head/sys/netgraph/ng_iface.c ============================================================================== --- head/sys/netgraph/ng_iface.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netgraph/ng_iface.c Tue Jun 21 13:48:49 2016 (r302054) @@ -786,5 +786,5 @@ vnet_ng_iface_uninit(const void *unused) delete_unrhdr(V_ng_iface_unit); } -VNET_SYSUNINIT(vnet_ng_iface_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_ng_iface_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_ng_iface_uninit, NULL); Modified: head/sys/netinet/igmp.c ============================================================================== --- head/sys/netinet/igmp.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet/igmp.c Tue Jun 21 13:48:49 2016 (r302054) @@ -227,7 +227,8 @@ static VNET_DEFINE(int, current_state_ti #define V_state_change_timers_running VNET(state_change_timers_running) #define V_current_state_timers_running VNET(current_state_timers_running) -static VNET_DEFINE(LIST_HEAD(, igmp_ifsoftc), igi_head); +static VNET_DEFINE(LIST_HEAD(, igmp_ifsoftc), igi_head) = + LIST_HEAD_INITIALIZER(igi_head); static VNET_DEFINE(struct igmpstat, igmpstat) = { .igps_version = IGPS_VERSION_3, .igps_len = sizeof(struct igmpstat), @@ -701,10 +702,6 @@ igi_delete_locked(const struct ifnet *if return; } } - -#ifdef INVARIANTS - panic("%s: igmp_ifsoftc not found for ifp %p\n", __func__, ifp); -#endif } /* @@ -3595,57 +3592,28 @@ igmp_rec_type_to_str(const int type) } #endif -static void -igmp_init(void *unused __unused) -{ - - CTR1(KTR_IGMPV3, "%s: initializing", __func__); - - IGMP_LOCK_INIT(); - - m_raopt = igmp_ra_alloc(); - - netisr_register(&igmp_nh); -} -SYSINIT(igmp_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, igmp_init, NULL); - -static void -igmp_uninit(void *unused __unused) -{ - - CTR1(KTR_IGMPV3, "%s: tearing down", __func__); - - netisr_unregister(&igmp_nh); - - m_free(m_raopt); - m_raopt = NULL; - - IGMP_LOCK_DESTROY(); -} -SYSUNINIT(igmp_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, igmp_uninit, NULL); - +#ifdef VIMAGE static void vnet_igmp_init(const void *unused __unused) { - CTR1(KTR_IGMPV3, "%s: initializing", __func__); - - LIST_INIT(&V_igi_head); + netisr_register_vnet(&igmp_nh); } -VNET_SYSINIT(vnet_igmp_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_igmp_init, - NULL); +VNET_SYSINIT(vnet_igmp_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, + vnet_igmp_init, NULL); static void vnet_igmp_uninit(const void *unused __unused) { + /* This can happen when we shutdown the entire network stack. */ CTR1(KTR_IGMPV3, "%s: tearing down", __func__); - KASSERT(LIST_EMPTY(&V_igi_head), - ("%s: igi list not empty; ifnets not detached?", __func__)); + netisr_unregister_vnet(&igmp_nh); } -VNET_SYSUNINIT(vnet_igmp_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_igmp_uninit, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_igmp_uninit, NULL); +#endif #ifdef DDB DB_SHOW_COMMAND(igi_list, db_show_igi_list) @@ -3682,14 +3650,24 @@ static int igmp_modevent(module_t mod, int type, void *unused __unused) { - switch (type) { - case MOD_LOAD: - case MOD_UNLOAD: - break; - default: - return (EOPNOTSUPP); - } - return (0); + switch (type) { + case MOD_LOAD: + CTR1(KTR_IGMPV3, "%s: initializing", __func__); + IGMP_LOCK_INIT(); + m_raopt = igmp_ra_alloc(); + netisr_register(&igmp_nh); + break; + case MOD_UNLOAD: + CTR1(KTR_IGMPV3, "%s: tearing down", __func__); + netisr_unregister(&igmp_nh); + m_free(m_raopt); + m_raopt = NULL; + IGMP_LOCK_DESTROY(); + break; + default: + return (EOPNOTSUPP); + } + return (0); } static moduledata_t igmp_mod = { @@ -3697,4 +3675,4 @@ static moduledata_t igmp_mod = { igmp_modevent, 0 }; -DECLARE_MODULE(igmp, igmp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +DECLARE_MODULE(igmp, igmp_mod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE); Modified: head/sys/netinet/in.c ============================================================================== --- head/sys/netinet/in.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet/in.c Tue Jun 21 13:48:49 2016 (r302054) @@ -895,6 +895,39 @@ in_scrubprefix(struct in_ifaddr *target, #undef rtinitflags +void +in_ifscrub_all(void) +{ + struct ifnet *ifp; + struct ifaddr *ifa, *nifa; + struct ifaliasreq ifr; + + IFNET_RLOCK(); + TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + /* Cannot lock here - lock recursion. */ + /* IF_ADDR_RLOCK(ifp); */ + TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, nifa) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + + /* + * This is ugly but the only way for legacy IP to + * cleanly remove addresses and everything attached. + */ + bzero(&ifr, sizeof(ifr)); + ifr.ifra_addr = *ifa->ifa_addr; + if (ifa->ifa_dstaddr) + ifr.ifra_broadaddr = *ifa->ifa_dstaddr; + (void)in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, + ifp, NULL); + } + /* IF_ADDR_RUNLOCK(ifp); */ + in_purgemaddrs(ifp); + igmp_domifdetach(ifp); + } + IFNET_RUNLOCK(); +} + /* * Return 1 if the address might be a local broadcast address. */ Modified: head/sys/netinet/in_var.h ============================================================================== --- head/sys/netinet/in_var.h Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet/in_var.h Tue Jun 21 13:48:49 2016 (r302054) @@ -376,6 +376,7 @@ int in_control(struct socket *, u_long, struct thread *); int in_addprefix(struct in_ifaddr *, int); int in_scrubprefix(struct in_ifaddr *, u_int); +void in_ifscrub_all(void); void ip_input(struct mbuf *); void ip_direct_input(struct mbuf *); void in_ifadown(struct ifaddr *ifa, int); Modified: head/sys/netinet/ip_id.c ============================================================================== --- head/sys/netinet/ip_id.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet/ip_id.c Tue Jun 21 13:48:49 2016 (r302054) @@ -294,4 +294,4 @@ ipid_sysuninit(void) counter_u64_free(V_ip_id); mtx_destroy(&V_ip_id_mtx); } -VNET_SYSUNINIT(ip_id, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, ipid_sysuninit, NULL); +VNET_SYSUNINIT(ip_id, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ipid_sysuninit, NULL); Modified: head/sys/netinet/ip_input.c ============================================================================== --- head/sys/netinet/ip_input.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet/ip_input.c Tue Jun 21 13:48:49 2016 (r302054) @@ -370,6 +370,7 @@ ip_init(void) static void ip_destroy(void *unused __unused) { + struct ifnet *ifp; int error; #ifdef RSS @@ -393,11 +394,21 @@ ip_destroy(void *unused __unused) "type HHOOK_TYPE_IPSEC_OUT, id HHOOK_IPSEC_INET: " "error %d returned\n", __func__, error); } - /* Cleanup in_ifaddr hash table; should be empty. */ - hashdestroy(V_in_ifaddrhashtbl, M_IFADDR, V_in_ifaddrhmask); + + /* Remove the IPv4 addresses from all interfaces. */ + in_ifscrub_all(); + + /* Make sure the IPv4 routes are gone as well. */ + IFNET_RLOCK(); + TAILQ_FOREACH(ifp, &V_ifnet, if_link) + rt_flushifroutes_af(ifp, AF_INET); + IFNET_RUNLOCK(); /* Destroy IP reassembly queue. */ ipreass_destroy(); + + /* Cleanup in_ifaddr hash table; should be empty. */ + hashdestroy(V_in_ifaddrhashtbl, M_IFADDR, V_in_ifaddrhmask); } VNET_SYSUNINIT(ip, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip_destroy, NULL); Modified: head/sys/netinet/ip_mroute.c ============================================================================== --- head/sys/netinet/ip_mroute.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet/ip_mroute.c Tue Jun 21 13:48:49 2016 (r302054) @@ -2822,7 +2822,7 @@ vnet_mroute_init(const void *unused __un callout_init(&V_bw_meter_ch, 1); } -VNET_SYSINIT(vnet_mroute_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mroute_init, +VNET_SYSINIT(vnet_mroute_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mroute_init, NULL); static void @@ -2833,7 +2833,7 @@ vnet_mroute_uninit(const void *unused __ V_nexpire = NULL; } -VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, +VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, vnet_mroute_uninit, NULL); static int @@ -2946,4 +2946,4 @@ static moduledata_t ip_mroutemod = { 0 }; -DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE); +DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE); Modified: head/sys/netinet6/in6.c ============================================================================== --- head/sys/netinet6/in6.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/in6.c Tue Jun 21 13:48:49 2016 (r302054) @@ -2419,7 +2419,7 @@ in6_domifdetach(struct ifnet *ifp, void mld_domifdetach(ifp); scope6_ifdetach(ext->scope6_id); - nd6_ifdetach(ext->nd_ifinfo); + nd6_ifdetach(ifp, ext->nd_ifinfo); lltable_free(ext->lltable); COUNTER_ARRAY_FREE(ext->in6_ifstat, sizeof(struct in6_ifstat) / sizeof(uint64_t)); Modified: head/sys/netinet6/in6_ifattach.c ============================================================================== --- head/sys/netinet6/in6_ifattach.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/in6_ifattach.c Tue Jun 21 13:48:49 2016 (r302054) @@ -761,19 +761,30 @@ in6_ifattach(struct ifnet *ifp, struct i /* * NOTE: in6_ifdetach() does not support loopback if at this moment. - * We don't need this function in bsdi, because interfaces are never removed - * from the ifnet list in bsdi. + * + * When shutting down a VNET we clean up layers top-down. In that case + * upper layer protocols (ulp) are cleaned up already and locks are destroyed + * and we must not call into these cleanup functions anymore, thus purgeulp + * is set to 0 in that case by in6_ifdetach_destroy(). + * The normal case of destroying a (cloned) interface still needs to cleanup + * everything related to the interface and will have purgeulp set to 1. */ -void -in6_ifdetach(struct ifnet *ifp) +static void +_in6_ifdetach(struct ifnet *ifp, int purgeulp) { struct ifaddr *ifa, *next; if (ifp->if_afdata[AF_INET6] == NULL) return; - /* remove neighbor management table */ - nd6_purge(ifp); + /* + * Remove neighbor management table. + * Enabling the nd6_purge will panic on vmove for interfaces on VNET + * teardown as the IPv6 layer is cleaned up already and the locks + * are destroyed. + */ + if (purgeulp) + nd6_purge(ifp); /* * nuke any of IPv6 addresses we have @@ -784,9 +795,11 @@ in6_ifdetach(struct ifnet *ifp) continue; in6_purgeaddr(ifa); } - in6_pcbpurgeif0(&V_udbinfo, ifp); - in6_pcbpurgeif0(&V_ulitecbinfo, ifp); - in6_pcbpurgeif0(&V_ripcbinfo, ifp); + if (purgeulp) { + in6_pcbpurgeif0(&V_udbinfo, ifp); + in6_pcbpurgeif0(&V_ulitecbinfo, ifp); + in6_pcbpurgeif0(&V_ripcbinfo, ifp); + } /* leave from all multicast groups joined */ in6_purgemaddrs(ifp); @@ -798,7 +811,22 @@ in6_ifdetach(struct ifnet *ifp) * prefixes after removing all addresses above. * (Or can we just delay calling nd6_purge until at this point?) */ - nd6_purge(ifp); + if (purgeulp) + nd6_purge(ifp); +} + +void +in6_ifdetach(struct ifnet *ifp) +{ + + _in6_ifdetach(ifp, 1); +} + +void +in6_ifdetach_destroy(struct ifnet *ifp) +{ + + _in6_ifdetach(ifp, 0); } int Modified: head/sys/netinet6/in6_ifattach.h ============================================================================== --- head/sys/netinet6/in6_ifattach.h Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/in6_ifattach.h Tue Jun 21 13:48:49 2016 (r302054) @@ -37,6 +37,7 @@ void in6_ifattach(struct ifnet *, struct ifnet *); void in6_ifattach_destroy(void); void in6_ifdetach(struct ifnet *); +void in6_ifdetach_destroy(struct ifnet *); int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int); void in6_tmpaddrtimer(void *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); Modified: head/sys/netinet6/ip6_input.c ============================================================================== --- head/sys/netinet6/ip6_input.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/ip6_input.c Tue Jun 21 13:48:49 2016 (r302054) @@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -314,6 +315,8 @@ ip6proto_unregister(short ip6proto) static void ip6_destroy(void *unused __unused) { + struct ifaddr *ifa, *nifa; + struct ifnet *ifp; int error; #ifdef RSS @@ -336,9 +339,30 @@ ip6_destroy(void *unused __unused) "type HHOOK_TYPE_IPSEC_OUT, id HHOOK_IPSEC_INET6: " "error %d returned\n", __func__, error); } - hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask); + + /* Cleanup addresses. */ + IFNET_RLOCK(); + TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + /* Cannot lock here - lock recursion. */ + /* IF_ADDR_LOCK(ifp); */ + TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, nifa) { + + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + in6_purgeaddr(ifa); + } + /* IF_ADDR_UNLOCK(ifp); */ + in6_ifdetach_destroy(ifp); + mld_domifdetach(ifp); + /* Make sure any routes are gone as well. */ + rt_flushifroutes_af(ifp, AF_INET6); + } + IFNET_RUNLOCK(); + nd6_destroy(); in6_ifattach_destroy(); + + hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask); } VNET_SYSUNINIT(inet6, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_destroy, NULL); Modified: head/sys/netinet6/ip6_mroute.c ============================================================================== --- head/sys/netinet6/ip6_mroute.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/ip6_mroute.c Tue Jun 21 13:48:49 2016 (r302054) @@ -1966,4 +1966,4 @@ static moduledata_t ip6_mroutemod = { 0 }; -DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY); +DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_ANY); Modified: head/sys/netinet6/mld6.c ============================================================================== --- head/sys/netinet6/mld6.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/mld6.c Tue Jun 21 13:48:49 2016 (r302054) @@ -612,9 +612,6 @@ mli_delete_locked(const struct ifnet *if return; } } -#ifdef INVARIANTS - panic("%s: mld_ifsoftc not found for ifp %p\n", __func__, ifp); -#endif } /* @@ -3265,7 +3262,7 @@ mld_init(void *unused __unused) mld_po.ip6po_prefer_tempaddr = IP6PO_TEMPADDR_NOTPREFER; mld_po.ip6po_flags = IP6PO_DONTFRAG; } -SYSINIT(mld_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, mld_init, NULL); +SYSINIT(mld_init, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, mld_init, NULL); static void mld_uninit(void *unused __unused) @@ -3274,7 +3271,7 @@ mld_uninit(void *unused __unused) CTR1(KTR_MLD, "%s: tearing down", __func__); MLD_LOCK_DESTROY(); } -SYSUNINIT(mld_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, mld_uninit, NULL); +SYSUNINIT(mld_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, mld_uninit, NULL); static void vnet_mld_init(const void *unused __unused) @@ -3284,19 +3281,17 @@ vnet_mld_init(const void *unused __unuse LIST_INIT(&V_mli_head); } -VNET_SYSINIT(vnet_mld_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_init, +VNET_SYSINIT(vnet_mld_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mld_init, NULL); static void vnet_mld_uninit(const void *unused __unused) { + /* This can happen if we shutdown the network stack. */ CTR1(KTR_MLD, "%s: tearing down", __func__); - - KASSERT(LIST_EMPTY(&V_mli_head), - ("%s: mli list not empty; ifnets not detached?", __func__)); } -VNET_SYSUNINIT(vnet_mld_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_uninit, +VNET_SYSUNINIT(vnet_mld_uninit, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mld_uninit, NULL); static int @@ -3318,4 +3313,4 @@ static moduledata_t mld_mod = { mld_modevent, 0 }; -DECLARE_MODULE(mld, mld_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +DECLARE_MODULE(mld, mld_mod, SI_SUB_PROTO_MC, SI_ORDER_ANY); Modified: head/sys/netinet6/nd6.c ============================================================================== --- head/sys/netinet6/nd6.c Tue Jun 21 07:05:49 2016 (r302053) +++ head/sys/netinet6/nd6.c Tue Jun 21 13:48:49 2016 (r302054) @@ -292,8 +292,19 @@ nd6_ifattach(struct ifnet *ifp) } void -nd6_ifdetach(struct nd_ifinfo *nd) +nd6_ifdetach(struct ifnet *ifp, struct nd_ifinfo *nd) { + struct ifaddr *ifa, *next; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***