Date: Sun, 11 Aug 2013 23:01:12 +0300 From: Mikolaj Golub <trociny@FreeBSD.org> To: freebsd-virtualization@freebsd.org Cc: Marko Zec <zec@fer.hr> Subject: RFC: ipfw nat VIMAGE improvements Message-ID: <20130811200111.GA49895@gmail.com>
next in thread | raw e-mail | index | archive | help
--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
I would like to commit this patch that fixes some issues related to
ipfw nat module load/unload on VIMAGE featured system.
Any comments, objections?
--
Mikolaj Golub
--mP3DRpeJDSE+ciuQ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: inline; filename="ip_fw_nat.c.VIMAGE.1.patch"
commit 47338ad7fea6d0280461562f0345570557b0d9b1
Author: Mikolaj Golub <trociny@freebsd.org>
Date: Sun Aug 4 13:49:50 2013 +0300
Make ipfw nat init/unint work correctly for VIMAGE:
* Do per vnet instance cleanup (previously it was only for vnet0 on
module unload, and led to libalias leaks and possible panics due to
stale pointer dereferences).
* When registering/deregistering ipfw hooks lock all vnets, not only
vnet0.
* Devirtualize ifaddr_event_tag as we run only one event handler for
all vnets.
* It is supposed that ifaddr_change event handler is called in the
interface vnet context, so add the assertion.
diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c
index 84852db..0f34f1d 100644
--- a/sys/netpfil/ipfw/ip_fw_nat.c
+++ b/sys/netpfil/ipfw/ip_fw_nat.c
@@ -53,8 +53,7 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h> /* XXX for in_cksum */
-static VNET_DEFINE(eventhandler_tag, ifaddr_event_tag);
-#define V_ifaddr_event_tag VNET(ifaddr_event_tag)
+static eventhandler_tag ifaddr_event_tag;
static void
ifaddr_change(void *arg __unused, struct ifnet *ifp)
@@ -63,6 +62,8 @@ ifaddr_change(void *arg __unused, struct ifnet *ifp)
struct ifaddr *ifa;
struct ip_fw_chain *chain;
+ KASSERT(curvnet == ifp->if_vnet,
+ ("curvnet(%p) differs from iface vnet(%p)", curvnet, ifp->if_vnet));
chain = &V_layer3_chain;
IPFW_WLOCK(chain);
/* Check every nat entry... */
@@ -589,20 +590,57 @@ ipfw_nat_get_log(struct sockopt *sopt)
return(0);
}
+static int
+vnet_ipfw_nat_init(const void *arg __unused)
+{
+
+ return (0);
+}
+
+static int
+vnet_ipfw_nat_uninit(const void *arg __unused)
+{
+ struct cfg_nat *ptr, *ptr_temp;
+ struct ip_fw_chain *chain;
+
+ chain = &V_layer3_chain;
+ IPFW_WLOCK(chain);
+ LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) {
+ LIST_REMOVE(ptr, _next);
+ del_redir_spool_cfg(ptr, &ptr->redir_chain);
+ LibAliasUninit(ptr->lib);
+ free(ptr, M_IPFW);
+ }
+ flush_nat_ptrs(chain, -1 /* flush all */);
+ IPFW_WUNLOCK(chain);
+ return (0);
+}
+
static void
ipfw_nat_init(void)
{
+ VNET_ITERATOR_DECL(vnet_iter);
- IPFW_WLOCK(&V_layer3_chain);
/* init ipfw hooks */
+ VNET_LIST_RLOCK();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ IPFW_WLOCK(&V_layer3_chain);
+ CURVNET_RESTORE();
+ }
ipfw_nat_ptr = ipfw_nat;
lookup_nat_ptr = lookup_nat;
ipfw_nat_cfg_ptr = ipfw_nat_cfg;
ipfw_nat_del_ptr = ipfw_nat_del;
ipfw_nat_get_cfg_ptr = ipfw_nat_get_cfg;
ipfw_nat_get_log_ptr = ipfw_nat_get_log;
- IPFW_WUNLOCK(&V_layer3_chain);
- V_ifaddr_event_tag = EVENTHANDLER_REGISTER(
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ IPFW_WUNLOCK(&V_layer3_chain);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK();
+ ifaddr_event_tag = EVENTHANDLER_REGISTER(
ifaddr_event, ifaddr_change,
NULL, EVENTHANDLER_PRI_ANY);
}
@@ -610,19 +648,15 @@ ipfw_nat_init(void)
static void
ipfw_nat_destroy(void)
{
- struct cfg_nat *ptr, *ptr_temp;
- struct ip_fw_chain *chain;
-
- chain = &V_layer3_chain;
- IPFW_WLOCK(chain);
- LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) {
- LIST_REMOVE(ptr, _next);
- del_redir_spool_cfg(ptr, &ptr->redir_chain);
- LibAliasUninit(ptr->lib);
- free(ptr, M_IPFW);
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_event_tag);
+ VNET_LIST_RLOCK();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ IPFW_WLOCK(&V_layer3_chain);
+ CURVNET_RESTORE();
}
- EVENTHANDLER_DEREGISTER(ifaddr_event, V_ifaddr_event_tag);
- flush_nat_ptrs(chain, -1 /* flush all */);
/* deregister ipfw_nat */
ipfw_nat_ptr = NULL;
lookup_nat_ptr = NULL;
@@ -630,7 +664,12 @@ ipfw_nat_destroy(void)
ipfw_nat_del_ptr = NULL;
ipfw_nat_get_cfg_ptr = NULL;
ipfw_nat_get_log_ptr = NULL;
- IPFW_WUNLOCK(chain);
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ IPFW_WUNLOCK(&V_layer3_chain);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK();
}
static int
@@ -640,11 +679,9 @@ ipfw_nat_modevent(module_t mod, int type, void *unused)
switch (type) {
case MOD_LOAD:
- ipfw_nat_init();
break;
case MOD_UNLOAD:
- ipfw_nat_destroy();
break;
default:
@@ -660,8 +697,25 @@ static moduledata_t ipfw_nat_mod = {
0
};
-DECLARE_MODULE(ipfw_nat, ipfw_nat_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+/* Define startup order. */
+#define IPFW_NAT_SI_SUB_FIREWALL SI_SUB_PROTO_IFATTACHDOMAIN
+#define IPFW_NAT_MODEVENT_ORDER (SI_ORDER_ANY - 255)
+#define IPFW_NAT_MODULE_ORDER (IPFW_NAT_MODEVENT_ORDER + 1)
+#define IPFW_NAT_VNET_ORDER (IPFW_NAT_MODEVENT_ORDER + 2)
+
+DECLARE_MODULE(ipfw_nat, ipfw_nat_mod, IPFW_NAT_SI_SUB_FIREWALL, SI_ORDER_ANY);
MODULE_DEPEND(ipfw_nat, libalias, 1, 1, 1);
MODULE_DEPEND(ipfw_nat, ipfw, 2, 2, 2);
MODULE_VERSION(ipfw_nat, 1);
+
+SYSINIT(ipfw_nat_init, IPFW_NAT_SI_SUB_FIREWALL, IPFW_NAT_MODULE_ORDER,
+ ipfw_nat_init, NULL);
+VNET_SYSINIT(vnet_ipfw_nat_init, IPFW_NAT_SI_SUB_FIREWALL, IPFW_NAT_VNET_ORDER,
+ vnet_ipfw_nat_init, NULL);
+
+SYSUNINIT(ipfw_nat_destroy, IPFW_NAT_SI_SUB_FIREWALL, IPFW_NAT_MODULE_ORDER,
+ ipfw_nat_destroy, NULL);
+VNET_SYSUNINIT(vnet_ipfw_nat_uninit, IPFW_NAT_SI_SUB_FIREWALL,
+ IPFW_NAT_VNET_ORDER, vnet_ipfw_nat_uninit, NULL);
+
/* end of file */
--mP3DRpeJDSE+ciuQ--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130811200111.GA49895>
