Commit 58401572 authored by Krzysztof Piotr Oledzki's avatar Krzysztof Piotr Oledzki Committed by David S. Miller

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: default avatarKrzysztof Piotr Oledzki <ole@ans.pl>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 07a7c107
...@@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches ...@@ -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 Why: Over 1K .text/.data size reduction, data is available in other
ways (ioctls) ways (ioctls)
Who: Johannes Berg <johannes@sipsolutions.net> Who: Johannes Berg <johannes@sipsolutions.net>
---------------------------
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 <ole@ans.pl>
...@@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -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 This usage is only documented in each driver source
file if at all. 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] nfsaddrs= [NFS]
See Documentation/filesystems/nfsroot.txt. See Documentation/filesystems/nfsroot.txt.
......
...@@ -122,7 +122,7 @@ enum ip_conntrack_events ...@@ -122,7 +122,7 @@ enum ip_conntrack_events
IPCT_NATINFO_BIT = 10, IPCT_NATINFO_BIT = 10,
IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), 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_BIT = 11,
IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
...@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events { ...@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events {
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
struct ip_conntrack_counter
{
u_int32_t packets;
u_int32_t bytes;
};
struct ip_conntrack_stat struct ip_conntrack_stat
{ {
unsigned int searched; unsigned int searched;
......
...@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp { ...@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp {
enum ctattr_counters { enum ctattr_counters {
CTA_COUNTERS_UNSPEC, CTA_COUNTERS_UNSPEC,
CTA_COUNTERS_PACKETS, /* old 64bit counters */ CTA_COUNTERS_PACKETS, /* 64bit counters */
CTA_COUNTERS_BYTES, /* old 64bit counters */ CTA_COUNTERS_BYTES, /* 64bit counters */
CTA_COUNTERS32_PACKETS, CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
CTA_COUNTERS32_BYTES, CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
__CTA_COUNTERS_MAX __CTA_COUNTERS_MAX
}; };
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
......
...@@ -88,7 +88,6 @@ struct nf_conn_help { ...@@ -88,7 +88,6 @@ struct nf_conn_help {
u8 expecting[NF_CT_MAX_EXPECT_CLASSES]; u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
}; };
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
...@@ -111,11 +110,6 @@ struct nf_conn ...@@ -111,11 +110,6 @@ struct nf_conn
/* Timer function; drops refcnt when it goes off. */ /* Timer function; drops refcnt when it goes off. */
struct timer_list timeout; 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) #if defined(CONFIG_NF_CONNTRACK_MARK)
u_int32_t mark; u_int32_t mark;
#endif #endif
......
/*
* (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* 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 */
...@@ -7,11 +7,13 @@ enum nf_ct_ext_id ...@@ -7,11 +7,13 @@ enum nf_ct_ext_id
{ {
NF_CT_EXT_HELPER, NF_CT_EXT_HELPER,
NF_CT_EXT_NAT, NF_CT_EXT_NAT,
NF_CT_EXT_ACCT,
NF_CT_EXT_NUM, NF_CT_EXT_NUM,
}; };
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #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. */ /* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext { struct nf_ct_ext {
......
...@@ -18,19 +18,7 @@ ...@@ -18,19 +18,7 @@
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_acct.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
struct ct_iter_state { struct ct_iter_state {
unsigned int bucket; unsigned int bucket;
...@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; 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; return -ENOSPC;
if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 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,7 +126,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; 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; return -ENOSPC;
if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (test_bit(IPS_ASSURED_BIT, &ct->status))
......
...@@ -49,6 +49,15 @@ config NF_CT_ACCT ...@@ -49,6 +49,15 @@ config NF_CT_ACCT
Those counters can be used for flow-based accounting or the Those counters can be used for flow-based accounting or the
`connbytes' match. `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'. If unsure, say `N'.
config NF_CONNTRACK_MARK config NF_CONNTRACK_MARK
......
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 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 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
obj-$(CONFIG_NETFILTER) = netfilter.o obj-$(CONFIG_NETFILTER) = netfilter.o
......
/* Accouting handling for netfilter. */
/*
* (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* 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);
}
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_extend.h> #include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_acct.h>
#define NF_CONNTRACK_VERSION "0.5.0" #define NF_CONNTRACK_VERSION "0.5.0"
...@@ -555,6 +556,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, ...@@ -555,6 +556,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
return NULL; return NULL;
} }
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
exp = nf_ct_find_expectation(tuple); exp = nf_ct_find_expectation(tuple);
if (exp) { if (exp) {
...@@ -828,17 +831,16 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, ...@@ -828,17 +831,16 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
} }
acct: acct:
#ifdef CONFIG_NF_CT_ACCT
if (do_acct) { if (do_acct) {
ct->counters[CTINFO2DIR(ctinfo)].packets++; struct nf_conn_counter *acct;
ct->counters[CTINFO2DIR(ctinfo)].bytes +=
skb->len - skb_network_offset(skb);
if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) acct = nf_conn_acct_find(ct);
|| (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) if (acct) {
event |= IPCT_COUNTER_FILLING; acct[CTINFO2DIR(ctinfo)].packets++;
acct[CTINFO2DIR(ctinfo)].bytes +=
skb->len - skb_network_offset(skb);
}
} }
#endif
spin_unlock_bh(&nf_conntrack_lock); spin_unlock_bh(&nf_conntrack_lock);
...@@ -853,15 +855,19 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, ...@@ -853,15 +855,19 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
int do_acct) int do_acct)
{ {
#ifdef CONFIG_NF_CT_ACCT
if (do_acct) { if (do_acct) {
struct nf_conn_counter *acct;
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
ct->counters[CTINFO2DIR(ctinfo)].packets++; acct = nf_conn_acct_find(ct);
ct->counters[CTINFO2DIR(ctinfo)].bytes += if (acct) {
skb->len - skb_network_offset(skb); acct[CTINFO2DIR(ctinfo)].packets++;
acct[CTINFO2DIR(ctinfo)].bytes +=
skb->len - skb_network_offset(skb);
}
spin_unlock_bh(&nf_conntrack_lock); spin_unlock_bh(&nf_conntrack_lock);
} }
#endif
if (del_timer(&ct->timeout)) { if (del_timer(&ct->timeout)) {
ct->timeout.function((unsigned long)ct); ct->timeout.function((unsigned long)ct);
return true; return true;
...@@ -1029,6 +1035,7 @@ void nf_conntrack_cleanup(void) ...@@ -1029,6 +1035,7 @@ void nf_conntrack_cleanup(void)
nf_conntrack_proto_fini(); nf_conntrack_proto_fini();
nf_conntrack_helper_fini(); nf_conntrack_helper_fini();
nf_conntrack_expect_fini(); nf_conntrack_expect_fini();
nf_conntrack_acct_fini();
} }
struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
...@@ -1168,6 +1175,10 @@ int __init nf_conntrack_init(void) ...@@ -1168,6 +1175,10 @@ int __init nf_conntrack_init(void)
if (ret < 0) if (ret < 0)
goto out_fini_expect; goto out_fini_expect;
ret = nf_conntrack_acct_init();
if (ret < 0)
goto out_fini_helper;
/* For use by REJECT target */ /* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
...@@ -1180,6 +1191,8 @@ int __init nf_conntrack_init(void) ...@@ -1180,6 +1191,8 @@ int __init nf_conntrack_init(void)
return ret; return ret;
out_fini_helper:
nf_conntrack_helper_fini();
out_fini_expect: out_fini_expect:
nf_conntrack_expect_fini(); nf_conntrack_expect_fini();
out_fini_proto: out_fini_proto:
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_acct.h>
#ifdef CONFIG_NF_NAT_NEEDED #ifdef CONFIG_NF_NAT_NEEDED
#include <net/netfilter/nf_nat_core.h> #include <net/netfilter/nf_nat_core.h>
#include <net/netfilter/nf_nat_protocol.h> #include <net/netfilter/nf_nat_protocol.h>
...@@ -206,22 +207,26 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) ...@@ -206,22 +207,26 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
return -1; return -1;
} }
#ifdef CONFIG_NF_CT_ACCT
static int static int
ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
enum ip_conntrack_dir dir) enum ip_conntrack_dir dir)
{ {
enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
struct nlattr *nest_count; struct nlattr *nest_count;
const struct nf_conn_counter *acct;
acct = nf_conn_acct_find(ct);
if (!acct)
return 0;
nest_count = nla_nest_start(skb, type | NLA_F_NESTED); nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
if (!nest_count) if (!nest_count)
goto nla_put_failure; goto nla_put_failure;
NLA_PUT_BE32(skb, CTA_COUNTERS32_PACKETS, NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
htonl(ct->counters[dir].packets)); cpu_to_be64(acct[dir].packets));
NLA_PUT_BE32(skb, CTA_COUNTERS32_BYTES, NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
htonl(ct->counters[dir].bytes)); cpu_to_be64(acct[dir].bytes));
nla_nest_end(skb, nest_count); nla_nest_end(skb, nest_count);
...@@ -230,9 +235,6 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, ...@@ -230,9 +235,6 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
nla_put_failure: nla_put_failure:
return -1; return -1;
} }
#else
#define ctnetlink_dump_counters(a, b, c) (0)
#endif
#ifdef CONFIG_NF_CONNTRACK_MARK #ifdef CONFIG_NF_CONNTRACK_MARK
static inline int static inline int
...@@ -501,11 +503,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, ...@@ -501,11 +503,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
goto nla_put_failure; goto nla_put_failure;
#endif #endif
if (events & IPCT_COUNTER_FILLING &&
(ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
goto nla_put_failure;
if (events & IPCT_RELATED && if (events & IPCT_RELATED &&
ctnetlink_dump_master(skb, ct) < 0) ctnetlink_dump_master(skb, ct) < 0)
goto nla_put_failure; goto nla_put_failure;
...@@ -576,11 +573,15 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -576,11 +573,15 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
cb->args[1] = (unsigned long)ct; cb->args[1] = (unsigned long)ct;
goto out; goto out;
} }
#ifdef CONFIG_NF_CT_ACCT
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
IPCTNL_MSG_CT_GET_CTRZERO) IPCTNL_MSG_CT_GET_CTRZERO) {
memset(&ct->counters, 0, sizeof(ct->counters)); struct nf_conn_counter *acct;
#endif
acct = nf_conn_acct_find(ct);
if (acct)
memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
}
} }
if (cb->args[1]) { if (cb->args[1]) {
cb->args[1] = 0; cb->args[1] = 0;
...@@ -832,14 +833,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -832,14 +833,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family; u_int8_t u3 = nfmsg->nfgen_family;
int err = 0; int err = 0;
if (nlh->nlmsg_flags & NLM_F_DUMP) { if (nlh->nlmsg_flags & NLM_F_DUMP)
#ifndef CONFIG_NF_CT_ACCT
if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
return -ENOTSUPP;
#endif
return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
ctnetlink_done); ctnetlink_done);
}
if (cda[CTA_TUPLE_ORIG]) if (cda[CTA_TUPLE_ORIG])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
...@@ -1152,6 +1148,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ...@@ -1152,6 +1148,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
goto err; goto err;
} }
nf_ct_acct_ext_add(ct, GFP_KERNEL);
#if defined(CONFIG_NF_CONNTRACK_MARK) #if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK]) if (cda[CTA_MARK])
ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_acct.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -38,19 +39,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, ...@@ -38,19 +39,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
} }
EXPORT_SYMBOL_GPL(print_tuple); EXPORT_SYMBOL_GPL(print_tuple);
#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
struct ct_iter_state { struct ct_iter_state {
unsigned int bucket; unsigned int bucket;
}; };
...@@ -146,7 +134,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -146,7 +134,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; 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; return -ENOSPC;
if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 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,7 +145,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; 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; return -ENOSPC;
if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (test_bit(IPS_ASSURED_BIT, &ct->status))
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_connbytes.h> #include <linux/netfilter/xt_connbytes.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_acct.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
...@@ -27,12 +28,15 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in, ...@@ -27,12 +28,15 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in,
u_int64_t what = 0; /* initialize to make gcc happy */ u_int64_t what = 0; /* initialize to make gcc happy */
u_int64_t bytes = 0; u_int64_t bytes = 0;
u_int64_t pkts = 0; u_int64_t pkts = 0;
const struct ip_conntrack_counter *counters; const struct nf_conn_counter *counters;
ct = nf_ct_get(skb, &ctinfo); ct = nf_ct_get(skb, &ctinfo);
if (!ct) if (!ct)
return false; return false;
counters = ct->counters;
counters = nf_conn_acct_find(ct);
if (!counters)
return false;
switch (sinfo->what) { switch (sinfo->what) {
case XT_CONNBYTES_PKTS: case XT_CONNBYTES_PKTS:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment