All of lore.kernel.org
 help / color / mirror / Atom feed
From: Philip Craig <philipc@snapgear.com>
To: Netfilter Developer Mailing List <netfilter-devel@lists.netfilter.org>
Subject: [RFC][PATCH] optimise iptables interface matching
Date: Thu, 24 May 2007 15:55:23 +1000	[thread overview]
Message-ID: <465528CB.4020108@snapgear.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1022 bytes --]

Optimise iptables for rules that specify 0 or 1 interface matches,
which is the more common case (at least for my rulesets).

Below are the oprofile cpu cycle percentages from a 30 second
period of an iperf throughput test on a 667MHz IXP465 with
Realtek 8169 network interfaces.

rules	iface	% cpu before	% cpu after	saving (adjusted)
0		 7.7662		 4.9191		 2.8471
10 	0	15.9798		 9.8453		 3.2874
20 	0	23.6914		14.2051		 6.6392
10	1	14.6068		11.7332		 0.0265
20	1	21.1646		17.1905		 1.1270
10	2	14.6497		13.0306		-1.2280
20	2	21.1647		20.3536		-2.0360

- saving with 0 rules is due to policies
- adjusted saving means with the 0 rules saving subtracted
- iface 0 means "iptables -I FORWARD"
- iface 1 means "iptables -I FORWARD -i eth0"
- iface 2 means "iptables -I FORWARD -i eth0 -o eth1"

If you think this is an acceptable approach then I can update
the patch for IPv6.  Any suggestions for other parts of
netfilter/iptables to look at optimising are also welcome.

Signed-off-by: Philip Craig <philipc@snapgear.com>

[-- Attachment #2: iptables-iface-optim.patch --]
[-- Type: text/plain, Size: 4134 bytes --]

--- linux-2.6.x/include/linux/netfilter_ipv4/ip_tables.h	26 Apr 2007 13:13:50 -0000	1.2
+++ linux-2.6.x/include/linux/netfilter_ipv4/ip_tables.h	24 May 2007 04:46:59 -0000
@@ -63,6 +63,10 @@ struct ipt_ip {
 #define IPT_F_GOTO		0x02	/* Set if jump is a goto */
 #define IPT_F_MASK		0x03	/* All possible flag bits mask. */
 
+/* Internal values used for optimisation */
+#define IPT_F_VIA_IN		0x10	/* Set if rule has iif match */
+#define IPT_F_VIA_OUT		0x20	/* Set if rule has oif match */
+
 /* Values for "inv" field in struct ipt_ip. */
 #define IPT_INV_VIA_IN		0x01	/* Invert the sense of IN IFACE. */
 #define IPT_INV_VIA_OUT		0x02	/* Invert the sense of OUT IFACE */
--- linux-2.6.x/net/ipv4/netfilter/ip_tables.c	26 Apr 2007 11:17:49 -0000	1.1.1.29
+++ linux-2.6.x/net/ipv4/netfilter/ip_tables.c	24 May 2007 04:46:59 -0000
@@ -112,30 +112,34 @@ ip_packet_match(const struct iphdr *ip,
 	}
 
 	/* Look for ifname matches; this should unroll nicely. */
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
-		ret |= (((const unsigned long *)indev)[i]
-			^ ((const unsigned long *)ipinfo->iniface)[i])
-			& ((const unsigned long *)ipinfo->iniface_mask)[i];
-	}
+	if (ipinfo->flags & IPT_F_VIA_IN) {
+		for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
+			ret |= (((const unsigned long *)indev)[i]
+				^ ((const unsigned long *)ipinfo->iniface)[i])
+				& ((const unsigned long *)ipinfo->iniface_mask)[i];
+		}
 
-	if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
-		dprintf("VIA in mismatch (%s vs %s).%s\n",
-			indev, ipinfo->iniface,
-			ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
-		return 0;
+		if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
+			dprintf("VIA in mismatch (%s vs %s).%s\n",
+				indev, ipinfo->iniface,
+				ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
+			return 0;
+		}
 	}
 
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
-		ret |= (((const unsigned long *)outdev)[i]
-			^ ((const unsigned long *)ipinfo->outiface)[i])
-			& ((const unsigned long *)ipinfo->outiface_mask)[i];
-	}
+	if (ipinfo->flags & IPT_F_VIA_OUT) {
+		for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
+			ret |= (((const unsigned long *)outdev)[i]
+				^ ((const unsigned long *)ipinfo->outiface)[i])
+				& ((const unsigned long *)ipinfo->outiface_mask)[i];
+		}
 
-	if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
-		dprintf("VIA out mismatch (%s vs %s).%s\n",
-			outdev, ipinfo->outiface,
-			ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
-		return 0;
+		if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
+			dprintf("VIA out mismatch (%s vs %s).%s\n",
+				outdev, ipinfo->outiface,
+				ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
+			return 0;
+		}
 	}
 
 	/* Check specific protocol */
@@ -159,13 +163,21 @@ ip_packet_match(const struct iphdr *ip,
 }
 
 static inline int
-ip_checkentry(const struct ipt_ip *ip)
+ip_checkentry(struct ipt_ip *ip)
 {
+	size_t i;
+
 	if (ip->flags & ~IPT_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ip->flags & ~IPT_F_MASK);
 		return 0;
 	}
+	for (i = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
+		if (ip->iniface_mask[i])
+			ip->flags |= IPT_F_VIA_IN;
+		if (ip->outiface_mask[i])
+			ip->flags |= IPT_F_VIA_OUT;
+	}
 	if (ip->invflags & ~IPT_INV_MASK) {
 		duprintf("Unknown invflag bits set: %08X\n",
 			 ip->invflags & ~IPT_INV_MASK);
@@ -869,8 +881,9 @@ copy_entries_to_user(unsigned int total_
 	}
 
 	/* FIXME: use iterator macros --RR */
-	/* ... then go back and fix counters and names */
+	/* ... then go back and fix counters, flags, and names */
 	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
+		u_int8_t flags;
 		unsigned int i;
 		struct ipt_entry_match *m;
 		struct ipt_entry_target *t;
@@ -884,6 +897,15 @@ copy_entries_to_user(unsigned int total_
 			goto free_counters;
 		}
 
+		flags = e->ip.flags & IPT_F_MASK;
+		if (copy_to_user(userptr + off
+				 + offsetof(struct ipt_entry, ip.flags),
+				 &flags,
+				 sizeof(flags)) != 0) {
+			ret = -EFAULT;
+			goto free_counters;
+		}
+
 		for (i = sizeof(struct ipt_entry);
 		     i < e->target_offset;
 		     i += m->u.match_size) {

             reply	other threads:[~2007-05-24  5:55 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-24  5:55 Philip Craig [this message]
2007-05-24 17:43 ` [RFC][PATCH] optimise iptables interface matching Patrick McHardy
2007-05-24 23:07   ` Philip Craig
2007-05-26  8:47     ` Patrick McHardy
2007-05-25  0:44 ` Yasuyuki KOZAKAI
2007-05-25  0:56   ` Philip Craig
2007-05-25  4:11     ` Yasuyuki KOZAKAI
2007-05-26  9:20     ` Patrick McHardy
2007-05-28 19:53       ` Henrik Nordstrom
2007-05-29  0:24         ` Philip Craig
2007-05-30  1:34           ` Henrik Nordstrom
2007-06-06  5:49             ` Philip Craig
2007-06-06  6:13               ` Eric Dumazet
2007-05-29  9:54         ` Patrick McHardy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=465528CB.4020108@snapgear.com \
    --to=philipc@snapgear.com \
    --cc=netfilter-devel@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.