Commit 0c4c9288ada0e6642d511ef872f10a4781a896ff

Authored by Alexey Dobriyan
Committed by Patrick McHardy
1 parent e099a17357

netfilter: netns nat: per-netns bysource hash

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>

Showing 2 changed files with 47 additions and 27 deletions Side-by-side Diff

include/net/netns/ipv4.h
... ... @@ -39,6 +39,8 @@
39 39 struct xt_table *arptable_filter;
40 40 struct xt_table *iptable_security;
41 41 struct xt_table *nat_table;
  42 + struct hlist_head *nat_bysource;
  43 + int nat_vmalloced;
42 44 #endif
43 45  
44 46 int sysctl_icmp_echo_ignore_all;
net/ipv4/netfilter/nf_nat_core.c
... ... @@ -37,10 +37,7 @@
37 37  
38 38 /* Calculated at init based on memory size */
39 39 static unsigned int nf_nat_htable_size __read_mostly;
40   -static int nf_nat_vmalloced;
41 40  
42   -static struct hlist_head *bysource __read_mostly;
43   -
44 41 #define MAX_IP_NAT_PROTO 256
45 42 static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]
46 43 __read_mostly;
... ... @@ -145,7 +142,8 @@
145 142  
146 143 /* Only called for SRC manip */
147 144 static int
148   -find_appropriate_src(const struct nf_conntrack_tuple *tuple,
  145 +find_appropriate_src(struct net *net,
  146 + const struct nf_conntrack_tuple *tuple,
149 147 struct nf_conntrack_tuple *result,
150 148 const struct nf_nat_range *range)
151 149 {
... ... @@ -155,7 +153,7 @@
155 153 const struct hlist_node *n;
156 154  
157 155 rcu_read_lock();
158   - hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) {
  156 + hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) {
159 157 ct = nat->ct;
160 158 if (same_src(ct, tuple)) {
161 159 /* Copy source part from reply tuple. */
... ... @@ -231,6 +229,7 @@
231 229 struct nf_conn *ct,
232 230 enum nf_nat_manip_type maniptype)
233 231 {
  232 + struct net *net = nf_ct_net(ct);
234 233 const struct nf_nat_protocol *proto;
235 234  
236 235 /* 1) If this srcip/proto/src-proto-part is currently mapped,
... ... @@ -242,7 +241,7 @@
242 241 manips not an issue. */
243 242 if (maniptype == IP_NAT_MANIP_SRC &&
244 243 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
245   - if (find_appropriate_src(orig_tuple, tuple, range)) {
  244 + if (find_appropriate_src(net, orig_tuple, tuple, range)) {
246 245 pr_debug("get_unique_tuple: Found current src map\n");
247 246 if (!nf_nat_used_tuple(tuple, ct))
248 247 return;
... ... @@ -283,6 +282,7 @@
283 282 const struct nf_nat_range *range,
284 283 enum nf_nat_manip_type maniptype)
285 284 {
  285 + struct net *net = nf_ct_net(ct);
286 286 struct nf_conntrack_tuple curr_tuple, new_tuple;
287 287 struct nf_conn_nat *nat;
288 288 int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
... ... @@ -334,7 +334,8 @@
334 334 /* nf_conntrack_alter_reply might re-allocate exntension aera */
335 335 nat = nfct_nat(ct);
336 336 nat->ct = ct;
337   - hlist_add_head_rcu(&nat->bysource, &bysource[srchash]);
  337 + hlist_add_head_rcu(&nat->bysource,
  338 + &net->ipv4.nat_bysource[srchash]);
338 339 spin_unlock_bh(&nf_nat_lock);
339 340 }
340 341  
... ... @@ -583,6 +584,40 @@
583 584 .flags = NF_CT_EXT_F_PREALLOC,
584 585 };
585 586  
  587 +static int __net_init nf_nat_net_init(struct net *net)
  588 +{
  589 + net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
  590 + &net->ipv4.nat_vmalloced);
  591 + if (!net->ipv4.nat_bysource)
  592 + return -ENOMEM;
  593 + return 0;
  594 +}
  595 +
  596 +/* Clear NAT section of all conntracks, in case we're loaded again. */
  597 +static int clean_nat(struct nf_conn *i, void *data)
  598 +{
  599 + struct nf_conn_nat *nat = nfct_nat(i);
  600 +
  601 + if (!nat)
  602 + return 0;
  603 + memset(nat, 0, sizeof(*nat));
  604 + i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
  605 + return 0;
  606 +}
  607 +
  608 +static void __net_exit nf_nat_net_exit(struct net *net)
  609 +{
  610 + nf_ct_iterate_cleanup(net, &clean_nat, NULL);
  611 + synchronize_rcu();
  612 + nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_vmalloced,
  613 + nf_nat_htable_size);
  614 +}
  615 +
  616 +static struct pernet_operations nf_nat_net_ops = {
  617 + .init = nf_nat_net_init,
  618 + .exit = nf_nat_net_exit,
  619 +};
  620 +
586 621 static int __init nf_nat_init(void)
587 622 {
588 623 size_t i;
589 624  
... ... @@ -599,12 +634,9 @@
599 634 /* Leave them the same for the moment. */
600 635 nf_nat_htable_size = nf_conntrack_htable_size;
601 636  
602   - bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
603   - &nf_nat_vmalloced);
604   - if (!bysource) {
605   - ret = -ENOMEM;
  637 + ret = register_pernet_subsys(&nf_nat_net_ops);
  638 + if (ret < 0)
606 639 goto cleanup_extend;
607   - }
608 640  
609 641 /* Sew in builtin protocols. */
610 642 spin_lock_bh(&nf_nat_lock);
611 643  
... ... @@ -629,23 +661,9 @@
629 661 return ret;
630 662 }
631 663  
632   -/* Clear NAT section of all conntracks, in case we're loaded again. */
633   -static int clean_nat(struct nf_conn *i, void *data)
634   -{
635   - struct nf_conn_nat *nat = nfct_nat(i);
636   -
637   - if (!nat)
638   - return 0;
639   - memset(nat, 0, sizeof(*nat));
640   - i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
641   - return 0;
642   -}
643   -
644 664 static void __exit nf_nat_cleanup(void)
645 665 {
646   - nf_ct_iterate_cleanup(&init_net, &clean_nat, NULL);
647   - synchronize_rcu();
648   - nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
  666 + unregister_pernet_subsys(&nf_nat_net_ops);
649 667 nf_ct_l3proto_put(l3proto);
650 668 nf_ct_extend_unregister(&nat_extend);
651 669 rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);