summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2016-06-21 13:48:49 +0000
committerbz <bz@FreeBSD.org>2016-06-21 13:48:49 +0000
commit7a1c0b1ad10703084b50a5b307bbd60603471e1c (patch)
treef2fb0a7a66c6cdafb62dc189a1c8a15c38cdf22e
parent63f808402a81b996671f13068a235f1e5407c58b (diff)
downloadFreeBSD-src-7a1c0b1ad10703084b50a5b307bbd60603471e1c.zip
FreeBSD-src-7a1c0b1ad10703084b50a5b307bbd60603471e1c.tar.gz
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
-rw-r--r--sys/contrib/ipfilter/netinet/mlfk_ipl.c2
-rw-r--r--sys/dev/usb/net/usb_ethernet.c6
-rw-r--r--sys/kern/kern_hhook.c4
-rw-r--r--sys/net/if.c106
-rw-r--r--sys/net/if_bridge.c2
-rw-r--r--sys/net/if_disc.c4
-rw-r--r--sys/net/if_edsc.c2
-rw-r--r--sys/net/if_enc.c37
-rw-r--r--sys/net/if_epair.c6
-rw-r--r--sys/net/if_lagg.c2
-rw-r--r--sys/net/if_loop.c4
-rw-r--r--sys/net/if_vlan.c2
-rw-r--r--sys/net/pfil.c11
-rw-r--r--sys/net/route.c2
-rw-r--r--sys/net/vnet.c3
-rw-r--r--sys/net/vnet.h8
-rw-r--r--sys/netgraph/ng_eiface.c2
-rw-r--r--sys/netgraph/ng_iface.c2
-rw-r--r--sys/netinet/igmp.c80
-rw-r--r--sys/netinet/in.c33
-rw-r--r--sys/netinet/in_var.h1
-rw-r--r--sys/netinet/ip_id.c2
-rw-r--r--sys/netinet/ip_input.c15
-rw-r--r--sys/netinet/ip_mroute.c6
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/in6_ifattach.c48
-rw-r--r--sys/netinet6/in6_ifattach.h1
-rw-r--r--sys/netinet6/ip6_input.c26
-rw-r--r--sys/netinet6/ip6_mroute.c2
-rw-r--r--sys/netinet6/mld6.c17
-rw-r--r--sys/netinet6/nd6.c13
-rw-r--r--sys/netinet6/nd6.h2
-rw-r--r--sys/netipsec/ipsec.c2
-rw-r--r--sys/netipsec/xform_tcp.c2
-rw-r--r--sys/netpfil/ipfw/dn_sched.h2
-rw-r--r--sys/netpfil/ipfw/ip_dummynet.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw_nat.c2
-rw-r--r--sys/netpfil/pf/pf_ioctl.c2
39 files changed, 326 insertions, 141 deletions
diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c
index 83a9189..4b0ca84 100644
--- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c
+++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c
@@ -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
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
index 5350da9..0b0350c 100644
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -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);
diff --git a/sys/kern/kern_hhook.c b/sys/kern/kern_hhook.c
index 12410cb..85168fc 100644
--- a/sys/kern/kern_hhook.c
+++ b/sys/kern/kern_hhook.c
@@ -510,7 +510,7 @@ hhook_vnet_uninit(const void *unused __unused)
/*
* 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_MBUF, SI_ORDER_FIRST,
* 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);
diff --git a/sys/net/if.c b/sys/net/if.c
index 4d475d9..5bad9e2 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -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, int vmove, struct if_clone **ifcp)
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, int vmove, struct if_clone **ifcp)
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, int vmove, struct if_clone **ifcp)
#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, int vmove, struct if_clone **ifcp)
}
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, int vmove, struct if_clone **ifcp)
* 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 ifnet *ifp, char *ifname, int jid)
{
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 ifnet *ifp, char *ifname, int jid)
/* 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 *ifname, int jid)
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 *ifname, int jid)
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, caddr_t data, struct thread *td)
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);
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 4fe5e67..384ef89 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -541,7 +541,7 @@ vnet_bridge_uninit(const void *unused __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
diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c
index d7ea59e..3f7472c 100644
--- a/sys/net/if_disc.c
+++ b/sys/net/if_disc.c
@@ -137,7 +137,7 @@ vnet_disc_init(const void *unused __unused)
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 __unused)
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
diff --git a/sys/net/if_edsc.c b/sys/net/if_edsc.c
index a58cc44..26c2109 100644
--- a/sys/net/if_edsc.c
+++ b/sys/net/if_edsc.c
@@ -336,7 +336,7 @@ vnet_edsc_uninit(const void *unused __unused)
*/
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);
/*
diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c
index e3bf5b8..8e176e7 100644
--- a/sys/net/if_enc.c
+++ b/sys/net/if_enc.c
@@ -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, int unit, caddr_t params)
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 __unused)
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);
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index 949a417..86e8379 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -963,7 +963,7 @@ vnet_epair_init(const void *unused __unused)
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 __unused)
#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);
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 8b81abf..16f872a 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -271,7 +271,7 @@ vnet_lagg_uninit(const void *unused __unused)
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
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 1623732..4d7de10 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -156,7 +156,7 @@ vnet_loif_init(const void *unused __unused)
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 __unused)
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
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 415be01..73470dc 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -823,7 +823,7 @@ vnet_vlan_uninit(const void *unused __unused)
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
diff --git a/sys/net/pfil.c b/sys/net/pfil.c
index 248d183..625bcb8 100644
--- a/sys/net/pfil.c
+++ b/sys/net/pfil.c
@@ -383,17 +383,14 @@ vnet_pfil_uninit(const void *unused __unused)
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_SYSINIT_ORDER, PFIL_VNET_ORDER,
*
* 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);
diff --git a/sys/net/route.c b/sys/net/route.c
index f2f8897..d7b3b96 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -334,7 +334,7 @@ vnet_route_uninit(const void *unused __unused)
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
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index afb836a..b2cad63 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -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);
/*
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index cc23f87..4985d4b 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -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) \
diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c
index 08b85ad..db4e87c 100644
--- a/sys/netgraph/ng_eiface.c
+++ b/sys/netgraph/ng_eiface.c
@@ -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);
diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c
index 6bd55c7..b5f5626 100644
--- a/sys/netgraph/ng_iface.c
+++ b/sys/netgraph/ng_iface.c
@@ -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);
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index 1fc1812..5dba31d 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -227,7 +227,8 @@ static VNET_DEFINE(int, current_state_timers_running); /* IGMPv1/v2 host
#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 *ifp)
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);
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 11b140d..7a17386 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -895,6 +895,39 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
#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.
*/
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index c5f27b0..af83e9a 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -376,6 +376,7 @@ int in_control(struct socket *, u_long, caddr_t, struct ifnet *,
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);
diff --git a/sys/netinet/ip_id.c b/sys/netinet/ip_id.c
index de4ae75..6a80b6e 100644
--- a/sys/netinet/ip_id.c
+++ b/sys/netinet/ip_id.c
@@ -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);
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index d728eaf..3a07ad8 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -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);
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index ba21edc..d6164ef 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -2822,7 +2822,7 @@ vnet_mroute_init(const void *unused __unused)
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 __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);
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index e972ac7..1279d31 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2419,7 +2419,7 @@ in6_domifdetach(struct ifnet *ifp, void *aux)
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));
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 471dd82..6c69399 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -761,19 +761,30 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
/*
* 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
diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h
index a5a82c0..a34530d 100644
--- a/sys/netinet6/in6_ifattach.h
+++ b/sys/netinet6/in6_ifattach.h
@@ -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 *);
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 754de6a..485499d 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/icmp6.h>
#include <netinet6/scope6_var.h>
#include <netinet6/in6_ifattach.h>
+#include <netinet6/mld6_var.h>
#include <netinet6/nd6.h>
#include <netinet6/in6_rss.h>
@@ -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);
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index f560dc5..3ae900d 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -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);
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index dcae9f8..c7ad5a2 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -612,9 +612,6 @@ mli_delete_locked(const struct ifnet *ifp)
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 __unused)
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);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index a75d588..8fc229f 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -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;
+
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ /* stop DAD processing */
+ nd6_dad_stop(ifa);
+ }
+ IF_ADDR_RUNLOCK(ifp);
free(nd, M_IP6NDP);
}
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index ce98975..33ac438 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -414,7 +414,7 @@ void nd6_init(void);
void nd6_destroy(void);
#endif
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
-void nd6_ifdetach(struct nd_ifinfo *);
+void nd6_ifdetach(struct ifnet *, struct nd_ifinfo *);
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
void nd6_option_init(void *, int, union nd_opts *);
struct nd_opt_hdr *nd6_option(union nd_opts *);
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index fbe4b1a..6cdfc65 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -1715,7 +1715,7 @@ def_policy_init(const void *unused __unused)
V_def_policy.policy = IPSEC_POLICY_NONE;
V_def_policy.refcnt = 1;
}
-VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY,
+VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
def_policy_init, NULL);
diff --git a/sys/netipsec/xform_tcp.c b/sys/netipsec/xform_tcp.c
index 267e377..6a55ed2 100644
--- a/sys/netipsec/xform_tcp.c
+++ b/sys/netipsec/xform_tcp.c
@@ -166,5 +166,5 @@ tcpsignature_attach(void)
xform_register(&tcpsignature_xformsw);
}
-SYSINIT(tcpsignature_xform_init, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+SYSINIT(tcpsignature_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
tcpsignature_attach, NULL);
diff --git a/sys/netpfil/ipfw/dn_sched.h b/sys/netpfil/ipfw/dn_sched.h
index 602fdf9..ab32771 100644
--- a/sys/netpfil/ipfw/dn_sched.h
+++ b/sys/netpfil/ipfw/dn_sched.h
@@ -196,6 +196,6 @@ int dn_sched_modevent(module_t mod, int cmd, void *arg);
#name, dn_sched_modevent, dnsched \
}; \
DECLARE_MODULE(name, name##_mod, \
- SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); \
+ SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY); \
MODULE_DEPEND(name, dummynet, 3, 3, 3)
#endif /* _DN_SCHED_H */
diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c
index dbd5aa7..f6d9c28 100644
--- a/sys/netpfil/ipfw/ip_dummynet.c
+++ b/sys/netpfil/ipfw/ip_dummynet.c
@@ -2629,7 +2629,7 @@ static moduledata_t dummynet_mod = {
"dummynet", dummynet_modevent, NULL
};
-#define DN_SI_SUB SI_SUB_PROTO_IFATTACHDOMAIN
+#define DN_SI_SUB SI_SUB_PROTO_FIREWALL
#define DN_MODEV_ORD (SI_ORDER_ANY - 128) /* after ipfw */
DECLARE_MODULE(dummynet, dummynet_mod, DN_SI_SUB, DN_MODEV_ORD);
MODULE_DEPEND(dummynet, ipfw, 3, 3, 3);
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index 45da69d..26e596c 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -2890,7 +2890,7 @@ static moduledata_t ipfwmod = {
};
/* Define startup order. */
-#define IPFW_SI_SUB_FIREWALL SI_SUB_PROTO_IFATTACHDOMAIN
+#define IPFW_SI_SUB_FIREWALL SI_SUB_PROTO_FIREWALL
#define IPFW_MODEVENT_ORDER (SI_ORDER_ANY - 255) /* On boot slot in here. */
#define IPFW_MODULE_ORDER (IPFW_MODEVENT_ORDER + 1) /* A little later. */
#define IPFW_VNET_ORDER (IPFW_MODEVENT_ORDER + 2) /* Later still. */
diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c
index a32d32f..eb61021 100644
--- a/sys/netpfil/ipfw/ip_fw_nat.c
+++ b/sys/netpfil/ipfw/ip_fw_nat.c
@@ -1213,7 +1213,7 @@ static moduledata_t ipfw_nat_mod = {
};
/* Define startup order. */
-#define IPFW_NAT_SI_SUB_FIREWALL SI_SUB_PROTO_IFATTACHDOMAIN
+#define IPFW_NAT_SI_SUB_FIREWALL SI_SUB_PROTO_FIREWALL
#define IPFW_NAT_MODEVENT_ORDER (SI_ORDER_ANY - 128) /* after ipfw */
#define IPFW_NAT_MODULE_ORDER (IPFW_NAT_MODEVENT_ORDER + 1)
#define IPFW_NAT_VNET_ORDER (IPFW_NAT_MODEVENT_ORDER + 2)
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 3291c9b..b1918fe 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -3794,5 +3794,5 @@ static moduledata_t pf_mod = {
0
};
-DECLARE_MODULE(pf, pf_mod, SI_SUB_PSEUDO, SI_ORDER_FIRST);
+DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_FIRST);
MODULE_VERSION(pf, PF_MODVER);
OpenPOWER on IntegriCloud