aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-10-08 05:35:07 -0400
committerPatrick McHardy <kaber@trash.net>2008-10-08 05:35:07 -0400
commit0d55af8791bfb42e04cc456b348910582f230343 (patch)
tree619c5a6a46691ca90237d6ad239a4fb4391e61b9
parent6058fa6bb96a5b6145cba10c5171f09c2783ca69 (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.h8
-rw-r--r--include/net/netns/conntrack.h1
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c49
-rw-r--r--net/netfilter/nf_conntrack_expect.c4
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
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;
290extern int nf_conntrack_checksum; 290extern int nf_conntrack_checksum;
291extern int nf_conntrack_max; 291extern int nf_conntrack_max;
292 292
293DECLARE_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) \
296do { \ 296do { \
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);
56unsigned int nf_ct_log_invalid __read_mostly; 56unsigned int nf_ct_log_invalid __read_mostly;
57static struct kmem_cache *nf_conntrack_cachep __read_mostly; 57static struct kmem_cache *nf_conntrack_cachep __read_mostly;
58 58
59DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
60EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
61
62static int nf_conntrack_hash_rnd_initted; 59static int nf_conntrack_hash_rnd_initted;
63static unsigned int nf_conntrack_hash_rnd; 60static unsigned int nf_conntrack_hash_rnd;
64 61
@@ -171,6 +168,7 @@ static void
171destroy_conntrack(struct nf_conntrack *nfct) 168destroy_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)
216static void death_by_timeout(unsigned long ul_conntrack) 214static 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
383out: 382out:
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:
1222err_hash: 1225err_hash:
1223 nf_conntrack_ecache_fini(net); 1226 nf_conntrack_ecache_fini(net);
1224err_ecache: 1227err_ecache:
1228 free_percpu(net->ct.stat);
1229err_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}
58EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); 58EXPORT_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;