All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: netdev@vger.kernel.org, netfilter-devel@lists.netfilter.org,
	davem@davemloft.net
Subject: Re: [PATCH 05/13]: [IPV4/6]: Netfilter IPsec output hooks
Date: Mon, 28 Nov 2005 02:07:03 +0100	[thread overview]
Message-ID: <438A5837.5040706@trash.net> (raw)
In-Reply-To: <20051122121358.GA9057@gondor.apana.org.au>

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

Herbert Xu wrote:
> On Tue, Nov 22, 2005 at 09:31:39PM +1100, herbert wrote:
> 
>>Unfortunately it looks like gcc 3.3.5 at least is too dumb to optimise
>>it away.  I think we'll need a better strategy.
> 
> 
> OK, the idea is still the same: Move the loop from dst_output into
> xfrm4_output/xfrm6_output since they're the only ones who need to it.
> 
> In order to avoid the tail call issue, I've added the inline function
> nf_hook which is nf_hook_slow plus the empty list check.

Thanks, this looks great. I've changed it to only call the hooks
before tunnel mode transforms and added a missing dst_output call
for the final packet.

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 8459 bytes --]

[XFRM4/6]: Netfilter IPsec output hooks

Call netfilter hooks before IPsec transforms. Packets visit the FORWARD/LOCAL_OUT
and POST_ROUTING hook before the first encapsulation and the LOCAL_OUT and
POST_ROUTING hook before each following tunnel mode transform.

Based in large parts on patch by Herbert Xu <herbert@gondor.apana.org.au>,
that hides everything within xfrm{4,6}_output.c. Original description:
-
Move the loop from dst_output into xfrm4_output/xfrm6_output since they're
the only ones who need to it.

In order to avoid the tail call issue, I've added the inline function
nf_hook which is nf_hook_slow plus the empty list check.
-

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 7abb84c6c3916fc365051a090c752db682b022ab
tree 31b5c4089aaf23cd2c44516f95fddf2158d0fd70
parent b47e6dc58fa6342f2403a32dd1060bc8b1cef56b
author Patrick McHardy <kaber@trash.net> Mon, 28 Nov 2005 01:56:11 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 28 Nov 2005 01:56:11 +0100

 include/linux/netfilter.h |   61 +++++++++++++++++++++++++++------------------
 include/net/dst.h         |   11 +-------
 net/ipv4/xfrm4_output.c   |   39 +++++++++++++++++++++++++++--
 net/ipv6/xfrm6_output.c   |   39 +++++++++++++++++++++++++++--
 4 files changed, 112 insertions(+), 38 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index be365e7..79bb977 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -168,6 +168,37 @@ void nf_log_packet(int pf,
 		   const struct net_device *out,
 		   struct nf_loginfo *li,
 		   const char *fmt, ...);
+
+int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
+		 struct net_device *indev, struct net_device *outdev,
+		 int (*okfn)(struct sk_buff *), int thresh);
+
+/**
+ *	nf_hook_thresh - call a netfilter hook
+ *	
+ *	Returns 1 if the hook has allowed the packet to pass.  The function
+ *	okfn must be invoked by the caller in this case.  Any other return
+ *	value indicates the packet has been consumed by the hook.
+ */
+static inline int nf_hook_thresh(int pf, unsigned int hook,
+				 struct sk_buff **pskb,
+				 struct net_device *indev,
+				 struct net_device *outdev,
+				 int (*okfn)(struct sk_buff *), int thresh)
+{
+#ifndef CONFIG_NETFILTER_DEBUG
+	if (list_empty(&nf_hooks[pf][hook]))
+		return 1;
+#endif
+	return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh);
+}
+
+static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
+			  struct net_device *indev, struct net_device *outdev,
+			  int (*okfn)(struct sk_buff *))
+{
+	return nf_hook_thresh(pf, hook, pskb, indev, outdev, okfn, INT_MIN);
+}
                    
 /* Activate hook; either okfn or kfree_skb called, unless a hook
    returns NF_STOLEN (in which case, it's up to the hook to deal with
@@ -188,35 +219,17 @@ void nf_log_packet(int pf,
 
 /* This is gross, but inline doesn't cut it for avoiding the function
    call in fast path: gcc doesn't inline (needs value tracking?). --RR */
