Skip to content

Commit 2ba3911

Browse files
YiHungWeiummakynes
authored andcommitted
netfilter: nf_conncount: Move locking into count_tree()
This patch is originally from Florian Westphal. This is a preparation patch to allow lockless traversal of the tree via RCU. Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 976afca commit 2ba3911

File tree

1 file changed

+25
-27
lines changed

1 file changed

+25
-27
lines changed

net/netfilter/nf_conncount.c

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -262,18 +262,26 @@ static void tree_nodes_free(struct rb_root *root,
262262
}
263263

264264
static unsigned int
265-
count_tree(struct net *net, struct rb_root *root,
266-
const u32 *key, u8 keylen,
265+
count_tree(struct net *net,
266+
struct nf_conncount_data *data,
267+
const u32 *key,
267268
const struct nf_conntrack_tuple *tuple,
268269
const struct nf_conntrack_zone *zone)
269270
{
270271
struct nf_conncount_rb *gc_nodes[CONNCOUNT_GC_MAX_NODES];
272+
struct rb_root *root;
271273
struct rb_node **rbnode, *parent;
272274
struct nf_conncount_rb *rbconn;
273275
struct nf_conncount_tuple *conn;
274-
unsigned int gc_count;
276+
unsigned int gc_count, hash;
275277
bool no_gc = false;
278+
unsigned int count = 0;
279+
u8 keylen = data->keylen;
276280

281+
hash = jhash2(key, data->keylen, conncount_rnd) % CONNCOUNT_SLOTS;
282+
root = &data->root[hash];
283+
284+
spin_lock_bh(&nf_conncount_locks[hash % CONNCOUNT_LOCK_SLOTS]);
277285
restart:
278286
gc_count = 0;
279287
parent = NULL;
@@ -292,20 +300,20 @@ count_tree(struct net *net, struct rb_root *root,
292300
rbnode = &((*rbnode)->rb_right);
293301
} else {
294302
/* same source network -> be counted! */
295-
unsigned int count;
296-
297303
nf_conncount_lookup(net, &rbconn->list, tuple, zone,
298304
&addit);
299305
count = rbconn->list.count;
300306

301307
tree_nodes_free(root, gc_nodes, gc_count);
302308
if (!addit)
303-
return count;
309+
goto out_unlock;
304310

305311
if (!nf_conncount_add(&rbconn->list, tuple, zone))
306-
return 0; /* hotdrop */
312+
count = 0; /* hotdrop */
313+
goto out_unlock;
307314

308-
return count + 1;
315+
count++;
316+
goto out_unlock;
309317
}
310318

311319
if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes))
@@ -328,18 +336,18 @@ count_tree(struct net *net, struct rb_root *root,
328336
goto restart;
329337
}
330338

339+
count = 0;
331340
if (!tuple)
332-
return 0;
333-
341+
goto out_unlock;
334342
/* no match, need to insert new node */
335343
rbconn = kmem_cache_alloc(conncount_rb_cachep, GFP_ATOMIC);
336344
if (rbconn == NULL)
337-
return 0;
345+
goto out_unlock;
338346

339347
conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
340348
if (conn == NULL) {
341349
kmem_cache_free(conncount_rb_cachep, rbconn);
342-
return 0;
350+
goto out_unlock;
343351
}
344352

345353
conn->tuple = *tuple;
@@ -348,10 +356,13 @@ count_tree(struct net *net, struct rb_root *root,
348356

349357
nf_conncount_list_init(&rbconn->list);
350358
list_add(&conn->node, &rbconn->list.head);
359+
count = 1;
351360

352361
rb_link_node(&rbconn->node, parent, rbnode);
353362
rb_insert_color(&rbconn->node, root);
354-
return 1;
363+
out_unlock:
364+
spin_unlock_bh(&nf_conncount_locks[hash % CONNCOUNT_LOCK_SLOTS]);
365+
return count;
355366
}
356367

357368
/* Count and return number of conntrack entries in 'net' with particular 'key'.
@@ -363,20 +374,7 @@ unsigned int nf_conncount_count(struct net *net,
363374
const struct nf_conntrack_tuple *tuple,
364375
const struct nf_conntrack_zone *zone)
365376
{
366-
struct rb_root *root;
367-
int count;
368-
u32 hash;
369-
370-
hash = jhash2(key, data->keylen, conncount_rnd) % CONNCOUNT_SLOTS;
371-
root = &data->root[hash];
372-
373-
spin_lock_bh(&nf_conncount_locks[hash % CONNCOUNT_LOCK_SLOTS]);
374-
375-
count = count_tree(net, root, key, data->keylen, tuple, zone);
376-
377-
spin_unlock_bh(&nf_conncount_locks[hash % CONNCOUNT_LOCK_SLOTS]);
378-
379-
return count;
377+
return count_tree(net, data, key, tuple, zone);
380378
}
381379
EXPORT_SYMBOL_GPL(nf_conncount_count);
382380

0 commit comments

Comments
 (0)