Skip to content

Commit 5840157

Browse files
ole2pldavem330
authored andcommitted
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>
1 parent 07a7c10 commit 5840157

15 files changed

+248
-86
lines changed

Documentation/feature-removal-schedule.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches
336336
Why: Over 1K .text/.data size reduction, data is available in other
337337
ways (ioctls)
338338
Who: Johannes Berg <johannes@sipsolutions.net>
339+
340+
---------------------------
341+
342+
What: CONFIG_NF_CT_ACCT
343+
When: 2.6.29
344+
Why: 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.
347+
Who: Krzysztof Piotr Oledzki <ole@ans.pl>
348+

Documentation/kernel-parameters.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file
12791279
This usage is only documented in each driver source
12801280
file if at all.
12811281

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+
12821289
nfsaddrs= [NFS]
12831290
See Documentation/filesystems/nfsroot.txt.
12841291

include/linux/netfilter/nf_conntrack_common.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ enum ip_conntrack_events
122122
IPCT_NATINFO_BIT = 10,
123123
IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
124124

125-
/* Counter highest bit has been set */
125+
/* Counter highest bit has been set, unused */
126126
IPCT_COUNTER_FILLING_BIT = 11,
127127
IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
128128

@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events {
145145
};
146146

147147
#ifdef __KERNEL__
148-
struct ip_conntrack_counter
149-
{
150-
u_int32_t packets;
151-
u_int32_t bytes;
152-
};
153-
154148
struct ip_conntrack_stat
155149
{
156150
unsigned int searched;

include/linux/netfilter/nfnetlink_conntrack.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp {
115115

116116
enum ctattr_counters {
117117
CTA_COUNTERS_UNSPEC,
118-
CTA_COUNTERS_PACKETS, /* old 64bit counters */
119-
CTA_COUNTERS_BYTES, /* old 64bit counters */
120-
CTA_COUNTERS32_PACKETS,
121-
CTA_COUNTERS32_BYTES,
118+
CTA_COUNTERS_PACKETS, /* 64bit counters */
119+
CTA_COUNTERS_BYTES, /* 64bit counters */
120+
CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
121+
CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
122122
__CTA_COUNTERS_MAX
123123
};
124124
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)

include/net/netfilter/nf_conntrack.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ struct nf_conn_help {
8888
u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
8989
};
9090

91-
9291
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
9392
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
9493

@@ -111,11 +110,6 @@ struct nf_conn
111110
/* Timer function; drops refcnt when it goes off. */
112111
struct timer_list timeout;
113112

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-
119113
#if defined(CONFIG_NF_CONNTRACK_MARK)
120114
u_int32_t mark;
121115
#endif
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
16+
struct nf_conn_counter {
17+
u_int64_t packets;
18+
u_int64_t bytes;
19+
};
20+
21+
extern int nf_ct_acct;
22+
23+
static inline
24+
struct 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+
29+
static inline
30+
struct 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+
45+
extern unsigned int
46+
seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
47+
48+
extern int nf_conntrack_acct_init(void);
49+
extern void nf_conntrack_acct_fini(void);
50+
51+
#endif /* _NF_CONNTRACK_ACCT_H */

include/net/netfilter/nf_conntrack_extend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ enum nf_ct_ext_id
77
{
88
NF_CT_EXT_HELPER,
99
NF_CT_EXT_NAT,
10+
NF_CT_EXT_ACCT,
1011
NF_CT_EXT_NUM,
1112
};
1213

1314
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
1415
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
16+
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
1517

1618
/* Extensions: optional stuff which isn't permanently in struct. */
1719
struct nf_ct_ext {

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,7 @@
1818
#include <net/netfilter/nf_conntrack_l3proto.h>
1919
#include <net/netfilter/nf_conntrack_l4proto.h>
2020
#include <net/netfilter/nf_conntrack_expect.h>
21-
22-
#ifdef CONFIG_NF_CT_ACCT
23-
static unsigned int
24-
seq_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
21+
#include <net/netfilter/nf_conntrack_acct.h>
3422

3523
struct ct_iter_state {
3624
unsigned int bucket;
@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
127115
l3proto, l4proto))
128116
return -ENOSPC;
129117

130-
if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
118+
if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
131119
return -ENOSPC;
132120

133121
if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -138,7 +126,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
138126
l3proto, l4proto))
139127
return -ENOSPC;
140128

141-
if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
129+
if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
142130
return -ENOSPC;
143131

144132
if (test_bit(IPS_ASSURED_BIT, &ct->status))

net/netfilter/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ config NF_CT_ACCT
4949
Those counters can be used for flow-based accounting or the
5050
`connbytes' match.
5151

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+
5261
If unsure, say `N'.
5362

5463
config NF_CONNTRACK_MARK

net/netfilter/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
22

3-
nf_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
3+
nf_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
44
nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
55

66
obj-$(CONFIG_NETFILTER) = netfilter.o

net/netfilter/nf_conntrack_acct.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
25+
int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
26+
EXPORT_SYMBOL_GPL(nf_ct_acct);
27+
28+
module_param_named(acct, nf_ct_acct, bool, 0644);
29+
MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
30+
31+
#ifdef CONFIG_SYSCTL
32+
static struct ctl_table_header *acct_sysctl_header;
33+
static 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+
46+
unsigned int
47+
seq_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+
};
59+
EXPORT_SYMBOL_GPL(seq_print_acct);
60+
61+
static 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+
67+
int 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+
98+
void 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+
}

0 commit comments

Comments
 (0)