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; ...@@ -38,12 +38,23 @@ static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED;
See Alexey's formal explanation in net/sched/sch_tbf.c. See Alexey's formal explanation in net/sched/sch_tbf.c.
To avoid underflow, we multiply by 128 (ie. you get 128 credits per To get the maxmum range, we multiply by this factor (ie. you get N
jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds credits per jiffy). We want to allow a rate as low as 1 per day
at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes (slowest userspace tool allows), which means
per second at 100HZ. */ CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32. ie. */
#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
#define CREDITS_PER_JIFFY 128
/* 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 static int
ipt_limit_match(const struct sk_buff *skb, ipt_limit_match(const struct sk_buff *skb,
...@@ -99,7 +110,7 @@ ipt_limit_checkentry(const char *tablename, ...@@ -99,7 +110,7 @@ ipt_limit_checkentry(const char *tablename,
/* Check for overflow. */ /* Check for overflow. */
if (r->burst == 0 if (r->burst == 0
|| user2credits(r->avg * r->burst) < user2credits(r->avg)) { || 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); r->avg, r->burst);
return 0; 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