
olenf at ans
Oct 28, 2006, 9:48 AM
Post #3 of 22
(3317 views)
Permalink
|
On Thu, 26 Oct 2006, Patrick McHardy wrote: > Krzysztof Oledzki wrote: >> Hello, >> >> It seems there is something wrong with connbytes and 64bit conters. >> >> The "iptables" manual mention that counters are 64bit, so there should >> be no problem with overflows, but it seems it might not be true. My >> firewall puts long living ftp & http connections to a different TC class >> when they reach 256MB, but aftear they reach 4GB (probably) they go back >> to the default class, with no speed limit. >> >> After some researches I found that ip_conntrack_counter structure >> defined in nf_conntrack_common.h uses u_int32_t. I always thought that >> netfilter has 64bit counters, hasn't it? And I'm quite sure it used to >> work when I set up my firewall, about 1 year ago. Stange... > > > It was changed to save some memory in struct ip_conntrack. > The idea was mainly that its only used for ctnetlink and > it is possible to send events before overflow. Obviously, > this wasn't true (besides the fact that events are unreliable). > Not sure what we should do about it .. How about attached (and inlined for easy review) patch? [NETFILTER] Reimplementation of 64bit counters for bytes/packets accounting 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. Add possibility to choose between 32 and 64bits but keep default 32bit counters. Signed-off-by: Krzysztof Piotr Oledzki <ole [at] ans> diff -Nur linux-2.6.19-rc3-orig/include/linux/netfilter/nf_conntrack_common.h linux-2.6.19-rc3/include/linux/netfilter/nf_conntrack_common.h --- linux-2.6.19-rc3-orig/include/linux/netfilter/nf_conntrack_common.h 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/include/linux/netfilter/nf_conntrack_common.h 2006-10-28 17:42:48.000000000 +0200 @@ -139,8 +139,13 @@ #ifdef __KERNEL__ struct ip_conntrack_counter { +#if defined(CONFIG_IP_NF_CT_ACCT_64BIT_COUNTERS) || defined(CONFIG_NF_CT_ACCT_64BIT_COUNTERS) + u_int64_t packets; + u_int64_t bytes; +#else u_int32_t packets; u_int32_t bytes; +#endif }; struct ip_conntrack_stat diff -Nur linux-2.6.19-rc3-orig/include/linux/netfilter/nfnetlink_conntrack.h linux-2.6.19-rc3/include/linux/netfilter/nfnetlink_conntrack.h --- linux-2.6.19-rc3-orig/include/linux/netfilter/nfnetlink_conntrack.h 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/include/linux/netfilter/nfnetlink_conntrack.h 2006-10-25 14:55:19.000000000 +0200 @@ -89,8 +89,8 @@ enum ctattr_counters { CTA_COUNTERS_UNSPEC, - CTA_COUNTERS_PACKETS, /* old 64bit counters */ - CTA_COUNTERS_BYTES, /* old 64bit counters */ + CTA_COUNTERS_PACKETS, /* optional 64bit counters */ + CTA_COUNTERS_BYTES, /* optional 64bit counters */ CTA_COUNTERS32_PACKETS, CTA_COUNTERS32_BYTES, __CTA_COUNTERS_MAX diff -Nur linux-2.6.19-rc3-orig/net/ipv4/netfilter/Kconfig linux-2.6.19-rc3/net/ipv4/netfilter/Kconfig --- linux-2.6.19-rc3-orig/net/ipv4/netfilter/Kconfig 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/net/ipv4/netfilter/Kconfig 2006-10-28 18:44:16.000000000 +0200 @@ -46,6 +46,21 @@ If unsure, say `N'. +config IP_NF_CT_ACCT_64BIT_COUNTERS + bool 'Enable 64bit counters for conntrack-based accounting' + depends on IP_NF_CT_ACCT + default n + help + Use 64 bit counters for bytes/packets accounting instead of default 32. + + This will make every connection entry larger by 16 bytes, enlarging + it by about 5%. + + Say Y if you have plenty of RAM and want to be able to detect + long-lived connections, using for example "connbytes" extension. + + If unsure, say N. + config IP_NF_CONNTRACK_MARK bool 'Connection mark tracking support' depends on IP_NF_CONNTRACK diff -Nur linux-2.6.19-rc3-orig/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.19-rc3/net/ipv4/netfilter/ip_conntrack_core.c --- linux-2.6.19-rc3-orig/net/ipv4/netfilter/ip_conntrack_core.c 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2006-10-28 17:44:28.000000000 +0200 @@ -1148,9 +1148,15 @@ ct->counters[CTINFO2DIR(ctinfo)].packets++; ct->counters[CTINFO2DIR(ctinfo)].bytes += ntohs(skb->nh.iph->tot_len); +#ifdef CONFIG_IP_NF_CT_ACCT_64BIT_COUNTERS + if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x8000000000000000LL) + || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x8000000000000000LL)) + event |= IPCT_COUNTER_FILLING; +#else if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) event |= IPCT_COUNTER_FILLING; +#endif } #endif diff -Nur linux-2.6.19-rc3-orig/net/ipv4/netfilter/ip_conntrack_netlink.c linux-2.6.19-rc3/net/ipv4/netfilter/ip_conntrack_netlink.c --- linux-2.6.19-rc3-orig/net/ipv4/netfilter/ip_conntrack_netlink.c 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/net/ipv4/netfilter/ip_conntrack_netlink.c 2006-10-28 18:23:06.000000000 +0200 @@ -185,6 +185,15 @@ { enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; struct nfattr *nest_count = NFA_NEST(skb, type); +#ifdef CONFIG_IP_NF_CT_ACCT_64BIT_COUNTERS + __be64 tmp; + + tmp = cpu_to_be64(ct->counters[dir].packets); + NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(__be64), &tmp); + + tmp = cpu_to_be64(ct->counters[dir].bytes); + NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(__be64), &tmp); +#else __be32 tmp; tmp = htonl(ct->counters[dir].packets); @@ -192,6 +201,7 @@ tmp = htonl(ct->counters[dir].bytes); NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(__be32), &tmp); +#endif NFA_NEST_END(skb, nest_count); diff -Nur linux-2.6.19-rc3-orig/net/netfilter/Kconfig linux-2.6.19-rc3/net/netfilter/Kconfig --- linux-2.6.19-rc3-orig/net/netfilter/Kconfig 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/net/netfilter/Kconfig 2006-10-28 18:43:54.000000000 +0200 @@ -51,6 +51,21 @@ If unsure, say `N'. +config NF_CT_ACCT_64BIT_COUNTERS + bool 'Enable 64bit counters for conntrack-based accounting' + depends on NF_CT_ACCT + default n + help + Use 64 bit counters for bytes/packets accounting instead of default 32. + + This will make every connection entry larger by 16 bytes, enlarging + it by about 5%. + + Say Y if you have plenty of RAM and want to be able to detect + long-lived connections, using for example "connbytes" extension. + + If unsure, say N. + config NF_CONNTRACK_MARK bool 'Connection mark tracking support' depends on NF_CONNTRACK diff -Nur linux-2.6.19-rc3-orig/net/netfilter/nf_conntrack_core.c linux-2.6.19-rc3/net/netfilter/nf_conntrack_core.c --- linux-2.6.19-rc3-orig/net/netfilter/nf_conntrack_core.c 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/net/netfilter/nf_conntrack_core.c 2006-10-28 17:44:11.000000000 +0200 @@ -1412,9 +1412,15 @@ ct->counters[CTINFO2DIR(ctinfo)].packets++; ct->counters[CTINFO2DIR(ctinfo)].bytes += skb->len - (unsigned int)(skb->nh.raw - skb->data); +#ifdef CONFIG_NF_CT_ACCT_64BIT_COUNTERS + if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x8000000000000000LL) + || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x8000000000000000LL)) + event |= IPCT_COUNTER_FILLING; +#else if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) event |= IPCT_COUNTER_FILLING; +#endif } #endif diff -Nur linux-2.6.19-rc3-orig/net/netfilter/nf_conntrack_netlink.c linux-2.6.19-rc3/net/netfilter/nf_conntrack_netlink.c --- linux-2.6.19-rc3-orig/net/netfilter/nf_conntrack_netlink.c 2006-10-24 01:02:02.000000000 +0200 +++ linux-2.6.19-rc3/net/netfilter/nf_conntrack_netlink.c 2006-10-28 18:24:12.000000000 +0200 @@ -194,13 +194,23 @@ { enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; struct nfattr *nest_count = NFA_NEST(skb, type); - u_int32_t tmp; +#ifdef CONFIG_NF_CT_ACCT_64BIT_COUNTERS + __be64 tmp; + + tmp = cpu_to_be64(ct->counters[dir].packets); + NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(__be64), &tmp); + + tmp = cpu_to_be64(ct->counters[dir].bytes); + NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(__be64), &tmp); +#else + __be32 tmp; tmp = htonl(ct->counters[dir].packets); - NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); + NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(__be32), &tmp); tmp = htonl(ct->counters[dir].bytes); - NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp); + NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(__be32), &tmp); +#endif NFA_NEST_END(skb, nest_count); Best regards, Krzysztof Olędzki
|