svn commit: r298548 - in projects/vnet/sys: net netinet netinet6
Bjoern A. Zeeb
bz at FreeBSD.org
Sun Apr 24 16:41:56 UTC 2016
Author: bz
Date: Sun Apr 24 16:41:54 2016
New Revision: 298548
URL: https://svnweb.freebsd.org/changeset/base/298548
Log:
Virtualise the netisr registration in order to do a per-vnet
de-registration to prevent further packets for a specific protocol
(IP, ARP, IPv6) to come up from ether_demux().
We currently have not better "plug-and-play" hook in place at that
level but should think about that in some distant future (e.g.,
to one day be able to load ip, or ipv6).
Note: this commit will be reverted soon. It turns out that while
the idea is good, and basically works, it can possibly lead to
deadlocks.
Sponsored by: The FreeBSD Foundation
Modified:
projects/vnet/sys/net/if_epair.c
projects/vnet/sys/net/if_ethersubr.c
projects/vnet/sys/net/netisr.c
projects/vnet/sys/net/rtsock.c
projects/vnet/sys/netinet/if_ether.c
projects/vnet/sys/netinet/igmp.c
projects/vnet/sys/netinet/ip_input.c
projects/vnet/sys/netinet6/ip6_input.c
Modified: projects/vnet/sys/net/if_epair.c
==============================================================================
--- projects/vnet/sys/net/if_epair.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/net/if_epair.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -959,6 +959,7 @@ vnet_epair_init(const void *unused __unu
V_epair_cloner = if_clone_advanced(epairname, 0,
epair_clone_match, epair_clone_create, epair_clone_destroy);
+ netisr_register(&epair_nh);
}
VNET_SYSINIT(vnet_epair_init, SI_SUB_PSEUDO, SI_ORDER_ANY,
vnet_epair_init, NULL);
@@ -967,6 +968,7 @@ static void
vnet_epair_uninit(const void *unused __unused)
{
+ netisr_unregister(&epair_nh);
if_clone_detach(V_epair_cloner);
}
VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY,
@@ -984,12 +986,10 @@ epair_modevent(module_t mod, int type, v
epair_nh.nh_qlimit = 42 * ifqmaxlen; /* 42 shall be the number. */
if (TUNABLE_INT_FETCH("net.link.epair.netisr_maxqlen", &qlimit))
epair_nh.nh_qlimit = qlimit;
- netisr_register(&epair_nh);
if (bootverbose)
printf("%s initialized.\n", epairname);
break;
case MOD_UNLOAD:
- netisr_unregister(&epair_nh);
epair_dpcpu_detach();
if (bootverbose)
printf("%s unloaded.\n", epairname);
@@ -1006,5 +1006,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: projects/vnet/sys/net/if_ethersubr.c
==============================================================================
--- projects/vnet/sys/net/if_ethersubr.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/net/if_ethersubr.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -654,14 +654,6 @@ static struct netisr_handler ether_nh =
};
static void
-ether_init(__unused void *arg)
-{
-
- netisr_register(ðer_nh);
-}
-SYSINIT(ether, SI_SUB_INIT_IF, SI_ORDER_ANY, ether_init, NULL);
-
-static void
vnet_ether_init(__unused void *arg)
{
int i;
@@ -672,12 +664,13 @@ vnet_ether_init(__unused void *arg)
if ((i = pfil_head_register(&V_link_pfil_hook)) != 0)
printf("%s: WARNING: unable to register pfil link hook, "
"error %d\n", __func__, i);
+ netisr_register(ðer_nh);
}
VNET_SYSINIT(vnet_ether_init, SI_SUB_PROTO_IF, SI_ORDER_ANY,
vnet_ether_init, NULL);
static void
-vnet_ether_destroy(__unused void *arg)
+vnet_ether_pfil_destroy(__unused void *arg)
{
int i;
@@ -685,10 +678,17 @@ vnet_ether_destroy(__unused void *arg)
printf("%s: WARNING: unable to unregister pfil link hook, "
"error %d\n", __func__, i);
}
-VNET_SYSUNINIT(vnet_ether_uninit, SI_SUB_PROTO_PFIL, SI_ORDER_ANY,
- vnet_ether_destroy, NULL);
+VNET_SYSUNINIT(vnet_ether_pfil_uninit, SI_SUB_PROTO_PFIL, SI_ORDER_ANY,
+ vnet_ether_pfil_destroy, NULL);
+static void
+vnet_ether_destroy(__unused void *arg)
+{
+ netisr_unregister(ðer_nh);
+}
+VNET_SYSUNINIT(vnet_ether_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY,
+ vnet_ether_destroy, NULL);
static void
ether_input(struct ifnet *ifp, struct mbuf *m)
@@ -710,7 +710,9 @@ ether_input(struct ifnet *ifp, struct mb
* so assert it is correct here.
*/
KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch", __func__));
+ CURVNET_SET_QUIET(ifp->if_vnet);
netisr_dispatch(NETISR_ETHER, m);
+ CURVNET_RESTORE();
m = mn;
}
}
Modified: projects/vnet/sys/net/netisr.c
==============================================================================
--- projects/vnet/sys/net/netisr.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/net/netisr.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -208,7 +208,8 @@ SYSCTL_UINT(_net_isr, OID_AUTO, maxprot,
* The netisr_proto array describes all registered protocols, indexed by
* protocol number. See netisr_internal.h for more details.
*/
-static struct netisr_proto netisr_proto[NETISR_MAXPROT];
+static VNET_DEFINE(struct netisr_proto, netisr_proto[NETISR_MAXPROT]);
+#define V_netisr_proto VNET(netisr_proto)
/*
* Per-CPU workstream data. See netisr_internal.h for more details.
@@ -396,31 +397,31 @@ netisr_register(const struct netisr_hand
* Test that no existing registration exists for this protocol.
*/
NETISR_WLOCK();
- KASSERT(netisr_proto[proto].np_name == NULL,
+ KASSERT(V_netisr_proto[proto].np_name == NULL,
("%s(%u, %s): name present", __func__, proto, name));
- KASSERT(netisr_proto[proto].np_handler == NULL,
+ KASSERT(V_netisr_proto[proto].np_handler == NULL,
("%s(%u, %s): handler present", __func__, proto, name));
- netisr_proto[proto].np_name = name;
- netisr_proto[proto].np_handler = nhp->nh_handler;
- netisr_proto[proto].np_m2flow = nhp->nh_m2flow;
- netisr_proto[proto].np_m2cpuid = nhp->nh_m2cpuid;
- netisr_proto[proto].np_drainedcpu = nhp->nh_drainedcpu;
+ V_netisr_proto[proto].np_name = name;
+ V_netisr_proto[proto].np_handler = nhp->nh_handler;
+ V_netisr_proto[proto].np_m2flow = nhp->nh_m2flow;
+ V_netisr_proto[proto].np_m2cpuid = nhp->nh_m2cpuid;
+ V_netisr_proto[proto].np_drainedcpu = nhp->nh_drainedcpu;
if (nhp->nh_qlimit == 0)
- netisr_proto[proto].np_qlimit = netisr_defaultqlimit;
+ V_netisr_proto[proto].np_qlimit = netisr_defaultqlimit;
else if (nhp->nh_qlimit > netisr_maxqlimit) {
printf("%s: %s requested queue limit %u capped to "
"net.isr.maxqlimit %u\n", __func__, name, nhp->nh_qlimit,
netisr_maxqlimit);
- netisr_proto[proto].np_qlimit = netisr_maxqlimit;
+ V_netisr_proto[proto].np_qlimit = netisr_maxqlimit;
} else
- netisr_proto[proto].np_qlimit = nhp->nh_qlimit;
- netisr_proto[proto].np_policy = nhp->nh_policy;
- netisr_proto[proto].np_dispatch = nhp->nh_dispatch;
+ V_netisr_proto[proto].np_qlimit = nhp->nh_qlimit;
+ V_netisr_proto[proto].np_policy = nhp->nh_policy;
+ V_netisr_proto[proto].np_dispatch = nhp->nh_dispatch;
CPU_FOREACH(i) {
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
bzero(npwp, sizeof(*npwp));
- npwp->nw_qlimit = netisr_proto[proto].np_qlimit;
+ npwp->nw_qlimit = V_netisr_proto[proto].np_qlimit;
}
NETISR_WUNLOCK();
}
@@ -445,7 +446,7 @@ netisr_clearqdrops(const struct netisr_h
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_WLOCK();
- KASSERT(netisr_proto[proto].np_handler != NULL,
+ KASSERT(V_netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
@@ -478,7 +479,7 @@ netisr_getqdrops(const struct netisr_han
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_RLOCK(&tracker);
- KASSERT(netisr_proto[proto].np_handler != NULL,
+ KASSERT(V_netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
@@ -509,10 +510,10 @@ netisr_getqlimit(const struct netisr_han
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_RLOCK(&tracker);
- KASSERT(netisr_proto[proto].np_handler != NULL,
+ KASSERT(V_netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- *qlimitp = netisr_proto[proto].np_qlimit;
+ *qlimitp = V_netisr_proto[proto].np_qlimit;
NETISR_RUNLOCK(&tracker);
}
@@ -541,11 +542,11 @@ netisr_setqlimit(const struct netisr_han
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_WLOCK();
- KASSERT(netisr_proto[proto].np_handler != NULL,
+ KASSERT(V_netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- netisr_proto[proto].np_qlimit = qlimit;
+ V_netisr_proto[proto].np_qlimit = qlimit;
CPU_FOREACH(i) {
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
npwp->nw_qlimit = qlimit;
@@ -600,16 +601,16 @@ netisr_unregister(const struct netisr_ha
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_WLOCK();
- KASSERT(netisr_proto[proto].np_handler != NULL,
+ KASSERT(V_netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- netisr_proto[proto].np_name = NULL;
- netisr_proto[proto].np_handler = NULL;
- netisr_proto[proto].np_m2flow = NULL;
- netisr_proto[proto].np_m2cpuid = NULL;
- netisr_proto[proto].np_qlimit = 0;
- netisr_proto[proto].np_policy = 0;
+ V_netisr_proto[proto].np_name = NULL;
+ V_netisr_proto[proto].np_handler = NULL;
+ V_netisr_proto[proto].np_m2flow = NULL;
+ V_netisr_proto[proto].np_m2cpuid = NULL;
+ V_netisr_proto[proto].np_qlimit = 0;
+ V_netisr_proto[proto].np_policy = 0;
CPU_FOREACH(i) {
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
netisr_drain_proto(npwp);
@@ -763,13 +764,16 @@ netisr_process_workstream_proto(struct n
VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
CURVNET_SET(m->m_pkthdr.rcvif->if_vnet);
- netisr_proto[proto].np_handler(m);
+ V_netisr_proto[proto].np_handler(m);
CURVNET_RESTORE();
}
KASSERT(local_npw.nw_len == 0,
("%s(%u): len %u", __func__, proto, local_npw.nw_len));
- if (netisr_proto[proto].np_drainedcpu)
- netisr_proto[proto].np_drainedcpu(nwsp->nws_cpu);
+ /* We can just use the one from the default VNET. */
+ CURVNET_SET_QUIET(vnet0);
+ if (V_netisr_proto[proto].np_drainedcpu)
+ V_netisr_proto[proto].np_drainedcpu(nwsp->nws_cpu);
+ CURVNET_RESTORE();
NWS_LOCK(nwsp);
npwp->nw_handled += handled;
return (handled);
@@ -905,10 +909,12 @@ netisr_queue_src(u_int proto, uintptr_t
#ifdef NETISR_LOCKING
NETISR_RLOCK(&tracker);
#endif
- KASSERT(netisr_proto[proto].np_handler != NULL,
- ("%s: invalid proto %u", __func__, proto));
+ if (V_netisr_proto[proto].np_handler == NULL) {
+ m_freem(m);
+ return (ENOPROTOOPT);
+ }
- m = netisr_select_cpuid(&netisr_proto[proto], NETISR_DISPATCH_DEFERRED,
+ m = netisr_select_cpuid(&V_netisr_proto[proto], NETISR_DISPATCH_DEFERRED,
source, m, &cpuid);
if (m != NULL) {
KASSERT(!CPU_ABSENT(cpuid), ("%s: CPU %u absent", __func__,
@@ -950,9 +956,11 @@ netisr_dispatch_src(u_int proto, uintptr
#ifdef NETISR_LOCKING
NETISR_RLOCK(&tracker);
#endif
- npp = &netisr_proto[proto];
- KASSERT(npp->np_handler != NULL, ("%s: invalid proto %u", __func__,
- proto));
+ npp = &V_netisr_proto[proto];
+ if (npp->np_handler == NULL) {
+ m_freem(m);
+ return (ENOPROTOOPT);
+ }
dispatch_policy = netisr_get_dispatch(npp);
if (dispatch_policy == NETISR_DISPATCH_DEFERRED)
@@ -970,7 +978,7 @@ netisr_dispatch_src(u_int proto, uintptr
npwp = &nwsp->nws_work[proto];
npwp->nw_dispatched++;
npwp->nw_handled++;
- netisr_proto[proto].np_handler(m);
+ V_netisr_proto[proto].np_handler(m);
error = 0;
goto out_unlock;
}
@@ -984,7 +992,7 @@ netisr_dispatch_src(u_int proto, uintptr
* already running.
*/
sched_pin();
- m = netisr_select_cpuid(&netisr_proto[proto], NETISR_DISPATCH_HYBRID,
+ m = netisr_select_cpuid(&V_netisr_proto[proto], NETISR_DISPATCH_HYBRID,
source, m, &cpuid);
if (m == NULL) {
error = ENOBUFS;
@@ -1021,7 +1029,7 @@ netisr_dispatch_src(u_int proto, uintptr
*/
nwsp->nws_flags |= NWS_DISPATCHING;
NWS_UNLOCK(nwsp);
- netisr_proto[proto].np_handler(m);
+ V_netisr_proto[proto].np_handler(m);
NWS_LOCK(nwsp);
nwsp->nws_flags &= ~NWS_DISPATCHING;
npwp->nw_handled++;
@@ -1194,7 +1202,7 @@ sysctl_netisr_proto(SYSCTL_HANDLER_ARGS)
counter = 0;
NETISR_RLOCK(&tracker);
for (proto = 0; proto < NETISR_MAXPROT; proto++) {
- npp = &netisr_proto[proto];
+ npp = &V_netisr_proto[proto];
if (npp->np_name == NULL)
continue;
snpp = &snp_array[counter];
@@ -1303,7 +1311,7 @@ sysctl_netisr_work(SYSCTL_HANDLER_ARGS)
continue;
NWS_LOCK(nwsp);
for (proto = 0; proto < NETISR_MAXPROT; proto++) {
- npp = &netisr_proto[proto];
+ npp = &V_netisr_proto[proto];
if (npp->np_name == NULL)
continue;
nwp = &nwsp->nws_work[proto];
@@ -1352,7 +1360,7 @@ DB_SHOW_COMMAND(netisr, db_show_netisr)
continue;
first = 1;
for (proto = 0; proto < NETISR_MAXPROT; proto++) {
- if (netisr_proto[proto].np_handler == NULL)
+ if (V_netisr_proto[proto].np_handler == NULL)
continue;
nwp = &nwsp->nws_work[proto];
if (first) {
@@ -1362,7 +1370,7 @@ DB_SHOW_COMMAND(netisr, db_show_netisr)
db_printf("%3s ", "");
db_printf(
"%6s %5d %5d %5d %8ju %8ju %8ju %8ju\n",
- netisr_proto[proto].np_name, nwp->nw_len,
+ V_netisr_proto[proto].np_name, nwp->nw_len,
nwp->nw_watermark, nwp->nw_qlimit,
nwp->nw_dispatched, nwp->nw_hybrid_dispatched,
nwp->nw_qdrops, nwp->nw_queued);
Modified: projects/vnet/sys/net/rtsock.c
==============================================================================
--- projects/vnet/sys/net/rtsock.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/net/rtsock.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -197,10 +197,27 @@ rts_init(void)
if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp))
rtsock_nh.nh_qlimit = tmp;
- netisr_register(&rtsock_nh);
}
SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0);
+static void
+vnet_rts_init(void)
+{
+
+ netisr_register(&rtsock_nh);
+}
+VNET_SYSINIT(vnet_rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
+ vnet_rts_init, 0);
+
+static void
+vnet_rts_uninit(void)
+{
+
+ netisr_unregister(&rtsock_nh);
+}
+VNET_SYSUNINIT(vnet_rts_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
+ vnet_rts_uninit, 0);
+
static int
raw_input_rts_cb(struct mbuf *m, struct sockproto *proto, struct sockaddr *src,
struct rawcb *rp)
Modified: projects/vnet/sys/netinet/if_ether.c
==============================================================================
--- projects/vnet/sys/netinet/if_ether.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/netinet/if_ether.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -143,7 +143,6 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUT
} while (0)
-static void arp_init(void);
static void arpintr(struct mbuf *);
static void arptimer(void *);
#ifdef INET
@@ -1327,7 +1326,7 @@ arp_iflladdr(void *arg __unused, struct
}
static void
-arp_init(void)
+vnet_arp_init(void)
{
netisr_register(&arp_nh);
@@ -1335,4 +1334,20 @@ arp_init(void)
iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
}
-SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, arp_init, 0);
+VNET_SYSINIT(vnet_arp_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND,
+ vnet_arp_init, 0);
+
+#ifdef VIMAGE
+/*
+ * We have to unregister ARP along with IP otherwise we risk doing INADDR_HASH
+ * lookups after destroying the hash. Ideally this would go on SI_ORDER_3.5.
+ */
+static void
+vnet_arp_destroy(__unused void *arg)
+{
+
+ netisr_unregister(&arp_nh);
+}
+VNET_SYSUNINIT(vnet_arp_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
+ vnet_arp_destroy, NULL);
+#endif
Modified: projects/vnet/sys/netinet/igmp.c
==============================================================================
--- projects/vnet/sys/netinet/igmp.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/netinet/igmp.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -3592,6 +3592,15 @@ igmp_rec_type_to_str(const int type)
}
#endif
+static void
+vnet_igmp_init(const void *unused __unused)
+{
+
+ netisr_register(&igmp_nh);
+}
+VNET_SYSINIT(vnet_igmp_init, SI_SUB_PROTO_MC, SI_ORDER_ANY,
+ vnet_igmp_init, NULL);
+
#ifdef VIMAGE
static void
vnet_igmp_uninit(const void *unused __unused)
@@ -3599,6 +3608,8 @@ vnet_igmp_uninit(const void *unused __un
/* This can happen when we shutdown the entire network stack. */
CTR1(KTR_IGMPV3, "%s: tearing down", __func__);
+
+ netisr_unregister(&igmp_nh);
}
VNET_SYSUNINIT(vnet_igmp_uninit, SI_SUB_PROTO_MC, SI_ORDER_ANY,
vnet_igmp_uninit, NULL);
@@ -3644,11 +3655,9 @@ igmp_modevent(module_t mod, int type, vo
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();
@@ -3664,4 +3673,4 @@ static moduledata_t igmp_mod = {
igmp_modevent,
0
};
-DECLARE_MODULE(igmp, igmp_mod, SI_SUB_PROTO_MC, SI_ORDER_ANY);
+DECLARE_MODULE(igmp, igmp_mod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE);
Modified: projects/vnet/sys/netinet/ip_input.c
==============================================================================
--- projects/vnet/sys/netinet/ip_input.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/netinet/ip_input.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -332,7 +332,7 @@ ip_init(void)
/* Skip initialization of globals for non-default instances. */
if (!IS_DEFAULT_VNET(curvnet))
- return;
+ goto out;
pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
if (pr == NULL)
@@ -354,6 +354,7 @@ ip_init(void)
ip_protox[pr->pr_protocol] = pr - inetsw;
}
+out:
netisr_register(&ip_nh);
#ifdef RSS
netisr_register(&ip_direct_nh);
@@ -367,6 +368,11 @@ ip_destroy(void *unused __unused)
struct ifnet *ifp;
int error;
+#ifdef RSS
+ netisr_unregister(&ip_direct_nh);
+#endif
+ netisr_unregister(&ip_nh);
+
if ((error = pfil_head_unregister(&V_inet_pfil_hook)) != 0)
printf("%s: WARNING: unable to unregister pfil hook, "
"error %d\n", __func__, error);
Modified: projects/vnet/sys/netinet6/ip6_input.c
==============================================================================
--- projects/vnet/sys/netinet6/ip6_input.c Sun Apr 24 16:36:33 2016 (r298547)
+++ projects/vnet/sys/netinet6/ip6_input.c Sun Apr 24 16:41:54 2016 (r298548)
@@ -219,7 +219,7 @@ ip6_init(void)
/* Skip global initialization stuff for non-default instances. */
if (!IS_DEFAULT_VNET(curvnet))
- return;
+ goto out;
pr = pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
if (pr == NULL)
@@ -241,6 +241,7 @@ ip6_init(void)
ip6_protox[pr->pr_protocol] = pr - inet6sw;
}
+out:
netisr_register(&ip6_nh);
#ifdef RSS
netisr_register(&ip6_direct_nh);
@@ -313,6 +314,11 @@ ip6_destroy(void *unused __unused)
struct ifnet *ifp;
int error;
+#ifdef RSS
+ netisr_unregister(&ip6_direct_nh);
+#endif
+ netisr_unregister(&ip6_nh);
+
if ((error = pfil_head_unregister(&V_inet6_pfil_hook)) != 0)
printf("%s: WARNING: unable to unregister pfil hook, "
"error %d\n", __func__, error);
More information about the svn-src-projects
mailing list