aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-12-14 08:45:20 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2011-12-17 19:19:19 -0500
commitb3e0bfa71b1db9d7a9fbea6965867784fd00ca3c (patch)
tree2b8463810415b36edcb0e96b17f7a86047c1bfd5 /net/netfilter
parent76ad94fc5df865e34e09406614f29951a046394a (diff)
netfilter: nf_conntrack: use atomic64 for accounting counters
We can use atomic64_t infrastructure to avoid taking a spinlock in fast path, and remove inaccuracies while reading values in ctnetlink_dump_counters() and connbytes_mt() on 32bit arches. Suggested by Pablo. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_conntrack_acct.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c14
-rw-r--r--net/netfilter/nf_conntrack_netlink.c12
-rw-r--r--net/netfilter/xt_connbytes.c32
4 files changed, 31 insertions, 31 deletions
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 369df3f08d42..93329067a6a2 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -46,8 +46,8 @@ seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
46 return 0; 46 return 0;
47 47
48 return seq_printf(s, "packets=%llu bytes=%llu ", 48 return seq_printf(s, "packets=%llu bytes=%llu ",
49 (unsigned long long)acct[dir].packets, 49 (unsigned long long)atomic64_read(&acct[dir].packets),
50 (unsigned long long)acct[dir].bytes); 50 (unsigned long long)atomic64_read(&acct[dir].bytes));
51}; 51};
52EXPORT_SYMBOL_GPL(seq_print_acct); 52EXPORT_SYMBOL_GPL(seq_print_acct);
53 53
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 7202b0631cd6..8b2842e321fb 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1044,10 +1044,8 @@ acct:
1044 1044
1045 acct = nf_conn_acct_find(ct); 1045 acct = nf_conn_acct_find(ct);
1046 if (acct) { 1046 if (acct) {
1047 spin_lock_bh(&ct->lock); 1047 atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets);
1048 acct[CTINFO2DIR(ctinfo)].packets++; 1048 atomic64_add(skb->len, &acct[CTINFO2DIR(ctinfo)].bytes);
1049 acct[CTINFO2DIR(ctinfo)].bytes += skb->len;
1050 spin_unlock_bh(&ct->lock);
1051 } 1049 }
1052 } 1050 }
1053} 1051}
@@ -1063,11 +1061,9 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
1063 1061
1064 acct = nf_conn_acct_find(ct); 1062 acct = nf_conn_acct_find(ct);
1065 if (acct) { 1063 if (acct) {
1066 spin_lock_bh(&ct->lock); 1064 atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets);
1067 acct[CTINFO2DIR(ctinfo)].packets++; 1065 atomic64_add(skb->len - skb_network_offset(skb),
1068 acct[CTINFO2DIR(ctinfo)].bytes += 1066 &acct[CTINFO2DIR(ctinfo)].bytes);
1069 skb->len - skb_network_offset(skb);
1070 spin_unlock_bh(&ct->lock);
1071 } 1067 }
1072 } 1068 }
1073 1069
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ef21b221f036..a36e6553ddb3 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -219,9 +219,9 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
219 goto nla_put_failure; 219 goto nla_put_failure;
220 220
221 NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, 221 NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
222 cpu_to_be64(acct[dir].packets)); 222 cpu_to_be64(atomic64_read(&acct[dir].packets)));
223 NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, 223 NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
224 cpu_to_be64(acct[dir].bytes)); 224 cpu_to_be64(atomic64_read(&acct[dir].bytes)));
225 225
226 nla_nest_end(skb, nest_count); 226 nla_nest_end(skb, nest_count);
227 227
@@ -720,8 +720,12 @@ restart:
720 struct nf_conn_counter *acct; 720 struct nf_conn_counter *acct;
721 721
722 acct = nf_conn_acct_find(ct); 722 acct = nf_conn_acct_find(ct);
723 if (acct) 723 if (acct) {
724 memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX])); 724 atomic64_set(&acct[IP_CT_DIR_ORIGINAL].bytes, 0);
725 atomic64_set(&acct[IP_CT_DIR_ORIGINAL].packets, 0);
726 atomic64_set(&acct[IP_CT_DIR_REPLY].bytes, 0);
727 atomic64_set(&acct[IP_CT_DIR_REPLY].packets, 0);
728 }
725 } 729 }
726 } 730 }
727 if (cb->args[1]) { 731 if (cb->args[1]) {
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 5b138506690e..2b8418c257c9 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -40,46 +40,46 @@ connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par)
40 case XT_CONNBYTES_PKTS: 40 case XT_CONNBYTES_PKTS:
41 switch (sinfo->direction) { 41 switch (sinfo->direction) {
42 case XT_CONNBYTES_DIR_ORIGINAL: 42 case XT_CONNBYTES_DIR_ORIGINAL:
43 what = counters[IP_CT_DIR_ORIGINAL].packets; 43 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
44 break; 44 break;
45 case XT_CONNBYTES_DIR_REPLY: 45 case XT_CONNBYTES_DIR_REPLY:
46 what = counters[IP_CT_DIR_REPLY].packets; 46 what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
47 break; 47 break;
48 case XT_CONNBYTES_DIR_BOTH: 48 case XT_CONNBYTES_DIR_BOTH:
49 what = counters[IP_CT_DIR_ORIGINAL].packets; 49 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
50 what += counters[IP_CT_DIR_REPLY].packets; 50 what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
51 break; 51 break;
52 } 52 }
53 break; 53 break;
54 case XT_CONNBYTES_BYTES: 54 case XT_CONNBYTES_BYTES:
55 switch (sinfo->direction) { 55 switch (sinfo->direction) {
56 case XT_CONNBYTES_DIR_ORIGINAL: 56 case XT_CONNBYTES_DIR_ORIGINAL:
57 what = counters[IP_CT_DIR_ORIGINAL].bytes; 57 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
58 break; 58 break;
59 case XT_CONNBYTES_DIR_REPLY: 59 case XT_CONNBYTES_DIR_REPLY:
60 what = counters[IP_CT_DIR_REPLY].bytes; 60 what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
61 break; 61 break;
62 case XT_CONNBYTES_DIR_BOTH: 62 case XT_CONNBYTES_DIR_BOTH:
63 what = counters[IP_CT_DIR_ORIGINAL].bytes; 63 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
64 what += counters[IP_CT_DIR_REPLY].bytes; 64 what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
65 break; 65 break;
66 } 66 }
67 break; 67 break;
68 case XT_CONNBYTES_AVGPKT: 68 case XT_CONNBYTES_AVGPKT:
69 switch (sinfo->direction) { 69 switch (sinfo->direction) {
70 case XT_CONNBYTES_DIR_ORIGINAL: 70 case XT_CONNBYTES_DIR_ORIGINAL:
71 bytes = counters[IP_CT_DIR_ORIGINAL].bytes; 71 bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
72 pkts = counters[IP_CT_DIR_ORIGINAL].packets; 72 pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
73 break; 73 break;
74 case XT_CONNBYTES_DIR_REPLY: 74 case XT_CONNBYTES_DIR_REPLY:
75 bytes = counters[IP_CT_DIR_REPLY].bytes; 75 bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
76 pkts = counters[IP_CT_DIR_REPLY].packets; 76 pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
77 break; 77 break;
78 case XT_CONNBYTES_DIR_BOTH: 78 case XT_CONNBYTES_DIR_BOTH:
79 bytes = counters[IP_CT_DIR_ORIGINAL].bytes + 79 bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) +
80 counters[IP_CT_DIR_REPLY].bytes; 80 atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
81 pkts = counters[IP_CT_DIR_ORIGINAL].packets + 81 pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) +
82 counters[IP_CT_DIR_REPLY].packets; 82 atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
83 break; 83 break;
84 } 84 }
85 if (pkts != 0) 85 if (pkts != 0)