[PATCH][EBTABLES] add ebt_limit match
Bart De Schuymer <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Dave, The patch below adds the ebt_limit match, which is the equivalent of the iptables limit match. This enables limiting the number of frames processed per time unit. The patch is from Tom Marshall <tommy_at_home.tig-grr.com>. cheers, Bart --- linux-2.6.0-test5/net/bridge/netfilter/Kconfig.old Sat Sep 27 21:35:09 2003 +++ linux-2.6.0-test5/net/bridge/netfilter/Kconfig Sat Sep 27 21:38:35 2003 @@ -79,6 +79,17 @@ config BRIDGE_EBT_IP If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. If unsure, say `N'. +config BRIDGE_EBT_LIMIT + tristate "ebt: limit match support" + depends on BRIDGE_NF_EBTABLES + help + This option adds the limit match, which allows you to control + the rate at which a rule can be matched. This match is the + equivalent of the iptables limit match. + + If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. If unsure, say `N'. + config BRIDGE_EBT_MARK tristate "ebt: mark filter support" depends on BRIDGE_NF_EBTABLES --- linux-2.6.0-test5/net/bridge/netfilter/Makefile.old Sat Sep 27 21:38:40 2003 +++ linux-2.6.0-test5/net/bridge/netfilter/Makefile Sat Sep 27 21:38:56 2003 @@ -13,6 +13,7 @@ obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtabl obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o +obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o obj-$(CONFIG_BRIDGE_EBT_STP) += ebt_stp.o --- /dev/null Thu Aug 24 11:00:32 2000 +++ linux-2.6.0-test5/net/bridge/netfilter/ebt_limit.c Sat Sep 27 21:43:40 2003 @@ -0,0 +1,104 @@ +/* + * ebt_limit + * + * Authors: + * Tom Marshall <tommy-qZBa9ISwN9Q+/[email protected]> + * + * Mostly copied from netfilter's ipt_limit.c, see that file for + * more explanation + * + * September, 2003 + * + */ + +#include <linux/netfilter_bridge/ebtables.h> +#include <linux/netfilter_bridge/ebt_limit.h> +#include <linux/module.h> + +#include <linux/netdevice.h> +#include <linux/spinlock.h> + +static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED; + +#define CREDITS_PER_JIFFY 128 + +static int ebt_limit_match(const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + const void *data, unsigned int datalen) +{ + struct ebt_limit_info *info = (struct ebt_limit_info *)data; + unsigned long now = jiffies; + + spin_lock_bh(&limit_lock); + info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY; + if (info->credit > info->credit_cap) + info->credit = info->credit_cap; + + if (info->credit >= info->cost) { + /* We're not limited. */ + info->credit -= info->cost; + spin_unlock_bh(&limit_lock); + return EBT_MATCH; + } + + spin_unlock_bh(&limit_lock); + return EBT_NOMATCH; +} + +/* Precision saver. */ +static u_int32_t +user2credits(u_int32_t user) +{ + /* If multiplying would overflow... */ + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) + /* Divide first. */ + return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; + + return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE; +} + +static int ebt_limit_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ + struct ebt_limit_info *info = (struct ebt_limit_info *)data; + + if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info))) + return -EINVAL; + + /* Check for overflow. */ + if (info->burst == 0 || + user2credits(info->avg * info->burst) < user2credits(info->avg)) { + printk("Overflow in ebt_limit: %u/%u\n", + info->avg, info->burst); + return -EINVAL; + } + + /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */ + info->prev = jiffies; + info->credit = user2credits(info->avg * info->burst); + info->credit_cap = user2credits(info->avg * info->burst); + info->cost = user2credits(info->avg); + return 0; +} + +static struct ebt_match ebt_limit_reg = +{ + .name = EBT_LIMIT_MATCH, + .match = ebt_limit_match, + .check = ebt_limit_check, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ebt_register_match(&ebt_limit_reg); +} + +static void __exit fini(void) +{ + ebt_unregister_match(&ebt_limit_reg); +} + +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); --- /dev/null Thu Aug 24 11:00:32 2000 +++ linux-2.6.0-test5/include/linux/netfilter_bridge/ebt_limit.h Sat Sep 27 21:39:56 2003 @@ -0,0 +1,23 @@ +#ifndef __LINUX_BRIDGE_EBT_LIMIT_H +#define __LINUX_BRIDGE_EBT_LIMIT_H + +#define EBT_LIMIT_MATCH "limit" + +/* timings are in milliseconds. */ +#define EBT_LIMIT_SCALE 10000 + +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 + seconds, or one every 59 hours. */ + +struct ebt_limit_info +{ + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + u_int32_t credit; + u_int32_t credit_cap, cost; +}; + +#endif ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf