From b3be1c6e3bd7d3b5cf946ddb04c1c5811644229b Mon Sep 17 00:00:00 2001 From: rwatson Date: Thu, 23 Jul 2009 20:46:49 +0000 Subject: [PATCH] Introduce and use a sysinit-based initialization scheme for virtual network stacks, VNET_SYSINIT: - Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will occur each time a network stack is instantiated and destroyed. In the !VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT. For the VIMAGE case, we instead use SYSINIT's to track their order and properties on registration, using them for each vnet when created/ destroyed, or immediately on module load for already-started vnets. - Remove vnet_modinfo mechanism that existed to serve this purpose previously, as well as its dependency scheme: we now just use the SYSINIT ordering scheme. - Implement VNET_DOMAIN_SET() to allow protocol domains to declare that they want init functions to be called for each virtual network stack rather than just once at boot, compiling down to DOMAIN_SET() in the non-VIMAGE case. - Walk all virtualized kernel subsystems and make use of these instead of modinfo or DOMAIN_SET() for init/uninit events. In some cases, convert modular components from using modevent to using sysinit (where appropriate). In some cases, do minor rejuggling of SYSINIT ordering to make room for or better manage events. Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup) Discussed with: jhb, bz, julian, zec Reviewed by: bz Approved by: re (VIMAGE blanket) --- sys/kern/kern_vimage.c | 212 +------------------- sys/kern/uipc_domain.c | 55 ++--- sys/net/flowtable.c | 40 +--- sys/net/if.c | 52 ++--- sys/net/if_clone.c | 18 +- sys/net/if_clone.h | 1 + sys/net/if_gif.c | 60 ++---- sys/net/if_loop.c | 56 ++---- sys/net/route.c | 40 ++-- sys/net/rtsock.c | 4 +- sys/net/vnet.c | 142 +++++++++++++ sys/net/vnet.h | 51 +++++ sys/netgraph/bluetooth/socket/ng_btsocket.c | 7 +- sys/netgraph/netgraph.h | 2 +- sys/netgraph/ng_base.c | 24 +-- sys/netgraph/ng_eiface.c | 39 +--- sys/netgraph/ng_ether.c | 31 +-- sys/netgraph/ng_iface.c | 39 +--- sys/netgraph/ng_socket.c | 12 +- sys/netinet/igmp.c | 52 ++--- sys/netinet/in_proto.c | 2 +- sys/netinet6/in6_proto.c | 2 +- sys/netinet6/mld6.c | 53 ++--- sys/netipsec/ipsec.c | 28 +-- sys/netipsec/keysock.c | 2 +- sys/sys/domain.h | 30 ++- sys/sys/kernel.h | 2 + sys/sys/vimage.h | 62 +----- 28 files changed, 397 insertions(+), 721 deletions(-) diff --git a/sys/kern/kern_vimage.c b/sys/kern/kern_vimage.c index b5742df17e8..fa2d1f4ae86 100644 --- a/sys/kern/kern_vimage.c +++ b/sys/kern/kern_vimage.c @@ -52,12 +52,6 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_VNET, "vnet", "network stack control block"); -static TAILQ_HEAD(vnet_modlink_head, vnet_modlink) vnet_modlink_head; -static TAILQ_HEAD(vnet_modpending_head, vnet_modlink) vnet_modpending_head; -static void vnet_mod_complete_registration(struct vnet_modlink *); -static int vnet_mod_constructor(struct vnet_modlink *); -static int vnet_mod_destructor(struct vnet_modlink *); - struct rwlock vnet_rwlock; struct sx vnet_sxlock; @@ -130,185 +124,10 @@ vi_if_move(struct thread *td, struct ifnet *ifp, char *ifname, int jid) return (error); } - -/* - * Kernel interfaces and handlers. - */ - -void -vnet_mod_register(const struct vnet_modinfo *vmi) -{ - - vnet_mod_register_multi(vmi, NULL, NULL); -} - -void -vnet_mod_register_multi(const struct vnet_modinfo *vmi, void *iarg, - char *iname) -{ - struct vnet_modlink *vml, *vml_iter; - - /* Do not register the same {module, iarg} pair more than once. */ - TAILQ_FOREACH(vml_iter, &vnet_modlink_head, vml_mod_le) - if (vml_iter->vml_modinfo == vmi && vml_iter->vml_iarg == iarg) - break; - if (vml_iter != NULL) - panic("registering an already registered vnet module: %s", - vml_iter->vml_modinfo->vmi_name); - vml = malloc(sizeof(struct vnet_modlink), M_VNET, M_NOWAIT); - - /* - * XXX we support only statically assigned module IDs at the time. - * In principle modules should be able to get a dynamically - * assigned ID at registration time. - * - * If a module is registered in multiple instances, then each - * instance must have both iarg and iname set. - */ - if (vmi->vmi_id >= VNET_MOD_MAX) - panic("invalid vnet module ID: %d", vmi->vmi_id); - if (vmi->vmi_name == NULL) - panic("vnet module with no name: %d", vmi->vmi_id); - if ((iarg == NULL) ^ (iname == NULL)) - panic("invalid vnet module instance: %s", vmi->vmi_name); - - vml->vml_modinfo = vmi; - vml->vml_iarg = iarg; - vml->vml_iname = iname; - - /* Check whether the module we depend on is already registered. */ - if (vmi->vmi_dependson != vmi->vmi_id) { - TAILQ_FOREACH(vml_iter, &vnet_modlink_head, vml_mod_le) - if (vml_iter->vml_modinfo->vmi_id == - vmi->vmi_dependson) - break; /* Depencency found, we are done. */ - if (vml_iter == NULL) { -#ifdef DEBUG_ORDERING - printf("dependency %d missing for vnet mod %s," - "postponing registration\n", - vmi->vmi_dependson, vmi->vmi_name); -#endif /* DEBUG_ORDERING */ - TAILQ_INSERT_TAIL(&vnet_modpending_head, vml, - vml_mod_le); - return; - } - } - - vnet_mod_complete_registration(vml); -} - -void -vnet_mod_complete_registration(struct vnet_modlink *vml) -{ - VNET_ITERATOR_DECL(vnet_iter); - struct vnet_modlink *vml_iter; - - TAILQ_INSERT_TAIL(&vnet_modlink_head, vml, vml_mod_le); - - VNET_FOREACH(vnet_iter) { - CURVNET_SET_QUIET(vnet_iter); - vnet_mod_constructor(vml); - CURVNET_RESTORE(); - } - - /* Check for pending modules depending on us. */ - do { - TAILQ_FOREACH(vml_iter, &vnet_modpending_head, vml_mod_le) - if (vml_iter->vml_modinfo->vmi_dependson == - vml->vml_modinfo->vmi_id) - break; - if (vml_iter != NULL) { -#ifdef DEBUG_ORDERING - printf("vnet mod %s now registering," - "dependency %d loaded\n", - vml_iter->vml_modinfo->vmi_name, - vml->vml_modinfo->vmi_id); -#endif /* DEBUG_ORDERING */ - TAILQ_REMOVE(&vnet_modpending_head, vml_iter, - vml_mod_le); - vnet_mod_complete_registration(vml_iter); - } - } while (vml_iter != NULL); -} - -void -vnet_mod_deregister(const struct vnet_modinfo *vmi) -{ - - vnet_mod_deregister_multi(vmi, NULL, NULL); -} - -void -vnet_mod_deregister_multi(const struct vnet_modinfo *vmi, void *iarg, - char *iname) -{ - VNET_ITERATOR_DECL(vnet_iter); - struct vnet_modlink *vml; - - TAILQ_FOREACH(vml, &vnet_modlink_head, vml_mod_le) - if (vml->vml_modinfo == vmi && vml->vml_iarg == iarg) - break; - if (vml == NULL) - panic("cannot deregister unregistered vnet module %s", - vmi->vmi_name); - - VNET_FOREACH(vnet_iter) { - CURVNET_SET_QUIET(vnet_iter); - vnet_mod_destructor(vml); - CURVNET_RESTORE(); - } - - TAILQ_REMOVE(&vnet_modlink_head, vml, vml_mod_le); - free(vml, M_VNET); -} - -static int -vnet_mod_constructor(struct vnet_modlink *vml) -{ - const struct vnet_modinfo *vmi = vml->vml_modinfo; - -#ifdef DEBUG_ORDERING - printf("instantiating vnet_%s", vmi->vmi_name); - if (vml->vml_iarg) - printf("/%s", vml->vml_iname); - printf(": "); - if (vmi->vmi_iattach != NULL) - printf("iattach()"); - printf("\n"); -#endif - - if (vmi->vmi_iattach != NULL) - vmi->vmi_iattach(vml->vml_iarg); - - return (0); -} - -static int -vnet_mod_destructor(struct vnet_modlink *vml) -{ - const struct vnet_modinfo *vmi = vml->vml_modinfo; - -#ifdef DEBUG_ORDERING - printf("destroying vnet_%s", vmi->vmi_name); - if (vml->vml_iarg) - printf("/%s", vml->vml_iname); - printf(": "); - if (vmi->vmi_idetach != NULL) - printf("idetach(); "); - printf("\n"); -#endif - - if (vmi->vmi_idetach) - vmi->vmi_idetach(vml->vml_iarg); - - return (0); -} - struct vnet * vnet_alloc(void) { struct vnet *vnet; - struct vnet_modlink *vml; vnet = malloc(sizeof(struct vnet), M_VNET, M_WAITOK | M_ZERO); vnet->vnet_magic_n = VNET_MAGIC_N; @@ -316,11 +135,12 @@ vnet_alloc(void) /* Initialize / attach vnet module instances. */ CURVNET_SET_QUIET(vnet); - TAILQ_FOREACH(vml, &vnet_modlink_head, vml_mod_le) - vnet_mod_constructor(vml); + + sx_xlock(&vnet_sxlock); + vnet_sysinit(); CURVNET_RESTORE(); - VNET_LIST_WLOCK(); + rw_wlock(&vnet_rwlock); LIST_INSERT_HEAD(&vnet_head, vnet, vnet_le); VNET_LIST_WUNLOCK(); @@ -331,14 +151,13 @@ void vnet_destroy(struct vnet *vnet) { struct ifnet *ifp, *nifp; - struct vnet_modlink *vml; KASSERT(vnet->vnet_sockcnt == 0, ("%s: vnet still has sockets", __func__)); VNET_LIST_WLOCK(); LIST_REMOVE(vnet, vnet_le); - VNET_LIST_WUNLOCK(); + rw_wunlock(&vnet_rwlock); CURVNET_SET_QUIET(vnet); @@ -348,10 +167,8 @@ vnet_destroy(struct vnet *vnet) if_vmove(ifp, ifp->if_home_vnet); } - /* Detach / free per-module state instances. */ - TAILQ_FOREACH_REVERSE(vml, &vnet_modlink_head, - vnet_modlink_head, vml_mod_le) - vnet_mod_destructor(vml); + vnet_sysuninit(); + sx_xunlock(&vnet_sxlock); CURVNET_RESTORE(); @@ -387,9 +204,6 @@ static void vnet0_init(void *arg) { - TAILQ_INIT(&vnet_modlink_head); - TAILQ_INIT(&vnet_modpending_head); - /* * We MUST clear curvnet in vi_init_done() before going SMP, * otherwise CURVNET_SET() macros would scream about unnecessary @@ -402,20 +216,8 @@ SYSINIT(vnet0_init, SI_SUB_VNET, SI_ORDER_FIRST, vnet0_init, NULL); static void vnet_init_done(void *unused) { - struct vnet_modlink *vml_iter; curvnet = NULL; - - if (TAILQ_EMPTY(&vnet_modpending_head)) - return; - - printf("vnet modules with unresolved dependencies:\n"); - TAILQ_FOREACH(vml_iter, &vnet_modpending_head, vml_mod_le) - printf(" %d:%s depending on %d\n", - vml_iter->vml_modinfo->vmi_id, - vml_iter->vml_modinfo->vmi_name, - vml_iter->vml_modinfo->vmi_dependson); - panic("going nowhere without my vnet modules!"); } SYSINIT(vnet_init_done, SI_SUB_VNET_DONE, SI_ORDER_FIRST, vnet_init_done, diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index 88322d56448..dd0602ee889 100644 --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -59,17 +59,12 @@ __FBSDID("$FreeBSD$"); */ static void domaininit(void *); -SYSINIT(domain, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, domaininit, NULL); +SYSINIT(domain, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, domaininit, NULL); static void domainfinalize(void *); SYSINIT(domainfin, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, domainfinalize, NULL); -static vnet_attach_fn net_init_domain; -#ifdef VIMAGE -static vnet_detach_fn net_detach_domain; -#endif - static struct callout pffast_callout; static struct callout pfslow_callout; @@ -106,15 +101,6 @@ struct pr_usrreqs nousrreqs = { .pru_sopoll = pru_sopoll_notsupp, }; -#ifdef VIMAGE -vnet_modinfo_t vnet_domain_modinfo = { - .vmi_id = VNET_MOD_DOMAIN, - .vmi_name = "domain", - .vmi_iattach = net_init_domain, - .vmi_idetach = net_detach_domain, -}; -#endif - static void protosw_init(struct protosw *pr) { @@ -174,10 +160,10 @@ protosw_init(struct protosw *pr) * Note: you cant unload it again because a socket may be using it. * XXX can't fail at this time. */ -static int -net_init_domain(const void *arg) +void +domain_init(void *arg) { - const struct domain *dp = arg; + struct domain *dp = arg; struct protosw *pr; if (dp->dom_init) @@ -191,17 +177,21 @@ net_init_domain(const void *arg) max_datalen = MHLEN - max_hdr; if (max_datalen < 1) panic("%s: max_datalen < 1", __func__); - return (0); } #ifdef VIMAGE -/* - * Detach / free a domain instance. - */ -static int -net_detach_domain(const void *arg) +void +vnet_domain_init(void *arg) +{ + + /* Virtualized case is no different -- call init functions. */ + domain_init(arg); +} + +void +vnet_domain_uninit(void *arg) { - const struct domain *dp = arg; + struct domain *dp = arg; struct protosw *pr; for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) @@ -209,8 +199,6 @@ net_detach_domain(const void *arg) (*pr->pr_destroy)(); if (dp->dom_destroy) (*dp->dom_destroy)(); - - return (0); } #endif @@ -220,7 +208,7 @@ net_detach_domain(const void *arg) * XXX can't fail at this time. */ void -net_add_domain(void *data) +domain_add(void *data) { struct domain *dp; @@ -234,24 +222,19 @@ net_add_domain(void *data) dp->dom_name)); #ifndef INVARIANTS if (domain_init_status < 1) - printf("WARNING: attempt to net_add_domain(%s) before " + printf("WARNING: attempt to domain_add(%s) before " "domaininit()\n", dp->dom_name); #endif #ifdef notyet KASSERT(domain_init_status < 2, - ("attempt to net_add_domain(%s) after domainfinalize()", + ("attempt to domain_add(%s) after domainfinalize()", dp->dom_name)); #else if (domain_init_status >= 2) - printf("WARNING: attempt to net_add_domain(%s) after " + printf("WARNING: attempt to domain_add(%s) after " "domainfinalize()\n", dp->dom_name); #endif mtx_unlock(&dom_mtx); -#ifdef VIMAGE - vnet_mod_register_multi(&vnet_domain_modinfo, dp, dp->dom_name); -#else - net_init_domain(dp); -#endif } static void diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index d16ffa30d24..1fe2bbe69b8 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -173,18 +174,6 @@ static VNET_DEFINE(uma_zone_t, flow_ipv6_zone); #define V_flow_ipv4_zone VNET(flow_ipv4_zone) #define V_flow_ipv6_zone VNET(flow_ipv6_zone) -static int flowtable_iattach(const void *); -#ifdef VIMAGE -static int flowtable_idetach(const void *); - -static const vnet_modinfo_t flowtable_modinfo = { - .vmi_id = VNET_MOD_FLOWTABLE, - .vmi_name = "flowtable", - .vmi_iattach = flowtable_iattach, - .vmi_idetach = flowtable_idetach -}; -#endif - /* * TODO: * - Make flowtable stats per-cpu, aggregated at sysctl call time, @@ -802,18 +791,7 @@ flowtable_alloc(int nentry, int flags) } static void -flowtable_setup(void *arg) -{ - -#ifdef VIMAGE - vnet_mod_register(&flowtable_modinfo); -#else - flowtable_iattach(NULL); -#endif -} - -static int -flowtable_iattach(const void *unused __unused) +flowtable_init(const void *unused __unused) { V_flow_ipv4_zone = uma_zcreate("ip4flow", sizeof(struct flentry_v4), @@ -822,21 +800,23 @@ flowtable_iattach(const void *unused __unused) NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET); uma_zone_set_max(V_flow_ipv4_zone, V_flowtable_nmbflows); uma_zone_set_max(V_flow_ipv6_zone, V_flowtable_nmbflows); - return (0); } +VNET_SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, + flowtable_init, NULL); + #ifdef VIMAGE -static int -flowtable_idetach(const void *unused __unused) +static void +flowtable_uninit(const void *unused __unused) { uma_zdestroy(V_flow_ipv4_zone); uma_zdestroy(V_flow_ipv6_zone); - return (0); } -#endif -SYSINIT(flowtable_setup, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, flowtable_setup, NULL); +VNET_SYSUNINIT(flowtable_uninit, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, + flowtable_uninit, NULL); +#endif /* * The rest of the code is devoted to garbage collection of expired entries. diff --git a/sys/net/if.c b/sys/net/if.c index 608eb08356c..39166756f6b 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -150,11 +150,6 @@ static void if_detach_internal(struct ifnet *, int); extern void nd6_setmtu(struct ifnet *); #endif -static int vnet_net_iattach(const void *); -#ifdef VIMAGE -static int vnet_net_idetach(const void *); -#endif - VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */ VNET_DEFINE(struct ifgrouphead, ifg_head); VNET_DEFINE(int, if_index); @@ -171,19 +166,9 @@ struct rwlock ifnet_lock; static if_com_alloc_t *if_com_alloc[256]; static if_com_free_t *if_com_free[256]; -#ifdef VIMAGE -static const vnet_modinfo_t vnet_net_modinfo = { - .vmi_id = VNET_MOD_NET, - .vmi_name = "net", - .vmi_iattach = vnet_net_iattach, - .vmi_idetach = vnet_net_idetach -}; -#endif - /* * System initialization */ -SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL); SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL); MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals"); @@ -255,44 +240,41 @@ ifaddr_byindex(u_short idx) * parameters. */ +static void +vnet_if_init(const void *unused __unused) +{ + + TAILQ_INIT(&V_ifnet); + TAILQ_INIT(&V_ifg_head); + if_grow(); /* create initial table */ + vnet_if_clone_init(); +} +VNET_SYSINIT(vnet_if_init, SI_SUB_INIT_IF, SI_ORDER_FIRST, vnet_if_init, + NULL); + /* ARGSUSED*/ static void if_init(void *dummy __unused) { -#ifdef VIMAGE - vnet_mod_register(&vnet_net_modinfo); -#else - vnet_net_iattach(NULL); -#endif - IFNET_LOCK_INIT(); if_clone_init(); } +SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_SECOND, if_init, NULL); -static int -vnet_net_iattach(const void *unused __unused) -{ - - TAILQ_INIT(&V_ifnet); - TAILQ_INIT(&V_ifg_head); - if_grow(); /* create initial table */ - - return (0); -} #ifdef VIMAGE -static int -vnet_net_idetach(const void *unused __unused) +static void +vnet_if_uninit(const void *unused __unused) { VNET_ASSERT(TAILQ_EMPTY(&V_ifnet)); VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head)); free((caddr_t)V_ifindex_table, M_IFNET); - - return (0); } +VNET_SYSUNINIT(vnet_if_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST, + vnet_if_uninit, NULL); #endif void diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index 4e3f7873d3a..95c07b731d0 100644 --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -55,7 +55,6 @@ static void if_clone_free(struct if_clone *ifc); static int if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params); -static int vnet_clone_iattach(const void *); static struct mtx if_cloners_mtx; static VNET_DEFINE(int, if_cloners_count); @@ -116,19 +115,11 @@ VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners); static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework"); -#ifdef VIMAGE -static const vnet_modinfo_t vnet_clone_modinfo = { - .vmi_id = VNET_MOD_IF_CLONE, - .vmi_name = "if_clone", - .vmi_iattach = vnet_clone_iattach -}; -#endif - -static int vnet_clone_iattach(const void *unused __unused) +void +vnet_if_clone_init(void) { LIST_INIT(&V_if_cloners); - return (0); } void @@ -136,11 +127,6 @@ if_clone_init(void) { IF_CLONERS_LOCK_INIT(); -#ifdef VIMAGE - vnet_mod_register(&vnet_clone_modinfo); -#else - vnet_clone_iattach(NULL); -#endif } /* diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h index 280a5455db8..f125f8b5060 100644 --- a/sys/net/if_clone.h +++ b/sys/net/if_clone.h @@ -72,6 +72,7 @@ struct if_clone { void if_clone_init(void); void if_clone_attach(struct if_clone *); void if_clone_detach(struct if_clone *); +void vnet_if_clone_init(void); int if_clone_create(char *, size_t, caddr_t); int if_clone_destroy(const char *); diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index f663283c678..3d75dd46e42 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -96,19 +96,15 @@ static struct mtx gif_mtx; static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list); -static VNET_DEFINE(int, max_gif_nesting); -static VNET_DEFINE(int, parallel_tunnels); #define V_gif_softc_list VNET(gif_softc_list) -#define V_max_gif_nesting VNET(max_gif_nesting) -#define V_parallel_tunnels VNET(parallel_tunnels) #ifdef INET -VNET_DEFINE(int, ip_gif_ttl); +VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL; #define V_ip_gif_ttl VNET(ip_gif_ttl) #endif #ifdef INET6 -VNET_DEFINE(int, ip6_gif_hlim); +VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM; #define V_ip6_gif_hlim VNET(ip6_gif_hlim) #endif @@ -120,16 +116,6 @@ void (*ng_gif_detach_p)(struct ifnet *ifp); static void gif_start(struct ifnet *); static int gif_clone_create(struct if_clone *, int, caddr_t); static void gif_clone_destroy(struct ifnet *); -static int vnet_gif_iattach(const void *); - -#ifdef VIMAGE -static const vnet_modinfo_t vnet_gif_modinfo = { - .vmi_id = VNET_MOD_GIF, - .vmi_name = "gif", - .vmi_dependson = VNET_MOD_NET, - .vmi_iattach = vnet_gif_iattach -}; -#endif IFC_SIMPLE_DECLARE(gif, 0); @@ -149,6 +135,10 @@ SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0, */ #define MAX_GIF_NEST 1 #endif + +static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST; +#define V_max_gif_nesting VNET(max_gif_nesting) + SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, &VNET_NAME(max_gif_nesting), 0, "Max nested tunnels"); @@ -163,6 +153,13 @@ SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW, * pair of addresses. Some applications require this functionality so * we allow control over this check here. */ +#ifdef XBONEHACK +static VNET_DEFINE(int, parallel_tunnels) = 1; +#else +static VNET_DEFINE(int, parallel_tunnels) = 0; +#endif +#define V_parallel_tunnels VNET(parallel_tunnels) + SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, &VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?"); @@ -259,26 +256,14 @@ gif_clone_destroy(ifp) free(sc, M_GIF); } -static int -vnet_gif_iattach(const void *unused __unused) +static void +vnet_gif_init(const void *unused __unused) { LIST_INIT(&V_gif_softc_list); - V_max_gif_nesting = MAX_GIF_NEST; -#ifdef XBONEHACK - V_parallel_tunnels = 1; -#else - V_parallel_tunnels = 0; -#endif -#ifdef INET - V_ip_gif_ttl = GIF_TTL; -#endif -#ifdef INET6 - V_ip6_gif_hlim = GIF_HLIM; -#endif - - return (0); } +VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_gif_init, + NULL); static int gifmodevent(mod, type, data) @@ -290,20 +275,11 @@ gifmodevent(mod, type, data) switch (type) { case MOD_LOAD: mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF); - -#ifdef VIMAGE - vnet_mod_register(&vnet_gif_modinfo); -#else - vnet_gif_iattach(NULL); -#endif if_clone_attach(&gif_cloner); - break; + case MOD_UNLOAD: if_clone_detach(&gif_cloner); -#ifdef VIMAGE - vnet_mod_deregister(&vnet_gif_modinfo); -#endif mtx_destroy(&gif_mtx); break; default: diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index 78895700fb4..043c808f7f0 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -103,30 +103,14 @@ int looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct route *ro); static int lo_clone_create(struct if_clone *, int, caddr_t); static void lo_clone_destroy(struct ifnet *); -static int vnet_loif_iattach(const void *); -#ifdef VIMAGE -static int vnet_loif_idetach(const void *); -#endif VNET_DEFINE(struct ifnet *, loif); /* Used externally */ #ifdef VIMAGE -static VNET_DEFINE(struct ifc_simple_data *, lo_cloner_data); -static VNET_DEFINE(struct if_clone *, lo_cloner); +static VNET_DEFINE(struct ifc_simple_data, lo_cloner_data); +static VNET_DEFINE(struct if_clone, lo_cloner); #define V_lo_cloner_data VNET(lo_cloner_data) #define V_lo_cloner VNET(lo_cloner) - -MALLOC_DEFINE(M_LO_CLONER, "lo_cloner", "lo_cloner"); -#endif - -#ifdef VIMAGE -static const vnet_modinfo_t vnet_loif_modinfo = { - .vmi_id = VNET_MOD_LOIF, - .vmi_dependson = VNET_MOD_IF_CLONE, - .vmi_name = "loif", - .vmi_iattach = vnet_loif_iattach, - .vmi_idetach = vnet_loif_idetach -}; #endif IFC_SIMPLE_DECLARE(lo, 1); @@ -170,37 +154,32 @@ lo_clone_create(struct if_clone *ifc, int unit, caddr_t params) return (0); } -static int -vnet_loif_iattach(const void *unused __unused) +static void +vnet_loif_init(const void *unused __unused) { #ifdef VIMAGE - V_lo_cloner = malloc(sizeof(*V_lo_cloner), M_LO_CLONER, - M_WAITOK | M_ZERO); - V_lo_cloner_data = malloc(sizeof(*V_lo_cloner_data), M_LO_CLONER, - M_WAITOK | M_ZERO); - bcopy(&lo_cloner, V_lo_cloner, sizeof(*V_lo_cloner)); - bcopy(lo_cloner.ifc_data, V_lo_cloner_data, sizeof(*V_lo_cloner_data)); - V_lo_cloner->ifc_data = V_lo_cloner_data; - if_clone_attach(V_lo_cloner); + V_lo_cloner = lo_cloner; + V_lo_cloner_data = lo_cloner_data; + V_lo_cloner.ifc_data = &V_lo_cloner_data; + if_clone_attach(&V_lo_cloner); #else if_clone_attach(&lo_cloner); #endif - return (0); } +VNET_SYSINIT(vnet_loif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, + vnet_loif_init, NULL); #ifdef VIMAGE -static int -vnet_loif_idetach(const void *unused __unused) +static void +vnet_loif_uninit(const void *unused __unused) { - if_clone_detach(V_lo_cloner); - free(V_lo_cloner, M_LO_CLONER); - free(V_lo_cloner_data, M_LO_CLONER); + if_clone_detach(&V_lo_cloner); V_loif = NULL; - - return (0); } +VNET_SYSUNINIT(vnet_loif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, + vnet_loif_uninit, NULL); #endif static int @@ -209,11 +188,6 @@ loop_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: -#ifdef VIMAGE - vnet_mod_register(&vnet_loif_modinfo); -#else - vnet_loif_iattach(NULL); -#endif break; case MOD_UNLOAD: diff --git a/sys/net/route.c b/sys/net/route.c index de677bce95b..544c3b64362 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -99,17 +99,6 @@ VNET_DEFINE(struct rtstat, rtstat); static void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); -static int vnet_route_iattach(const void *); -#ifdef VIMAGE -static int vnet_route_idetach(const void *); - -static const vnet_modinfo_t vnet_rtable_modinfo = { - .vmi_id = VNET_MOD_RTABLE, - .vmi_name = "rtable", - .vmi_iattach = vnet_route_iattach, - .vmi_idetach = vnet_route_idetach -}; -#endif /* compare two sockaddr structures */ #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0) @@ -174,6 +163,10 @@ rt_tables_get_rnh(int table, int fam) return (*rt_tables_get_rnh_ptr(table, fam)); } +/* + * route initialization must occur before ip6_init2(), which happenas at + * SI_ORDER_MIDDLE. + */ static void route_init(void) { @@ -184,16 +177,11 @@ route_init(void) if (rt_numfibs == 0) rt_numfibs = 1; rn_init(); /* initialize all zeroes, all ones, mask table */ - -#ifdef VIMAGE - vnet_mod_register(&vnet_rtable_modinfo); -#else - vnet_route_iattach(NULL); -#endif } +SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0); -static int -vnet_route_iattach(const void *unused __unused) +static void +vnet_route_init(const void *unused __unused) { struct domain *dom; struct radix_node_head **rnh; @@ -229,13 +217,13 @@ vnet_route_iattach(const void *unused __unused) } } } - - return (0); } +VNET_SYSINIT(vnet_route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, + vnet_route_init, 0); #ifdef VIMAGE -static int -vnet_route_idetach(const void *unused __unused) +static void +vnet_route_uninit(const void *unused __unused) { int table; int fam; @@ -259,8 +247,9 @@ vnet_route_idetach(const void *unused __unused) } } } - return (0); } +VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, + vnet_route_uninit, 0); #endif #ifndef _SYS_SYSPROTO_H_ @@ -1510,6 +1499,3 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) fib = -1; return (rtinit1(ifa, cmd, flags, fib)); } - -/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */ -SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index bdea325cf31..88c98070306 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -35,9 +35,9 @@ #include "opt_inet6.h" #include -#include #include #include +#include #include #include #include @@ -1525,4 +1525,4 @@ static struct domain routedomain = { .dom_protoswNPROTOSW = &routesw[sizeof(routesw)/sizeof(routesw[0])] }; -DOMAIN_SET(route); +VNET_DOMAIN_SET(route); diff --git a/sys/net/vnet.c b/sys/net/vnet.c index a3148868bf9..cd5b2b37edb 100644 --- a/sys/net/vnet.c +++ b/sys/net/vnet.c @@ -126,6 +126,16 @@ MALLOC_DEFINE(M_VNET_DATA, "vnet_data", "VNET data"); */ static VNET_DEFINE(char, modspace[VNET_MODMIN]); +/* + * Global lists of subsystem constructor and destructors for vnets. + * They are registered via VNET_SYSINIT() and VNET_SYSUNINIT(). The + * lists are protected by the vnet_sxlock global lock. + */ +static TAILQ_HEAD(vnet_sysinit_head, vnet_sysinit) vnet_constructors = + TAILQ_HEAD_INITIALIZER(vnet_constructors); +static TAILQ_HEAD(vnet_sysuninit_head, vnet_sysinit) vnet_destructors = + TAILQ_HEAD_INITIALIZER(vnet_destructors); + struct vnet_data_free { uintptr_t vnd_start; int vnd_len; @@ -339,3 +349,135 @@ vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS) arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1); return (sysctl_handle_int(oidp, arg1, arg2, req)); } + +/* + * Support for special SYSINIT handlers registered via VNET_SYSINIT() + * and VNET_SYSUNINIT(). + */ +void +vnet_register_sysinit(void *arg) +{ + struct vnet_sysinit *vs, *vs2; + struct vnet *vnet; + + vs = arg; + KASSERT(vs->subsystem > SI_SUB_VNET, ("vnet sysinit too early")); + + /* Add the constructor to the global list of vnet constructors. */ + sx_xlock(&vnet_sxlock); + TAILQ_FOREACH(vs2, &vnet_constructors, link) { + if (vs2->subsystem > vs->subsystem) + break; + if (vs2->subsystem == vs->subsystem && vs2->order > vs->order) + break; + } + if (vs2 != NULL) + TAILQ_INSERT_BEFORE(vs2, vs, link); + else + TAILQ_INSERT_TAIL(&vnet_constructors, vs, link); + + /* + * Invoke the constructor on all the existing vnets when it is + * registered. + */ + VNET_FOREACH(vnet) { + CURVNET_SET_QUIET(vnet); + vs->func(vs->arg); + CURVNET_RESTORE(); + } + sx_xunlock(&vnet_sxlock); +} + +void +vnet_deregister_sysinit(void *arg) +{ + struct vnet_sysinit *vs; + + vs = arg; + + /* Remove the constructor from the global list of vnet constructors. */ + sx_xlock(&vnet_sxlock); + TAILQ_REMOVE(&vnet_constructors, vs, link); + sx_xunlock(&vnet_sxlock); +} + +void +vnet_register_sysuninit(void *arg) +{ + struct vnet_sysinit *vs, *vs2; + + vs = arg; + + /* Add the destructor to the global list of vnet destructors. */ + sx_xlock(&vnet_sxlock); + TAILQ_FOREACH(vs2, &vnet_destructors, link) { + if (vs2->subsystem > vs->subsystem) + break; + if (vs2->subsystem == vs->subsystem && vs2->order > vs->order) + break; + } + if (vs2 != NULL) + TAILQ_INSERT_BEFORE(vs2, vs, link); + else + TAILQ_INSERT_TAIL(&vnet_destructors, vs, link); + sx_xunlock(&vnet_sxlock); +} + +void +vnet_deregister_sysuninit(void *arg) +{ + struct vnet_sysinit *vs; + struct vnet *vnet; + + vs = arg; + + /* + * Invoke the destructor on all the existing vnets when it is + * deregistered. + */ + sx_xlock(&vnet_sxlock); + VNET_FOREACH(vnet) { + CURVNET_SET_QUIET(vnet); + vs->func(vs->arg); + CURVNET_RESTORE(); + } + + /* Remove the destructor from the global list of vnet destructors. */ + TAILQ_REMOVE(&vnet_destructors, vs, link); + sx_xunlock(&vnet_sxlock); +} + +/* + * Invoke all registered vnet constructors on the current vnet. Used + * during vnet construction. The caller is responsible for ensuring + * the new vnet is the current vnet and that the vnet_sxlock lock is + * locked. + */ +void +vnet_sysinit(void) +{ + struct vnet_sysinit *vs; + + sx_assert(&vnet_sxlock, SA_LOCKED); + TAILQ_FOREACH(vs, &vnet_constructors, link) { + vs->func(vs->arg); + } +} + +/* + * Invoke all registered vnet destructors on the current vnet. Used + * during vnet destruction. The caller is responsible for ensuring + * the dying vnet is the current vnet and that the vnet_sxlock lock is + * locked. + */ +void +vnet_sysuninit(void) +{ + struct vnet_sysinit *vs; + + sx_assert(&vnet_sxlock, SA_LOCKED); + TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head, + link) { + vs->func(vs->arg); + } +} diff --git a/sys/net/vnet.h b/sys/net/vnet.h index aec448a1133..8877bab203b 100644 --- a/sys/net/vnet.h +++ b/sys/net/vnet.h @@ -46,6 +46,43 @@ #ifdef _KERNEL #ifdef VIMAGE +#include + +/* + * SYSINIT/SYSUNINIT variants that provide per-vnet constructors and + * destructors. + */ +struct vnet_sysinit { + enum sysinit_sub_id subsystem; + enum sysinit_elem_order order; + sysinit_cfunc_t func; + const void *arg; + TAILQ_ENTRY(vnet_sysinit) link; +}; + +#define VNET_SYSINIT(ident, subsystem, order, func, arg) \ + static struct vnet_sysinit ident ## _vnet_init = { \ + subsystem, \ + order, \ + (sysinit_cfunc_t)(sysinit_nfunc_t)func, \ + (arg) \ + }; \ + SYSINIT(vnet_init_ ## ident, subsystem, order, \ + vnet_register_sysinit, &ident ## _vnet_init); \ + SYSUNINIT(vnet_init_ ## ident, subsystem, order, \ + vnet_deregister_sysinit, &ident ## _vnet_init) + +#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \ + static struct vnet_sysinit ident ## _vnet_uninit = { \ + subsystem, \ + order, \ + (sysinit_cfunc_t)(sysinit_nfunc_t)func, \ + (arg) \ + }; \ + SYSINIT(vnet_uninit_ ## ident, subsystem, order, \ + vnet_register_sysuninit, &ident ## _vnet_uninit); \ + SYSUNINIT(vnet_uninit_ ## ident, subsystem, order, \ + vnet_deregister_sysuninit, &ident ## _vnet_uninit) #if defined(__arm__) __asm__(".section " VNET_SETNAME ", \"aw\", %progbits"); @@ -121,6 +158,16 @@ void vnet_data_free(void *start_arg, int size); struct vnet; void vnet_data_init(struct vnet *vnet); void vnet_data_destroy(struct vnet *vnet); +void vnet_sysinit(void); +void vnet_sysuninit(void); + +/* + * Interfaces for managing per-vnet constructors and destructors. + */ +void vnet_register_sysinit(void *arg); +void vnet_register_sysuninit(void *arg); +void vnet_deregister_sysinit(void *arg); +void vnet_deregister_sysuninit(void *arg); #else /* !VIMAGE */ @@ -132,6 +179,10 @@ void vnet_data_destroy(struct vnet *vnet); #define VNET_DECLARE(t, n) extern t n #define VNET_DEFINE(t, n) t n #define _VNET_PTR(b, n) &VNET_NAME(n) +#define VNET_SYSINIT(ident, subsystem, order, func, arg) \ + SYSINIT(ident, subsystem, order, func, arg) +#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \ + SYSUNINIT(ident, subsystem, order, func, arg) #ifdef SYSCTL_OID #define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \ diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket.c b/sys/netgraph/bluetooth/socket/ng_btsocket.c index 6c6b1f3f701..f1620bc92a8 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket.c @@ -45,6 +45,7 @@ #include #include #include + #include #include #include @@ -57,7 +58,7 @@ #include static int ng_btsocket_modevent (module_t, int, void *); -extern struct domain ng_btsocket_domain; +static struct domain ng_btsocket_domain; /* * Bluetooth raw HCI sockets @@ -219,7 +220,7 @@ static struct protosw ng_btsocket_protosw[] = { * BLUETOOTH domain */ -struct domain ng_btsocket_domain = { +static struct domain ng_btsocket_domain = { .dom_family = AF_BLUETOOTH, .dom_name = "bluetooth", .dom_protosw = ng_btsocket_protosw, @@ -269,7 +270,6 @@ ng_btsocket_modevent(module_t mod, int event, void *data) switch (event) { case MOD_LOAD: - net_add_domain(&ng_btsocket_domain); break; case MOD_UNLOAD: @@ -285,3 +285,4 @@ ng_btsocket_modevent(module_t mod, int event, void *data) return (error); } /* ng_btsocket_modevent */ +DOMAIN_SET(ng_btsocket_); diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h index 37ef833cae4..8dbf0b5fac9 100644 --- a/sys/netgraph/netgraph.h +++ b/sys/netgraph/netgraph.h @@ -1113,7 +1113,7 @@ MODULE_DEPEND(ng_##typename, netgraph, NG_ABI_VERSION, \ NG_ABI_VERSION) #define NETGRAPH_INIT(tn, tp) \ - NETGRAPH_INIT_ORDERED(tn, tp, SI_SUB_PSEUDO, SI_ORDER_ANY) + NETGRAPH_INIT_ORDERED(tn, tp, SI_SUB_PSEUDO, SI_ORDER_MIDDLE) /* Special malloc() type for netgraph structs and ctrl messages */ /* Only these two types should be visible to nodes */ diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 084c676cb8e..b618bb48dc9 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -79,10 +79,6 @@ MODULE_VERSION(netgraph, NG_ABI_VERSION); /* Mutex to protect topology events. */ static struct mtx ng_topo_mtx; -#ifdef VIMAGE -static vnet_detach_fn vnet_netgraph_idetach; -#endif - #ifdef NETGRAPH_DEBUG static struct mtx ng_nodelist_mtx; /* protects global node/hook lists */ static struct mtx ngq_mtx; /* protects the queue item list */ @@ -3068,18 +3064,9 @@ ng_mod_event(module_t mod, int event, void *data) return (error); } -#ifdef VIMAGE -static const vnet_modinfo_t vnet_netgraph_modinfo = { - .vmi_id = VNET_MOD_NETGRAPH, - .vmi_name = "netgraph", - .vmi_dependson = VNET_MOD_LOIF, - .vmi_idetach = vnet_netgraph_idetach -}; -#endif - #ifdef VIMAGE -static int -vnet_netgraph_idetach(const void *unused __unused) +static void +vnet_netgraph_uninit(const void *unused __unused) { #if 0 node_p node, last_killed = NULL; @@ -3101,9 +3088,9 @@ vnet_netgraph_idetach(const void *unused __unused) last_killed = node; } #endif - - return (0); } +VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_NETGRAPH, SI_ORDER_ANY, + vnet_netgraph_uninit, NULL); #endif /* VIMAGE */ /* @@ -3120,9 +3107,6 @@ ngb_mod_event(module_t mod, int event, void *data) switch (event) { case MOD_LOAD: /* Initialize everything. */ -#ifdef VIMAGE - vnet_mod_register(&vnet_netgraph_modinfo); -#endif NG_WORKLIST_LOCK_INIT(); mtx_init(&ng_typelist_mtx, "netgraph types mutex", NULL, MTX_DEF); diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c index fb43eef5e4c..ad9668e9556 100644 --- a/sys/netgraph/ng_eiface.c +++ b/sys/netgraph/ng_eiface.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -113,22 +114,9 @@ static struct ng_type typestruct = { }; NETGRAPH_INIT(eiface, &typestruct); -static vnet_attach_fn ng_eiface_iattach; -static vnet_detach_fn ng_eiface_idetach; - static VNET_DEFINE(struct unrhdr *, ng_eiface_unit); #define V_ng_eiface_unit VNET(ng_eiface_unit) -#ifdef VIMAGE -static vnet_modinfo_t vnet_ng_eiface_modinfo = { - .vmi_id = VNET_MOD_NG_EIFACE, - .vmi_name = "ng_eiface", - .vmi_dependson = VNET_MOD_NETGRAPH, - .vmi_iattach = ng_eiface_iattach, - .vmi_idetach = ng_eiface_idetach -}; -#endif - /************************************************************************ INTERFACE STUFF ************************************************************************/ @@ -601,18 +589,7 @@ ng_eiface_mod_event(module_t mod, int event, void *data) switch (event) { case MOD_LOAD: -#ifdef VIMAGE - vnet_mod_register(&vnet_ng_eiface_modinfo); -#else - ng_eiface_iattach(NULL); -#endif - break; case MOD_UNLOAD: -#ifdef VIMAGE - vnet_mod_deregister(&vnet_ng_eiface_modinfo); -#else - ng_eiface_idetach(NULL); -#endif break; default: error = EOPNOTSUPP; @@ -621,18 +598,20 @@ ng_eiface_mod_event(module_t mod, int event, void *data) return (error); } -static int ng_eiface_iattach(const void *unused) +static void +vnet_ng_eiface_init(const void *unused) { V_ng_eiface_unit = new_unrhdr(0, 0xffff, NULL); - - return (0); } +VNET_SYSINIT(vnet_ng_eiface_init, SI_SUB_PSEUDO, SI_ORDER_ANY, + vnet_ng_eiface_init, NULL); -static int ng_eiface_idetach(const void *unused) +static void +vnet_ng_eiface_uninit(const void *unused) { delete_unrhdr(V_ng_eiface_unit); - - return (0); } +VNET_SYSUNINIT(vnet_ng_eiface_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, + vnet_ng_eiface_uninit, NULL); diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c index 09a8615ab87..85fc7fc5ab9 100644 --- a/sys/netgraph/ng_ether.c +++ b/sys/netgraph/ng_ether.c @@ -72,17 +72,6 @@ #define IFP2NG(ifp) (IFP2AC((ifp))->ac_netgraph) -static vnet_attach_fn ng_ether_iattach; - -#ifdef VIMAGE -static vnet_modinfo_t vnet_ng_ether_modinfo = { - .vmi_id = VNET_MOD_NG_ETHER, - .vmi_name = "ng_ether", - .vmi_dependson = VNET_MOD_NETGRAPH, - .vmi_iattach = ng_ether_iattach, -}; -#endif - /* Per-node private data */ struct private { struct ifnet *ifp; /* associated interface */ @@ -783,11 +772,6 @@ ng_ether_mod_event(module_t mod, int event, void *data) ng_ether_input_orphan_p = ng_ether_input_orphan; ng_ether_link_state_p = ng_ether_link_state; -#ifdef VIMAGE - vnet_mod_register(&vnet_ng_ether_modinfo); -#else - error = ng_ether_iattach(NULL); -#endif break; case MOD_UNLOAD: @@ -800,10 +784,6 @@ ng_ether_mod_event(module_t mod, int event, void *data) * is MOD_UNLOAD, so there's no need to detach any nodes. */ -#ifdef VIMAGE - vnet_mod_deregister(&vnet_ng_ether_modinfo); -#endif - /* Unregister function hooks */ ng_ether_attach_p = NULL; ng_ether_detach_p = NULL; @@ -821,10 +801,15 @@ ng_ether_mod_event(module_t mod, int event, void *data) return (error); } -static int ng_ether_iattach(const void *unused) +static void +vnet_ng_ether_init(const void *unused) { struct ifnet *ifp; + /* If module load was rejected, don't attach to vnets. */ + if (ng_ether_attach_p != ng_ether_attach) + return; + /* Create nodes for any already-existing Ethernet interfaces. */ IFNET_RLOCK(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { @@ -833,6 +818,6 @@ static int ng_ether_iattach(const void *unused) ng_ether_attach(ifp); } IFNET_RUNLOCK(); - - return (0); } +VNET_SYSINIT(vnet_ng_ether_init, SI_SUB_PSEUDO, SI_ORDER_ANY, + vnet_ng_ether_init, NULL); diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c index 6ed1daf6170..49cba258080 100644 --- a/sys/netgraph/ng_iface.c +++ b/sys/netgraph/ng_iface.c @@ -76,6 +76,7 @@ #include #include #include +#include #include @@ -209,22 +210,9 @@ static struct ng_type typestruct = { }; NETGRAPH_INIT(iface, &typestruct); -static vnet_attach_fn ng_iface_iattach; -static vnet_detach_fn ng_iface_idetach; - static VNET_DEFINE(struct unrhdr *, ng_iface_unit); #define V_ng_iface_unit VNET(ng_iface_unit) -#ifdef VIMAGE -static vnet_modinfo_t vnet_ng_iface_modinfo = { - .vmi_id = VNET_MOD_NG_IFACE, - .vmi_name = "ng_iface", - .vmi_dependson = VNET_MOD_NETGRAPH, - .vmi_iattach = ng_iface_iattach, - .vmi_idetach = ng_iface_idetach -}; -#endif - /************************************************************************ HELPER STUFF ************************************************************************/ @@ -849,18 +837,7 @@ ng_iface_mod_event(module_t mod, int event, void *data) switch (event) { case MOD_LOAD: -#ifdef VIMAGE - vnet_mod_register(&vnet_ng_iface_modinfo); -#else - ng_iface_iattach(NULL); -#endif - break; case MOD_UNLOAD: -#ifdef VIMAGE - vnet_mod_deregister(&vnet_ng_iface_modinfo); -#else - ng_iface_idetach(NULL); -#endif break; default: error = EOPNOTSUPP; @@ -869,18 +846,20 @@ ng_iface_mod_event(module_t mod, int event, void *data) return (error); } -static int ng_iface_iattach(const void *unused) +static void +vnet_ng_iface_init(const void *unused) { V_ng_iface_unit = new_unrhdr(0, 0xffff, NULL); - - return (0); } +VNET_SYSINIT(vnet_ng_iface_init, SI_SUB_PSEUDO, SI_ORDER_ANY, + vnet_ng_iface_init, NULL); -static int ng_iface_idetach(const void *unused) +static void +vnet_ng_iface_uninit(const void *unused) { delete_unrhdr(V_ng_iface_unit); - - return (0); } +VNET_SYSUNINIT(vnet_ng_iface_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, + vnet_ng_iface_uninit, NULL); diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index 0d59979a5fd..af68c636d9b 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -67,6 +67,9 @@ #ifdef NOTYET #include #endif + +#include + #include #include #include @@ -1112,17 +1115,12 @@ ngs_mod_event(module_t mod, int event, void *data) switch (event) { case MOD_LOAD: - /* Register protocol domain. */ - net_add_domain(&ngdomain); break; case MOD_UNLOAD: #ifdef NOTYET /* Unregister protocol domain XXX can't do this yet.. */ - if ((error = net_rm_domain(&ngdomain)) != 0) - break; - else #endif - error = EBUSY; + error = EBUSY; break; default: error = EOPNOTSUPP; @@ -1131,6 +1129,8 @@ ngs_mod_event(module_t mod, int event, void *data) return (error); } +VNET_DOMAIN_SET(ng); + SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, ""); SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA"); SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, ""); diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 2c7ed2ee746..44796def2bb 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -114,7 +114,6 @@ static char * igmp_rec_type_to_str(const int); #endif static void igmp_set_version(struct igmp_ifinfo *, const int); static void igmp_slowtimo_vnet(void); -static void igmp_sysinit(void); static int igmp_v1v2_queue_report(struct in_multi *, const int); static void igmp_v1v2_process_group_timer(struct in_multi *, const int); static void igmp_v1v2_process_querier_timers(struct igmp_ifinfo *); @@ -137,9 +136,6 @@ static int sysctl_igmp_default_version(SYSCTL_HANDLER_ARGS); static int sysctl_igmp_gsr(SYSCTL_HANDLER_ARGS); static int sysctl_igmp_ifinfo(SYSCTL_HANDLER_ARGS); -static vnet_attach_fn vnet_igmp_iattach; -static vnet_detach_fn vnet_igmp_idetach; - static const struct netisr_handler igmp_nh = { .nh_name = "igmp", .nh_handler = igmp_intr, @@ -3580,7 +3576,7 @@ igmp_rec_type_to_str(const int type) #endif static void -igmp_sysinit(void) +igmp_init(void *unused __unused) { CTR1(KTR_IGMPV3, "%s: initializing", __func__); @@ -3591,9 +3587,10 @@ igmp_sysinit(void) netisr_register(&igmp_nh); } +SYSINIT(igmp_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, igmp_init, NULL); static void -igmp_sysuninit(void) +igmp_uninit(void *unused __unused) { CTR1(KTR_IGMPV3, "%s: tearing down", __func__); @@ -3605,42 +3602,30 @@ igmp_sysuninit(void) IGMP_LOCK_DESTROY(); } +SYSUNINIT(igmp_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, igmp_uninit, NULL); -/* - * Initialize an IGMPv3 instance. - * VIMAGE: Assumes curvnet set by caller and called per vimage. - */ -static int -vnet_igmp_iattach(const void *unused __unused) +static void +vnet_igmp_init(const void *unused __unused) { CTR1(KTR_IGMPV3, "%s: initializing", __func__); LIST_INIT(&V_igi_head); - - return (0); } +VNET_SYSINIT(vnet_igmp_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_igmp_init, + NULL); -static int -vnet_igmp_idetach(const void *unused __unused) +static void +vnet_igmp_uninit(const void *unused __unused) { CTR1(KTR_IGMPV3, "%s: tearing down", __func__); KASSERT(LIST_EMPTY(&V_igi_head), ("%s: igi list not empty; ifnets not detached?", __func__)); - - return (0); } - -#ifdef VIMAGE -static vnet_modinfo_t vnet_igmp_modinfo = { - .vmi_id = VNET_MOD_IGMP, - .vmi_name = "igmp", - .vmi_iattach = vnet_igmp_iattach, - .vmi_idetach = vnet_igmp_idetach -}; -#endif +VNET_SYSUNINIT(vnet_igmp_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, + vnet_igmp_uninit, NULL); static int igmp_modevent(module_t mod, int type, void *unused __unused) @@ -3648,20 +3633,7 @@ igmp_modevent(module_t mod, int type, void *unused __unused) switch (type) { case MOD_LOAD: - igmp_sysinit(); -#ifdef VIMAGE - vnet_mod_register(&vnet_igmp_modinfo); -#else - vnet_igmp_iattach(NULL); -#endif - break; case MOD_UNLOAD: -#ifdef VIMAGE - vnet_mod_deregister(&vnet_igmp_modinfo); -#else - vnet_igmp_idetach(NULL); -#endif - igmp_sysuninit(); break; default: return (EOPNOTSUPP); diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 8384600e34f..bf3c7132e4a 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -383,7 +383,7 @@ struct domain inetdomain = { .dom_ifdetach = in_domifdetach }; -DOMAIN_SET(inet); +VNET_DOMAIN_SET(inet); SYSCTL_NODE(_net, PF_INET, inet, CTLFLAG_RW, 0, "Internet Family"); diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 57253f73546..8c4094d9d25 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -375,7 +375,7 @@ struct domain inet6domain = { .dom_ifdetach = in6_domifdetach }; -DOMAIN_SET(inet6); +VNET_DOMAIN_SET(inet6); /* * Internet configuration info diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c index f47671e7b87..e23dea3cc1c 100644 --- a/sys/netinet6/mld6.c +++ b/sys/netinet6/mld6.c @@ -117,8 +117,6 @@ static char * mld_rec_type_to_str(const int); #endif static void mld_set_version(struct mld_ifinfo *, const int); static void mld_slowtimo_vnet(void); -static void mld_sysinit(void); -static void mld_sysuninit(void); static int mld_v1_input_query(struct ifnet *, const struct ip6_hdr *, /*const*/ struct mld_hdr *); static int mld_v1_input_report(struct ifnet *, const struct ip6_hdr *, @@ -147,9 +145,6 @@ static int mld_v2_process_group_query(struct in6_multi *, static int sysctl_mld_gsr(SYSCTL_HANDLER_ARGS); static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS); -static vnet_attach_fn vnet_mld_iattach; -static vnet_detach_fn vnet_mld_idetach; - /* * Normative references: RFC 2710, RFC 3590, RFC 3810. * @@ -3201,7 +3196,7 @@ mld_rec_type_to_str(const int type) #endif static void -mld_sysinit(void) +mld_init(void *unused __unused) { CTR1(KTR_MLD, "%s: initializing", __func__); @@ -3213,50 +3208,39 @@ mld_sysinit(void) 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); static void -mld_sysuninit(void) +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); -/* - * Initialize an MLDv2 instance. - * VIMAGE: Assumes curvnet set by caller and called per vimage. - */ -static int -vnet_mld_iattach(const void *unused __unused) +static void +vnet_mld_init(const void *unused __unused) { CTR1(KTR_MLD, "%s: initializing", __func__); LIST_INIT(&V_mli_head); - - return (0); } +VNET_SYSINIT(vnet_mld_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_init, + NULL); -static int -vnet_mld_idetach(const void *unused __unused) +static void +vnet_mld_uninit(const void *unused __unused) { CTR1(KTR_MLD, "%s: tearing down", __func__); KASSERT(LIST_EMPTY(&V_mli_head), ("%s: mli list not empty; ifnets not detached?", __func__)); - - return (0); } - -#ifdef VIMAGE -static vnet_modinfo_t vnet_mld_modinfo = { - .vmi_id = VNET_MOD_MLD, - .vmi_name = "mld", - .vmi_iattach = vnet_mld_iattach, - .vmi_idetach = vnet_mld_idetach -}; -#endif +VNET_SYSUNINIT(vnet_mld_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_uninit, + NULL); static int mld_modevent(module_t mod, int type, void *unused __unused) @@ -3264,20 +3248,7 @@ mld_modevent(module_t mod, int type, void *unused __unused) switch (type) { case MOD_LOAD: - mld_sysinit(); -#ifdef VIMAGE - vnet_mod_register(&vnet_mld_modinfo); -#else - vnet_mld_iattach(NULL); -#endif - break; case MOD_UNLOAD: -#ifdef VIMAGE - vnet_mod_deregister(&vnet_mld_modinfo); -#else - vnet_mld_idetach(NULL); -#endif - mld_sysuninit(); break; default: return (EOPNOTSUPP); diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index c393dce160d..07ae90edeb3 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -240,15 +240,6 @@ static void vshiftl __P((unsigned char *, int, int)); MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy"); -static int ipsec_iattach(const void *); -#ifdef VIMAGE -static const vnet_modinfo_t vnet_ipsec_modinfo = { - .vmi_id = VNET_MOD_IPSEC, - .vmi_name = "ipsec", - .vmi_iattach = ipsec_iattach, -}; -#endif - /* * Return a held reference to the default SP. */ @@ -1711,27 +1702,14 @@ ipsec_dumpmbuf(struct mbuf *m) } static void -ipsec_attach(const void *unused __unused) -{ - -#ifdef VIMAGE - vnet_mod_register(&vnet_ipsec_modinfo); -#else - ipsec_iattach(NULL); -#endif -} - -static int -ipsec_iattach(const void *unused __unused) +ipsec_init(const void *unused __unused) { SECPOLICY_LOCK_INIT(&V_ip4_def_policy); V_ip4_def_policy.refcnt = 1; /* NB: disallow free. */ - - return (0); } - -SYSINIT(ipsec, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, ipsec_attach, NULL); +VNET_SYSINIT(ipsec_init, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, ipsec_init, + NULL); /* XXX This stuff doesn't belong here... */ diff --git a/sys/netipsec/keysock.c b/sys/netipsec/keysock.c index c35a3bd8de2..a8fbd5e9ebb 100644 --- a/sys/netipsec/keysock.c +++ b/sys/netipsec/keysock.c @@ -580,4 +580,4 @@ struct domain keydomain = { .dom_protoswNPROTOSW = &keysw[sizeof(keysw)/sizeof(keysw[0])] }; -DOMAIN_SET(key); +VNET_DOMAIN_SET(key); diff --git a/sys/sys/domain.h b/sys/sys/domain.h index 431429ef1a9..2563cb6e05c 100644 --- a/sys/sys/domain.h +++ b/sys/sys/domain.h @@ -76,11 +76,31 @@ struct domain { #ifdef _KERNEL extern int domain_init_status; extern struct domain *domains; -extern void net_add_domain(void *); +void domain_add(void *); +void domain_init(void *); +#ifdef VIMAGE +void vnet_domain_init(void *); +void vnet_domain_uninit(void *); +#endif -#define DOMAIN_SET(name) \ - SYSINIT(domain_ ## name, SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, net_add_domain, & name ## domain) +#define DOMAIN_SET(name) \ + SYSINIT(domain_add_ ## name, SI_SUB_PROTO_DOMAIN, \ + SI_ORDER_FIRST, domain_add, & name ## domain); \ + SYSINIT(domain_init_ ## name, SI_SUB_PROTO_DOMAIN, \ + SI_ORDER_SECOND, domain_init, & name ## domain); +#ifdef VIMAGE +#define VNET_DOMAIN_SET(name) \ + SYSINIT(domain_add_ ## name, SI_SUB_PROTO_DOMAIN, \ + SI_ORDER_FIRST, domain_add, & name ## domain); \ + VNET_SYSINIT(vnet_domain_init_ ## name, SI_SUB_PROTO_DOMAIN, \ + SI_ORDER_SECOND, vnet_domain_init, & name ## domain); \ + VNET_SYSUNINIT(vnet_domain_uninit_ ## name, \ + SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, vnet_domain_uninit, \ + & name ## domain) +#else /* !VIMAGE */ +#define VNET_DOMAIN_SET(name) DOMAIN_SET(name) +#endif /* VIMAGE */ -#endif +#endif /* _KERNEL */ -#endif +#endif /* !_SYS_DOMAIN_H_ */ diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 87a4bfea569..5461dfd2b96 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -147,6 +147,7 @@ enum sysinit_sub_id { SI_SUB_EXEC = 0x7400000, /* execve() handlers */ SI_SUB_PROTO_BEGIN = 0x8000000, /* XXX: set splimp (kludge)*/ SI_SUB_PROTO_IF = 0x8400000, /* interfaces*/ + SI_SUB_PROTO_DOMAININIT = 0x8600000, /* domain registration system */ SI_SUB_PROTO_DOMAIN = 0x8800000, /* domains (address families?)*/ SI_SUB_PROTO_IFATTACHDOMAIN = 0x8800001, /* domain dependent data init*/ SI_SUB_PROTO_END = 0x8ffffff, /* XXX: set splx (kludge)*/ @@ -178,6 +179,7 @@ enum sysinit_elem_order { SI_ORDER_FIRST = 0x0000000, /* first*/ SI_ORDER_SECOND = 0x0000001, /* second*/ SI_ORDER_THIRD = 0x0000002, /* third*/ + SI_ORDER_FOURTH = 0x0000003, /* fourth*/ SI_ORDER_MIDDLE = 0x1000000, /* somewhere in the middle */ SI_ORDER_ANY = 0xfffffff /* last*/ }; diff --git a/sys/sys/vimage.h b/sys/sys/vimage.h index 41a7d9c3fc2..9dd0e5fef42 100644 --- a/sys/sys/vimage.h +++ b/sys/sys/vimage.h @@ -63,69 +63,11 @@ struct vnet { #define VNET_DEBUG #endif -struct vnet; -struct ifnet; - -typedef int vnet_attach_fn(const void *); -typedef int vnet_detach_fn(const void *); - #ifdef VIMAGE -struct vnet_modinfo { - u_int vmi_id; - u_int vmi_dependson; - char *vmi_name; - vnet_attach_fn *vmi_iattach; - vnet_detach_fn *vmi_idetach; -}; -typedef struct vnet_modinfo vnet_modinfo_t; - -struct vnet_modlink { - TAILQ_ENTRY(vnet_modlink) vml_mod_le; - const struct vnet_modinfo *vml_modinfo; - const void *vml_iarg; - const char *vml_iname; -}; - -/* Stateful modules. */ -#define VNET_MOD_NET 0 /* MUST be 0 - implicit dependency */ -#define VNET_MOD_NETGRAPH 1 -#define VNET_MOD_INET 2 -#define VNET_MOD_INET6 3 -#define VNET_MOD_IPSEC 4 -#define VNET_MOD_IPFW 5 -#define VNET_MOD_DUMMYNET 6 -#define VNET_MOD_PF 7 -#define VNET_MOD_ALTQ 8 -#define VNET_MOD_IPX 9 -#define VNET_MOD_ATALK 10 -#define VNET_MOD_ACCF_HTTP 11 -#define VNET_MOD_IGMP 12 -#define VNET_MOD_MLD 13 -#define VNET_MOD_RTABLE 14 - -/* Stateless modules. */ -#define VNET_MOD_IF_CLONE 19 -#define VNET_MOD_NG_ETHER 20 -#define VNET_MOD_NG_IFACE 21 -#define VNET_MOD_NG_EIFACE 22 -#define VNET_MOD_ESP 23 -#define VNET_MOD_IPIP 24 -#define VNET_MOD_AH 25 -#define VNET_MOD_IPCOMP 26 -#define VNET_MOD_GIF 27 - /* 28 */ -#define VNET_MOD_FLOWTABLE 29 -#define VNET_MOD_LOIF 30 -#define VNET_MOD_DOMAIN 31 -#define VNET_MOD_DYNAMIC_START 32 -#define VNET_MOD_MAX 64 - +struct vnet; +struct ifnet; int vi_if_move(struct thread *, struct ifnet *, char *, int); -void vnet_mod_register(const struct vnet_modinfo *); -void vnet_mod_register_multi(const struct vnet_modinfo *, void *, char *); -void vnet_mod_deregister(const struct vnet_modinfo *); -void vnet_mod_deregister_multi(const struct vnet_modinfo *, void *, char *); struct vnet *vnet_alloc(void); void vnet_destroy(struct vnet *); void vnet_foreach(void (*vnet_foreach_fn)(struct vnet *, void *), -- 2.45.0