1 /* Kernel module to control the rate
3 * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
4 * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
6 * 2 September 1999: Changed from the target RATE to the match
7 * `limit', removed logging. Did I mention that
8 * Alexey is a fucking genius?
9 * Rusty Russell (rusty@rustcorp.com.au). */
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
12 #include <linux/spinlock.h>
13 #include <linux/interrupt.h>
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <linux/netfilter_ipv4/ipt_limit.h>
18 /* The algorithm used is the Simple Token Bucket Filter (TBF)
19 * see net/sched/sch_tbf.c in the linux source tree
22 static spinlock_t limit_lock
= SPIN_LOCK_UNLOCKED
;
24 /* Rusty: This is my (non-mathematically-inclined) understanding of
25 this algorithm. The `average rate' in jiffies becomes your initial
26 amount of credit `credit' and the most credit you can ever have
27 `credit_cap'. The `peak rate' becomes the cost of passing the
30 `prev' tracks the last packet hit: you gain one credit per jiffy.
31 If you get credit balance more than this, the extra credit is
32 discarded. Every time the match passes, you lose `cost' credits;
33 if you don't have that many, the test fails.
35 See Alexey's formal explanation in net/sched/sch_tbf.c.
37 To avoid underflow, we multiply by 128 (ie. you get 128 credits per
38 jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds
39 at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes
40 per second at 100HZ. */
42 #define CREDITS_PER_JIFFY 128
45 ipt_limit_match(const struct sk_buff
*skb
,
46 const struct net_device
*in
,
47 const struct net_device
*out
,
48 const void *matchinfo
,
54 struct ipt_rateinfo
*r
= ((struct ipt_rateinfo
*)matchinfo
)->master
;
55 unsigned long now
= jiffies
;
57 spin_lock_bh(&limit_lock
);
58 r
->credit
+= (now
- xchg(&r
->prev
, now
)) * CREDITS_PER_JIFFY
;
59 if (r
->credit
> r
->credit_cap
)
60 r
->credit
= r
->credit_cap
;
62 if (r
->credit
>= r
->cost
) {
63 /* We're not limited. */
65 spin_unlock_bh(&limit_lock
);
69 spin_unlock_bh(&limit_lock
);
73 /* Precision saver. */
75 user2credits(u_int32_t user
)
77 /* If multiplying would overflow... */
78 if (user
> 0xFFFFFFFF / (HZ
*CREDITS_PER_JIFFY
))
80 return (user
/ IPT_LIMIT_SCALE
) * HZ
* CREDITS_PER_JIFFY
;
82 return (user
* HZ
* CREDITS_PER_JIFFY
) / IPT_LIMIT_SCALE
;
86 ipt_limit_checkentry(const char *tablename
,
87 const struct ipt_ip
*ip
,
89 unsigned int matchsize
,
90 unsigned int hook_mask
)
92 struct ipt_rateinfo
*r
= matchinfo
;
94 if (matchsize
!= IPT_ALIGN(sizeof(struct ipt_rateinfo
)))
97 /* Check for overflow. */
99 || user2credits(r
->avg
* r
->burst
) < user2credits(r
->avg
)) {
100 printk("Call rusty: overflow in ipt_limit: %u/%u\n",
105 /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies *
108 r
->credit
= user2credits(r
->avg
* r
->burst
); /* Credits full. */
109 r
->credit_cap
= user2credits(r
->avg
* r
->burst
); /* Credits full. */
110 r
->cost
= user2credits(r
->avg
);
112 /* For SMP, we only want to use one set of counters. */
118 static struct ipt_match ipt_limit_reg
119 = { { NULL
, NULL
}, "limit", ipt_limit_match
, ipt_limit_checkentry
, NULL
,
122 static int __init
init(void)
124 if (ipt_register_match(&ipt_limit_reg
))
129 static void __exit
fini(void)
131 ipt_unregister_match(&ipt_limit_reg
);
136 MODULE_LICENSE("GPL");