Skip to content

Commit

Permalink
netfilter: accounting rework: ct_extend + 64bit counters (v4)
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Patrick McHardy <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Krzysztof Piotr Oledzki authored and davem330 committed Jul 21, 2008
1 parent 07a7c10 commit 5840157
Show file tree
Hide file tree
Showing 15 changed files with 248 additions and 86 deletions.
10 changes: 10 additions & 0 deletions Documentation/feature-removal-schedule.txt
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches
Why: Over 1K .text/.data size reduction, data is available in other
ways (ioctls)
Who: Johannes Berg <[email protected]>

---------------------------

What: CONFIG_NF_CT_ACCT
When: 2.6.29
Why: Accounting can now be enabled/disabled without kernel recompilation.
Currently used only to set a default value for a feature that is also
controlled by a kernel/module/sysfs/sysctl parameter.
Who: Krzysztof Piotr Oledzki <[email protected]>

7 changes: 7 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file
This usage is only documented in each driver source
file if at all.

nf_conntrack.acct=
[NETFILTER] Enable connection tracking flow accounting
0 to disable accounting
1 to enable accounting
Default value depends on CONFIG_NF_CT_ACCT that is
going to be removed in 2.6.29.

nfsaddrs= [NFS]
See Documentation/filesystems/nfsroot.txt.

Expand Down
8 changes: 1 addition & 7 deletions include/linux/netfilter/nf_conntrack_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ enum ip_conntrack_events
IPCT_NATINFO_BIT = 10,
IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),

/* Counter highest bit has been set */
/* Counter highest bit has been set, unused */
IPCT_COUNTER_FILLING_BIT = 11,
IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),

Expand All @@ -145,12 +145,6 @@ enum ip_conntrack_expect_events {
};

#ifdef __KERNEL__
struct ip_conntrack_counter
{
u_int32_t packets;
u_int32_t bytes;
};

struct ip_conntrack_stat
{
unsigned int searched;
Expand Down
8 changes: 4 additions & 4 deletions include/linux/netfilter/nfnetlink_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp {

enum ctattr_counters {
CTA_COUNTERS_UNSPEC,
CTA_COUNTERS_PACKETS, /* old 64bit counters */
CTA_COUNTERS_BYTES, /* old 64bit counters */
CTA_COUNTERS32_PACKETS,
CTA_COUNTERS32_BYTES,
CTA_COUNTERS_PACKETS, /* 64bit counters */
CTA_COUNTERS_BYTES, /* 64bit counters */
CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
__CTA_COUNTERS_MAX
};
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
Expand Down
6 changes: 0 additions & 6 deletions include/net/netfilter/nf_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ struct nf_conn_help {
u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
};


#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>

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

#ifdef CONFIG_NF_CT_ACCT
/* Accounting Information (same cache line as other written members) */
struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
#endif

#if defined(CONFIG_NF_CONNTRACK_MARK)
u_int32_t mark;
#endif
Expand Down
51 changes: 51 additions & 0 deletions include/net/netfilter/nf_conntrack_acct.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* (C) 2008 Krzysztof Piotr Oledzki <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef _NF_CONNTRACK_ACCT_H
#define _NF_CONNTRACK_ACCT_H
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>

struct nf_conn_counter {
u_int64_t packets;
u_int64_t bytes;
};

extern int nf_ct_acct;

static inline
struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
}

static inline
struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
{
struct nf_conn_counter *acct;

if (!nf_ct_acct)
return NULL;

acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
if (!acct)
pr_debug("failed to add accounting extension area");


return acct;
};

extern unsigned int
seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);

extern int nf_conntrack_acct_init(void);
extern void nf_conntrack_acct_fini(void);

#endif /* _NF_CONNTRACK_ACCT_H */
2 changes: 2 additions & 0 deletions include/net/netfilter/nf_conntrack_extend.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ enum nf_ct_ext_id
{
NF_CT_EXT_HELPER,
NF_CT_EXT_NAT,
NF_CT_EXT_ACCT,
NF_CT_EXT_NUM,
};

#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter

/* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext {
Expand Down
18 changes: 3 additions & 15 deletions net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,7 @@
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h>

#ifdef CONFIG_NF_CT_ACCT
static unsigned int
seq_print_counters(struct seq_file *s,
const struct ip_conntrack_counter *counter)
{
return seq_printf(s, "packets=%llu bytes=%llu ",
(unsigned long long)counter->packets,
(unsigned long long)counter->bytes);
}
#else
#define seq_print_counters(x, y) 0
#endif
#include <net/netfilter/nf_conntrack_acct.h>

struct ct_iter_state {
unsigned int bucket;
Expand Down Expand Up @@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto))
return -ENOSPC;

if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
return -ENOSPC;

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

if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
return -ENOSPC;

if (test_bit(IPS_ASSURED_BIT, &ct->status))
Expand Down
9 changes: 9 additions & 0 deletions net/netfilter/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ config NF_CT_ACCT
Those counters can be used for flow-based accounting or the
`connbytes' match.

Please note that currently this option only sets a default state.
You may change it at boot time with nf_conntrack.acct=0/1 kernel
paramater or by loading the nf_conntrack module with acct=0/1.

You may also disable/enable it on a running system with:
sysctl net.netfilter.nf_conntrack_acct=0/1

This option will be removed in 2.6.29.

If unsure, say `N'.

config NF_CONNTRACK_MARK
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o

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

obj-$(CONFIG_NETFILTER) = netfilter.o
Expand Down
104 changes: 104 additions & 0 deletions net/netfilter/nf_conntrack_acct.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* Accouting handling for netfilter. */

/*
* (C) 2008 Krzysztof Piotr Oledzki <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/netfilter.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_acct.h>

#ifdef CONFIG_NF_CT_ACCT
#define NF_CT_ACCT_DEFAULT 1
#else
#define NF_CT_ACCT_DEFAULT 0
#endif

int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
EXPORT_SYMBOL_GPL(nf_ct_acct);

module_param_named(acct, nf_ct_acct, bool, 0644);
MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");

#ifdef CONFIG_SYSCTL
static struct ctl_table_header *acct_sysctl_header;
static struct ctl_table acct_sysctl_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "nf_conntrack_acct",
.data = &nf_ct_acct,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{}
};
#endif /* CONFIG_SYSCTL */

unsigned int
seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
{
struct nf_conn_counter *acct;

acct = nf_conn_acct_find(ct);
if (!acct)
return 0;

return seq_printf(s, "packets=%llu bytes=%llu ",
(unsigned long long)acct[dir].packets,
(unsigned long long)acct[dir].bytes);
};
EXPORT_SYMBOL_GPL(seq_print_acct);

static struct nf_ct_ext_type acct_extend __read_mostly = {
.len = sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),
.align = __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),
.id = NF_CT_EXT_ACCT,
};

int nf_conntrack_acct_init(void)
{
int ret;

#ifdef CONFIG_NF_CT_ACCT
printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
#endif

ret = nf_ct_extend_register(&acct_extend);
if (ret < 0) {
printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
return ret;
}

#ifdef CONFIG_SYSCTL
acct_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
acct_sysctl_table);

if (!acct_sysctl_header) {
nf_ct_extend_unregister(&acct_extend);

printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
return -ENOMEM;
}
#endif

return 0;
}

void nf_conntrack_acct_fini(void)
{
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(acct_sysctl_header);
#endif
nf_ct_extend_unregister(&acct_extend);
}
Loading

0 comments on commit 5840157

Please sign in to comment.