1 From: Pablo Neira Ayuso <pablo@netfilter.org>
2 Date: Tue, 9 Jan 2018 02:42:11 +0100
3 Subject: [PATCH] netfilter: nf_tables: get rid of pernet families
5 Now that we have a single table list for each netns, we can get rid of
6 one pointer per family and the global afinfo list, thus, shrinking
7 struct netns for nftables that now becomes 64 bytes smaller.
9 And call __nft_release_afinfo() from __net_exit path accordingly to
10 release netnamespace objects on removal.
12 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
15 --- a/include/net/netfilter/nf_tables.h
16 +++ b/include/net/netfilter/nf_tables.h
17 @@ -969,8 +969,8 @@ struct nft_af_info {
21 -int nft_register_afinfo(struct net *, struct nft_af_info *);
22 -void nft_unregister_afinfo(struct net *, struct nft_af_info *);
23 +int nft_register_afinfo(struct nft_af_info *);
24 +void nft_unregister_afinfo(struct nft_af_info *);
26 int nft_register_chain_type(const struct nf_chain_type *);
27 void nft_unregister_chain_type(const struct nf_chain_type *);
28 --- a/include/net/netns/nftables.h
29 +++ b/include/net/netns/nftables.h
33 struct netns_nftables {
34 - struct list_head af_info;
35 struct list_head tables;
36 struct list_head commit_list;
37 - struct nft_af_info *ipv4;
38 - struct nft_af_info *ipv6;
39 - struct nft_af_info *inet;
40 - struct nft_af_info *arp;
41 - struct nft_af_info *bridge;
42 - struct nft_af_info *netdev;
43 unsigned int base_seq;
46 --- a/net/bridge/netfilter/nf_tables_bridge.c
47 +++ b/net/bridge/netfilter/nf_tables_bridge.c
48 @@ -47,34 +47,6 @@ static struct nft_af_info nft_af_bridge
52 -static int nf_tables_bridge_init_net(struct net *net)
54 - net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
55 - if (net->nft.bridge == NULL)
58 - memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge));
60 - if (nft_register_afinfo(net, net->nft.bridge) < 0)
65 - kfree(net->nft.bridge);
69 -static void nf_tables_bridge_exit_net(struct net *net)
71 - nft_unregister_afinfo(net, net->nft.bridge);
72 - kfree(net->nft.bridge);
75 -static struct pernet_operations nf_tables_bridge_net_ops = {
76 - .init = nf_tables_bridge_init_net,
77 - .exit = nf_tables_bridge_exit_net,
80 static const struct nf_chain_type filter_bridge = {
82 .type = NFT_CHAIN_T_DEFAULT,
83 @@ -98,17 +70,17 @@ static int __init nf_tables_bridge_init(
87 - ret = nft_register_chain_type(&filter_bridge);
88 + ret = nft_register_afinfo(&nft_af_bridge);
92 - ret = register_pernet_subsys(&nf_tables_bridge_net_ops);
93 + ret = nft_register_chain_type(&filter_bridge);
95 - goto err_register_subsys;
96 + goto err_register_chain;
100 -err_register_subsys:
102 nft_unregister_chain_type(&filter_bridge);
105 @@ -116,8 +88,8 @@ err_register_subsys:
107 static void __exit nf_tables_bridge_exit(void)
109 - unregister_pernet_subsys(&nf_tables_bridge_net_ops);
110 nft_unregister_chain_type(&filter_bridge);
111 + nft_unregister_afinfo(&nft_af_bridge);
114 module_init(nf_tables_bridge_init);
115 --- a/net/ipv4/netfilter/nf_tables_arp.c
116 +++ b/net/ipv4/netfilter/nf_tables_arp.c
117 @@ -32,34 +32,6 @@ static struct nft_af_info nft_af_arp __r
118 .owner = THIS_MODULE,
121 -static int nf_tables_arp_init_net(struct net *net)
123 - net->nft.arp = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
124 - if (net->nft.arp== NULL)
127 - memcpy(net->nft.arp, &nft_af_arp, sizeof(nft_af_arp));
129 - if (nft_register_afinfo(net, net->nft.arp) < 0)
134 - kfree(net->nft.arp);
138 -static void nf_tables_arp_exit_net(struct net *net)
140 - nft_unregister_afinfo(net, net->nft.arp);
141 - kfree(net->nft.arp);
144 -static struct pernet_operations nf_tables_arp_net_ops = {
145 - .init = nf_tables_arp_init_net,
146 - .exit = nf_tables_arp_exit_net,
149 static const struct nf_chain_type filter_arp = {
151 .type = NFT_CHAIN_T_DEFAULT,
152 @@ -77,21 +49,26 @@ static int __init nf_tables_arp_init(voi
156 - ret = nft_register_chain_type(&filter_arp);
157 + ret = nft_register_afinfo(&nft_af_arp);
161 - ret = register_pernet_subsys(&nf_tables_arp_net_ops);
162 + ret = nft_register_chain_type(&filter_arp);
164 - nft_unregister_chain_type(&filter_arp);
165 + goto err_register_chain;
170 + nft_unregister_chain_type(&filter_arp);
175 static void __exit nf_tables_arp_exit(void)
177 - unregister_pernet_subsys(&nf_tables_arp_net_ops);
178 nft_unregister_chain_type(&filter_arp);
179 + nft_unregister_afinfo(&nft_af_arp);
182 module_init(nf_tables_arp_init);
183 --- a/net/ipv4/netfilter/nf_tables_ipv4.c
184 +++ b/net/ipv4/netfilter/nf_tables_ipv4.c
185 @@ -35,34 +35,6 @@ static struct nft_af_info nft_af_ipv4 __
186 .owner = THIS_MODULE,
189 -static int nf_tables_ipv4_init_net(struct net *net)
191 - net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
192 - if (net->nft.ipv4 == NULL)
195 - memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4));
197 - if (nft_register_afinfo(net, net->nft.ipv4) < 0)
202 - kfree(net->nft.ipv4);
206 -static void nf_tables_ipv4_exit_net(struct net *net)
208 - nft_unregister_afinfo(net, net->nft.ipv4);
209 - kfree(net->nft.ipv4);
212 -static struct pernet_operations nf_tables_ipv4_net_ops = {
213 - .init = nf_tables_ipv4_init_net,
214 - .exit = nf_tables_ipv4_exit_net,
217 static const struct nf_chain_type filter_ipv4 = {
219 .type = NFT_CHAIN_T_DEFAULT,
220 @@ -86,21 +58,25 @@ static int __init nf_tables_ipv4_init(vo
224 - ret = nft_register_chain_type(&filter_ipv4);
225 + ret = nft_register_afinfo(&nft_af_ipv4);
229 - ret = register_pernet_subsys(&nf_tables_ipv4_net_ops);
230 + ret = nft_register_chain_type(&filter_ipv4);
232 - nft_unregister_chain_type(&filter_ipv4);
233 + goto err_register_chain;
238 + nft_unregister_afinfo(&nft_af_ipv4);
242 static void __exit nf_tables_ipv4_exit(void)
244 - unregister_pernet_subsys(&nf_tables_ipv4_net_ops);
245 nft_unregister_chain_type(&filter_ipv4);
246 + nft_unregister_afinfo(&nft_af_ipv4);
249 module_init(nf_tables_ipv4_init);
250 --- a/net/ipv6/netfilter/nf_tables_ipv6.c
251 +++ b/net/ipv6/netfilter/nf_tables_ipv6.c
252 @@ -33,34 +33,6 @@ static struct nft_af_info nft_af_ipv6 __
253 .owner = THIS_MODULE,
256 -static int nf_tables_ipv6_init_net(struct net *net)
258 - net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
259 - if (net->nft.ipv6 == NULL)
262 - memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));
264 - if (nft_register_afinfo(net, net->nft.ipv6) < 0)
269 - kfree(net->nft.ipv6);
273 -static void nf_tables_ipv6_exit_net(struct net *net)
275 - nft_unregister_afinfo(net, net->nft.ipv6);
276 - kfree(net->nft.ipv6);
279 -static struct pernet_operations nf_tables_ipv6_net_ops = {
280 - .init = nf_tables_ipv6_init_net,
281 - .exit = nf_tables_ipv6_exit_net,
284 static const struct nf_chain_type filter_ipv6 = {
286 .type = NFT_CHAIN_T_DEFAULT,
287 @@ -84,20 +56,24 @@ static int __init nf_tables_ipv6_init(vo
291 - ret = nft_register_chain_type(&filter_ipv6);
292 + ret = nft_register_afinfo(&nft_af_ipv6);
296 - ret = register_pernet_subsys(&nf_tables_ipv6_net_ops);
297 + ret = nft_register_chain_type(&filter_ipv6);
299 - nft_unregister_chain_type(&filter_ipv6);
300 + goto err_register_chain;
305 + nft_unregister_afinfo(&nft_af_ipv6);
309 static void __exit nf_tables_ipv6_exit(void)
311 - unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
312 + nft_unregister_afinfo(&nft_af_ipv6);
313 nft_unregister_chain_type(&filter_ipv6);
316 --- a/net/netfilter/nf_tables_api.c
317 +++ b/net/netfilter/nf_tables_api.c
319 static LIST_HEAD(nf_tables_expressions);
320 static LIST_HEAD(nf_tables_objects);
321 static LIST_HEAD(nf_tables_flowtables);
322 +static LIST_HEAD(nf_tables_af_info);
325 * nft_register_afinfo - register nf_tables address family info
326 @@ -35,17 +36,15 @@ static LIST_HEAD(nf_tables_flowtables);
327 * Register the address family for use with nf_tables. Returns zero on
328 * success or a negative errno code otherwise.
330 -int nft_register_afinfo(struct net *net, struct nft_af_info *afi)
331 +int nft_register_afinfo(struct nft_af_info *afi)
333 nfnl_lock(NFNL_SUBSYS_NFTABLES);
334 - list_add_tail_rcu(&afi->list, &net->nft.af_info);
335 + list_add_tail_rcu(&afi->list, &nf_tables_af_info);
336 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
339 EXPORT_SYMBOL_GPL(nft_register_afinfo);
341 -static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi);
344 * nft_unregister_afinfo - unregister nf_tables address family info
346 @@ -53,10 +52,9 @@ static void __nft_release_afinfo(struct
348 * Unregister the address family for use with nf_tables.
350 -void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi)
351 +void nft_unregister_afinfo(struct nft_af_info *afi)
353 nfnl_lock(NFNL_SUBSYS_NFTABLES);
354 - __nft_release_afinfo(net, afi);
355 list_del_rcu(&afi->list);
356 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
358 @@ -66,7 +64,7 @@ static struct nft_af_info *nft_afinfo_lo
360 struct nft_af_info *afi;
362 - list_for_each_entry(afi, &net->nft.af_info, list) {
363 + list_for_each_entry(afi, &nf_tables_af_info, list) {
364 if (afi->family == family)
367 @@ -4968,15 +4966,12 @@ void nft_flow_table_iterate(struct net *
370 struct nft_flowtable *flowtable;
371 - const struct nft_af_info *afi;
372 const struct nft_table *table;
375 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
376 - list_for_each_entry_rcu(table, &net->nft.tables, list) {
377 - list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
378 - iter(&flowtable->data, data);
380 + list_for_each_entry_rcu(table, &net->nft.tables, list) {
381 + list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
382 + iter(&flowtable->data, data);
386 @@ -6461,21 +6456,6 @@ int nft_data_dump(struct sk_buff *skb, i
388 EXPORT_SYMBOL_GPL(nft_data_dump);
390 -static int __net_init nf_tables_init_net(struct net *net)
392 - INIT_LIST_HEAD(&net->nft.af_info);
393 - INIT_LIST_HEAD(&net->nft.tables);
394 - INIT_LIST_HEAD(&net->nft.commit_list);
395 - net->nft.base_seq = 1;
399 -static void __net_exit nf_tables_exit_net(struct net *net)
401 - WARN_ON_ONCE(!list_empty(&net->nft.af_info));
402 - WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
405 int __nft_release_basechain(struct nft_ctx *ctx)
407 struct nft_rule *rule, *nr;
408 @@ -6496,8 +6476,7 @@ int __nft_release_basechain(struct nft_c
410 EXPORT_SYMBOL_GPL(__nft_release_basechain);
412 -/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */
413 -static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
414 +static void __nft_release_afinfo(struct net *net)
416 struct nft_flowtable *flowtable, *nf;
417 struct nft_table *table, *nt;
418 @@ -6507,10 +6486,11 @@ static void __nft_release_afinfo(struct
419 struct nft_set *set, *ns;
420 struct nft_ctx ctx = {
422 - .family = afi->family,
425 list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
426 + ctx.family = table->afi->family;
428 list_for_each_entry(chain, &table->chains, list)
429 nf_tables_unregister_hook(net, table, chain);
430 list_for_each_entry(flowtable, &table->flowtables, list)
431 @@ -6551,6 +6531,21 @@ static void __nft_release_afinfo(struct
435 +static int __net_init nf_tables_init_net(struct net *net)
437 + INIT_LIST_HEAD(&net->nft.tables);
438 + INIT_LIST_HEAD(&net->nft.commit_list);
439 + net->nft.base_seq = 1;
443 +static void __net_exit nf_tables_exit_net(struct net *net)
445 + __nft_release_afinfo(net);
446 + WARN_ON_ONCE(!list_empty(&net->nft.tables));
447 + WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
450 static struct pernet_operations nf_tables_net_ops = {
451 .init = nf_tables_init_net,
452 .exit = nf_tables_exit_net,
453 --- a/net/netfilter/nf_tables_inet.c
454 +++ b/net/netfilter/nf_tables_inet.c
455 @@ -43,34 +43,6 @@ static struct nft_af_info nft_af_inet __
456 .owner = THIS_MODULE,
459 -static int __net_init nf_tables_inet_init_net(struct net *net)
461 - net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
462 - if (net->nft.inet == NULL)
464 - memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet));
466 - if (nft_register_afinfo(net, net->nft.inet) < 0)
472 - kfree(net->nft.inet);
476 -static void __net_exit nf_tables_inet_exit_net(struct net *net)
478 - nft_unregister_afinfo(net, net->nft.inet);
479 - kfree(net->nft.inet);
482 -static struct pernet_operations nf_tables_inet_net_ops = {
483 - .init = nf_tables_inet_init_net,
484 - .exit = nf_tables_inet_exit_net,
487 static const struct nf_chain_type filter_inet = {
489 .type = NFT_CHAIN_T_DEFAULT,
490 @@ -94,21 +66,24 @@ static int __init nf_tables_inet_init(vo
494 - ret = nft_register_chain_type(&filter_inet);
496 + if (nft_register_afinfo(&nft_af_inet) < 0)
499 - ret = register_pernet_subsys(&nf_tables_inet_net_ops);
500 + ret = nft_register_chain_type(&filter_inet);
502 - nft_unregister_chain_type(&filter_inet);
503 + goto err_register_chain;
508 + nft_unregister_afinfo(&nft_af_inet);
512 static void __exit nf_tables_inet_exit(void)
514 - unregister_pernet_subsys(&nf_tables_inet_net_ops);
515 nft_unregister_chain_type(&filter_inet);
516 + nft_unregister_afinfo(&nft_af_inet);
519 module_init(nf_tables_inet_init);
520 --- a/net/netfilter/nf_tables_netdev.c
521 +++ b/net/netfilter/nf_tables_netdev.c
522 @@ -43,34 +43,6 @@ static struct nft_af_info nft_af_netdev
523 .owner = THIS_MODULE,
526 -static int nf_tables_netdev_init_net(struct net *net)
528 - net->nft.netdev = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
529 - if (net->nft.netdev == NULL)
532 - memcpy(net->nft.netdev, &nft_af_netdev, sizeof(nft_af_netdev));
534 - if (nft_register_afinfo(net, net->nft.netdev) < 0)
539 - kfree(net->nft.netdev);
543 -static void nf_tables_netdev_exit_net(struct net *net)
545 - nft_unregister_afinfo(net, net->nft.netdev);
546 - kfree(net->nft.netdev);
549 -static struct pernet_operations nf_tables_netdev_net_ops = {
550 - .init = nf_tables_netdev_init_net,
551 - .exit = nf_tables_netdev_exit_net,
554 static const struct nf_chain_type nft_filter_chain_netdev = {
556 .type = NFT_CHAIN_T_DEFAULT,
557 @@ -145,32 +117,32 @@ static int __init nf_tables_netdev_init(
561 - ret = nft_register_chain_type(&nft_filter_chain_netdev);
563 + if (nft_register_afinfo(&nft_af_netdev) < 0)
566 - ret = register_pernet_subsys(&nf_tables_netdev_net_ops);
567 + ret = nft_register_chain_type(&nft_filter_chain_netdev);
570 + goto err_register_chain_type;
572 ret = register_netdevice_notifier(&nf_tables_netdev_notifier);
575 + goto err_register_netdevice_notifier;
580 - unregister_pernet_subsys(&nf_tables_netdev_net_ops);
582 +err_register_netdevice_notifier:
583 nft_unregister_chain_type(&nft_filter_chain_netdev);
584 +err_register_chain_type:
585 + nft_unregister_afinfo(&nft_af_netdev);
590 static void __exit nf_tables_netdev_exit(void)
592 unregister_netdevice_notifier(&nf_tables_netdev_notifier);
593 - unregister_pernet_subsys(&nf_tables_netdev_net_ops);
594 nft_unregister_chain_type(&nft_filter_chain_netdev);
595 + nft_unregister_afinfo(&nft_af_netdev);
598 module_init(nf_tables_netdev_init);