From b6e31b8e1e3b9fb29adcef9b1dde2b9865494c7c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 8 Oct 2003 17:42:03 -0700 Subject: [PATCH] [PATCH] ipt_limit fix for HZ=1000 The range that the iptables limit extension can specify depends on HZ. This means that rules which worked i386 2.4 (100 HZ) won't work on 2.6. The solution is to adjust the precision based on the HZ value (keeping the range of possible values the same). For extra geek cred, this is done by calculating a power-of-two constant below the maximum multiplication factor, which gcc then turns into a simple shift. --- net/ipv4/netfilter/ipt_limit.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/ipv4/netfilter/ipt_limit.c index 217a3c6d3625f..deac142298302 100644 --- a/net/ipv4/netfilter/ipt_limit.c +++ b/net/ipv4/netfilter/ipt_limit.c @@ -38,12 +38,23 @@ static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED; See Alexey's formal explanation in net/sched/sch_tbf.c. - To avoid underflow, we multiply by 128 (ie. you get 128 credits per - jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds - at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes - per second at 100HZ. */ - -#define CREDITS_PER_JIFFY 128 + To get the maxmum range, we multiply by this factor (ie. you get N + credits per jiffy). We want to allow a rate as low as 1 per day + (slowest userspace tool allows), which means + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32. ie. */ +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24)) + +/* Repeated shift and or gives us all 1s, final shift and add 1 gives + * us the power of 2 below the theoretical max, so GCC simply does a + * shift. */ +#define _POW2_BELOW2(x) ((x)|((x)>>1)) +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2)) +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4)) +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8)) +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16)) +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1) + +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) static int ipt_limit_match(const struct sk_buff *skb, @@ -99,7 +110,7 @@ ipt_limit_checkentry(const char *tablename, /* Check for overflow. */ if (r->burst == 0 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { - printk("Call rusty: overflow in ipt_limit: %u/%u\n", + printk("Overflow in ipt_limit, try lower: %u/%u\n", r->avg, r->burst); return 0; } -- 2.53.0