-#ifdef CONFIG_NETFILTER_DEBUG
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			       \
-({int __ret;								       \
-if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
-	__ret = (okfn)(skb);						       \
-__ret;})
-#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)	       \
-({int __ret;								       \
-if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1)  \
-	__ret = (okfn)(skb);						       \
-__ret;})
-#else
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			       \
-({int __ret;								       \
-if (list_empty(&nf_hooks[pf][hook]) ||					       \
-    (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
-	__ret = (okfn)(skb);						       \
-__ret;})
+
+/* HX: It's slightly less gross now. */
+
 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)	       \
 ({int __ret;								       \
-if (list_empty(&nf_hooks[pf][hook]) ||					       \
-    (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1)  \
+if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1)\
 	__ret = (okfn)(skb);						       \
 __ret;})
-#endif
 
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
-		 struct net_device *indev, struct net_device *outdev,
-		 int (*okfn)(struct sk_buff *), int thresh);
+#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
+	NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)
 
 /* Call setsockopt() */
 int nf_setsockopt(struct sock *sk, int pf, int optval, char __user *opt, 
diff --git a/include/net/dst.h b/include/net/dst.h
index 6c196a5..e641dd2 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -224,16 +224,7 @@ static inline void dst_set_expires(struc
 /* Output packet to network from transport.  */
 static inline int dst_output(struct sk_buff *skb)
 {
-	int err;
-
-	for (;;) {
-		err = skb->dst->output(skb);
-
-		if (likely(err == 0))
-			return err;
-		if (unlikely(err != NET_XMIT_BYPASS))
-			return err;
-	}
+	return skb->dst->output(skb);
 }
 
 /* Input packet from network to transport.  */
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 66620a9..67b9483 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -8,8 +8,10 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/compiler.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
+#include <linux/netfilter_ipv4.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
@@ -95,7 +97,7 @@ out:
 	return ret;
 }
 
-int xfrm4_output(struct sk_buff *skb)
+static int xfrm4_output_one(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
@@ -133,7 +135,7 @@ int xfrm4_output(struct sk_buff *skb)
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
-	err = NET_XMIT_BYPASS;
+	err = 0;
 
 out_exit:
 	return err;
@@ -143,3 +145,36 @@ error_nolock:
 	kfree_skb(skb);
 	goto out_exit;
 }
+
+static int xfrm4_output_finish(struct sk_buff *skb)
+{
+	int err;
+
+	while (likely((err = xfrm4_output_one(skb)) == 0)) {
+		if (!skb->dst->xfrm || skb->dst->xfrm->props.mode) {
+			nf_reset(skb);
+			err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
+				      skb->dst->dev, dst_output);
+			if (unlikely(err != 1))
+				break;
+
+			if (!skb->dst->xfrm) {
+				err = dst_output(skb);
+				break;
+			}
+
+			err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
+				      skb->dst->dev, xfrm4_output_finish);
+			if (unlikely(err != 1))
+				break;
+		}
+	}
+
+	return err;
+}
+
+int xfrm4_output(struct sk_buff *skb)
+{
+	return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
+		       xfrm4_output_finish);
+}
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6b98677..69ee2bf 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -9,9 +9,11 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/compiler.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
+#include <linux/netfilter_ipv6.h>
 #include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ipv6.h>
@@ -92,7 +94,7 @@ static int xfrm6_tunnel_check_size(struc
 	return ret;
 }
 
-int xfrm6_output(struct sk_buff *skb)
+static int xfrm6_output_one(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
@@ -132,7 +134,7 @@ int xfrm6_output(struct sk_buff *skb)
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
-	err = NET_XMIT_BYPASS;
+	err = 0;
 
 out_exit:
 	return err;
@@ -142,3 +144,36 @@ error_nolock:
 	kfree_skb(skb);
 	goto out_exit;
 }
