netfilter: xtables: use percpu rule counters
[firefly-linux-kernel-4.4.55.git] / net / ipv6 / netfilter / ip6_tables.c
index cdd085f8b77011644e502c73da7b43188a267817..a1190ee1472397ac1d68657e5363c72adf8d7f46 100644 (file)
@@ -367,6 +367,7 @@ ip6t_do_table(struct sk_buff *skb,
        do {
                const struct xt_entry_target *t;
                const struct xt_entry_match *ematch;
+               struct xt_counters *counter;
 
                IP_NF_ASSERT(e);
                acpar.thoff = 0;
@@ -384,7 +385,8 @@ ip6t_do_table(struct sk_buff *skb,
                                goto no_match;
                }
 
-               ADD_COUNTER(e->counters, skb->len, 1);
+               counter = xt_get_this_cpu_counter(&e->counters);
+               ADD_COUNTER(*counter, skb->len, 1);
 
                t = ip6t_get_target_c(e);
                IP_NF_ASSERT(t->u.kernel.target);
@@ -679,6 +681,10 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
        if (ret)
                return ret;
 
+       e->counters.pcnt = xt_percpu_counter_alloc();
+       if (IS_ERR_VALUE(e->counters.pcnt))
+               return -ENOMEM;
+
        j = 0;
        mtpar.net       = net;
        mtpar.table     = name;
@@ -714,6 +720,9 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
                        break;
                cleanup_match(ematch, net);
        }
+
+       xt_percpu_counter_free(e->counters.pcnt);
+
        return ret;
 }
 
@@ -797,6 +806,8 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net)
        if (par.target->destroy != NULL)
                par.target->destroy(&par);
        module_put(par.target->me);
+
+       xt_percpu_counter_free(e->counters.pcnt);
 }
 
 /* Checks and translates the user-supplied table segment (held in
@@ -901,13 +912,15 @@ get_counters(const struct xt_table_info *t,
 
                i = 0;
                xt_entry_foreach(iter, t->entries[cpu], t->size) {
+                       struct xt_counters *tmp;
                        u64 bcnt, pcnt;
                        unsigned int start;
 
+                       tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
                        do {
                                start = read_seqcount_begin(s);
-                               bcnt = iter->counters.bcnt;
-                               pcnt = iter->counters.pcnt;
+                               bcnt = tmp->bcnt;
+                               pcnt = tmp->pcnt;
                        } while (read_seqcount_retry(s, start));
 
                        ADD_COUNTER(counters[i], bcnt, pcnt);
@@ -1374,7 +1387,6 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
                goto free;
        }
 
-
        local_bh_disable();
        private = t->private;
        if (private->number != num_counters) {
@@ -1388,7 +1400,10 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
        addend = xt_write_recseq_begin();
        loc_cpu_entry = private->entries[curcpu];
        xt_entry_foreach(iter, loc_cpu_entry, private->size) {
-               ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
+               struct xt_counters *tmp;
+
+               tmp = xt_get_this_cpu_counter(&iter->counters);
+               ADD_COUNTER(*tmp, paddc[i].bcnt, paddc[i].pcnt);
                ++i;
        }
        xt_write_recseq_end(addend);
@@ -1621,6 +1636,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
        struct xt_mtchk_param mtpar;
        struct xt_entry_match *ematch;
 
+       e->counters.pcnt = xt_percpu_counter_alloc();
+       if (IS_ERR_VALUE(e->counters.pcnt))
+               return -ENOMEM;
        j = 0;
        mtpar.net       = net;
        mtpar.table     = name;
@@ -1645,6 +1663,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
                        break;
                cleanup_match(ematch, net);
        }
+
+       xt_percpu_counter_free(e->counters.pcnt);
+
        return ret;
 }