Commit a6fda211 authored by Florian Westphal's avatar Florian Westphal Committed by Luis Henriques

netfilter: x_tables: pass xt_counters struct to counter allocator

BugLink: https://bugs.launchpad.net/bugs/1640786

Keeps some noise away from a followup patch.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
(backported from commit f28e15ba)
Signed-off-by: default avatarEric Desrochers <eric.desrochers@canonical.com>
Acked-by: default avatarTim Gardner <tim.gardner@canonical.com>
Acked-by: default avatarSeth Forshee <seth.forshee@canonical.com>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 3e76b2af
......@@ -365,32 +365,7 @@ static inline unsigned long ifname_compare_aligned(const char *_a,
}
/* On SMP, ip(6)t_entry->counters.pcnt holds address of the
* real (percpu) counter. On !SMP, its just the packet count,
* so nothing needs to be done there.
*
* xt_percpu_counter_alloc returns the address of the percpu
* counter, or 0 on !SMP. We force an alignment of 16 bytes
* so that bytes/packets share a common cache line.
*
* Hence caller must use IS_ERR_VALUE to check for error, this
* allows us to return 0 for single core systems without forcing
* callers to deal with SMP vs. NONSMP issues.
*/
static inline u64 xt_percpu_counter_alloc(void)
{
if (nr_cpu_ids > 1) {
void __percpu *res = __alloc_percpu(sizeof(struct xt_counters),
sizeof(struct xt_counters));
if (res == NULL)
return (u64) -ENOMEM;
return (u64) (__force unsigned long) res;
}
return 0;
}
bool xt_percpu_counter_alloc(struct xt_counters *counters);
void xt_percpu_counter_free(struct xt_counters *cnt);
static inline struct xt_counters *
......
......@@ -532,8 +532,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
struct xt_target *target;
int ret;
e->counters.pcnt = xt_percpu_counter_alloc();
if (IS_ERR_VALUE(e->counters.pcnt))
if (!xt_percpu_counter_alloc(&e->counters))
return -ENOMEM;
t = arpt_get_target(e);
......
......@@ -674,8 +674,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
struct xt_mtchk_param mtpar;
struct xt_entry_match *ematch;
e->counters.pcnt = xt_percpu_counter_alloc();
if (IS_ERR_VALUE(e->counters.pcnt))
if (!xt_percpu_counter_alloc(&e->counters))
return -ENOMEM;
j = 0;
......
......@@ -687,8 +687,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
struct xt_mtchk_param mtpar;
struct xt_entry_match *ematch;
e->counters.pcnt = xt_percpu_counter_alloc();
if (IS_ERR_VALUE(e->counters.pcnt))
if (!xt_percpu_counter_alloc(&e->counters))
return -ENOMEM;
j = 0;
......
......@@ -1550,6 +1550,36 @@ void xt_proto_fini(struct net *net, u_int8_t af)
}
EXPORT_SYMBOL_GPL(xt_proto_fini);
/**
* xt_percpu_counter_alloc - allocate x_tables rule counter
*
* @counter: pointer to counter struct inside the ip(6)/arpt_entry struct
*
* On SMP, the packet counter [ ip(6)t_entry->counters.pcnt ] will then
* contain the address of the real (percpu) counter.
*
* Rule evaluation needs to use xt_get_this_cpu_counter() helper
* to fetch the real percpu counter.
*
* returns false on error.
*/
bool xt_percpu_counter_alloc(struct xt_counters *counter)
{
void __percpu *res;
if (nr_cpu_ids <= 1)
return true;
res = __alloc_percpu(sizeof(struct xt_counters),
sizeof(struct xt_counters));
if (!res)
return false;
counter->pcnt = (__force unsigned long)res;
return true;
}
EXPORT_SYMBOL_GPL(xt_percpu_counter_alloc);
void xt_percpu_counter_free(struct xt_counters *counters)
{
unsigned long pcnt = counters->pcnt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment