From owner-svn-src-all@FreeBSD.ORG Sun Mar 25 20:38:00 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 2A0291065687; Sun, 25 Mar 2012 20:38:00 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 12B388FC20; Sun, 25 Mar 2012 20:38:00 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2PKbxcL098624; Sun, 25 Mar 2012 20:37:59 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2PKbxhw098617; Sun, 25 Mar 2012 20:37:59 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201203252037.q2PKbxhw098617@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Sun, 25 Mar 2012 20:37:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r233478 - in head: sbin/ipfw sys/netinet sys/netinet/ipfw X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Mar 2012 20:38:00 -0000 Author: melifaro Date: Sun Mar 25 20:37:59 2012 New Revision: 233478 URL: http://svn.freebsd.org/changeset/base/233478 Log: - Permit number of ipfw tables to be changed in runtime. net.inet.ip.fw.tables_max is now read-write. - Bump IPFW_TABLES_MAX to 65535 Default number of tables is still 128 - Remove IPFW_TABLES_MAX from ipfw(8) code. Sponsored by Yandex LLC Approved by: kib(mentor) MFC after: 2 weeks Modified: head/sbin/ipfw/ipfw.8 head/sbin/ipfw/ipfw2.c head/sys/netinet/ip_fw.h head/sys/netinet/ipfw/ip_fw2.c head/sys/netinet/ipfw/ip_fw_private.h head/sys/netinet/ipfw/ip_fw_table.c Modified: head/sbin/ipfw/ipfw.8 ============================================================================== --- head/sbin/ipfw/ipfw.8 Sun Mar 25 20:09:02 2012 (r233477) +++ head/sbin/ipfw/ipfw.8 Sun Mar 25 20:37:59 2012 (r233478) @@ -2845,7 +2845,7 @@ node is not passed though the firewall a Otherwise, after an action, the packet is reinjected into the firewall at the next rule. .It Va net.inet.ip.fw.tables_max : No 128 -Maximum number of tables (read-only). +Maximum number of tables. .It Va net.inet.ip.fw.verbose : No 1 Enables verbose messages. .It Va net.inet.ip.fw.verbose_limit : No 0 Modified: head/sbin/ipfw/ipfw2.c ============================================================================== --- head/sbin/ipfw/ipfw2.c Sun Mar 25 20:09:02 2012 (r233477) +++ head/sbin/ipfw/ipfw2.c Sun Mar 25 20:37:59 2012 (r233478) @@ -3932,15 +3932,9 @@ ipfw_table_handler(int ac, char *av[]) len = sizeof(tables_max); if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len, - NULL, 0) == -1) { -#ifdef IPFW_TABLES_MAX - warn("Warn: Failed to get the max tables number via sysctl. " - "Using the compiled in defaults. \nThe reason was"); - tables_max = IPFW_TABLES_MAX; -#else - errx(1, "Failed sysctlbyname(\"net.inet.ip.fw.tables_max\")"); -#endif - } + NULL, 0) == -1) + errx(1, "Can't determine maximum number of ipfw tables. " + "Perhaps you forgot to load ipfw module?"); memset(&xent, 0, sizeof(xent)); Modified: head/sys/netinet/ip_fw.h ============================================================================== --- head/sys/netinet/ip_fw.h Sun Mar 25 20:09:02 2012 (r233477) +++ head/sys/netinet/ip_fw.h Sun Mar 25 20:37:59 2012 (r233478) @@ -39,7 +39,8 @@ /* * Default number of ipfw tables. */ -#define IPFW_TABLES_MAX 128 +#define IPFW_TABLES_MAX 65535 +#define IPFW_TABLES_DEFAULT 128 /* * Most commands (queue, pipe, tag, untag, limit...) can have a 16-bit Modified: head/sys/netinet/ipfw/ip_fw2.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw2.c Sun Mar 25 20:09:02 2012 (r233477) +++ head/sys/netinet/ipfw/ip_fw2.c Sun Mar 25 20:37:59 2012 (r233478) @@ -116,8 +116,9 @@ static int default_to_accept; VNET_DEFINE(int, autoinc_step); VNET_DEFINE(int, fw_one_pass) = 1; +VNET_DEFINE(unsigned int, fw_tables_max); /* Use 128 tables by default */ -int fw_tables_max = IPFW_TABLES_MAX; +static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT; /* * Each rule belongs to one of 32 different sets (0..31). @@ -148,6 +149,7 @@ ipfw_nat_cfg_t *ipfw_nat_get_log_ptr; #ifdef SYSCTL_NODE uint32_t dummy_def = IPFW_DEFAULT_RULE; +static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS); SYSBEGIN(f3) @@ -167,14 +169,14 @@ SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUT SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD, &dummy_def, 0, "The default/max possible rule number."); -SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD, - &V_fw_tables_max, 0, - "The maximum number of tables."); +SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, tables_max, + CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_ipfw_table_num, "IU", + "Maximum number of tables"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN, &default_to_accept, 0, "Make the default rule accept all packets."); TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept); -TUNABLE_INT("net.inet.ip.fw.tables_max", &V_fw_tables_max); +TUNABLE_INT("net.inet.ip.fw.tables_max", &default_fw_tables); SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count, CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0, "Number of static rules"); @@ -2488,6 +2490,26 @@ pullup_failed: } /* + * Set maximum number of tables that can be used in given VNET ipfw instance. + */ +#ifdef SYSCTL_NODE +static int +sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS) +{ + int error; + unsigned int ntables; + + ntables = V_fw_tables_max; + + error = sysctl_handle_int(oidp, &ntables, 0, req); + /* Read operation or some error */ + if ((error != 0) || (req->newptr == NULL)) + return (error); + + return (ipfw_resize_tables(&V_layer3_chain, ntables)); +} +#endif +/* * Module and VNET glue */ @@ -2543,6 +2565,10 @@ ipfw_init(void) printf("limited to %d packets/entry by default\n", V_verbose_limit); + /* Check user-supplied table count for validness */ + if (default_fw_tables > IPFW_TABLES_MAX) + default_fw_tables = IPFW_TABLES_MAX; + ipfw_log_bpf(1); /* init */ return (error); } @@ -2585,18 +2611,15 @@ vnet_ipfw_init(const void *unused) LIST_INIT(&chain->nat); #endif - /* Check user-supplied number for validness */ - if (V_fw_tables_max < 0) - V_fw_tables_max = IPFW_TABLES_MAX; - if (V_fw_tables_max > 65534) - V_fw_tables_max = 65534; - /* insert the default rule and create the initial map */ chain->n_rules = 1; chain->static_len = sizeof(struct ip_fw); chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO); if (chain->map) rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO); + + /* Set initial number of tables */ + V_fw_tables_max = default_fw_tables; error = ipfw_init_tables(chain); if (error) { printf("ipfw2: setting up tables failed\n"); Modified: head/sys/netinet/ipfw/ip_fw_private.h ============================================================================== --- head/sys/netinet/ipfw/ip_fw_private.h Sun Mar 25 20:09:02 2012 (r233477) +++ head/sys/netinet/ipfw/ip_fw_private.h Sun Mar 25 20:37:59 2012 (r233478) @@ -209,8 +209,8 @@ VNET_DECLARE(u_int32_t, set_disable); VNET_DECLARE(int, autoinc_step); #define V_autoinc_step VNET(autoinc_step) -extern int fw_tables_max; -#define V_fw_tables_max fw_tables_max +VNET_DECLARE(unsigned int, fw_tables_max); +#define V_fw_tables_max VNET(fw_tables_max) struct ip_fw_chain { struct ip_fw *rules; /* list of rules */ @@ -292,6 +292,7 @@ int ipfw_dump_table_entry(struct radix_n int ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl); int ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt); int ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl); +int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables); /* In ip_fw_nat.c -- XXX to be moved to ip_var.h */ Modified: head/sys/netinet/ipfw/ip_fw_table.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw_table.c Sun Mar 25 20:09:02 2012 (r233477) +++ head/sys/netinet/ipfw/ip_fw_table.c Sun Mar 25 20:37:59 2012 (r233478) @@ -460,6 +460,68 @@ ipfw_init_tables(struct ip_fw_chain *ch) } int +ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables) +{ + struct radix_node_head **tables, **xtables, *rnh; + struct radix_node_head **tables_old, **xtables_old; + uint8_t *tabletype, *tabletype_old; + unsigned int ntables_old, tbl; + + /* Check new value for validity */ + if (ntables > IPFW_TABLES_MAX) + ntables = IPFW_TABLES_MAX; + + /* Allocate new pointers */ + tables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO); + xtables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO); + tabletype = malloc(ntables * sizeof(uint8_t), M_IPFW, M_WAITOK | M_ZERO); + + IPFW_WLOCK(ch); + + tbl = (ntables >= V_fw_tables_max) ? V_fw_tables_max : ntables; + + /* Copy old table pointers */ + memcpy(tables, ch->tables, sizeof(void *) * tbl); + memcpy(xtables, ch->xtables, sizeof(void *) * tbl); + memcpy(tabletype, ch->tabletype, sizeof(uint8_t) * tbl); + + /* Change pointers and number of tables */ + tables_old = ch->tables; + xtables_old = ch->xtables; + tabletype_old = ch->tabletype; + ch->tables = tables; + ch->xtables = xtables; + ch->tabletype = tabletype; + + ntables_old = V_fw_tables_max; + V_fw_tables_max = ntables; + + IPFW_WUNLOCK(ch); + + /* Check if we need to destroy radix trees */ + if (ntables < ntables_old) { + for (tbl = ntables; tbl < ntables_old; tbl++) { + if ((rnh = tables_old[tbl]) != NULL) { + rnh->rnh_walktree(rnh, flush_table_entry, rnh); + rn_detachhead((void **)&rnh); + } + + if ((rnh = xtables_old[tbl]) != NULL) { + rnh->rnh_walktree(rnh, flush_table_entry, rnh); + rn_detachhead((void **)&rnh); + } + } + } + + /* Free old pointers */ + free(tables_old, M_IPFW); + free(xtables_old, M_IPFW); + free(tabletype_old, M_IPFW); + + return (0); +} + +int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, uint32_t *val) {