svn commit: r298548 - in projects/vnet/sys: net netinet netinet6

Marko Zec zec at fer.hr
Mon Apr 25 09:20:46 UTC 2016


On Sun, 24 Apr 2016 16:41:54 +0000
"Bjoern A. Zeeb" <bz at freebsd.org> wrote:

> 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().

There's still a single PCPU mbuf queue per protocol, so if a vnet
referenced by a queued mbuf disappears before netisr processing takes
place, all we gain here is that we'll panic earlier due to referencing
freed memory in netisr_dispatch(), instead of panicing later, in
ether_demux().

This patch introduces redundant (per-vnet) copies of handler fuction
pointers, along with several extra per-packet checks whether those
function pointers are NULL or not.  If the goal was to reduce the
possibility for the race described above, wouldn't it be simpler to add
a single "dying" flag to a vnet, and prevent any further netisr queuing
of mbufs once the flag was set?,

In both cases, we'd need to walk all PCPU netisr queues and prune any
stale mbufs referencing a dying vnet, before we could let the vnet go.

Or am I missing something here?

>   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(&ether_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(&ether_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(&ether_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