nvass-gmx.com updated this revision to Diff 5290.
nvass-gmx.com added a comment.

Hi,

Please review this. It updates the previous patch, with another way to unload 
pf.

Eventhandlers are also touched, they should behave correctly now.


CHANGES SINCE LAST UPDATE
  https://reviews.freebsd.org/D1944?vs=3915&id=5290

REVISION DETAIL
  https://reviews.freebsd.org/D1944

AFFECTED FILES
  sys/net/pfvar.h
  sys/netpfil/pf/pf.c
  sys/netpfil/pf/pf_if.c
  sys/netpfil/pf/pf_ioctl.c
  sys/netpfil/pf/pf_norm.c

EMAIL PREFERENCES
  https://reviews.freebsd.org/settings/panel/emailpreferences/

To: nvass-gmx.com, bz, zec, trociny, glebius, rodrigc, kristof, gnn
Cc: robak, freebsd-virtualization, freebsd-pf, freebsd-net
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -34,6 +34,7 @@
 #include "opt_pf.h"
 
 #include <sys/param.h>
+#include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
@@ -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
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -87,7 +87,8 @@
 #include <net/altq/altq.h>
 #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
diff --git a/sys/netpfil/pf/pf_if.c b/sys/netpfil/pf/pf_if.c
--- a/sys/netpfil/pf/pf_if.c
+++ b/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
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/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();
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/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 *);

_______________________________________________
freebsd-virtualization@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-virtualization
To unsubscribe, send any mail to 
"freebsd-virtualization-unsubscr...@freebsd.org"

Reply via email to