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;
next prev parent reply other threads:[~2012-09-03 21:12 UTC|newest]
Thread overview: 11+ 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 11:58 ` Hans Schillstrom
2012-08-27 12:02 ` Patrick McHardy
2012-08-29 9:37 ` Jesper Dangaard Brouer
2012-08-29 9:37 ` Jesper Dangaard Brouer
2012-08-29 12:28 ` Patrick McHardy
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 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.