From owner-freebsd-virtualization@FreeBSD.ORG Sun Aug 11 20:01:20 2013 Return-Path: Delivered-To: freebsd-virtualization@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 3F0233ED for ; Sun, 11 Aug 2013 20:01:20 +0000 (UTC) (envelope-from to.my.trociny@gmail.com) Received: from mail-la0-x236.google.com (mail-la0-x236.google.com [IPv6:2a00:1450:4010:c03::236]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 9D41B2562 for ; Sun, 11 Aug 2013 20:01:19 +0000 (UTC) Received: by mail-la0-f54.google.com with SMTP id ea20so4250717lab.27 for ; Sun, 11 Aug 2013 13:01:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; bh=m95fzA9Mn03JSU4ZpDdV/CTkok6QSysg/FI7CsAPQiM=; b=YUteQ65AMYeg1a/GCXRAPi0rlpObIWpcYB3QA7JyDKPcBga6O7Jm4/MUBa7E67LcyW k0R0G/Pfosbrl8x7M4voHru3du6tv9ao1an5KMlFwApMcWv3kVyPDdJTZpczZDFUD4QA 03mS4qtXfdU30z6eROpCK65cyDFxbUUzraUXGQmS0MYwGV7g3Jd84hmPil4JFnrKQigk mO913mAPMyeUx1JCuEIno68560djChyUxxIwfp7da2MTJwQrqNpz6DUlVi4NaiOXn/PJ 0W0k5yOOhNuxhkHg5hH5OHPiLLjohqZfIQjTtEmV00SvuBuGOlod0AzNlicpo1jH/m1H TdRQ== X-Received: by 10.112.50.72 with SMTP id a8mr8316283lbo.50.1376251277492; Sun, 11 Aug 2013 13:01:17 -0700 (PDT) Received: from localhost ([178.150.115.244]) by mx.google.com with ESMTPSA id k6sm10549279lae.9.2013.08.11.13.01.15 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 11 Aug 2013 13:01:16 -0700 (PDT) Sender: Mikolaj Golub Date: Sun, 11 Aug 2013 23:01:12 +0300 From: Mikolaj Golub To: freebsd-virtualization@freebsd.org Subject: RFC: ipfw nat VIMAGE improvements Message-ID: <20130811200111.GA49895@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="mP3DRpeJDSE+ciuQ" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Cc: Marko Zec X-BeenThere: freebsd-virtualization@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Discussion of various virtualization techniques FreeBSD supports." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 Aug 2013 20:01:20 -0000 --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 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 /* 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--