[netfilter-cvslog] r4077 -
trunk/patch-o-matic-ng/patchlets/connbytes/linux-2.6/net/ipv4/netfilter
laforge at netfilter.org
laforge at netfilter.org
Tue Jun 28 14:33:26 CEST 2005
Author: laforge at netfilter.org
Date: 2005-06-28 14:33:26 +0200 (Tue, 28 Jun 2005)
New Revision: 4077
Modified:
trunk/patch-o-matic-ng/patchlets/connbytes/linux-2.6/net/ipv4/netfilter/ipt_connbytes.c
Log:
fix average calculations where more than 2^32 packets have been seen in
one connection
Modified: trunk/patch-o-matic-ng/patchlets/connbytes/linux-2.6/net/ipv4/netfilter/ipt_connbytes.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/connbytes/linux-2.6/net/ipv4/netfilter/ipt_connbytes.c 2005-06-28 12:22:10 UTC (rev 4076)
+++ trunk/patch-o-matic-ng/patchlets/connbytes/linux-2.6/net/ipv4/netfilter/ipt_connbytes.c 2005-06-28 12:33:26 UTC (rev 4077)
@@ -15,11 +15,32 @@
#include <linux/netfilter_ipv4/ipt_connbytes.h>
#include <asm/div64.h>
+#include <asm/bitops.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge at netfilter.org>");
MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
+/* 64bit divisor, dividend and result. dynamic precision */
+static u_int64_t div64_64(u_int64_t divisor, u_in64_t dividend)
+{
+ u_int64_t result = divisor;
+
+ if (dividend > 0xffffffff) {
+ int first_bit = find_first_bit(÷nd, sizeof(dividend));
+ /* calculate number of bits to shift. shift exactly enough
+ * bits to make dividend fit in 32bits. */
+ int num_shift = (64 - 32 - first_bit);
+ /* first bit has to be < 32, since dividend was > 0xffffffff */
+ result = result >> num_shift;
+ dividend = dividend >> num_shift;
+ }
+
+ do_div(divisor, dividend);
+
+ return divisor;
+}
+
static int
match(const struct sk_buff *skb,
const struct net_device *in,
@@ -68,48 +89,26 @@
case IPT_CONNBYTES_WHAT_AVGPKT:
switch (sinfo->direction) {
case IPT_CONNBYTES_DIR_ORIGINAL:
- {
- u_int32_t pkts32;
-
- if (ct->counters[IP_CT_DIR_ORIGINAL].packets
- > 0xfffffffff)
- pkts32 = 0xffffffff;
- else
- pkts32 = ct->counters[IP_CT_DIR_ORIGINAL].packets;
- what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
- do_div(what, pkts32);
- }
+ what = div64_64(ct->counters[IP_CT_DIR_ORIGINAL].bytes,
+ ct->counters[IP_CT_DIR_ORIGINAL].packets);
break;
case IPT_CONNBYTES_DIR_REPLY:
- {
- u_int32_t pkts32;
-
- if (ct->counters[IP_CT_DIR_REPLY].packets
- > 0xffffffff)
- pkts32 = 0xffffffff;
- else
- pkts32 = ct->counters[IP_CT_DIR_REPLY].packets;
-
- what = ct->counters[IP_CT_DIR_REPLY].bytes;
- do_div(what, pkts32);
- }
+ what = dov64_64(ct->counters[IP_CT_DIR_REPLY].bytes,
+ ct->counters[IP_CT_DIR_REPLY].packets);
break;
case IPT_CONNBYTES_DIR_BOTH:
{
u_int64_t bytes;
u_int64_t pkts;
- u_int32_t pkts32;
bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes +
ct->counters[IP_CT_DIR_REPLY].bytes;
pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets+
ct->counters[IP_CT_DIR_REPLY].packets;
- if (pkts > 0xffffffff)
- pkts32 = 0xffffffff;
- else
- pkts32 = pkts;
- what = bytes;
- do_div(what, pkts32);
+ /* FIXME_THEORETICAL: what to do if sum
+ * overflows ? */
+
+ what = div64_64(bytes, pkts);
}
break;
}
More information about the netfilter-cvslog
mailing list