Date: Fri, 6 May 2016 13:41:43 +0000 (UTC) From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r299173 - in projects/vnet/sys: net netinet netinet6 Message-ID: <201605061341.u46DfhUb072991@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bz Date: Fri May 6 13:41:43 2016 New Revision: 299173 URL: https://svnweb.freebsd.org/changeset/base/299173 Log: Revert the netisr changes. Introduce a per-VNET flag to enable/disable netisr prcessing on that VNET. Add functions to toggle the state. Update consumers. Upon disabling netisr processing for a VNET drain the netisr queue. In if_attachdomain1() there is no need for trylock. Also do not update the status before the initialisation has happened. Reshuffle things a bit more in if_detach_internal(); always set the interface down; set the if_afdata to NULL after clearing it. In the vmove functions, as well as the if_ioctl, make sure the VNET we are working on is not in the process of shutting down already. Add a couple of __ununsed to vnet.c functions. Improve DDB printing there to properly zero-prefix hex numbers to 8 digits. Add an extra ifp argument to nd6_ifdetach() in order to be able to walk the address list and stop DAD processing. In nd6_timer() do not reset the callout before we are done with handling everything. Sponsored by: The FreeBSD Foundation Modified: projects/vnet/sys/net/if.c projects/vnet/sys/net/if_epair.c projects/vnet/sys/net/if_ethersubr.c projects/vnet/sys/net/netisr.c projects/vnet/sys/net/netisr.h projects/vnet/sys/net/rtsock.c projects/vnet/sys/net/vnet.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/in6.c projects/vnet/sys/netinet6/ip6_input.c projects/vnet/sys/netinet6/nd6.c projects/vnet/sys/netinet6/nd6.h Modified: projects/vnet/sys/net/if.c ============================================================================== --- projects/vnet/sys/net/if.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/if.c Fri May 6 13:41:43 2016 (r299173) @@ -814,15 +814,13 @@ if_attachdomain1(struct ifnet *ifp) * Since dp->dom_ifattach calls malloc() with M_WAITOK, we * cannot lock ifp->if_afdata initialization, entirely. */ - if (IF_AFDATA_TRYLOCK(ifp) == 0) - return; + IF_AFDATA_LOCK(ifp); if (ifp->if_afdata_initialized >= domain_init_status) { IF_AFDATA_UNLOCK(ifp); log(LOG_WARNING, "%s called more than once on %s\n", __func__, ifp->if_xname); return; } - ifp->if_afdata_initialized = domain_init_status; IF_AFDATA_UNLOCK(ifp); /* address family dependent data region */ @@ -832,6 +830,10 @@ if_attachdomain1(struct ifnet *ifp) ifp->if_afdata[dp->dom_family] = (*dp->dom_ifattach)(ifp); } + + IF_AFDATA_LOCK(ifp); + ifp->if_afdata_initialized = domain_init_status; + IF_AFDATA_UNLOCK(ifp); } /* @@ -936,10 +938,6 @@ if_detach_internal(struct ifnet *ifp, in found = 1; break; } -#ifdef VIMAGE - if (found) - curvnet->vnet_ifcnt--; -#endif IFNET_WUNLOCK(); if (!found) { /* @@ -961,6 +959,9 @@ if_detach_internal(struct ifnet *ifp, in * 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 @@ -980,6 +981,8 @@ if_detach_internal(struct ifnet *ifp, in if (vmove && ifcp != NULL) *ifcp = if_clone_findifc(ifp); + if_down(ifp); + /* * On VNET shutdown abort here as the stack teardown will do all * the work top-down for us. @@ -1004,7 +1007,6 @@ if_detach_internal(struct ifnet *ifp, in /* * Remove routes and flush queues. */ - if_down(ifp); #ifdef ALTQ if (ALTQ_IS_ENABLED(&ifp->if_snd)) altq_disable(&ifp->if_snd); @@ -1070,9 +1072,11 @@ finish_vnet_shutdown: ifp->if_afdata_initialized = 0; IF_AFDATA_UNLOCK(ifp); for (dp = domains; i > 0 && dp; dp = dp->dom_next) { - if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family]) + if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family]) { (*dp->dom_ifdetach)(ifp, ifp->if_afdata[dp->dom_family]); + ifp->if_afdata[dp->dom_family] = NULL; + } } return (0); @@ -1153,6 +1157,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); @@ -1173,12 +1178,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); @@ -1195,6 +1210,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); @@ -1222,6 +1238,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(); @@ -2673,8 +2698,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: projects/vnet/sys/net/if_epair.c ============================================================================== --- projects/vnet/sys/net/if_epair.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/if_epair.c Fri May 6 13:41:43 2016 (r299173) @@ -959,7 +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); + netisr_register_vnet(&epair_nh); } VNET_SYSINIT(vnet_epair_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_epair_init, NULL); @@ -968,7 +968,7 @@ static void vnet_epair_uninit(const void *unused __unused) { - netisr_unregister(&epair_nh); + netisr_unregister_vnet(&epair_nh); if_clone_detach(V_epair_cloner); } VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, @@ -986,10 +986,12 @@ 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); Modified: projects/vnet/sys/net/if_ethersubr.c ============================================================================== --- projects/vnet/sys/net/if_ethersubr.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/if_ethersubr.c Fri May 6 13:41:43 2016 (r299173) @@ -654,6 +654,14 @@ 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; @@ -664,7 +672,7 @@ 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); + netisr_register_vnet(ðer_nh); } VNET_SYSINIT(vnet_ether_init, SI_SUB_PROTO_IF, SI_ORDER_ANY, vnet_ether_init, NULL); @@ -685,7 +693,7 @@ static void vnet_ether_destroy(__unused void *arg) { - netisr_unregister(ðer_nh); + netisr_unregister_vnet(ðer_nh); } VNET_SYSUNINIT(vnet_ether_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY, vnet_ether_destroy, NULL); @@ -709,7 +717,8 @@ ether_input(struct ifnet *ifp, struct mb * We will rely on rcvif being set properly in the deferred context, * so assert it is correct here. */ - KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch", __func__)); + KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch m %p " + "rcvif %p ifp %p", __func__, m, m->m_pkthdr.rcvif, ifp)); CURVNET_SET_QUIET(ifp->if_vnet); netisr_dispatch(NETISR_ETHER, m); CURVNET_RESTORE(); Modified: projects/vnet/sys/net/netisr.c ============================================================================== --- projects/vnet/sys/net/netisr.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/netisr.c Fri May 6 13:41:43 2016 (r299173) @@ -208,8 +208,22 @@ 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 VNET_DEFINE(struct netisr_proto, netisr_proto[NETISR_MAXPROT]); -#define V_netisr_proto VNET(netisr_proto) +static struct netisr_proto netisr_proto[NETISR_MAXPROT]; + +/* + * The netisr_enable array describes a per-VNET flag for registered + * protocols on whether this netisr is active in this VNET or not. + * netisr_register() will automatically enable the netisr for the + * default VNET and all currently active instances. + * netisr_unregister() will disable all active VNETs, including vnet0. + * Individual network stack instances can be enabled/disabled by the + * netisr_(un)register _vnet() functions. + * With this we keep the one netisr_proto per protocol but add a + * mechanism to stop netisr processing for vnet teardown. + * Apart from that we expect a VNET to always be enabled. + */ +static VNET_DEFINE(u_int, netisr_enable[NETISR_MAXPROT]); +#define V_netisr_enable VNET(netisr_enable) /* * Per-CPU workstream data. See netisr_internal.h for more details. @@ -355,6 +369,7 @@ sysctl_netisr_dispatch_policy(SYSCTL_HAN void netisr_register(const struct netisr_handler *nhp) { + VNET_ITERATOR_DECL(vnet_iter); struct netisr_work *npwp; const char *name; u_int i, proto; @@ -397,32 +412,48 @@ netisr_register(const struct netisr_hand * Test that no existing registration exists for this protocol. */ NETISR_WLOCK(); - KASSERT(V_netisr_proto[proto].np_name == NULL, + KASSERT(netisr_proto[proto].np_name == NULL, ("%s(%u, %s): name present", __func__, proto, name)); - KASSERT(V_netisr_proto[proto].np_handler == NULL, + KASSERT(netisr_proto[proto].np_handler == NULL, ("%s(%u, %s): handler present", __func__, proto, name)); - 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; + 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; if (nhp->nh_qlimit == 0) - V_netisr_proto[proto].np_qlimit = netisr_defaultqlimit; + 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); - V_netisr_proto[proto].np_qlimit = netisr_maxqlimit; + netisr_proto[proto].np_qlimit = netisr_maxqlimit; } else - 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; + netisr_proto[proto].np_qlimit = nhp->nh_qlimit; + netisr_proto[proto].np_policy = nhp->nh_policy; + 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 = V_netisr_proto[proto].np_qlimit; + npwp->nw_qlimit = netisr_proto[proto].np_qlimit; + } + +#ifdef VIMAGE + /* + * Test that we are in vnet0 and have a curvnet set. + */ + KASSERT(curvnet != NULL, ("%s: curvnet is NULL", __func__)); + KASSERT(IS_DEFAULT_VNET(curvnet), ("%s: curvnet %p is not vnet0 %p", + __func__, curvnet, vnet0)); + VNET_LIST_RLOCK_NOSLEEP(); + VNET_FOREACH(vnet_iter) { + CURVNET_SET(vnet_iter); + V_netisr_enable[proto] = 1; + CURVNET_RESTORE(); } + VNET_LIST_RUNLOCK_NOSLEEP(); +#endif NETISR_WUNLOCK(); } @@ -446,7 +477,7 @@ netisr_clearqdrops(const struct netisr_h ("%s(%u): protocol too big for %s", __func__, proto, name)); NETISR_WLOCK(); - KASSERT(V_netisr_proto[proto].np_handler != NULL, + KASSERT(netisr_proto[proto].np_handler != NULL, ("%s(%u): protocol not registered for %s", __func__, proto, name)); @@ -479,7 +510,7 @@ netisr_getqdrops(const struct netisr_han ("%s(%u): protocol too big for %s", __func__, proto, name)); NETISR_RLOCK(&tracker); - KASSERT(V_netisr_proto[proto].np_handler != NULL, + KASSERT(netisr_proto[proto].np_handler != NULL, ("%s(%u): protocol not registered for %s", __func__, proto, name)); @@ -510,10 +541,10 @@ netisr_getqlimit(const struct netisr_han ("%s(%u): protocol too big for %s", __func__, proto, name)); NETISR_RLOCK(&tracker); - KASSERT(V_netisr_proto[proto].np_handler != NULL, + KASSERT(netisr_proto[proto].np_handler != NULL, ("%s(%u): protocol not registered for %s", __func__, proto, name)); - *qlimitp = V_netisr_proto[proto].np_qlimit; + *qlimitp = netisr_proto[proto].np_qlimit; NETISR_RUNLOCK(&tracker); } @@ -542,11 +573,11 @@ netisr_setqlimit(const struct netisr_han ("%s(%u): protocol too big for %s", __func__, proto, name)); NETISR_WLOCK(); - KASSERT(V_netisr_proto[proto].np_handler != NULL, + KASSERT(netisr_proto[proto].np_handler != NULL, ("%s(%u): protocol not registered for %s", __func__, proto, name)); - V_netisr_proto[proto].np_qlimit = qlimit; + netisr_proto[proto].np_qlimit = qlimit; CPU_FOREACH(i) { npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto]; npwp->nw_qlimit = qlimit; @@ -587,6 +618,7 @@ netisr_drain_proto(struct netisr_work *n void netisr_unregister(const struct netisr_handler *nhp) { + VNET_ITERATOR_DECL(vnet_iter); struct netisr_work *npwp; #ifdef INVARIANTS const char *name; @@ -601,16 +633,26 @@ netisr_unregister(const struct netisr_ha ("%s(%u): protocol too big for %s", __func__, proto, name)); NETISR_WLOCK(); - KASSERT(V_netisr_proto[proto].np_handler != NULL, + KASSERT(netisr_proto[proto].np_handler != NULL, ("%s(%u): protocol not registered for %s", __func__, proto, name)); - 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; +#ifdef VIMAGE + VNET_LIST_RLOCK_NOSLEEP(); + VNET_FOREACH(vnet_iter) { + CURVNET_SET(vnet_iter); + V_netisr_enable[proto] = 0; + CURVNET_RESTORE(); + } + VNET_LIST_RUNLOCK_NOSLEEP(); +#endif + + 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; CPU_FOREACH(i) { npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto]; netisr_drain_proto(npwp); @@ -619,6 +661,117 @@ netisr_unregister(const struct netisr_ha NETISR_WUNLOCK(); } +#ifdef VIMAGE +void +netisr_register_vnet(const struct netisr_handler *nhp) +{ + u_int proto; + + proto = nhp->nh_proto; + + KASSERT(curvnet != NULL, ("%s: curvnet is NULL", __func__)); + KASSERT(proto < NETISR_MAXPROT, + ("%s(%u): protocol too big for %s", __func__, proto, nhp->nh_name)); + NETISR_WLOCK(); + KASSERT(netisr_proto[proto].np_handler != NULL, + ("%s(%u): protocol not registered for %s", __func__, proto, + nhp->nh_name)); + + V_netisr_enable[proto] = 1; + NETISR_WUNLOCK(); +} +#endif + +#ifdef VIMAGE +static void +netisr_drain_proto_vnet(struct vnet *vnet, u_int proto) +{ + struct netisr_workstream *nwsp; + struct netisr_work *npwp; + struct mbuf *m, *mp, *n, *ne; + u_int i; +#ifdef INVARIANTS + u_int b, k, f; +#endif + + KASSERT(vnet != NULL, ("%s: vnet is NULL", __func__)); + NETISR_LOCK_ASSERT(); + + CPU_FOREACH(i) { + nwsp = DPCPU_ID_PTR(i, nws); + if (nwsp->nws_intr_event == NULL) + continue; + npwp = &nwsp->nws_work[proto]; + NWS_LOCK(nwsp); +#ifdef INVARIANTS + b = npwp->nw_len; + k = f = 0; +#endif + + /* + * Rather than dissecting and removing mbufs from the middle + * of the chain, we build a new chain if the packet stays and + * update the head and tial pointers at the end. All packets + * matching the given vnet are freed. + */ + m = npwp->nw_head; + n = ne = NULL; + while (m != NULL) { + mp = m; + m = m->m_nextpkt; + mp->m_nextpkt = NULL; + if (mp->m_pkthdr.rcvif->if_vnet != vnet) { + if (n == NULL) { + n = ne = mp; + } else { + ne->m_nextpkt = mp; + ne = mp; + } +#ifdef INVARIANTS + k++; +#endif + continue; + } + /* This is a packet in the selected vnet. Free it. */ + npwp->nw_len--; +#ifdef INVARIANTS + f++; +#endif + m_freem(mp); + } + npwp->nw_head = n; + npwp->nw_tail = ne; +#ifdef INVARIANTS + KASSERT((k + f) == b, ("%s: b %u != k %u + f %u, nw_len %u " + "vnet %p proto %u", __func__, b, k, f, npwp->nw_len, + vnet, proto)); +#endif + NWS_UNLOCK(nwsp); + } +} + +void +netisr_unregister_vnet(const struct netisr_handler *nhp) +{ + u_int proto; + + proto = nhp->nh_proto; + + KASSERT(curvnet != NULL, ("%s: curvnet is NULL", __func__)); + KASSERT(proto < NETISR_MAXPROT, + ("%s(%u): protocol too big for %s", __func__, proto, nhp->nh_name)); + NETISR_WLOCK(); + KASSERT(netisr_proto[proto].np_handler != NULL, + ("%s(%u): protocol not registered for %s", __func__, proto, + nhp->nh_name)); + + V_netisr_enable[proto] = 0; + + netisr_drain_proto_vnet(curvnet, proto); + NETISR_WUNLOCK(); +} +#endif + /* * Compose the global and per-protocol policies on dispatch, and return the * dispatch policy to use. @@ -728,6 +881,9 @@ netisr_process_workstream_proto(struct n struct netisr_work local_npw, *npwp; u_int handled; struct mbuf *m; +#ifdef INVARIANTS + u_int b, f; +#endif NETISR_LOCK_ASSERT(); NWS_LOCK_ASSERT(nwsp); @@ -741,6 +897,10 @@ netisr_process_workstream_proto(struct n if (npwp->nw_len == 0) return (0); +#ifdef INVARIANTS + b = npwp->nw_len; + f = 0; +#endif /* * Move the global work queue to a thread-local work queue. * @@ -761,19 +921,18 @@ netisr_process_workstream_proto(struct n if (local_npw.nw_head == NULL) local_npw.nw_tail = NULL; local_npw.nw_len--; + f++; VNET_ASSERT(m->m_pkthdr.rcvif != NULL, ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m)); CURVNET_SET(m->m_pkthdr.rcvif->if_vnet); - V_netisr_proto[proto].np_handler(m); + netisr_proto[proto].np_handler(m); CURVNET_RESTORE(); } KASSERT(local_npw.nw_len == 0, - ("%s(%u): len %u", __func__, proto, local_npw.nw_len)); - /* 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(); + ("%s(%u): len %u b %u f %u", __func__, proto, local_npw.nw_len, + b, f)); + if (netisr_proto[proto].np_drainedcpu) + netisr_proto[proto].np_drainedcpu(nwsp->nws_cpu); NWS_LOCK(nwsp); npwp->nw_handled += handled; return (handled); @@ -909,12 +1068,15 @@ netisr_queue_src(u_int proto, uintptr_t #ifdef NETISR_LOCKING NETISR_RLOCK(&tracker); #endif - if (V_netisr_proto[proto].np_handler == NULL) { + KASSERT(netisr_proto[proto].np_handler != NULL, + ("%s: invalid proto %u", __func__, proto)); + + if (V_netisr_enable[proto] == 0) { m_freem(m); return (ENOPROTOOPT); } - m = netisr_select_cpuid(&V_netisr_proto[proto], NETISR_DISPATCH_DEFERRED, + m = netisr_select_cpuid(&netisr_proto[proto], NETISR_DISPATCH_DEFERRED, source, m, &cpuid); if (m != NULL) { KASSERT(!CPU_ABSENT(cpuid), ("%s: CPU %u absent", __func__, @@ -956,8 +1118,11 @@ netisr_dispatch_src(u_int proto, uintptr #ifdef NETISR_LOCKING NETISR_RLOCK(&tracker); #endif - npp = &V_netisr_proto[proto]; - if (npp->np_handler == NULL) { + npp = &netisr_proto[proto]; + KASSERT(npp->np_handler != NULL, ("%s: invalid proto %u", __func__, + proto)); + + if (V_netisr_enable[proto] == 0) { m_freem(m); return (ENOPROTOOPT); } @@ -978,7 +1143,7 @@ netisr_dispatch_src(u_int proto, uintptr npwp = &nwsp->nws_work[proto]; npwp->nw_dispatched++; npwp->nw_handled++; - V_netisr_proto[proto].np_handler(m); + netisr_proto[proto].np_handler(m); error = 0; goto out_unlock; } @@ -992,7 +1157,7 @@ netisr_dispatch_src(u_int proto, uintptr * already running. */ sched_pin(); - m = netisr_select_cpuid(&V_netisr_proto[proto], NETISR_DISPATCH_HYBRID, + m = netisr_select_cpuid(&netisr_proto[proto], NETISR_DISPATCH_HYBRID, source, m, &cpuid); if (m == NULL) { error = ENOBUFS; @@ -1029,7 +1194,7 @@ netisr_dispatch_src(u_int proto, uintptr */ nwsp->nws_flags |= NWS_DISPATCHING; NWS_UNLOCK(nwsp); - V_netisr_proto[proto].np_handler(m); + netisr_proto[proto].np_handler(m); NWS_LOCK(nwsp); nwsp->nws_flags &= ~NWS_DISPATCHING; npwp->nw_handled++; @@ -1202,7 +1367,7 @@ sysctl_netisr_proto(SYSCTL_HANDLER_ARGS) counter = 0; NETISR_RLOCK(&tracker); for (proto = 0; proto < NETISR_MAXPROT; proto++) { - npp = &V_netisr_proto[proto]; + npp = &netisr_proto[proto]; if (npp->np_name == NULL) continue; snpp = &snp_array[counter]; @@ -1311,7 +1476,7 @@ sysctl_netisr_work(SYSCTL_HANDLER_ARGS) continue; NWS_LOCK(nwsp); for (proto = 0; proto < NETISR_MAXPROT; proto++) { - npp = &V_netisr_proto[proto]; + npp = &netisr_proto[proto]; if (npp->np_name == NULL) continue; nwp = &nwsp->nws_work[proto]; @@ -1360,7 +1525,7 @@ DB_SHOW_COMMAND(netisr, db_show_netisr) continue; first = 1; for (proto = 0; proto < NETISR_MAXPROT; proto++) { - if (V_netisr_proto[proto].np_handler == NULL) + if (netisr_proto[proto].np_handler == NULL) continue; nwp = &nwsp->nws_work[proto]; if (first) { @@ -1370,7 +1535,7 @@ DB_SHOW_COMMAND(netisr, db_show_netisr) db_printf("%3s ", ""); db_printf( "%6s %5d %5d %5d %8ju %8ju %8ju %8ju\n", - V_netisr_proto[proto].np_name, nwp->nw_len, + 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/netisr.h ============================================================================== --- projects/vnet/sys/net/netisr.h Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/netisr.h Fri May 6 13:41:43 2016 (r299173) @@ -210,6 +210,10 @@ void netisr_getqlimit(const struct netis void netisr_register(const struct netisr_handler *nhp); int netisr_setqlimit(const struct netisr_handler *nhp, u_int qlimit); void netisr_unregister(const struct netisr_handler *nhp); +#ifdef VIMAGE +void netisr_register_vnet(const struct netisr_handler *nhp); +void netisr_unregister_vnet(const struct netisr_handler *nhp); +#endif /* * Process a packet destined for a protocol, and attempt direct dispatch. Modified: projects/vnet/sys/net/rtsock.c ============================================================================== --- projects/vnet/sys/net/rtsock.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/rtsock.c Fri May 6 13:41:43 2016 (r299173) @@ -191,20 +191,16 @@ SYSCTL_PROC(_net_route, OID_AUTO, netisr "maximum routing socket dispatch queue length"); static void -rts_init(void) -{ - int tmp; - - if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp)) - rtsock_nh.nh_qlimit = tmp; -} -SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0); - -static void vnet_rts_init(void) { + int tmp; - netisr_register(&rtsock_nh); + if (IS_DEFAULT_VNET(curvnet)) { + if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp)) + rtsock_nh.nh_qlimit = tmp; + netisr_register(&rtsock_nh); + } else + netisr_register_vnet(&rtsock_nh); } VNET_SYSINIT(vnet_rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, vnet_rts_init, 0); @@ -213,7 +209,7 @@ static void vnet_rts_uninit(void) { - netisr_unregister(&rtsock_nh); + netisr_unregister_vnet(&rtsock_nh); } VNET_SYSUNINIT(vnet_rts_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, vnet_rts_uninit, 0); Modified: projects/vnet/sys/net/vnet.c ============================================================================== --- projects/vnet/sys/net/vnet.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/net/vnet.c Fri May 6 13:41:43 2016 (r299173) @@ -309,7 +309,7 @@ SYSINIT(vnet_init_prelink, SI_SUB_VNET_P vnet_init_prelink, NULL); static void -vnet0_init(void *arg) +vnet0_init(void *arg __unused) { /* Warn people before take off - in case we crash early. */ @@ -326,12 +326,12 @@ vnet0_init(void *arg) SYSINIT(vnet0_init, SI_SUB_VNET, SI_ORDER_FIRST, vnet0_init, NULL); static void -vnet_init_done(void *unused) +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); /* @@ -350,6 +350,16 @@ vnet_data_startup(void *dummy __unused) } SYSINIT(vnet_data, SI_SUB_KLD, SI_ORDER_FIRST, vnet_data_startup, 0); +/* Dummy VNET_SYSINIT to make sure we reach the final end state. */ +static void +vnet_sysinit_done(void *unused __unused) +{ + + return; +} +VNET_SYSINIT(vnet_sysinit_done, SI_SUB_VNET_DONE, SI_ORDER_ANY, + vnet_sysinit_done, NULL); + /* * When a module is loaded and requires storage for a virtualized global * variable, allocate space from the modspace free list. This interface @@ -698,7 +708,7 @@ db_vnet_print(struct vnet *vnet) db_printf(" vnet_data_mem = %p\n", vnet->vnet_data_mem); db_printf(" vnet_data_base = 0x%jx\n", (uintmax_t)vnet->vnet_data_base); - db_printf(" vnet_state = %#x\n", vnet->vnet_state); + db_printf(" vnet_state = %#08x\n", vnet->vnet_state); db_printf("\n"); } @@ -747,7 +757,7 @@ db_show_vnet_print_vs(struct vnet_sysini sym = db_search_symbol((vm_offset_t)vs->func, DB_STGY_PROC, &offset); db_symbol_values(sym, &funcname, NULL); xprint("%s(%p)\n", (vsname != NULL) ? vsname : "", vs); - xprint(" 0x%08x 0x%08x\n", vs->subsystem, vs->order); + xprint(" %#08x %#08x\n", vs->subsystem, vs->order); xprint(" %p(%s)(%p)\n", vs->func, (funcname != NULL) ? funcname : "", vs->arg); #undef xprint Modified: projects/vnet/sys/netinet/if_ether.c ============================================================================== --- projects/vnet/sys/netinet/if_ether.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet/if_ether.c Fri May 6 13:41:43 2016 (r299173) @@ -1329,10 +1329,12 @@ static void vnet_arp_init(void) { - netisr_register(&arp_nh); - if (IS_DEFAULT_VNET(curvnet)) + if (IS_DEFAULT_VNET(curvnet)) { + netisr_register(&arp_nh); iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY); + } else + netisr_register_vnet(&arp_nh); } VNET_SYSINIT(vnet_arp_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, vnet_arp_init, 0); @@ -1346,7 +1348,7 @@ static void vnet_arp_destroy(__unused void *arg) { - netisr_unregister(&arp_nh); + netisr_unregister_vnet(&arp_nh); } VNET_SYSUNINIT(vnet_arp_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, vnet_arp_destroy, NULL); Modified: projects/vnet/sys/netinet/igmp.c ============================================================================== --- projects/vnet/sys/netinet/igmp.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet/igmp.c Fri May 6 13:41:43 2016 (r299173) @@ -3592,16 +3592,16 @@ igmp_rec_type_to_str(const int type) } #endif +#ifdef VIMAGE static void vnet_igmp_init(const void *unused __unused) { - netisr_register(&igmp_nh); + netisr_register_vnet(&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) { @@ -3609,7 +3609,7 @@ 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); + netisr_unregister_vnet(&igmp_nh); } VNET_SYSUNINIT(vnet_igmp_uninit, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_igmp_uninit, NULL); @@ -3655,9 +3655,11 @@ 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(); Modified: projects/vnet/sys/netinet/ip_input.c ============================================================================== --- projects/vnet/sys/netinet/ip_input.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet/ip_input.c Fri May 6 13:41:43 2016 (r299173) @@ -331,8 +331,13 @@ ip_init(void) __func__); /* Skip initialization of globals for non-default instances. */ - if (!IS_DEFAULT_VNET(curvnet)) - goto out; + if (!IS_DEFAULT_VNET(curvnet)) { + netisr_register_vnet(&ip_nh); +#ifdef RSS + netisr_register_vnet(&ip_direct_nh); +#endif + return; + } pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == NULL) @@ -354,7 +359,6 @@ ip_init(void) ip_protox[pr->pr_protocol] = pr - inetsw; } -out: netisr_register(&ip_nh); #ifdef RSS netisr_register(&ip_direct_nh); @@ -369,9 +373,9 @@ ip_destroy(void *unused __unused) int error; #ifdef RSS - netisr_unregister(&ip_direct_nh); + netisr_unregister_vnet(&ip_direct_nh); #endif - netisr_unregister(&ip_nh); + netisr_unregister_vnet(&ip_nh); if ((error = pfil_head_unregister(&V_inet_pfil_hook)) != 0) printf("%s: WARNING: unable to unregister pfil hook, " Modified: projects/vnet/sys/netinet6/in6.c ============================================================================== --- projects/vnet/sys/netinet6/in6.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet6/in6.c Fri May 6 13:41:43 2016 (r299173) @@ -2461,7 +2461,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: projects/vnet/sys/netinet6/ip6_input.c ============================================================================== --- projects/vnet/sys/netinet6/ip6_input.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet6/ip6_input.c Fri May 6 13:41:43 2016 (r299173) @@ -218,8 +218,13 @@ ip6_init(void) V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; /* Skip global initialization stuff for non-default instances. */ - if (!IS_DEFAULT_VNET(curvnet)) - goto out; + if (!IS_DEFAULT_VNET(curvnet)) { + netisr_register_vnet(&ip6_nh); +#ifdef RSS + netisr_register_vnet(&ip6_direct_nh); +#endif + return; + } pr = pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); if (pr == NULL) @@ -241,7 +246,6 @@ ip6_init(void) ip6_protox[pr->pr_protocol] = pr - inet6sw; } -out: netisr_register(&ip6_nh); #ifdef RSS netisr_register(&ip6_direct_nh); @@ -315,9 +319,9 @@ ip6_destroy(void *unused __unused) int error; #ifdef RSS - netisr_unregister(&ip6_direct_nh); + netisr_unregister_vnet(&ip6_direct_nh); #endif - netisr_unregister(&ip6_nh); + netisr_unregister_vnet(&ip6_nh); if ((error = pfil_head_unregister(&V_inet6_pfil_hook)) != 0) printf("%s: WARNING: unable to unregister pfil hook, " Modified: projects/vnet/sys/netinet6/nd6.c ============================================================================== --- projects/vnet/sys/netinet6/nd6.c Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet6/nd6.c Fri May 6 13:41:43 2016 (r299173) @@ -290,8 +290,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); } @@ -894,9 +905,6 @@ nd6_timer(void *arg) struct nd_prefix *pr, *npr; struct in6_ifaddr *ia6, *nia6; - callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz, - nd6_timer, curvnet); - TAILQ_INIT(&drq); /* expire default router list */ @@ -1023,6 +1031,10 @@ nd6_timer(void *arg) prelist_remove(pr); } } + + callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz, + nd6_timer, curvnet); + CURVNET_RESTORE(); } Modified: projects/vnet/sys/netinet6/nd6.h ============================================================================== --- projects/vnet/sys/netinet6/nd6.h Fri May 6 13:04:45 2016 (r299172) +++ projects/vnet/sys/netinet6/nd6.h Fri May 6 13:41:43 2016 (r299173) @@ -410,7 +410,7 @@ void nd6_init(void); void nd6_destroy(void); #endif struct nd_ifinfo *nd6_ifattach(struct ifnet *); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605061341.u46DfhUb072991>