Index: sys/net/pfvar.h =================================================================== --- sys/net/pfvar.h +++ sys/net/pfvar.h @@ -1494,7 +1494,9 @@ VNET_DECLARE(struct pf_rulequeue, pf_unlinked_rules); #define V_pf_unlinked_rules VNET(pf_unlinked_rules) -void pf_initialize(void); +void pf_init_eventhandlers(void); +void pf_uninit_eventhandlers(void); +void pf_vnet_initialize(void); void pf_mtag_initialize(void); void pf_mtag_cleanup(void); void pf_cleanup(void); @@ -1590,7 +1592,7 @@ struct pf_addr *, sa_family_t); int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); -void pf_normalize_init(void); +void pf_vnet_normalize_init(void); void pf_normalize_cleanup(void); int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *, struct pf_pdesc *); @@ -1648,7 +1650,7 @@ VNET_DECLARE(struct pfi_kif *, pfi_all); #define V_pfi_all VNET(pfi_all) -void pfi_initialize(void); +void pfi_vnet_initialize(void); void pfi_cleanup(void); void pfi_kif_ref(struct pfi_kif *); void pfi_kif_unref(struct pfi_kif *); Index: sys/netpfil/pf/pf.c =================================================================== --- sys/netpfil/pf/pf.c +++ sys/netpfil/pf/pf.c @@ -151,6 +151,7 @@ #define V_pf_sendqueue VNET(pf_sendqueue) static struct mtx pf_sendqueue_mtx; +MTX_SYSINIT(pf_sendqueue_mtx, &pf_sendqueue_mtx, "pf send queue", MTX_DEF); #define PF_SENDQ_LOCK() mtx_lock(&pf_sendqueue_mtx) #define PF_SENDQ_UNLOCK() mtx_unlock(&pf_sendqueue_mtx) @@ -172,11 +173,16 @@ #define V_pf_overloadtask VNET(pf_overloadtask) static struct mtx pf_overloadqueue_mtx; +MTX_SYSINIT(pf_overloadqueue_mtx, &pf_overloadqueue_mtx, + "pf overload/flush queue", MTX_DEF); + #define PF_OVERLOADQ_LOCK() mtx_lock(&pf_overloadqueue_mtx) #define PF_OVERLOADQ_UNLOCK() mtx_unlock(&pf_overloadqueue_mtx) VNET_DEFINE(struct pf_rulequeue, pf_unlinked_rules); struct mtx pf_unlnkdrules_mtx; +MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules", + MTX_DEF); static VNET_DEFINE(uma_zone_t, pf_sources_z); #define V_pf_sources_z VNET(pf_sources_z) @@ -749,7 +755,7 @@ /* Per-vnet data storage structures initialization. */ void -pf_initialize() +pf_vnet_initialize() { struct pf_keyhash *kh; struct pf_idhash *ih; @@ -809,13 +815,9 @@ STAILQ_INIT(&V_pf_sendqueue); SLIST_INIT(&V_pf_overloadqueue); TASK_INIT(&V_pf_overloadtask, 0, pf_overload_task, curvnet); - mtx_init(&pf_sendqueue_mtx, "pf send queue", NULL, MTX_DEF); - mtx_init(&pf_overloadqueue_mtx, "pf overload/flush queue", NULL, - MTX_DEF); /* Unlinked, but may be referenced rules. */ TAILQ_INIT(&V_pf_unlinked_rules); - mtx_init(&pf_unlnkdrules_mtx, "pf unlinked rules", NULL, MTX_DEF); } void @@ -858,10 +860,6 @@ free(pfse, M_PFTEMP); } - mtx_destroy(&pf_sendqueue_mtx); - mtx_destroy(&pf_overloadqueue_mtx); - mtx_destroy(&pf_unlnkdrules_mtx); - uma_zdestroy(V_pf_sources_z); uma_zdestroy(V_pf_state_z); uma_zdestroy(V_pf_state_key_z); @@ -1448,7 +1446,6 @@ PF_RULES_RLOCK(); V_pf_end_threads++; PF_RULES_RUNLOCK(); - wakeup(pf_purge_thread); kproc_exit(0); } PF_RULES_RUNLOCK(); Index: sys/netpfil/pf/pf_if.c =================================================================== --- sys/netpfil/pf/pf_if.c +++ sys/netpfil/pf/pf_if.c @@ -103,9 +103,11 @@ static VNET_DEFINE(struct pfi_list, pfi_unlinked_kifs); #define V_pfi_unlinked_kifs VNET(pfi_unlinked_kifs) static struct mtx pfi_unlnkdkifs_mtx; +MTX_SYSINIT(pfi_unlnkdkifs_mtx, &pfi_unlnkdkifs_mtx, "pf unlinked interfaces", + MTX_DEF); void -pfi_initialize(void) +pfi_vnet_initialize(void) { struct ifg_group *ifg; struct ifnet *ifp; @@ -115,8 +117,6 @@ V_pfi_buffer = malloc(V_pfi_buffer_max * sizeof(*V_pfi_buffer), PFI_MTYPE, M_WAITOK); - mtx_init(&pfi_unlnkdkifs_mtx, "pf unlinked interfaces", NULL, MTX_DEF); - kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); PF_RULES_WLOCK(); V_pfi_all = pfi_kif_attach(kif, IFG_ALL); @@ -123,16 +123,24 @@ PF_RULES_WUNLOCK(); IFNET_RLOCK(); - TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) + TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) { pfi_attach_ifgroup(ifg); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) + } + TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CURVNET_SET(ifp->if_vnet); pfi_attach_ifnet(ifp); + CURVNET_RESTORE(); + } IFNET_RUNLOCK(); +} +void +pf_init_eventhandlers(void) { + pfi_attach_cookie = EVENTHANDLER_REGISTER(ifnet_arrival_event, - pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); + pfi_attach_ifnet_event, curvnet, EVENTHANDLER_PRI_ANY); pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event, - pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); + pfi_detach_ifnet_event, curvnet, EVENTHANDLER_PRI_ANY); pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event, pfi_attach_group_event, curvnet, EVENTHANDLER_PRI_ANY); pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event, @@ -140,13 +148,11 @@ pfi_detach_group_cookie = EVENTHANDLER_REGISTER(group_detach_event, pfi_detach_group_event, curvnet, EVENTHANDLER_PRI_ANY); pfi_ifaddr_event_cookie = EVENTHANDLER_REGISTER(ifaddr_event, - pfi_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY); + pfi_ifaddr_event, curvnet, EVENTHANDLER_PRI_ANY); } void -pfi_cleanup(void) -{ - struct pfi_kif *p; +pf_uninit_eventhandlers(void) { EVENTHANDLER_DEREGISTER(ifnet_arrival_event, pfi_attach_cookie); EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfi_detach_cookie); @@ -154,7 +160,13 @@ EVENTHANDLER_DEREGISTER(group_change_event, pfi_change_group_cookie); EVENTHANDLER_DEREGISTER(group_detach_event, pfi_detach_group_cookie); EVENTHANDLER_DEREGISTER(ifaddr_event, pfi_ifaddr_event_cookie); +} +void +pfi_cleanup(void) +{ + struct pfi_kif *p; + V_pfi_all = NULL; while ((p = RB_MIN(pfi_ifhead, &V_pfi_ifs))) { RB_REMOVE(pfi_ifhead, &V_pfi_ifs, p); @@ -166,8 +178,6 @@ free(p, PFI_MTYPE); } - mtx_destroy(&pfi_unlnkdkifs_mtx); - free(V_pfi_buffer, PFI_MTYPE); } @@ -813,9 +823,7 @@ pfi_attach_group_event(void *arg , struct ifg_group *ifg) { - CURVNET_SET((struct vnet *)arg); pfi_attach_ifgroup(ifg); - CURVNET_RESTORE(); } static void @@ -825,13 +833,11 @@ kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); - CURVNET_SET((struct vnet *)arg); PF_RULES_WLOCK(); V_pfi_update++; kif = pfi_kif_attach(kif, gname); pfi_kif_update(kif); PF_RULES_WUNLOCK(); - CURVNET_RESTORE(); } static void Index: sys/netpfil/pf/pf_ioctl.c =================================================================== --- sys/netpfil/pf/pf_ioctl.c +++ sys/netpfil/pf/pf_ioctl.c @@ -87,7 +87,8 @@ #include #endif -static int pfattach(void); +static int pf_vnet_init(void); +static int pf_vnet_uninit(void); static struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t, u_int8_t, u_int8_t, u_int8_t); @@ -149,6 +150,7 @@ #define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x struct cdev *pf_dev; +int number_of_vnets = 0; /* * XXX - These are new and need to be checked when moveing to a new version @@ -205,17 +207,16 @@ pflog_packet_t *pflog_packet_ptr = NULL; static int -pfattach(void) +pf_vnet_init(void) { u_int32_t *my_timeout = V_pf_default_rule.timeout; int error; - if (IS_DEFAULT_VNET(curvnet)) - pf_mtag_initialize(); - pf_initialize(); + number_of_vnets++; + pf_vnet_initialize(); pfr_initialize(); - pfi_initialize(); - pf_normalize_init(); + pfi_vnet_initialize(); + pf_vnet_normalize_init(); V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT; V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT; @@ -287,7 +288,63 @@ return (0); } +VNET_SYSINIT(pf_vnet_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY - 255, + pf_vnet_init, NULL); +static int +pf_vnet_uninit(void) +{ + int error = 0; + + number_of_vnets--; + KASSERT(number_of_vnets >= 0, ("number of vnets < 0")); + + PF_RULES_RLOCK(); + V_pf_end_threads++; + PF_RULES_RUNLOCK(); + wakeup(pf_purge_thread); + while (V_pf_end_threads < 2) + pause("pfunld", hz / 9); + + V_pf_status.running = 0; + swi_remove(V_pf_swi_cookie); + error = dehook_pf(); + if (error) { + /* + * Should not happen! + * XXX Due to error code ESRCH, kldunload will show + * a message like 'No such process'. + */ + printf("%s : pfil unregisteration fail\n", __FUNCTION__); + return error; + } + PF_RULES_WLOCK(); + shutdown_pf(); + pf_normalize_cleanup(); + pfi_cleanup(); + pfr_cleanup(); + pf_osfp_flush(); + pf_cleanup(); + + /* + * For the last VNET we perform the final cleanup + */ + if (number_of_vnets == 0) { + pf_uninit_eventhandlers(); + pf_mtag_cleanup(); + } + PF_RULES_WUNLOCK(); + if (number_of_vnets == 0) { + destroy_dev(pf_dev); + rw_destroy(&pf_rules_lock); + sx_destroy(&pf_ioctl_lock); + } + + return (error); +} +VNET_SYSUNINIT(pf_vnet_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY - 255, + pf_vnet_uninit, NULL); + static struct pf_pool * pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action, u_int32_t rule_number, u_int8_t r_last, u_int8_t active, @@ -3707,27 +3764,12 @@ static int pf_load(void) { - int error; - VNET_ITERATOR_DECL(vnet_iter); - - VNET_LIST_RLOCK(); - VNET_FOREACH(vnet_iter) { - CURVNET_SET(vnet_iter); - V_pf_pfil_hooked = 0; - V_pf_end_threads = 0; - TAILQ_INIT(&V_pf_tags); - TAILQ_INIT(&V_pf_qids); - CURVNET_RESTORE(); - } - VNET_LIST_RUNLOCK(); - rw_init(&pf_rules_lock, "pf rulesets"); sx_init(&pf_ioctl_lock, "pf ioctl"); - pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME); - if ((error = pfattach()) != 0) - return (error); + pf_mtag_initialize(); + pf_init_eventhandlers(); return (0); } @@ -3735,40 +3777,8 @@ static int pf_unload(void) { - int error = 0; - V_pf_status.running = 0; - swi_remove(V_pf_swi_cookie); - error = dehook_pf(); - if (error) { - /* - * Should not happen! - * XXX Due to error code ESRCH, kldunload will show - * a message like 'No such process'. - */ - printf("%s : pfil unregisteration fail\n", __FUNCTION__); - return error; - } - PF_RULES_WLOCK(); - shutdown_pf(); - V_pf_end_threads = 1; - while (V_pf_end_threads < 2) { - wakeup_one(pf_purge_thread); - rw_sleep(pf_purge_thread, &pf_rules_lock, 0, "pftmo", 0); - } - pf_normalize_cleanup(); - pfi_cleanup(); - pfr_cleanup(); - pf_osfp_flush(); - pf_cleanup(); - if (IS_DEFAULT_VNET(curvnet)) - pf_mtag_cleanup(); - PF_RULES_WUNLOCK(); - destroy_dev(pf_dev); - rw_destroy(&pf_rules_lock); - sx_destroy(&pf_ioctl_lock); - - return (error); + return (0); } static int Index: sys/netpfil/pf/pf_norm.c =================================================================== --- sys/netpfil/pf/pf_norm.c +++ sys/netpfil/pf/pf_norm.c @@ -34,6 +34,7 @@ #include "opt_pf.h" #include +#include #include #include #include @@ -108,6 +109,7 @@ }; static struct mtx pf_frag_mtx; +MTX_SYSINIT(pf_frag_mtx, &pf_frag_mtx, "pf fragments", MTX_DEF); #define PF_FRAG_LOCK() mtx_lock(&pf_frag_mtx) #define PF_FRAG_UNLOCK() mtx_unlock(&pf_frag_mtx) #define PF_FRAG_ASSERT() mtx_assert(&pf_frag_mtx, MA_OWNED) @@ -181,7 +183,7 @@ #endif /* INET */ void -pf_normalize_init(void) +pf_vnet_normalize_init(void) { V_pf_frag_z = uma_zcreate("pf frags", sizeof(struct pf_fragment), @@ -197,8 +199,6 @@ uma_zone_set_max(V_pf_frent_z, PFFRAG_FRENT_HIWAT); uma_zone_set_warning(V_pf_frent_z, "PF frag entries limit reached"); - mtx_init(&pf_frag_mtx, "pf fragments", NULL, MTX_DEF); - TAILQ_INIT(&V_pf_fragqueue); TAILQ_INIT(&V_pf_cachequeue); } @@ -210,8 +210,6 @@ uma_zdestroy(V_pf_state_scrub_z); uma_zdestroy(V_pf_frent_z); uma_zdestroy(V_pf_frag_z); - - mtx_destroy(&pf_frag_mtx); } static int