diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2008-10-08 05:35:07 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-10-08 05:35:07 -0400 |
commit | 0d55af8791bfb42e04cc456b348910582f230343 (patch) | |
tree | 619c5a6a46691ca90237d6ad239a4fb4391e61b9 | |
parent | 6058fa6bb96a5b6145cba10c5171f09c2783ca69 (diff) |
netfilter: netns nf_conntrack: per-netns statistics
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/net/netfilter/nf_conntrack.h | 8 | ||||
-rw-r--r-- | include/net/netns/conntrack.h | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 4 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 49 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 4 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_standalone.c | 4 |
6 files changed, 38 insertions, 32 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index f5447f143047..c95561050f78 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -290,12 +290,12 @@ extern unsigned int nf_conntrack_htable_size; | |||
290 | extern int nf_conntrack_checksum; | 290 | extern int nf_conntrack_checksum; |
291 | extern int nf_conntrack_max; | 291 | extern int nf_conntrack_max; |
292 | 292 | ||
293 | DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); | 293 | #define NF_CT_STAT_INC(net, count) \ |
294 | #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++) | 294 | (per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++) |
295 | #define NF_CT_STAT_INC_ATOMIC(count) \ | 295 | #define NF_CT_STAT_INC_ATOMIC(net, count) \ |
296 | do { \ | 296 | do { \ |
297 | local_bh_disable(); \ | 297 | local_bh_disable(); \ |
298 | __get_cpu_var(nf_conntrack_stat).count++; \ | 298 | per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++; \ |
299 | local_bh_enable(); \ | 299 | local_bh_enable(); \ |
300 | } while (0) | 300 | } while (0) |
301 | 301 | ||
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 9d5c1623c51f..fc0a46d64cc9 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h | |||
@@ -12,6 +12,7 @@ struct netns_ct { | |||
12 | struct hlist_head *hash; | 12 | struct hlist_head *hash; |
13 | struct hlist_head *expect_hash; | 13 | struct hlist_head *expect_hash; |
14 | struct hlist_head unconfirmed; | 14 | struct hlist_head unconfirmed; |
15 | struct ip_conntrack_stat *stat; | ||
15 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 16 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
16 | struct nf_conntrack_ecache *ecache; | 17 | struct nf_conntrack_ecache *ecache; |
17 | #endif | 18 | #endif |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index b2940836d107..fdc85b370783 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -294,7 +294,7 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) | |||
294 | if (!cpu_possible(cpu)) | 294 | if (!cpu_possible(cpu)) |
295 | continue; | 295 | continue; |
296 | *pos = cpu+1; | 296 | *pos = cpu+1; |
297 | return &per_cpu(nf_conntrack_stat, cpu); | 297 | return per_cpu_ptr(init_net.ct.stat, cpu); |
298 | } | 298 | } |
299 | 299 | ||
300 | return NULL; | 300 | return NULL; |
@@ -308,7 +308,7 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
308 | if (!cpu_possible(cpu)) | 308 | if (!cpu_possible(cpu)) |
309 | continue; | 309 | continue; |
310 | *pos = cpu+1; | 310 | *pos = cpu+1; |
311 | return &per_cpu(nf_conntrack_stat, cpu); | 311 | return per_cpu_ptr(init_net.ct.stat, cpu); |
312 | } | 312 | } |
313 | 313 | ||
314 | return NULL; | 314 | return NULL; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index b55944e5e4e2..1e87fa0cd3af 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -56,9 +56,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_untracked); | |||
56 | unsigned int nf_ct_log_invalid __read_mostly; | 56 | unsigned int nf_ct_log_invalid __read_mostly; |
57 | static struct kmem_cache *nf_conntrack_cachep __read_mostly; | 57 | static struct kmem_cache *nf_conntrack_cachep __read_mostly; |
58 | 58 | ||
59 | DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); | ||
60 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat); | ||
61 | |||
62 | static int nf_conntrack_hash_rnd_initted; | 59 | static int nf_conntrack_hash_rnd_initted; |
63 | static unsigned int nf_conntrack_hash_rnd; | 60 | static unsigned int nf_conntrack_hash_rnd; |
64 | 61 | ||
@@ -171,6 +168,7 @@ static void | |||
171 | destroy_conntrack(struct nf_conntrack *nfct) | 168 | destroy_conntrack(struct nf_conntrack *nfct) |
172 | { | 169 | { |
173 | struct nf_conn *ct = (struct nf_conn *)nfct; | 170 | struct nf_conn *ct = (struct nf_conn *)nfct; |
171 | struct net *net = nf_ct_net(ct); | ||
174 | struct nf_conntrack_l4proto *l4proto; | 172 | struct nf_conntrack_l4proto *l4proto; |
175 | 173 | ||
176 | pr_debug("destroy_conntrack(%p)\n", ct); | 174 | pr_debug("destroy_conntrack(%p)\n", ct); |
@@ -203,7 +201,7 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
203 | hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); | 201 | hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); |
204 | } | 202 | } |
205 | 203 | ||
206 | NF_CT_STAT_INC(delete); | 204 | NF_CT_STAT_INC(net, delete); |
207 | spin_unlock_bh(&nf_conntrack_lock); | 205 | spin_unlock_bh(&nf_conntrack_lock); |
208 | 206 | ||
209 | if (ct->master) | 207 | if (ct->master) |
@@ -216,6 +214,7 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
216 | static void death_by_timeout(unsigned long ul_conntrack) | 214 | static void death_by_timeout(unsigned long ul_conntrack) |
217 | { | 215 | { |
218 | struct nf_conn *ct = (void *)ul_conntrack; | 216 | struct nf_conn *ct = (void *)ul_conntrack; |
217 | struct net *net = nf_ct_net(ct); | ||
219 | struct nf_conn_help *help = nfct_help(ct); | 218 | struct nf_conn_help *help = nfct_help(ct); |
220 | struct nf_conntrack_helper *helper; | 219 | struct nf_conntrack_helper *helper; |
221 | 220 | ||
@@ -230,7 +229,7 @@ static void death_by_timeout(unsigned long ul_conntrack) | |||
230 | spin_lock_bh(&nf_conntrack_lock); | 229 | spin_lock_bh(&nf_conntrack_lock); |
231 | /* Inside lock so preempt is disabled on module removal path. | 230 | /* Inside lock so preempt is disabled on module removal path. |
232 | * Otherwise we can get spurious warnings. */ | 231 | * Otherwise we can get spurious warnings. */ |
233 | NF_CT_STAT_INC(delete_list); | 232 | NF_CT_STAT_INC(net, delete_list); |
234 | clean_from_lists(ct); | 233 | clean_from_lists(ct); |
235 | spin_unlock_bh(&nf_conntrack_lock); | 234 | spin_unlock_bh(&nf_conntrack_lock); |
236 | nf_ct_put(ct); | 235 | nf_ct_put(ct); |
@@ -249,11 +248,11 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) | |||
249 | local_bh_disable(); | 248 | local_bh_disable(); |
250 | hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { | 249 | hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { |
251 | if (nf_ct_tuple_equal(tuple, &h->tuple)) { | 250 | if (nf_ct_tuple_equal(tuple, &h->tuple)) { |
252 | NF_CT_STAT_INC(found); | 251 | NF_CT_STAT_INC(net, found); |
253 | local_bh_enable(); | 252 | local_bh_enable(); |
254 | return h; | 253 | return h; |
255 | } | 254 | } |
256 | NF_CT_STAT_INC(searched); | 255 | NF_CT_STAT_INC(net, searched); |
257 | } | 256 | } |
258 | local_bh_enable(); | 257 | local_bh_enable(); |
259 | 258 | ||
@@ -366,7 +365,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
366 | add_timer(&ct->timeout); | 365 | add_timer(&ct->timeout); |
367 | atomic_inc(&ct->ct_general.use); | 366 | atomic_inc(&ct->ct_general.use); |
368 | set_bit(IPS_CONFIRMED_BIT, &ct->status); | 367 | set_bit(IPS_CONFIRMED_BIT, &ct->status); |
369 | NF_CT_STAT_INC(insert); | 368 | NF_CT_STAT_INC(net, insert); |
370 | spin_unlock_bh(&nf_conntrack_lock); | 369 | spin_unlock_bh(&nf_conntrack_lock); |
371 | help = nfct_help(ct); | 370 | help = nfct_help(ct); |
372 | if (help && help->helper) | 371 | if (help && help->helper) |
@@ -381,7 +380,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
381 | return NF_ACCEPT; | 380 | return NF_ACCEPT; |
382 | 381 | ||
383 | out: | 382 | out: |
384 | NF_CT_STAT_INC(insert_failed); | 383 | NF_CT_STAT_INC(net, insert_failed); |
385 | spin_unlock_bh(&nf_conntrack_lock); | 384 | spin_unlock_bh(&nf_conntrack_lock); |
386 | return NF_DROP; | 385 | return NF_DROP; |
387 | } | 386 | } |
@@ -405,11 +404,11 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, | |||
405 | hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { | 404 | hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { |
406 | if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && | 405 | if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && |
407 | nf_ct_tuple_equal(tuple, &h->tuple)) { | 406 | nf_ct_tuple_equal(tuple, &h->tuple)) { |
408 | NF_CT_STAT_INC(found); | 407 | NF_CT_STAT_INC(net, found); |
409 | rcu_read_unlock_bh(); | 408 | rcu_read_unlock_bh(); |
410 | return 1; | 409 | return 1; |
411 | } | 410 | } |
412 | NF_CT_STAT_INC(searched); | 411 | NF_CT_STAT_INC(net, searched); |
413 | } | 412 | } |
414 | rcu_read_unlock_bh(); | 413 | rcu_read_unlock_bh(); |
415 | 414 | ||
@@ -454,7 +453,7 @@ static noinline int early_drop(struct net *net, unsigned int hash) | |||
454 | if (del_timer(&ct->timeout)) { | 453 | if (del_timer(&ct->timeout)) { |
455 | death_by_timeout((unsigned long)ct); | 454 | death_by_timeout((unsigned long)ct); |
456 | dropped = 1; | 455 | dropped = 1; |
457 | NF_CT_STAT_INC_ATOMIC(early_drop); | 456 | NF_CT_STAT_INC_ATOMIC(net, early_drop); |
458 | } | 457 | } |
459 | nf_ct_put(ct); | 458 | nf_ct_put(ct); |
460 | return dropped; | 459 | return dropped; |
@@ -581,7 +580,7 @@ init_conntrack(struct net *net, | |||
581 | ct->secmark = exp->master->secmark; | 580 | ct->secmark = exp->master->secmark; |
582 | #endif | 581 | #endif |
583 | nf_conntrack_get(&ct->master->ct_general); | 582 | nf_conntrack_get(&ct->master->ct_general); |
584 | NF_CT_STAT_INC(expect_new); | 583 | NF_CT_STAT_INC(net, expect_new); |
585 | } else { | 584 | } else { |
586 | struct nf_conntrack_helper *helper; | 585 | struct nf_conntrack_helper *helper; |
587 | 586 | ||
@@ -591,7 +590,7 @@ init_conntrack(struct net *net, | |||
591 | if (help) | 590 | if (help) |
592 | rcu_assign_pointer(help->helper, helper); | 591 | rcu_assign_pointer(help->helper, helper); |
593 | } | 592 | } |
594 | NF_CT_STAT_INC(new); | 593 | NF_CT_STAT_INC(net, new); |
595 | } | 594 | } |
596 | 595 | ||
597 | /* Overload tuple linked list to put us in unconfirmed list. */ | 596 | /* Overload tuple linked list to put us in unconfirmed list. */ |
@@ -683,7 +682,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
683 | 682 | ||
684 | /* Previously seen (loopback or untracked)? Ignore. */ | 683 | /* Previously seen (loopback or untracked)? Ignore. */ |
685 | if (skb->nfct) { | 684 | if (skb->nfct) { |
686 | NF_CT_STAT_INC_ATOMIC(ignore); | 685 | NF_CT_STAT_INC_ATOMIC(net, ignore); |
687 | return NF_ACCEPT; | 686 | return NF_ACCEPT; |
688 | } | 687 | } |
689 | 688 | ||
@@ -693,8 +692,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
693 | &dataoff, &protonum); | 692 | &dataoff, &protonum); |
694 | if (ret <= 0) { | 693 | if (ret <= 0) { |
695 | pr_debug("not prepared to track yet or error occured\n"); | 694 | pr_debug("not prepared to track yet or error occured\n"); |
696 | NF_CT_STAT_INC_ATOMIC(error); | 695 | NF_CT_STAT_INC_ATOMIC(net, error); |
697 | NF_CT_STAT_INC_ATOMIC(invalid); | 696 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
698 | return -ret; | 697 | return -ret; |
699 | } | 698 | } |
700 | 699 | ||
@@ -706,8 +705,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
706 | if (l4proto->error != NULL) { | 705 | if (l4proto->error != NULL) { |
707 | ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum); | 706 | ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum); |
708 | if (ret <= 0) { | 707 | if (ret <= 0) { |
709 | NF_CT_STAT_INC_ATOMIC(error); | 708 | NF_CT_STAT_INC_ATOMIC(net, error); |
710 | NF_CT_STAT_INC_ATOMIC(invalid); | 709 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
711 | return -ret; | 710 | return -ret; |
712 | } | 711 | } |
713 | } | 712 | } |
@@ -716,13 +715,13 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
716 | l3proto, l4proto, &set_reply, &ctinfo); | 715 | l3proto, l4proto, &set_reply, &ctinfo); |
717 | if (!ct) { | 716 | if (!ct) { |
718 | /* Not valid part of a connection */ | 717 | /* Not valid part of a connection */ |
719 | NF_CT_STAT_INC_ATOMIC(invalid); | 718 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
720 | return NF_ACCEPT; | 719 | return NF_ACCEPT; |
721 | } | 720 | } |
722 | 721 | ||
723 | if (IS_ERR(ct)) { | 722 | if (IS_ERR(ct)) { |
724 | /* Too stressed to deal. */ | 723 | /* Too stressed to deal. */ |
725 | NF_CT_STAT_INC_ATOMIC(drop); | 724 | NF_CT_STAT_INC_ATOMIC(net, drop); |
726 | return NF_DROP; | 725 | return NF_DROP; |
727 | } | 726 | } |
728 | 727 | ||
@@ -735,7 +734,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
735 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); | 734 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); |
736 | nf_conntrack_put(skb->nfct); | 735 | nf_conntrack_put(skb->nfct); |
737 | skb->nfct = NULL; | 736 | skb->nfct = NULL; |
738 | NF_CT_STAT_INC_ATOMIC(invalid); | 737 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
739 | return -ret; | 738 | return -ret; |
740 | } | 739 | } |
741 | 740 | ||
@@ -1043,6 +1042,7 @@ void nf_conntrack_cleanup(struct net *net) | |||
1043 | 1042 | ||
1044 | nf_conntrack_acct_fini(); | 1043 | nf_conntrack_acct_fini(); |
1045 | nf_conntrack_expect_fini(net); | 1044 | nf_conntrack_expect_fini(net); |
1045 | free_percpu(net->ct.stat); | ||
1046 | nf_conntrack_helper_fini(); | 1046 | nf_conntrack_helper_fini(); |
1047 | nf_conntrack_proto_fini(); | 1047 | nf_conntrack_proto_fini(); |
1048 | } | 1048 | } |
@@ -1152,6 +1152,9 @@ int nf_conntrack_init(struct net *net) | |||
1152 | max_factor = 4; | 1152 | max_factor = 4; |
1153 | } | 1153 | } |
1154 | atomic_set(&net->ct.count, 0); | 1154 | atomic_set(&net->ct.count, 0); |
1155 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); | ||
1156 | if (!net->ct.stat) | ||
1157 | goto err_stat; | ||
1155 | ret = nf_conntrack_ecache_init(net); | 1158 | ret = nf_conntrack_ecache_init(net); |
1156 | if (ret < 0) | 1159 | if (ret < 0) |
1157 | goto err_ecache; | 1160 | goto err_ecache; |
@@ -1222,5 +1225,7 @@ err_free_hash: | |||
1222 | err_hash: | 1225 | err_hash: |
1223 | nf_conntrack_ecache_fini(net); | 1226 | nf_conntrack_ecache_fini(net); |
1224 | err_ecache: | 1227 | err_ecache: |
1228 | free_percpu(net->ct.stat); | ||
1229 | err_stat: | ||
1225 | return -ENOMEM; | 1230 | return -ENOMEM; |
1226 | } | 1231 | } |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 6a09200049ee..b7f751171613 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -53,7 +53,7 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | |||
53 | master_help->expecting[exp->class]--; | 53 | master_help->expecting[exp->class]--; |
54 | nf_ct_expect_put(exp); | 54 | nf_ct_expect_put(exp); |
55 | 55 | ||
56 | NF_CT_STAT_INC(expect_delete); | 56 | NF_CT_STAT_INC(net, expect_delete); |
57 | } | 57 | } |
58 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); | 58 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); |
59 | 59 | ||
@@ -326,7 +326,7 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) | |||
326 | add_timer(&exp->timeout); | 326 | add_timer(&exp->timeout); |
327 | 327 | ||
328 | atomic_inc(&exp->use); | 328 | atomic_inc(&exp->use); |
329 | NF_CT_STAT_INC(expect_create); | 329 | NF_CT_STAT_INC(net, expect_create); |
330 | } | 330 | } |
331 | 331 | ||
332 | /* Race with expectations being used means we could have none to find; OK. */ | 332 | /* Race with expectations being used means we could have none to find; OK. */ |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 02eaf8722778..a4fdbbf363a1 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -203,7 +203,7 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) | |||
203 | if (!cpu_possible(cpu)) | 203 | if (!cpu_possible(cpu)) |
204 | continue; | 204 | continue; |
205 | *pos = cpu + 1; | 205 | *pos = cpu + 1; |
206 | return &per_cpu(nf_conntrack_stat, cpu); | 206 | return per_cpu_ptr(init_net.ct.stat, cpu); |
207 | } | 207 | } |
208 | 208 | ||
209 | return NULL; | 209 | return NULL; |
@@ -217,7 +217,7 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
217 | if (!cpu_possible(cpu)) | 217 | if (!cpu_possible(cpu)) |
218 | continue; | 218 | continue; |
219 | *pos = cpu + 1; | 219 | *pos = cpu + 1; |
220 | return &per_cpu(nf_conntrack_stat, cpu); | 220 | return per_cpu_ptr(init_net.ct.stat, cpu); |
221 | } | 221 | } |
222 | 222 | ||
223 | return NULL; | 223 | return NULL; |