[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.