+
+static int xfrm6_output_finish(struct sk_buff *skb)
+{
+	int err;
+
+	while (likely((err = xfrm6_output_one(skb)) == 0)) {
+		if (!skb->dst->xfrm || skb->dst->xfrm->props.mode) {
+			nf_reset(skb);
+			err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL,
+				      skb->dst->dev, dst_output);
+			if (unlikely(err != 1))
+				break;
+
+			if (!skb->dst->xfrm) {
+				err = dst_output(skb);
+				break;
+			}
+
+			err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
+				      skb->dst->dev, xfrm6_output_finish);
+			if (unlikely(err != 1))
+				break;
+		}
+	}
+
+	return err;
+}
+
+int xfrm6_output(struct sk_buff *skb)
+{
+	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,
+		       xfrm6_output_finish);
+}

  reply	other threads:[~2005-11-28  1:07 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-20 16:31 [PATCH 00/13]: Netfilter IPsec support Patrick McHardy
2005-11-20 16:31 ` [PATCH 01/13]: [NETFILTER]: Remove okfn usage in ip_vs_core.c Patrick McHardy
2005-11-20 16:31 ` [PATCH 02/13]: [NETFILTER]: Call POST_ROUTING hook before fragmentation Patrick McHardy
2005-11-20 16:31 ` [PATCH 03/13]: [IPV4]: Replace dst_output by ip_dst_output Patrick McHardy
2005-11-20 16:31 ` [PATCH 04/13]: [IPV6]: Replace dst_output by ip6_dst_output Patrick McHardy
2005-11-20 16:31 ` [PATCH 05/13]: [IPV4/6]: Netfilter IPsec output hooks Patrick McHardy
2005-11-22  4:40   ` Herbert Xu
2005-11-22  4:53     ` Patrick McHardy
2005-11-22  5:13       ` Patrick McHardy
2005-11-22 10:30       ` Herbert Xu
2005-11-22 10:31         ` Herbert Xu
2005-11-22 12:13           ` Herbert Xu
2005-11-28  1:07             ` Patrick McHardy [this message]
2005-11-28  4:56               ` Herbert Xu
2005-11-28 12:25                 ` Patrick McHardy
2005-12-04 22:09                 ` Patrick McHardy
2005-12-04 22:15                   ` Herbert Xu
2005-11-20 16:31 ` [PATCH 06/13]: [IPV4/6]: Netfilter IPsec input hooks Patrick McHardy
2005-11-21  4:42   ` Yasuyuki KOZAKAI
     [not found]   ` <200511210442.jAL4gPoO001846@toshiba.co.jp>
2005-11-21  6:52     ` Patrick McHardy
2005-11-21  7:00       ` David S. Miller
2005-11-21  7:47         ` Herbert Xu
2005-11-21 16:52         ` Patrick McHardy
2005-11-21 10:53       ` Yasuyuki KOZAKAI
     [not found]       ` <200511211053.jALAro04019574@toshiba.co.jp>
2005-11-21 16:34         ` Patrick McHardy
     [not found]   ` <438185ED.3050005@miyazawa.org>
2005-11-21  8:50     ` YOSHIFUJI Hideaki / 吉藤英明
2005-11-21 16:29       ` Patrick McHardy
2005-12-01  1:27   ` Herbert Xu
2005-12-04 22:06     ` Patrick McHardy
2005-12-04 22:10       ` Herbert Xu
2005-12-04 22:49         ` Patrick McHardy
2005-11-20 16:31 ` [PATCH 07/13]: [NETFILTER]: Fix xfrm lookup in ip_route_me_harder/ip6_route_me_harder Patrick McHardy
2005-11-28 21:06   ` Herbert Xu
2005-11-29  7:02     ` Patrick McHardy
2005-11-29  7:34       ` Herbert Xu
2005-11-29  7:49         ` David S. Miller
2005-11-29 11:31           ` Herbert Xu
2005-11-20 16:31 ` [PATCH 08/13]: [NETFILTER]: Use conntrack information to determine if packet was NATed Patrick McHardy
2005-11-20 16:31 ` [PATCH 09/13]: [NETFILTER]: Redo policy lookups after NAT when neccessary Patrick McHardy
2005-11-20 16:43   ` Patrick McHardy
2005-11-20 16:31 ` [PATCH 10/13]: [NETFILTER]: Keep the conntrack reference until after policy checks Patrick McHardy
2005-11-20 16:31 ` [PATCH 11/13]: [NETFILTER]: Handle NAT in IPsec " Patrick McHardy
2005-11-20 16:31 ` [PATCH 12/13]: [NETFILTER]: Export ip6_masked_addrcmp, don't pass IPv6 addresses on stack Patrick McHardy
2005-11-20 16:31 ` [PATCH 13/13]: [NETFILTER]: Add ipt_policy/ip6t_policy matches Patrick McHardy
     [not found] ` <200511201902.10179.lists@naasa.net>
2005-11-20 18:07   ` [PATCH 00/13]: Netfilter IPsec support Patrick McHardy
2005-11-22 22:34 ` David S. Miller
2005-11-22 22:38   ` YOSHIFUJI Hideaki / 吉藤英明
2005-11-23  1:20     ` Patrick McHardy
2005-11-23  1:17   ` Patrick McHardy
2005-11-23  1:35     ` Herbert Xu
2005-11-23  3:36       ` David S. Miller
2005-11-23  4:47         ` Herbert Xu
2005-11-23  4:52         ` Yasuyuki KOZAKAI
2005-11-23  3:35     ` David S. Miller

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=438A5837.5040706@trash.net \
    --to=kaber@trash.net \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=netdev@vger.kernel.org \
    --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.