From b0f38338aef2dae5ade3c16acf713737e3b15a73 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 3 Dec 2017 00:58:47 +0100 Subject: netfilter: reduce size of hook entry point locations struct net contains: struct nf_hook_entries __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; which store the hook entry point locations for the various protocol families and the hooks. Using array results in compact c code when doing accesses, i.e. x = rcu_dereference(net->nf.hooks[pf][hook]); but its also wasting a lot of memory, as most families are not used. So split the array into those families that are used, which are only 5 (instead of 13). In most cases, the 'pf' argument is constant, i.e. gcc removes switch statement. struct net before: /* size: 5184, cachelines: 81, members: 46 */ after: /* size: 4672, cachelines: 73, members: 46 */ Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/core.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'net/netfilter/core.c') diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 6921f9f1cc81..a6eaaf303be8 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -264,8 +264,23 @@ out_assign: static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, const struct nf_hook_ops *reg) { - if (reg->pf != NFPROTO_NETDEV) - return net->nf.hooks[reg->pf]+reg->hooknum; + switch (reg->pf) { + case NFPROTO_NETDEV: + break; + case NFPROTO_ARP: + return net->nf.hooks_arp + reg->hooknum; + case NFPROTO_BRIDGE: + return net->nf.hooks_bridge + reg->hooknum; + case NFPROTO_IPV4: + return net->nf.hooks_ipv4 + reg->hooknum; + case NFPROTO_IPV6: + return net->nf.hooks_ipv6 + reg->hooknum; + case NFPROTO_DECNET: + return net->nf.hooks_decnet + reg->hooknum; + default: + WARN_ON_ONCE(1); + return NULL; + } #ifdef CONFIG_NETFILTER_INGRESS if (reg->hooknum == NF_NETDEV_INGRESS) { @@ -534,14 +549,21 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); EXPORT_SYMBOL(nf_nat_decode_session_hook); #endif -static int __net_init netfilter_net_init(struct net *net) +static void __net_init __netfilter_net_init(struct nf_hook_entries *e[NF_MAX_HOOKS]) { - int i, h; + int h; - for (i = 0; i < ARRAY_SIZE(net->nf.hooks); i++) { - for (h = 0; h < NF_MAX_HOOKS; h++) - RCU_INIT_POINTER(net->nf.hooks[i][h], NULL); - } + for (h = 0; h < NF_MAX_HOOKS; h++) + RCU_INIT_POINTER(e[h], NULL); +} + +static int __net_init netfilter_net_init(struct net *net) +{ + __netfilter_net_init(net->nf.hooks_ipv4); + __netfilter_net_init(net->nf.hooks_ipv6); + __netfilter_net_init(net->nf.hooks_arp); + __netfilter_net_init(net->nf.hooks_bridge); + __netfilter_net_init(net->nf.hooks_decnet); #ifdef CONFIG_PROC_FS net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter", -- cgit v1.2.3-59-g8ed1b