Commit b6e31b8e authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[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.
parent 9c0451e5
......@@ -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;
}
......
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