netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jesper Dangaard Brouer <brouer@redhat.com>
To: "Patrick McHardy" <kaber@trash.net>,
	Hans Schillstrom <hans@schillstrom.com>,
	Hans Schillstrom <hans.schillstrom@ericsson.com>
Cc: Jesper Dangaard Brouer <brouer@redhat.com>,
	netdev@vger.kernel.org, netfilter-devel@vger.kernel.org,
	Pablo Neira Ayuso <pablo@netfilter.org>
Subject: [RFC PATCH 1/2] net: Cache IPv6 extension header "skip" parsing
Date: Mon, 03 Sep 2012 23:16:26 +0200	[thread overview]
Message-ID: <20120903211602.8851.2843.stgit@dragon> (raw)
In-Reply-To: <20120903211504.8851.6894.stgit@dragon>

Store IPv6 exthdr data from ipv6_find_hdr() in skb->cb[].

Introducing struct inet6_skb_exthdr_cache / IP6CB_EXTHDR, as its not
possible to extend inet6_skb_parm directly, or else DCCP dccp_skb_cb
CB size gets too big.

Adding:
 __u16	thoff;   /* L4 Transport Header offset */
 __s16	protocol;/* L4 protocol */
 __u16	fragoff; /* packet is a fragment, with offset */

Optimize ip6t_do_table() by using the new ipv6_find_hdr_cb() in
ip6_packet_match().  Before ipv6_find_hdr() were called for each
iptables rule, with a "-p" protocol option (including -p all), which
is very commonly used. The function ipv6_find_hdr_cb() is inlined to
optimize this case and avoid a function call.

The inet6_skb_exthdr_cache / IP6CB_EXTHDR is added to linux/ipv6.h in
the hope that ipv6_skip_exthdr() might also take advantage of this, in
the future.

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>

---
Can someone tell me if netfilter (with all of its different HOOKs) can be
allowed to modify data after inet6_skb_parm/IP6CB ???


 include/linux/ipv6.h                      |   15 +++++++++++
 include/linux/netfilter_ipv6/ip6_tables.h |   40 +++++++++++++++++++++++++++++
 net/ipv6/netfilter/ip6_tables.c           |    2 +
 3 files changed, 56 insertions(+), 1 deletions(-)

diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 0b94e91..21d8cc3 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -266,6 +266,21 @@ struct inet6_skb_parm {
 #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
 #define IP6CBMTU(skb)	((struct ip6_mtuinfo *)((skb)->cb))
 
+/* Caching of exthdr info
+ * - This is used by netfilter and IPVS.
+ * (cannot extend inet6_skb_parm directly due to DCCP CB size gets too big)
+ */
+struct inet6_skb_exthdr_cache {
+	union {
+		struct inet6_skb_parm	h6;
+	} header;
+	/* Caching IPv6 exthdr "skip" info */
+	__u16	thoff;   /* L4 Transport Header offset */
+	__s16	protocol;/* L4 protocol */
+	__u16	fragoff; /* packet is a fragment, with offset */
+};
+#define IP6CB_EXTHDR(skb) ((struct inet6_skb_exthdr_cache*)((skb)->cb))
+
 static inline int inet6_iif(const struct sk_buff *skb)
 {
 	return IP6CB(skb)->iif;
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 08c2cbb..5209aff 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -303,6 +303,46 @@ enum {
 	IP6T_FH_F_AUTH	= (1 << 1),
 };
 
+/* Function caches IPv6 exthdr data from ipv6_find_hdr() in skb->cb[]
+ * - uses inet6_skb_exthdr_cache / IP6CB_EXTHDR
+ */
+static inline int
+ipv6_find_hdr_cb(const struct sk_buff *skb, unsigned int *offset,
+		 int target, unsigned short *fragoff, int *flags)
+{
+	struct inet6_skb_exthdr_cache *exthdr_cache = IP6CB_EXTHDR(skb);
+	__s16 protocol;
+
+	/* Only cache the "skip" exthdr usage */
+	if (target > 0) /* looking for a specific nexthdr target */
+		goto no_cache;
+	if (*offset) /* start at a specific offset */
+		goto no_cache;
+	if (flags) /* not caching flags at the moment */
+		goto no_cache;
+
+	/* Use thoff (transport header) as cache avail indicator */
+	if (exthdr_cache->thoff > 0) {
+		*offset  = exthdr_cache->thoff;
+		protocol = exthdr_cache->protocol;
+		if (fragoff)
+			*fragoff = exthdr_cache->fragoff;
+		return protocol;
+	}
+
+	protocol = ipv6_find_hdr(skb, offset, target, fragoff, flags);
+	if (protocol > 0) {
+                /* save a copy in the CB */
+		exthdr_cache->thoff = *offset;
+		exthdr_cache->protocol = protocol;
+		if (fragoff)
+			exthdr_cache->fragoff = *fragoff;
+	}
+	return protocol;
+no_cache:
+	return ipv6_find_hdr(skb, offset, target, fragoff, flags);
+}
+
 /* find specified header and get offset to it */
 extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 			 int target, unsigned short *fragoff, int *fragflg);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index d7cb045..79367f2 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -133,7 +133,7 @@ ip6_packet_match(const struct sk_buff *skb,
 		int protohdr;
 		unsigned short _frag_off;
 
-		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off, NULL);
+		protohdr = ipv6_find_hdr_cb(skb, protoff, -1, &_frag_off, NULL);
 		if (protohdr < 0) {
 			if (_frag_off == 0)
 				*hotdrop = true;


  reply	other threads:[~2012-09-03 21:12 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-27 11:58 Re[3]: [PATCH 2/3] ipvs: Fix faulty IPv6 extension header handling in IPVS Hans Schillstrom
2012-08-27 12:02 ` Patrick McHardy
2012-08-29  9:37   ` Jesper Dangaard Brouer
2012-08-29 12:28     ` Patrick McHardy
2012-09-03 21:15       ` [RFC PATCH 0/2] RFC: Caching IPv6 exthdr in skb->cb[] Jesper Dangaard Brouer
2012-09-03 21:16         ` Jesper Dangaard Brouer [this message]
2012-09-03 21:16         ` [RFC PATCH 2/2] netfilter: More users of ipv6_find_hdr_cb() Jesper Dangaard Brouer
2012-09-04  7:26         ` [RFC PATCH 0/2] RFC: Caching IPv6 exthdr in skb->cb[] Julian Anastasov

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=20120903211602.8851.2843.stgit@dragon \
    --to=brouer@redhat.com \
    --cc=hans.schillstrom@ericsson.com \
    --cc=hans@schillstrom.com \
    --cc=kaber@trash.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).