netfilter: reduce hook array sizes to what is needed
Subsystems (3)
Florian Westphal
maintainercover netfilter: reduce hook array sizes to what is needed
This series further reduces size of the hook arrays by only resevering space for the hooks that are implemented/supported (e.g., arp only supports 3 different hook points as it lacks PRE/POST_ROUTING).
Furthermore, add #ifdef guard to not declare arp/bridge/decnet hooks unless they are needed.
At least Fedora has CONFIG_DECNET=n so this even reduces size for some distro kernels.
I ran a few randconfig builds last night and it did not catch any build errors.
Florian Westphal (3):
netfilter: reduce hook array sizes to what is needed
netfilter: don't allocate space for decnet hooks unless needed
netfilter: don't allocate space for arp/bridge hooks unless needed
include/linux/netfilter.h | 6 ++++++ include/net/netns/netfilter.h | 19 ++++++++++++++----- net/Kconfig | 1 + net/bridge/netfilter/Kconfig | 2 ++ net/ipv4/netfilter/Kconfig | 2 ++ net/netfilter/Kconfig | 6 ++++++ net/netfilter/core.c | 22 ++++++++++++++++++++++ net/netfilter/nf_queue.c | 2 ++ 8 files changed, 55 insertions(+), 5 deletions(-)
Florian Westphal
maintainerPATCH 1/3 netfilter: reduce hook array sizes to what is needed
Not all families share the same hook count.
Can't use the corresponding ARP, BRIDGE, DECNET defines because they are defined in uapi headers and including them causes build failures.
struct net before:
/* size: 6592, cachelines: 103, members: 46 */
after:
/* size: 5952, cachelines: 93, members: 46 */
--- include/net/netns/netfilter.h | 13 ++++++++----- net/netfilter/core.c | 10 ++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-)
include/net/netns/netfilter.h +8 -5
@@ -17,11 +17,14 @@ struct netns_nf {#ifdef CONFIG_SYSCTL struct ctl_table_header *nf_log_dir_header;#endif -struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ]; +/* in/out/forward only */ +struct nf_hook_entries __rcu *hooks_arp[3 ]; +/* note: 'BROUTE' isn't a real hook (called via function pointer) */ +struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +/* also supports a 'HELLO' and 'ROUTE' type */ +struct nf_hook_entries __rcu *hooks_decnet[NF_INET_NUMHOOKS +2 ];#if IS_ENABLED (CONFIG_NF_DEFRAG_IPV4 )bool defrag_ipv4;#endif
net/netfilter/core.c +10 -0
@@ -268,14 +268,24 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, constcase NFPROTO_NETDEV :break ;case NFPROTO_ARP : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_arp) <= reg->hooknum)) +return NULL ;return net->nf.hooks_arp + reg->hooknum;case NFPROTO_BRIDGE : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_bridge) <= reg->hooknum)) +return NULL ;return net->nf.hooks_bridge + reg->hooknum;case NFPROTO_IPV4 : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv4) <= reg->hooknum)) +return NULL ;return net->nf.hooks_ipv4 + reg->hooknum;case NFPROTO_IPV6 : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv6) <= reg->hooknum)) +return NULL ;return net->nf.hooks_ipv6 + reg->hooknum;case NFPROTO_DECNET : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_decnet) <= reg->hooknum)) +return NULL ;return net->nf.hooks_decnet + reg->hooknum;default :WARN_ON_ONCE (1 );
Signature · 1 line
2.13.6
Pablo Neira Ayuso
maintainerQuoted 27 lines · Florian Westphal
Not all families share the same hook count.
Can't use the corresponding ARP, BRIDGE, DECNET defines because they are defined in uapi headers and including them causes build failures.
struct net before:
/* size: 6592, cachelines: 103, members: 46 */
after:
/* size: 5952, cachelines: 93, members: 46 */Signed-off-by Florian Westphal <[email protected]>--- include/net/netns/netfilter.h | 13 ++++++++----- net/netfilter/core.c | 10 ++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-)include/net/netns/netfilter.h +0
-3@@ -17,11 +17,14 @@ struct netns_nf {#ifdef CONFIG_SYSCTL struct ctl_table_header *nf_log_dir_header;#endif -struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS ];
include/net/netns/netfilter.h struct netns_nf { · line 27
Quoted 10 lines
include/net/netns/netfilter.h +8
-2-struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ]; +/* in/out/forward only */ +struct nf_hook_entries __rcu *hooks_arp[3 ]; +/* note: 'BROUTE' isn't a real hook (called via function pointer) */ +struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +/* also supports a 'HELLO' and 'ROUTE' type */ +struct nf_hook_entries __rcu *hooks_decnet[NF_INET_NUMHOOKS +2 ];
Just a suggestion, for a follow up patch: Get rid of magic numbers and add some NF_ARP_NUMHOOKS and NF_DECNET_NUMHOOKS too, so similar definition.
Make sense to you?
Florian Westphal
maintainerQuoted 43 lines · Pablo Neira Ayuso
Quoted 27 lines · Florian Westphal
Not all families share the same hook count.
Can't use the corresponding ARP, BRIDGE, DECNET defines because they are defined in uapi headers and including them causes build failures.
struct net before:
/* size: 6592, cachelines: 103, members: 46 */
after:
/* size: 5952, cachelines: 93, members: 46 */Signed-off-by Florian Westphal <[email protected]>--- include/net/netns/netfilter.h | 13 ++++++++----- net/netfilter/core.c | 10 ++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-)include/net/netns/netfilter.h +0
-3@@ -17,11 +17,14 @@ struct netns_nf {#ifdef CONFIG_SYSCTL struct ctl_table_header *nf_log_dir_header;#endif -struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS ];include/net/netns/netfilter.h struct netns_nf { · line 27
Quoted 10 lines
include/net/netns/netfilter.h +8
-2-struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ]; +/* in/out/forward only */ +struct nf_hook_entries __rcu *hooks_arp[3 ]; +/* note: 'BROUTE' isn't a real hook (called via function pointer) */ +struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +/* also supports a 'HELLO' and 'ROUTE' type */ +struct nf_hook_entries __rcu *hooks_decnet[NF_INET_NUMHOOKS +2 ];Just a suggestion, for a follow up patch: Get rid of magic numbers and add some
NF_ARP_NUMHOOKSandNF_DECNET_NUMHOOKStoo, so similar definition.
Quoted 1 line
Make sense to you?
Yes, I will add new define to include/linux/netfilter_defs.h for this.
I'll send a v3.
Florian Westphal
maintainerPATCH 2/3 netfilter: don't allocate space for decnet hooks unless needed
In reply to Florian Westphalno need to define hook points if the family isn't supported.
--- include/linux/netfilter.h | 2 ++ include/net/netns/netfilter.h | 2 ++ net/netfilter/core.c | 4 ++++ 3 files changed, 8 insertions(+)
include/linux/netfilter.h +2 -0
@@ -219,9 +219,11 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,case NFPROTO_BRIDGE : hook_head =rcu_dereference (net->nf.hooks_bridge[hook]);break ; +#if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET : hook_head =rcu_dereference (net->nf.hooks_decnet[hook]);break ; +#endif default :WARN_ON_ONCE (1 );break ;
include/net/netns/netfilter.h +2 -0
@@ -23,8 +23,10 @@ struct netns_nf {struct nf_hook_entries __rcu *hooks_arp[3 ];/* note: 'BROUTE' isn't a real hook (called via function pointer) */ struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +#if IS_ENABLED (CONFIG_DECNET )/* also supports a 'HELLO' and 'ROUTE' type */ struct nf_hook_entries __rcu *hooks_decnet[NF_INET_NUMHOOKS +2 ]; +#endif #if IS_ENABLED (CONFIG_NF_DEFRAG_IPV4 )bool defrag_ipv4;#endif
net/netfilter/core.c +4 -0
@@ -283,10 +283,12 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, constif (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv6) <= reg->hooknum))return NULL ;return net->nf.hooks_ipv6 + reg->hooknum; +#if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_decnet) <= reg->hooknum))return NULL ;return net->nf.hooks_decnet + reg->hooknum; +#endif default :WARN_ON_ONCE (1 );return NULL ;
@@ -573,7 +575,9 @@ static int __net_init netfilter_net_init(struct net *net)__netfilter_net_init (net->nf.hooks_ipv6);__netfilter_net_init (net->nf.hooks_arp);__netfilter_net_init (net->nf.hooks_bridge); +#if IS_ENABLED (CONFIG_DECNET )__netfilter_net_init (net->nf.hooks_decnet); +#endif #ifdef CONFIG_PROC_FS net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
Signature · 1 line
2.13.6
Florian Westphal
maintainerPATCH 3/3 netfilter: don't allocate space for arp/bridge hooks unless needed
In reply to Florian Westphalno need to define hook points if the family isn't supported. Because we need these hooks for either nftables, arp/ebtables or the 'call-iptables' hack we have in the bridge layer add two new dependencies, NETFILTER_FAMILY_{ARP,BRIDGE}, and have the users select them.
--- include/linux/netfilter.h | 4 ++++ include/net/netns/netfilter.h | 4 ++++ net/Kconfig | 1 + net/bridge/netfilter/Kconfig | 2 ++ net/ipv4/netfilter/Kconfig | 2 ++ net/netfilter/Kconfig | 6 ++++++ net/netfilter/core.c | 8 ++++++++ net/netfilter/nf_queue.c | 2 ++ 8 files changed, 29 insertions(+)
include/linux/netfilter.h +4 -0
@@ -213,12 +213,16 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,case NFPROTO_IPV6 : hook_head =rcu_dereference (net->nf.hooks_ipv6[hook]);break ; +#ifdef CONFIG_NETFILTER_FAMILY_ARP case NFPROTO_ARP : hook_head =rcu_dereference (net->nf.hooks_arp[hook]);break ; +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE case NFPROTO_BRIDGE : hook_head =rcu_dereference (net->nf.hooks_bridge[hook]);break ; +#endif #if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET : hook_head =rcu_dereference (net->nf.hooks_decnet[hook]);
include/net/netns/netfilter.h +4 -0
@@ -19,10 +19,14 @@ struct netns_nf {#endif struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS ];struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ]; +#ifdef CONFIG_NETFILTER_FAMILY_ARP /* in/out/forward only */ struct nf_hook_entries __rcu *hooks_arp[3 ]; +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE /* note: 'BROUTE' isn't a real hook (called via function pointer) */ struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +#endif #if IS_ENABLED (CONFIG_DECNET )/* also supports a 'HELLO' and 'ROUTE' type */ struct nf_hook_entries __rcu *hooks_decnet[NF_INET_NUMHOOKS +2 ];
net/Kconfig +1 -0
@@ -182,6 +182,7 @@ config BRIDGE_NETFILTER depends on BRIDGE depends on NETFILTER && INET depends on NETFILTER_ADVANCED + select NETFILTER_FAMILY_BRIDGE default m ---help--- Enabling this option will let arptables resp. iptables see bridged
net/bridge/netfilter/Kconfig +2 -0
@@ -4,6 +4,7 @@ # menuconfig NF_TABLES_BRIDGE depends on BRIDGE && NETFILTER && NF_TABLES + select NETFILTER_FAMILY_BRIDGE tristate "Ethernet Bridge nf_tables support" if NF_TABLES_BRIDGE
@@ -29,6 +30,7 @@ endif # NF_TABLES_BRIDGE menuconfig BRIDGE_NF_EBTABLES tristate "Ethernet Bridge tables (ebtables) support" depends on BRIDGE && NETFILTER && NETFILTER_XTABLES + select NETFILTER_FAMILY_BRIDGE help ebtables is a general, extensible frame/packet identification framework. Say 'Y' or 'M' here if you want to do Ethernet
net/ipv4/netfilter/Kconfig +2 -0
@@ -72,6 +72,7 @@ endif # NF_TABLES_IPV4 config NF_TABLES_ARP tristate "ARP nf_tables support" + select NETFILTER_FAMILY_ARP help This option enables the ARP support for nf_tables.
@@ -392,6 +393,7 @@ endif # IP_NF_IPTABLES config IP_NF_ARPTABLES tristate "ARP tables support" select NETFILTER_XTABLES + select NETFILTER_FAMILY_ARP depends on NETFILTER_ADVANCED help arptables is a general, extensible packet identification framework.
net/netfilter/Kconfig +6 -0
@@ -12,6 +12,12 @@ config NETFILTER_INGRESS config NETFILTER_NETLINK tristate +config NETFILTER_FAMILY_BRIDGE + bool + +config NETFILTER_FAMILY_ARP + bool + config NETFILTER_NETLINK_ACCT tristate "Netfilter NFACCT over NFNETLINK interface" depends on NETFILTER_ADVANCED
net/netfilter/core.c +8 -0
@@ -267,14 +267,18 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, constswitch (reg->pf) {case NFPROTO_NETDEV :break ; +#ifdef CONFIG_NETFILTER_FAMILY_ARP case NFPROTO_ARP :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_arp) <= reg->hooknum))return NULL ;return net->nf.hooks_arp + reg->hooknum; +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE case NFPROTO_BRIDGE :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_bridge) <= reg->hooknum))return NULL ;return net->nf.hooks_bridge + reg->hooknum; +#endif case NFPROTO_IPV4 :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv4) <= reg->hooknum))return NULL ;
@@ -573,8 +577,12 @@ static int __net_init netfilter_net_init(struct net *net) {__netfilter_net_init (net->nf.hooks_ipv4);__netfilter_net_init (net->nf.hooks_ipv6); +#ifdef CONFIG_NETFILTER_FAMILY_ARP __netfilter_net_init (net->nf.hooks_arp); +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE __netfilter_net_init (net->nf.hooks_bridge); +#endif #if IS_ENABLED (CONFIG_DECNET )__netfilter_net_init (net->nf.hooks_decnet);#endif
net/netfilter/nf_queue.c +2 -0
@@ -204,8 +204,10 @@ static unsigned int nf_iterate(struct sk_buff *skb,static struct nf_hook_entries *nf_hook_entries_head (const struct net *net,u8 pf,u8 hooknum) {switch (pf) { +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE case NFPROTO_BRIDGE :return rcu_dereference (net->nf.hooks_bridge[hooknum]); +#endif case NFPROTO_IPV4 :return rcu_dereference (net->nf.hooks_ipv4[hooknum]);case NFPROTO_IPV6 :
Signature · 1 line
2.13.6