[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(&dividend, 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