summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2026-04-29 09:30:00 +0300
committerFlorian Westphal <fw@strlen.de>2026-05-24 23:55:47 +0300
commite9fd2fb09cfe4abb5c6238141ffbbfcb4a01aa4b (patch)
tree2440e0107ccd3b6b77b444aa1c55616bc05a98ff
parentd4349ba9872d0c97a31fb2a18789297731061e88 (diff)
downloadlinux-e9fd2fb09cfe4abb5c6238141ffbbfcb4a01aa4b.tar.xz
netfilter: nf_conncount: use per-rule hash initval
As-is, different netns will use same slots if the key is the same. OVS uses this infrastructure to limit conntrack counts per zones. Those can easily overlap. Make them hash to different slots internally. Signed-off-by: Florian Westphal <fw@strlen.de>
-rw-r--r--net/netfilter/nf_conncount.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index 00eed5b4d1b1..ab28b47395bd 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -58,6 +58,7 @@ static spinlock_t nf_conncount_locks[CONNCOUNT_SLOTS] __cacheline_aligned_in_smp
struct nf_conncount_data {
unsigned int keylen;
+ u32 initval;
struct rb_root root[CONNCOUNT_SLOTS];
struct net *net;
struct work_struct gc_work;
@@ -65,7 +66,6 @@ struct nf_conncount_data {
unsigned int gc_tree;
};
-static u_int32_t conncount_rnd __read_mostly;
static struct kmem_cache *conncount_rb_cachep __read_mostly;
static struct kmem_cache *conncount_conn_cachep __read_mostly;
@@ -496,7 +496,7 @@ count_tree(struct net *net,
struct nf_conncount_rb *rbconn;
unsigned int hash;
- hash = jhash2(key, data->keylen, conncount_rnd) % CONNCOUNT_SLOTS;
+ hash = jhash2(key, data->keylen, data->initval) % CONNCOUNT_SLOTS;
root = &data->root[hash];
parent = rcu_dereference_raw(root->rb_node);
@@ -630,8 +630,6 @@ struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int keylen
keylen == 0)
return ERR_PTR(-EINVAL);
- net_get_random_once(&conncount_rnd, sizeof(conncount_rnd));
-
data = kmalloc_obj(*data);
if (!data)
return ERR_PTR(-ENOMEM);
@@ -641,6 +639,7 @@ struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int keylen
data->keylen = keylen / sizeof(u32);
data->net = net;
+ data->initval = get_random_u32();
INIT_WORK(&data->gc_work, tree_gc_worker);
return data;