aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Piotr Oledzki <ole@ans.pl>2008-07-21 13:01:34 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-21 13:10:58 -0400
commit584015727a3b88b46602b20077b46cd04f8b4ab3 (patch)
treea9b4ec18e2181e03ee24b59b30f7408bcbcf140c
parent07a7c1070ed382ad4562e3a0d453fd2001d92f7b (diff)
netfilter: accounting rework: ct_extend + 64bit counters (v4)
Initially netfilter has had 64bit counters for conntrack-based accounting, but it was changed in 2.6.14 to save memory. Unfortunately in-kernel 64bit counters are still required, for example for "connbytes" extension. However, 64bit counters waste a lot of memory and it was not possible to enable/disable it runtime. This patch: - reimplements accounting with respect to the extension infrastructure, - makes one global version of seq_print_acct() instead of two seq_print_counters(), - makes it possible to enable it at boot time (for CONFIG_SYSCTL/CONFIG_SYSFS=n), - makes it possible to enable/disable it at runtime by sysctl or sysfs, - extends counters from 32bit to 64bit, - renames ip_conntrack_counter -> nf_conn_counter, - enables accounting code unconditionally (no longer depends on CONFIG_NF_CT_ACCT), - set initial accounting enable state based on CONFIG_NF_CT_ACCT - removes buggy IPCT_COUNTER_FILLING event handling. If accounting is enabled newly created connections get additional acct extend. Old connections are not changed as it is not possible to add a ct_extend area to confirmed conntrack. Accounting is performed for all connections with acct extend regardless of a current state of "net.netfilter.nf_conntrack_acct". Signed-off-by: Krzysztof Piotr Oledzki <ole@ans.pl> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--Documentation/kernel-parameters.txt7
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h8
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h8
-rw-r--r--include/net/netfilter/nf_conntrack.h6
-rw-r--r--include/net/netfilter/nf_conntrack_acct.h51
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h2
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c18
-rw-r--r--net/netfilter/Kconfig9
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/nf_conntrack_acct.c104
-rw-r--r--net/netfilter/nf_conntrack_core.c39
-rw-r--r--net/netfilter/nf_conntrack_netlink.c44
-rw-r--r--net/netfilter/nf_conntrack_standalone.c18
-rw-r--r--net/netfilter/xt_connbytes.c8
15 files changed, 248 insertions, 86 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 86334b6f8238..9f73587219e8 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches
336Why: Over 1K .text/.data size reduction, data is available in other 336Why: Over 1K .text/.data size reduction, data is available in other
337 ways (ioctls) 337 ways (ioctls)
338Who: Johannes Berg <johannes@sipsolutions.net> 338Who: Johannes Berg <johannes@sipsolutions.net>
339
340---------------------------
341
342What: CONFIG_NF_CT_ACCT
343When: 2.6.29
344Why: Accounting can now be enabled/disabled without kernel recompilation.
345 Currently used only to set a default value for a feature that is also
346 controlled by a kernel/module/sysfs/sysctl parameter.
347Who: Krzysztof Piotr Oledzki <ole@ans.pl>
348
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 09ad7450647b..e4ef27584408 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file
1279 This usage is only documented in each driver source 1279 This usage is only documented in each driver source
1280 file if at all. 1280 file if at all.
1281 1281
1282 nf_conntrack.acct=
1283 [NETFILTER] Enable connection tracking flow accounting
1284 0 to disable accounting
1285 1 to enable accounting
1286 Default value depends on CONFIG_NF_CT_ACCT that is
1287 going to be removed in 2.6.29.
1288
1282 nfsaddrs= [NFS] 1289 nfsaddrs= [NFS]
1283 See Documentation/filesystems/nfsroot.txt. 1290 See Documentation/filesystems/nfsroot.txt.
1284 1291
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index bad1eb760f61..885cbe282260 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -122,7 +122,7 @@ enum ip_conntrack_events
122 IPCT_NATINFO_BIT = 10, 122 IPCT_NATINFO_BIT = 10,
123 IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), 123 IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
124 124
125 /* Counter highest bit has been set */ 125 /* Counter highest bit has been set, unused */
126 IPCT_COUNTER_FILLING_BIT = 11, 126 IPCT_COUNTER_FILLING_BIT = 11,
127 IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), 127 IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
128 128
@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events {
145}; 145};
146 146
147#ifdef __KERNEL__ 147#ifdef __KERNEL__
148struct ip_conntrack_counter
149{
150 u_int32_t packets;
151 u_int32_t bytes;
152};
153
154struct ip_conntrack_stat 148struct ip_conntrack_stat
155{ 149{
156 unsigned int searched; 150 unsigned int searched;
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 759bc043dc65..c19595c89304 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp {
115 115
116enum ctattr_counters { 116enum ctattr_counters {
117 CTA_COUNTERS_UNSPEC, 117 CTA_COUNTERS_UNSPEC,
118 CTA_COUNTERS_PACKETS, /* old 64bit counters */ 118 CTA_COUNTERS_PACKETS, /* 64bit counters */
119 CTA_COUNTERS_BYTES, /* old 64bit counters */ 119 CTA_COUNTERS_BYTES, /* 64bit counters */
120 CTA_COUNTERS32_PACKETS, 120 CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
121 CTA_COUNTERS32_BYTES, 121 CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
122 __CTA_COUNTERS_MAX 122 __CTA_COUNTERS_MAX
123}; 123};
124#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) 124#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 8f5b75734dd0..0741ad592da0 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -88,7 +88,6 @@ struct nf_conn_help {
88 u8 expecting[NF_CT_MAX_EXPECT_CLASSES]; 88 u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
89}; 89};
90 90
91
92#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 91#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
93#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 92#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
94 93
@@ -111,11 +110,6 @@ struct nf_conn
111 /* Timer function; drops refcnt when it goes off. */ 110 /* Timer function; drops refcnt when it goes off. */
112 struct timer_list timeout; 111 struct timer_list timeout;
113 112
114#ifdef CONFIG_NF_CT_ACCT
115 /* Accounting Information (same cache line as other written members) */
116 struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
117#endif
118
119#if defined(CONFIG_NF_CONNTRACK_MARK) 113#if defined(CONFIG_NF_CONNTRACK_MARK)
120 u_int32_t mark; 114 u_int32_t mark;
121#endif 115#endif
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
new file mode 100644
index 000000000000..5d5ae55d54c4
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -0,0 +1,51 @@
1/*
2 * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _NF_CONNTRACK_ACCT_H
10#define _NF_CONNTRACK_ACCT_H
11#include <linux/netfilter/nf_conntrack_common.h>
12#include <linux/netfilter/nf_conntrack_tuple_common.h>
13#include <net/netfilter/nf_conntrack.h>
14#include <net/netfilter/nf_conntrack_extend.h>
15
16struct nf_conn_counter {
17 u_int64_t packets;
18 u_int64_t bytes;
19};
20
21extern int nf_ct_acct;
22
23static inline
24struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
25{
26 return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
27}
28
29static inline
30struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
31{
32 struct nf_conn_counter *acct;
33
34 if (!nf_ct_acct)
35 return NULL;
36
37 acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
38 if (!acct)
39 pr_debug("failed to add accounting extension area");
40
41
42 return acct;
43};
44
45extern unsigned int
46seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
47
48extern int nf_conntrack_acct_init(void);
49extern void nf_conntrack_acct_fini(void);
50
51#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index f80c0ed6d870..da8ee52613a5 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -7,11 +7,13 @@ enum nf_ct_ext_id
7{ 7{
8 NF_CT_EXT_HELPER, 8 NF_CT_EXT_HELPER,
9 NF_CT_EXT_NAT, 9 NF_CT_EXT_NAT,
10 NF_CT_EXT_ACCT,
10 NF_CT_EXT_NUM, 11 NF_CT_EXT_NUM,
11}; 12};
12 13
13#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help 14#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
14#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat 15#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
16#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
15 17
16/* Extensions: optional stuff which isn't permanently in struct. */ 18/* Extensions: optional stuff which isn't permanently in struct. */
17struct nf_ct_ext { 19struct nf_ct_ext {
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 40a46d482490..3a020720e40b 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -18,19 +18,7 @@
18#include <net/netfilter/nf_conntrack_l3proto.h> 18#include <net/netfilter/nf_conntrack_l3proto.h>
19#include <net/netfilter/nf_conntrack_l4proto.h> 19#include <net/netfilter/nf_conntrack_l4proto.h>
20#include <net/netfilter/nf_conntrack_expect.h> 20#include <net/netfilter/nf_conntrack_expect.h>
21 21#include <net/netfilter/nf_conntrack_acct.h>
22#ifdef CONFIG_NF_CT_ACCT
23static unsigned int
24seq_print_counters(struct seq_file *s,
25 const struct ip_conntrack_counter *counter)
26{
27 return seq_printf(s, "packets=%llu bytes=%llu ",
28 (unsigned long long)counter->packets,
29 (unsigned long long)counter->bytes);
30}
31#else
32#define seq_print_counters(x, y) 0
33#endif
34 22
35struct ct_iter_state { 23struct ct_iter_state {
36 unsigned int bucket; 24 unsigned int bucket;
@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
127 l3proto, l4proto)) 115 l3proto, l4proto))
128 return -ENOSPC; 116 return -ENOSPC;
129 117
130 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) 118 if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
131 return -ENOSPC; 119 return -ENOSPC;
132 120
133 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 121 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -138,7 +126,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
138 l3proto, l4proto)) 126 l3proto, l4proto))
139 return -ENOSPC; 127 return -ENOSPC;
140 128
141 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) 129 if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
142 return -ENOSPC; 130 return -ENOSPC;
143 131
144 if (test_bit(IPS_ASSURED_BIT, &ct->status)) 132 if (test_bit(IPS_ASSURED_BIT, &ct->status))
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 316c7af1d2b1..ee898e74808d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -49,6 +49,15 @@ config NF_CT_ACCT
49 Those counters can be used for flow-based accounting or the 49 Those counters can be used for flow-based accounting or the
50 `connbytes' match. 50 `connbytes' match.
51 51
52 Please note that currently this option only sets a default state.
53 You may change it at boot time with nf_conntrack.acct=0/1 kernel
54 paramater or by loading the nf_conntrack module with acct=0/1.
55
56 You may also disable/enable it on a running system with:
57 sysctl net.netfilter.nf_conntrack_acct=0/1
58
59 This option will be removed in 2.6.29.
60
52 If unsure, say `N'. 61 If unsure, say `N'.
53 62
54config NF_CONNTRACK_MARK 63config NF_CONNTRACK_MARK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 5c4b183f6422..3bd2cc556aea 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2 2
3nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o 3nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o
4nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o 4nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
5 5
6obj-$(CONFIG_NETFILTER) = netfilter.o 6obj-$(CONFIG_NETFILTER) = netfilter.o
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
new file mode 100644
index 000000000000..59bd8b903a19
--- /dev/null
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -0,0 +1,104 @@
1/* Accouting handling for netfilter. */
2
3/*
4 * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/netfilter.h>
12#include <linux/kernel.h>
13#include <linux/moduleparam.h>
14
15#include <net/netfilter/nf_conntrack.h>
16#include <net/netfilter/nf_conntrack_extend.h>
17#include <net/netfilter/nf_conntrack_acct.h>
18
19#ifdef CONFIG_NF_CT_ACCT
20#define NF_CT_ACCT_DEFAULT 1
21#else
22#define NF_CT_ACCT_DEFAULT 0
23#endif
24
25int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
26EXPORT_SYMBOL_GPL(nf_ct_acct);
27
28module_param_named(acct, nf_ct_acct, bool, 0644);
29MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
30
31#ifdef CONFIG_SYSCTL
32static struct ctl_table_header *acct_sysctl_header;
33static struct ctl_table acct_sysctl_table[] = {
34 {
35 .ctl_name = CTL_UNNUMBERED,
36 .procname = "nf_conntrack_acct",
37 .data = &nf_ct_acct,
38 .maxlen = sizeof(unsigned int),
39 .mode = 0644,
40 .proc_handler = &proc_dointvec,
41 },
42 {}
43};
44#endif /* CONFIG_SYSCTL */
45
46unsigned int
47seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
48{
49 struct nf_conn_counter *acct;
50
51 acct = nf_conn_acct_find(ct);
52 if (!acct)
53 return 0;
54
55 return seq_printf(s, "packets=%llu bytes=%llu ",
56 (unsigned long long)acct[dir].packets,
57 (unsigned long long)acct[dir].bytes);
58};
59EXPORT_SYMBOL_GPL(seq_print_acct);
60
61static struct nf_ct_ext_type acct_extend __read_mostly = {
62 .len = sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),
63 .align = __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),
64 .id = NF_CT_EXT_ACCT,
65};
66
67int nf_conntrack_acct_init(void)
68{
69 int ret;
70
71#ifdef CONFIG_NF_CT_ACCT
72 printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
73 printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
74 printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
75#endif
76
77 ret = nf_ct_extend_register(&acct_extend);
78 if (ret < 0) {
79 printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
80 return ret;
81 }
82
83#ifdef CONFIG_SYSCTL
84 acct_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
85 acct_sysctl_table);
86
87 if (!acct_sysctl_header) {
88 nf_ct_extend_unregister(&acct_extend);
89
90 printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
91 return -ENOMEM;
92 }
93#endif
94
95 return 0;
96}
97
98void nf_conntrack_acct_fini(void)
99{
100#ifdef CONFIG_SYSCTL
101 unregister_sysctl_table(acct_sysctl_header);
102#endif
103 nf_ct_extend_unregister(&acct_extend);
104}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 28d03e64200b..c519d090bdb9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -37,6 +37,7 @@
37#include <net/netfilter/nf_conntrack_helper.h> 37#include <net/netfilter/nf_conntrack_helper.h>
38#include <net/netfilter/nf_conntrack_core.h> 38#include <net/netfilter/nf_conntrack_core.h>
39#include <net/netfilter/nf_conntrack_extend.h> 39#include <net/netfilter/nf_conntrack_extend.h>
40#include <net/netfilter/nf_conntrack_acct.h>
40 41
41#define NF_CONNTRACK_VERSION "0.5.0" 42#define NF_CONNTRACK_VERSION "0.5.0"
42 43
@@ -555,6 +556,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
555 return NULL; 556 return NULL;
556 } 557 }
557 558
559 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
560
558 spin_lock_bh(&nf_conntrack_lock); 561 spin_lock_bh(&nf_conntrack_lock);
559 exp = nf_ct_find_expectation(tuple); 562 exp = nf_ct_find_expectation(tuple);
560 if (exp) { 563 if (exp) {
@@ -828,17 +831,16 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
828 } 831 }
829 832
830acct: 833acct:
831#ifdef CONFIG_NF_CT_ACCT
832 if (do_acct) { 834 if (do_acct) {
833 ct->counters[CTINFO2DIR(ctinfo)].packets++; 835 struct nf_conn_counter *acct;
834 ct->counters[CTINFO2DIR(ctinfo)].bytes +=
835 skb->len - skb_network_offset(skb);
836 836
837 if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) 837 acct = nf_conn_acct_find(ct);
838 || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) 838 if (acct) {
839 event |= IPCT_COUNTER_FILLING; 839 acct[CTINFO2DIR(ctinfo)].packets++;
840 acct[CTINFO2DIR(ctinfo)].bytes +=
841 skb->len - skb_network_offset(skb);
842 }
840 } 843 }
841#endif
842 844
843 spin_unlock_bh(&nf_conntrack_lock); 845 spin_unlock_bh(&nf_conntrack_lock);
844 846
@@ -853,15 +855,19 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
853 const struct sk_buff *skb, 855 const struct sk_buff *skb,
854 int do_acct) 856 int do_acct)
855{ 857{
856#ifdef CONFIG_NF_CT_ACCT
857 if (do_acct) { 858 if (do_acct) {
859 struct nf_conn_counter *acct;
860
858 spin_lock_bh(&nf_conntrack_lock); 861 spin_lock_bh(&nf_conntrack_lock);
859 ct->counters[CTINFO2DIR(ctinfo)].packets++; 862 acct = nf_conn_acct_find(ct);
860 ct->counters[CTINFO2DIR(ctinfo)].bytes += 863 if (acct) {
861 skb->len - skb_network_offset(skb); 864 acct[CTINFO2DIR(ctinfo)].packets++;
865 acct[CTINFO2DIR(ctinfo)].bytes +=
866 skb->len - skb_network_offset(skb);
867 }
862 spin_unlock_bh(&nf_conntrack_lock); 868 spin_unlock_bh(&nf_conntrack_lock);
863 } 869 }
864#endif 870
865 if (del_timer(&ct->timeout)) { 871 if (del_timer(&ct->timeout)) {
866 ct->timeout.function((unsigned long)ct); 872 ct->timeout.function((unsigned long)ct);
867 return true; 873 return true;
@@ -1029,6 +1035,7 @@ void nf_conntrack_cleanup(void)
1029 nf_conntrack_proto_fini(); 1035 nf_conntrack_proto_fini();
1030 nf_conntrack_helper_fini(); 1036 nf_conntrack_helper_fini();
1031 nf_conntrack_expect_fini(); 1037 nf_conntrack_expect_fini();
1038 nf_conntrack_acct_fini();
1032} 1039}
1033 1040
1034struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) 1041struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
@@ -1168,6 +1175,10 @@ int __init nf_conntrack_init(void)
1168 if (ret < 0) 1175 if (ret < 0)
1169 goto out_fini_expect; 1176 goto out_fini_expect;
1170 1177
1178 ret = nf_conntrack_acct_init();
1179 if (ret < 0)
1180 goto out_fini_helper;
1181
1171 /* For use by REJECT target */ 1182 /* For use by REJECT target */
1172 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); 1183 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
1173 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); 1184 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
@@ -1180,6 +1191,8 @@ int __init nf_conntrack_init(void)
1180 1191
1181 return ret; 1192 return ret;
1182 1193
1194out_fini_helper:
1195 nf_conntrack_helper_fini();
1183out_fini_expect: 1196out_fini_expect:
1184 nf_conntrack_expect_fini(); 1197 nf_conntrack_expect_fini();
1185out_fini_proto: 1198out_fini_proto:
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 95a7967731f9..105a616c5c78 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -37,6 +37,7 @@
37#include <net/netfilter/nf_conntrack_l3proto.h> 37#include <net/netfilter/nf_conntrack_l3proto.h>
38#include <net/netfilter/nf_conntrack_l4proto.h> 38#include <net/netfilter/nf_conntrack_l4proto.h>
39#include <net/netfilter/nf_conntrack_tuple.h> 39#include <net/netfilter/nf_conntrack_tuple.h>
40#include <net/netfilter/nf_conntrack_acct.h>
40#ifdef CONFIG_NF_NAT_NEEDED 41#ifdef CONFIG_NF_NAT_NEEDED
41#include <net/netfilter/nf_nat_core.h> 42#include <net/netfilter/nf_nat_core.h>
42#include <net/netfilter/nf_nat_protocol.h> 43#include <net/netfilter/nf_nat_protocol.h>
@@ -206,22 +207,26 @@ nla_put_failure:
206 return -1; 207 return -1;
207} 208}
208 209
209#ifdef CONFIG_NF_CT_ACCT
210static int 210static int
211ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, 211ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
212 enum ip_conntrack_dir dir) 212 enum ip_conntrack_dir dir)
213{ 213{
214 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; 214 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
215 struct nlattr *nest_count; 215 struct nlattr *nest_count;
216 const struct nf_conn_counter *acct;
217
218 acct = nf_conn_acct_find(ct);
219 if (!acct)
220 return 0;
216 221
217 nest_count = nla_nest_start(skb, type | NLA_F_NESTED); 222 nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
218 if (!nest_count) 223 if (!nest_count)
219 goto nla_put_failure; 224 goto nla_put_failure;
220 225
221 NLA_PUT_BE32(skb, CTA_COUNTERS32_PACKETS, 226 NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
222 htonl(ct->counters[dir].packets)); 227 cpu_to_be64(acct[dir].packets));
223 NLA_PUT_BE32(skb, CTA_COUNTERS32_BYTES, 228 NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
224 htonl(ct->counters[dir].bytes)); 229 cpu_to_be64(acct[dir].bytes));
225 230
226 nla_nest_end(skb, nest_count); 231 nla_nest_end(skb, nest_count);
227 232
@@ -230,9 +235,6 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
230nla_put_failure: 235nla_put_failure:
231 return -1; 236 return -1;
232} 237}
233#else
234#define ctnetlink_dump_counters(a, b, c) (0)
235#endif
236 238
237#ifdef CONFIG_NF_CONNTRACK_MARK 239#ifdef CONFIG_NF_CONNTRACK_MARK
238static inline int 240static inline int
@@ -501,11 +503,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
501 goto nla_put_failure; 503 goto nla_put_failure;
502#endif 504#endif
503 505
504 if (events & IPCT_COUNTER_FILLING &&
505 (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
506 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
507 goto nla_put_failure;
508
509 if (events & IPCT_RELATED && 506 if (events & IPCT_RELATED &&
510 ctnetlink_dump_master(skb, ct) < 0) 507 ctnetlink_dump_master(skb, ct) < 0)
511 goto nla_put_failure; 508 goto nla_put_failure;
@@ -576,11 +573,15 @@ restart:
576 cb->args[1] = (unsigned long)ct; 573 cb->args[1] = (unsigned long)ct;
577 goto out; 574 goto out;
578 } 575 }
579#ifdef CONFIG_NF_CT_ACCT 576
580 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == 577 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
581 IPCTNL_MSG_CT_GET_CTRZERO) 578 IPCTNL_MSG_CT_GET_CTRZERO) {
582 memset(&ct->counters, 0, sizeof(ct->counters)); 579 struct nf_conn_counter *acct;
583#endif 580
581 acct = nf_conn_acct_find(ct);
582 if (acct)
583 memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
584 }
584 } 585 }
585 if (cb->args[1]) { 586 if (cb->args[1]) {
586 cb->args[1] = 0; 587 cb->args[1] = 0;
@@ -832,14 +833,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
832 u_int8_t u3 = nfmsg->nfgen_family; 833 u_int8_t u3 = nfmsg->nfgen_family;
833 int err = 0; 834 int err = 0;
834 835
835 if (nlh->nlmsg_flags & NLM_F_DUMP) { 836 if (nlh->nlmsg_flags & NLM_F_DUMP)
836#ifndef CONFIG_NF_CT_ACCT
837 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
838 return -ENOTSUPP;
839#endif
840 return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, 837 return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
841 ctnetlink_done); 838 ctnetlink_done);
842 }
843 839
844 if (cda[CTA_TUPLE_ORIG]) 840 if (cda[CTA_TUPLE_ORIG])
845 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); 841 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
@@ -1152,6 +1148,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
1152 goto err; 1148 goto err;
1153 } 1149 }
1154 1150
1151 nf_ct_acct_ext_add(ct, GFP_KERNEL);
1152
1155#if defined(CONFIG_NF_CONNTRACK_MARK) 1153#if defined(CONFIG_NF_CONNTRACK_MARK)
1156 if (cda[CTA_MARK]) 1154 if (cda[CTA_MARK])
1157 ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); 1155 ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 46ea542d0df9..869ef9349d0f 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -25,6 +25,7 @@
25#include <net/netfilter/nf_conntrack_l4proto.h> 25#include <net/netfilter/nf_conntrack_l4proto.h>
26#include <net/netfilter/nf_conntrack_expect.h> 26#include <net/netfilter/nf_conntrack_expect.h>
27#include <net/netfilter/nf_conntrack_helper.h> 27#include <net/netfilter/nf_conntrack_helper.h>
28#include <net/netfilter/nf_conntrack_acct.h>
28 29
29MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
30 31
@@ -38,19 +39,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
38} 39}
39EXPORT_SYMBOL_GPL(print_tuple); 40EXPORT_SYMBOL_GPL(print_tuple);
40 41
41#ifdef CONFIG_NF_CT_ACCT
42static unsigned int
43seq_print_counters(struct seq_file *s,
44 const struct ip_conntrack_counter *counter)
45{
46 return seq_printf(s, "packets=%llu bytes=%llu ",
47 (unsigned long long)counter->packets,
48 (unsigned long long)counter->bytes);
49}
50#else
51#define seq_print_counters(x, y) 0
52#endif
53
54struct ct_iter_state { 42struct ct_iter_state {
55 unsigned int bucket; 43 unsigned int bucket;
56}; 44};
@@ -146,7 +134,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
146 l3proto, l4proto)) 134 l3proto, l4proto))
147 return -ENOSPC; 135 return -ENOSPC;
148 136
149 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) 137 if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
150 return -ENOSPC; 138 return -ENOSPC;
151 139
152 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 140 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -157,7 +145,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
157 l3proto, l4proto)) 145 l3proto, l4proto))
158 return -ENOSPC; 146 return -ENOSPC;
159 147
160 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) 148 if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
161 return -ENOSPC; 149 return -ENOSPC;
162 150
163 if (test_bit(IPS_ASSURED_BIT, &ct->status)) 151 if (test_bit(IPS_ASSURED_BIT, &ct->status))
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index d7e8983cd37f..3e39c4fe1931 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -8,6 +8,7 @@
8#include <linux/netfilter/x_tables.h> 8#include <linux/netfilter/x_tables.h>
9#include <linux/netfilter/xt_connbytes.h> 9#include <linux/netfilter/xt_connbytes.h>
10#include <net/netfilter/nf_conntrack.h> 10#include <net/netfilter/nf_conntrack.h>
11#include <net/netfilter/nf_conntrack_acct.h>
11 12
12MODULE_LICENSE("GPL"); 13MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 14MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -27,12 +28,15 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in,
27 u_int64_t what = 0; /* initialize to make gcc happy */ 28 u_int64_t what = 0; /* initialize to make gcc happy */
28 u_int64_t bytes = 0; 29 u_int64_t bytes = 0;
29 u_int64_t pkts = 0; 30 u_int64_t pkts = 0;
30 const struct ip_conntrack_counter *counters; 31 const struct nf_conn_counter *counters;
31 32
32 ct = nf_ct_get(skb, &ctinfo); 33 ct = nf_ct_get(skb, &ctinfo);
33 if (!ct) 34 if (!ct)
34 return false; 35 return false;
35 counters = ct->counters; 36
37 counters = nf_conn_acct_find(ct);
38 if (!counters)
39 return false;
36 40
37 switch (sinfo->what) { 41 switch (sinfo->what) {
38 case XT_CONNBYTES_PKTS: 42 case XT_CONNBYTES_PKTS: