All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/12] vti6: prepare namespace and interfamily support.
@ 2014-02-28 10:31 Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly Steffen Klassert
                   ` (11 more replies)
  0 siblings, 12 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

This patchset prepares vti6 for proper namespace and interfamily support.

With this patchset vti6 uses a new IPsec protocol multiplexer to
register it's own receive side hooks for ESP, AH and IPCOMP exactly
like the ipv4 side does that now.

Vti6 does the following on receive side:

1. Do an input policy check for the IPsec packet we received.
   This is required because this packet could be already
   processed by IPsec (tunnel in tunnel or a block policy
   is present), so an inbound policy check is needed.

2. Mark the packet with the i_key. The policy and the state
   must match this key now. Policy and state belong to the vti
   namespace and policy enforcement is done at the further layers.

3. Call the generic xfrm layer to do decryption and decapsulation.

4. Wait for a callback from the xfrm layer to do an inbound policy check
   on the vti policy, properly clean the skb to not leak informations on
   namespace transitions and to update the device statistics.

On transmit side:

1. Mark the packet with the o_key. The policy and the state
   must match this key now.

2. Do a xfrm_lookup on the original packet with the mark applied.

3. Check if we got an IPsec route.

4. Clean the skb to not leak informations on namespace
   transitions.

5. Attach the dst_enty we got from the xfrm_lookup to the skb.

6. Call dst_output to do the IPsec processing.

7. Do the device statistics.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-03-03  1:09   ` David Miller
  2014-02-28 10:31 ` [PATCH RFC 02/12] xfrm6: Add IPsec protocol multiplexer Steffen Klassert
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

IPv6 can be build as a module, so we need mechanism to access
the address family dependent callback functions properly.
Therefore we introduce xfrm_input_afinfo, similar to that
what we have for the address family dependent part of
policies and states.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 include/net/xfrm.h        |   23 +++++++--------
 net/ipv4/xfrm4_policy.c   |    1 +
 net/ipv4/xfrm4_protocol.c |   13 ++++++++-
 net/xfrm/xfrm_input.c     |   71 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 8b92528..4cdc9fa 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -349,6 +349,16 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
 struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
 void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
+struct xfrm_input_afinfo {
+	unsigned int		family;
+	struct module		*owner;
+	int			(*callback)(struct sk_buff *skb, u8 protocol,
+					    int err);
+};
+
+int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo);
+int xfrm_input_unregister_afinfo(struct xfrm_input_afinfo *afinfo);
+
 void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
 struct xfrm_type {
@@ -1392,6 +1402,7 @@ void xfrm4_init(void);
 int xfrm_state_init(struct net *net);
 void xfrm_state_fini(struct net *net);
 void xfrm4_state_init(void);
+void xfrm4_protocol_init(void);
 #ifdef CONFIG_XFRM
 int xfrm6_init(void);
 void xfrm6_fini(void);
@@ -1773,18 +1784,6 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
 	return ret;
 }
 
-static inline int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family,
-			      u8 protocol, int err)
-{
-	switch(family) {
-#ifdef CONFIG_INET
-	case AF_INET:
-		return xfrm4_rcv_cb(skb, protocol, err);
-#endif
-	}
-	return 0;
-}
-
 static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
 				    unsigned int family)
 {
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index e1a6393..6156f68 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -325,6 +325,7 @@ void __init xfrm4_init(void)
 
 	xfrm4_state_init();
 	xfrm4_policy_init();
+	xfrm4_protocol_init();
 #ifdef CONFIG_SYSCTL
 	register_pernet_subsys(&xfrm4_net_ops);
 #endif
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c
index cdc09ef..7f7b243 100644
--- a/net/ipv4/xfrm4_protocol.c
+++ b/net/ipv4/xfrm4_protocol.c
@@ -179,6 +179,12 @@ static const struct net_protocol ipcomp4_protocol = {
 	.netns_ok	=	1,
 };
 
+static struct xfrm_input_afinfo xfrm4_input_afinfo = {
+	.family		=	AF_INET,
+	.owner		=	THIS_MODULE,
+	.callback	=	xfrm4_rcv_cb,
+};
+
 static inline const struct net_protocol *netproto(unsigned char protocol)
 {
 	switch (protocol) {
@@ -199,7 +205,6 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler,
 	struct xfrm4_protocol __rcu **pprev;
 	struct xfrm4_protocol *t;
 	bool add_netproto = false;
-
 	int ret = -EEXIST;
 	int priority = handler->priority;
 
@@ -273,3 +278,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
 	return ret;
 }
 EXPORT_SYMBOL(xfrm4_protocol_deregister);
+
+void __init xfrm4_protocol_init(void)
+{
+	xfrm_input_register_afinfo(&xfrm4_input_afinfo);
+}
+EXPORT_SYMBOL(xfrm4_protocol_init);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 4218164..8b4fb75 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -16,6 +16,77 @@
 
 static struct kmem_cache *secpath_cachep __read_mostly;
 
+static DEFINE_SPINLOCK(xfrm_input_afinfo_lock);
+static struct xfrm_input_afinfo __rcu *xfrm_input_afinfo[NPROTO];
+
+int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo)
+{
+	int err = 0;
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	if (unlikely(afinfo->family >= NPROTO))
+		return -EAFNOSUPPORT;
+	spin_lock_bh(&xfrm_input_afinfo_lock);
+	if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL))
+		err = -ENOBUFS;
+	else
+		rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo);
+	spin_unlock_bh(&xfrm_input_afinfo_lock);
+	return err;
+}
+EXPORT_SYMBOL(xfrm_input_register_afinfo);
+
+int xfrm_input_unregister_afinfo(struct xfrm_input_afinfo *afinfo)
+{
+	int err = 0;
+	if (unlikely(afinfo == NULL))
+		return -EINVAL;
+	if (unlikely(afinfo->family >= NPROTO))
+		return -EAFNOSUPPORT;
+	spin_lock_bh(&xfrm_input_afinfo_lock);
+	if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) {
+		if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo))
+			err = -EINVAL;
+		else
+			RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL);
+	}
+	spin_unlock_bh(&xfrm_input_afinfo_lock);
+	synchronize_rcu();
+	return err;
+}
+EXPORT_SYMBOL(xfrm_input_unregister_afinfo);
+
+static struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family)
+{
+	struct xfrm_input_afinfo *afinfo;
+	if (unlikely(family >= NPROTO))
+		return NULL;
+	rcu_read_lock();
+	afinfo = rcu_dereference(xfrm_input_afinfo[family]);
+	if (unlikely(!afinfo))
+		rcu_read_unlock();
+	return afinfo;
+}
+
+static void xfrm_input_put_afinfo(struct xfrm_input_afinfo *afinfo)
+{
+	rcu_read_unlock();
+}
+
+static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol,
+		       int err)
+{
+	int ret;
+	struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family);
+	if (!afinfo)
+		return -EAFNOSUPPORT;
+
+	ret = afinfo->callback(skb, protocol, err);
+	xfrm_input_put_afinfo(afinfo);
+
+	return ret;
+}
+
 void __secpath_destroy(struct sec_path *sp)
 {
 	int i;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 02/12] xfrm6: Add IPsec protocol multiplexer
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 03/12] esp6: Use the IPsec protocol multiplexer API Steffen Klassert
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

This patch adds an IPsec protocol multiplexer for ipv6. With
this it is possible to add alternative protocol handlers, as
needed for IPsec virtual tunnel interfaces.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 include/net/xfrm.h        |   15 +++
 net/ipv6/Makefile         |    2 +-
 net/ipv6/xfrm6_policy.c   |    7 ++
 net/ipv6/xfrm6_protocol.c |  270 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 293 insertions(+), 1 deletion(-)
 create mode 100644 net/ipv6/xfrm6_protocol.c

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4cdc9fa..60df20a 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1374,6 +1374,16 @@ struct xfrm4_protocol {
 	int priority;
 };
 
+struct xfrm6_protocol {
+	int (*handler)(struct sk_buff *skb);
+	int (*cb_handler)(struct sk_buff *skb, int err);
+	int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			   u8 type, u8 code, int offset, __be32 info);
+
+	struct xfrm6_protocol __rcu *next;
+	int priority;
+};
+
 /* XFRM tunnel handlers.  */
 struct xfrm_tunnel {
 	int (*handler)(struct sk_buff *skb);
@@ -1408,6 +1418,8 @@ int xfrm6_init(void);
 void xfrm6_fini(void);
 int xfrm6_state_init(void);
 void xfrm6_state_fini(void);
+int xfrm6_protocol_init(void);
+void xfrm6_protocol_fini(void);
 #else
 static inline int xfrm6_init(void)
 {
@@ -1552,6 +1564,9 @@ int xfrm6_rcv(struct sk_buff *skb);
 int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
 		     xfrm_address_t *saddr, u8 proto);
 void xfrm6_local_error(struct sk_buff *skb, u32 mtu);
+int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
+int xfrm6_protocol_register(struct xfrm6_protocol *handler, unsigned char protocol);
+int xfrm6_protocol_deregister(struct xfrm6_protocol *handler, unsigned char protocol);
 int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
 int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
 __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 17bb830..2fe6836 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -16,7 +16,7 @@ ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o
 ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
 
 ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
-	xfrm6_output.o
+	xfrm6_output.o xfrm6_protocol.o
 ipv6-$(CONFIG_NETFILTER) += netfilter.o
 ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
 ipv6-$(CONFIG_PROC_FS) += proc.o
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 5f8e128..2a0bbda 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -389,11 +389,17 @@ int __init xfrm6_init(void)
 	if (ret)
 		goto out_policy;
 
+	ret = xfrm6_protocol_init();
+	if (ret)
+		goto out_state;
+
 #ifdef CONFIG_SYSCTL
 	register_pernet_subsys(&xfrm6_net_ops);
 #endif
 out:
 	return ret;
+out_state:
+	xfrm6_state_fini();
 out_policy:
 	xfrm6_policy_fini();
 	goto out;
@@ -404,6 +410,7 @@ void xfrm6_fini(void)
 #ifdef CONFIG_SYSCTL
 	unregister_pernet_subsys(&xfrm6_net_ops);
 #endif
+	xfrm6_protocol_fini();
 	xfrm6_policy_fini();
 	xfrm6_state_fini();
 	dst_entries_destroy(&xfrm6_dst_ops);
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c
new file mode 100644
index 0000000..fd0ebf0
--- /dev/null
+++ b/net/ipv6/xfrm6_protocol.c
@@ -0,0 +1,270 @@
+/* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6.
+ *
+ * Copyright (C) 2013 secunet Security Networks AG
+ *
+ * Author:
+ * Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * Based on:
+ * net/ipv4/xfrm4_protocol.c
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/skbuff.h>
+#include <linux/icmpv6.h>
+#include <net/ipv6.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly;
+static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly;
+static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly;
+static DEFINE_MUTEX(xfrm6_protocol_mutex);
+
+static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol)
+{
+	switch (protocol) {
+	case IPPROTO_ESP:
+		return &esp6_handlers;
+	case IPPROTO_AH:
+		return &ah6_handlers;
+	case IPPROTO_COMP:
+		return &ipcomp6_handlers;
+	}
+
+	return NULL;
+}
+
+#define for_each_protocol_rcu(head, handler)		\
+	for (handler = rcu_dereference(head);		\
+	     handler != NULL;				\
+	     handler = rcu_dereference(handler->next))	\
+
+int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
+{
+	int ret;
+	struct xfrm6_protocol *handler;
+
+	for_each_protocol_rcu(*proto_handlers(protocol), handler)
+		if ((ret = handler->cb_handler(skb, err)) <= 0)
+			return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(xfrm6_rcv_cb);
+
+static int xfrm6_esp_rcv(struct sk_buff *skb)
+{
+	int ret;
+	struct xfrm6_protocol *handler;
+
+	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
+
+	for_each_protocol_rcu(esp6_handlers, handler)
+		if ((ret = handler->handler(skb)) != -EINVAL)
+			return ret;
+
+	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static void xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			  u8 type, u8 code, int offset, __be32 info)
+{
+	struct xfrm6_protocol *handler;
+
+	for_each_protocol_rcu(esp6_handlers, handler)
+		if (!handler->err_handler(skb, opt, type, code, offset, info))
+			break;
+}
+
+static int xfrm6_ah_rcv(struct sk_buff *skb)
+{
+	int ret;
+	struct xfrm6_protocol *handler;
+
+	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
+
+	for_each_protocol_rcu(ah6_handlers, handler)
+		if ((ret = handler->handler(skb)) != -EINVAL)
+			return ret;
+
+	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static void xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			 u8 type, u8 code, int offset, __be32 info)
+{
+	struct xfrm6_protocol *handler;
+
+	for_each_protocol_rcu(ah6_handlers, handler)
+		if (!handler->err_handler(skb ,opt, type, code, offset, info))
+			break;
+}
+
+static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
+{
+	int ret;
+	struct xfrm6_protocol *handler;
+
+	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
+
+	for_each_protocol_rcu(ipcomp6_handlers, handler)
+		if ((ret = handler->handler(skb)) != -EINVAL)
+			return ret;
+
+	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static void xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			     u8 type, u8 code, int offset, __be32 info)
+{
+	struct xfrm6_protocol *handler;
+
+	for_each_protocol_rcu(ipcomp6_handlers, handler)
+		if (!handler->err_handler(skb ,opt, type, code, offset, info))
+			break;
+}
+
+static const struct inet6_protocol esp6_protocol = {
+	.handler	=	xfrm6_esp_rcv,
+	.err_handler	=	xfrm6_esp_err,
+	.flags		=	INET6_PROTO_NOPOLICY,
+};
+
+static const struct inet6_protocol ah6_protocol = {
+	.handler	=	xfrm6_ah_rcv,
+	.err_handler	=	xfrm6_ah_err,
+	.flags		=	INET6_PROTO_NOPOLICY,
+};
+
+static const struct inet6_protocol ipcomp6_protocol = {
+	.handler	=	xfrm6_ipcomp_rcv,
+	.err_handler	=	xfrm6_ipcomp_err,
+	.flags		=	INET6_PROTO_NOPOLICY,
+};
+
+static struct xfrm_input_afinfo xfrm6_input_afinfo = {
+	.family		=	AF_INET6,
+	.owner		=	THIS_MODULE,
+	.callback	=	xfrm6_rcv_cb,
+};
+
+static inline const struct inet6_protocol *netproto(unsigned char protocol)
+{
+	switch (protocol) {
+	case IPPROTO_ESP:
+		return &esp6_protocol;
+	case IPPROTO_AH:
+		return &ah6_protocol;
+	case IPPROTO_COMP:
+		return &ipcomp6_protocol;
+	}
+
+	return NULL;
+}
+
+int xfrm6_protocol_register(struct xfrm6_protocol *handler,
+			    unsigned char protocol)
+{
+	struct xfrm6_protocol __rcu **pprev;
+	struct xfrm6_protocol *t;
+	bool add_netproto = false;
+
+	int ret = -EEXIST;
+	int priority = handler->priority;
+
+	mutex_lock(&xfrm6_protocol_mutex);
+
+	if (!rcu_dereference_protected(*proto_handlers(protocol),
+				       lockdep_is_held(&xfrm6_protocol_mutex)))
+		add_netproto = true;
+
+	for (pprev = proto_handlers(protocol);
+	     (t = rcu_dereference_protected(*pprev,
+			lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
+	     pprev = &t->next) {
+		if (t->priority < priority)
+			break;
+		if (t->priority == priority)
+			goto err;
+	}
+
+	handler->next = *pprev;
+	rcu_assign_pointer(*pprev, handler);
+
+	ret = 0;
+
+err:
+	mutex_unlock(&xfrm6_protocol_mutex);
+
+	if (add_netproto) {
+		if (inet6_add_protocol(netproto(protocol), protocol)) {
+			pr_err("%s: can't add protocol\n", __func__);
+			ret = -EAGAIN;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(xfrm6_protocol_register);
+
+int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
+			      unsigned char protocol)
+{
+	struct xfrm6_protocol __rcu **pprev;
+	struct xfrm6_protocol *t;
+	int ret = -ENOENT;
+
+	mutex_lock(&xfrm6_protocol_mutex);
+
+	for (pprev = proto_handlers(protocol);
+	     (t = rcu_dereference_protected(*pprev,
+			lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
+	     pprev = &t->next) {
+		if (t == handler) {
+			*pprev = handler->next;
+			ret = 0;
+			break;
+		}
+	}
+
+	if (!rcu_dereference_protected(*proto_handlers(protocol),
+				       lockdep_is_held(&xfrm6_protocol_mutex))) {
+		if (inet6_del_protocol(netproto(protocol), protocol) < 0) {
+			pr_err("%s: can't remove protocol\n", __func__);
+			ret = -EAGAIN;
+		}
+	}
+
+	mutex_unlock(&xfrm6_protocol_mutex);
+
+	synchronize_net();
+
+	return ret;
+}
+EXPORT_SYMBOL(xfrm6_protocol_deregister);
+
+int __init xfrm6_protocol_init(void)
+{
+	return xfrm_input_register_afinfo(&xfrm6_input_afinfo);
+}
+
+void xfrm6_protocol_fini(void)
+{
+	xfrm_input_unregister_afinfo(&xfrm6_input_afinfo);
+}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 03/12] esp6: Use the IPsec protocol multiplexer API
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 02/12] xfrm6: Add IPsec protocol multiplexer Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 04/12] ah6: " Steffen Klassert
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

Switch esp6 to use the new IPsec protocol multiplexer.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/esp6.c |   22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 6eef8a7..d979480 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -421,7 +421,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
 		 net_adj) & ~(blksize - 1)) + net_adj - 2;
 }
 
-static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 		     u8 type, u8 code, int offset, __be32 info)
 {
 	struct net *net = dev_net(skb->dev);
@@ -431,18 +431,20 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
 	if (type != ICMPV6_PKT_TOOBIG &&
 	    type != NDISC_REDIRECT)
-		return;
+		return 0;
 
 	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
 			      esph->spi, IPPROTO_ESP, AF_INET6);
 	if (!x)
-		return;
+		return 0;
 
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
 		ip6_update_pmtu(skb, net, info, 0, 0);
 	xfrm_state_put(x);
+
+	return 0;
 }
 
 static void esp6_destroy(struct xfrm_state *x)
@@ -614,6 +616,11 @@ error:
 	return err;
 }
 
+static int esp6_rcv_cb(struct sk_buff *skb, int err)
+{
+	return 0;
+}
+
 static const struct xfrm_type esp6_type =
 {
 	.description	= "ESP6",
@@ -628,10 +635,11 @@ static const struct xfrm_type esp6_type =
 	.hdr_offset	= xfrm6_find_1stfragopt,
 };
 
-static const struct inet6_protocol esp6_protocol = {
+static struct xfrm6_protocol esp6_protocol = {
 	.handler 	=	xfrm6_rcv,
+	.cb_handler 	=	esp6_rcv_cb,
 	.err_handler	=	esp6_err,
-	.flags		=	INET6_PROTO_NOPOLICY,
+	.priority	=	0,
 };
 
 static int __init esp6_init(void)
@@ -640,7 +648,7 @@ static int __init esp6_init(void)
 		pr_info("%s: can't add xfrm type\n", __func__);
 		return -EAGAIN;
 	}
-	if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) {
+	if (xfrm6_protocol_register(&esp6_protocol, IPPROTO_ESP) < 0) {
 		pr_info("%s: can't add protocol\n", __func__);
 		xfrm_unregister_type(&esp6_type, AF_INET6);
 		return -EAGAIN;
@@ -651,7 +659,7 @@ static int __init esp6_init(void)
 
 static void __exit esp6_fini(void)
 {
-	if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0)
+	if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0)
 		pr_info("%s: can't remove protocol\n", __func__);
 	if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0)
 		pr_info("%s: can't remove xfrm type\n", __func__);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 04/12] ah6: Use the IPsec protocol multiplexer API
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (2 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 03/12] esp6: Use the IPsec protocol multiplexer API Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 05/12] ipcomp6: " Steffen Klassert
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

Switch ah6 to use the new IPsec protocol multiplexer.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ah6.c |   22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 6c5f094..f35911e 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -643,7 +643,7 @@ out:
 	return err;
 }
 
-static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 		    u8 type, u8 code, int offset, __be32 info)
 {
 	struct net *net = dev_net(skb->dev);
@@ -653,17 +653,19 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
 	if (type != ICMPV6_PKT_TOOBIG &&
 	    type != NDISC_REDIRECT)
-		return;
+		return 0;
 
 	x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6);
 	if (!x)
-		return;
+		return 0;
 
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
 		ip6_update_pmtu(skb, net, info, 0, 0);
 	xfrm_state_put(x);
+
+	return 0;
 }
 
 static int ah6_init_state(struct xfrm_state *x)
@@ -748,6 +750,11 @@ static void ah6_destroy(struct xfrm_state *x)
 	kfree(ahp);
 }
 
+static int ah6_rcv_cb(struct sk_buff *skb, int err)
+{
+	return 0;
+}
+
 static const struct xfrm_type ah6_type =
 {
 	.description	= "AH6",
@@ -761,10 +768,11 @@ static const struct xfrm_type ah6_type =
 	.hdr_offset	= xfrm6_find_1stfragopt,
 };
 
-static const struct inet6_protocol ah6_protocol = {
+static struct xfrm6_protocol ah6_protocol = {
 	.handler	=	xfrm6_rcv,
+	.cb_handler	=	ah6_rcv_cb,
 	.err_handler	=	ah6_err,
-	.flags		=	INET6_PROTO_NOPOLICY,
+	.priority	=	0,
 };
 
 static int __init ah6_init(void)
@@ -774,7 +782,7 @@ static int __init ah6_init(void)
 		return -EAGAIN;
 	}
 
-	if (inet6_add_protocol(&ah6_protocol, IPPROTO_AH) < 0) {
+	if (xfrm6_protocol_register(&ah6_protocol, IPPROTO_AH) < 0) {
 		pr_info("%s: can't add protocol\n", __func__);
 		xfrm_unregister_type(&ah6_type, AF_INET6);
 		return -EAGAIN;
@@ -785,7 +793,7 @@ static int __init ah6_init(void)
 
 static void __exit ah6_fini(void)
 {
-	if (inet6_del_protocol(&ah6_protocol, IPPROTO_AH) < 0)
+	if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0)
 		pr_info("%s: can't remove protocol\n", __func__);
 
 	if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 05/12] ipcomp6: Use the IPsec protocol multiplexer API
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (3 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 04/12] ah6: " Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 06/12] vti6: Remove dst_entry caching Steffen Klassert
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

Switch ipcomp6 to use the new IPsec protocol multiplexer.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ipcomp6.c |   22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index da9becb..d1c793c 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -53,7 +53,7 @@
 #include <linux/icmpv6.h>
 #include <linux/mutex.h>
 
-static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 				u8 type, u8 code, int offset, __be32 info)
 {
 	struct net *net = dev_net(skb->dev);
@@ -65,19 +65,21 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
 	if (type != ICMPV6_PKT_TOOBIG &&
 	    type != NDISC_REDIRECT)
-		return;
+		return 0;
 
 	spi = htonl(ntohs(ipcomph->cpi));
 	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
 			      spi, IPPROTO_COMP, AF_INET6);
 	if (!x)
-		return;
+		return 0;
 
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
 		ip6_update_pmtu(skb, net, info, 0, 0);
 	xfrm_state_put(x);
+
+	return 0;
 }
 
 static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
@@ -174,6 +176,11 @@ out:
 	return err;
 }
 
+static int ipcomp6_rcv_cb(struct sk_buff *skb, int err)
+{
+	return 0;
+}
+
 static const struct xfrm_type ipcomp6_type =
 {
 	.description	= "IPCOMP6",
@@ -186,11 +193,12 @@ static const struct xfrm_type ipcomp6_type =
 	.hdr_offset	= xfrm6_find_1stfragopt,
 };
 
-static const struct inet6_protocol ipcomp6_protocol =
+static struct xfrm6_protocol ipcomp6_protocol =
 {
 	.handler	= xfrm6_rcv,
+	.cb_handler	= ipcomp6_rcv_cb,
 	.err_handler	= ipcomp6_err,
-	.flags		= INET6_PROTO_NOPOLICY,
+	.priority	= 0,
 };
 
 static int __init ipcomp6_init(void)
@@ -199,7 +207,7 @@ static int __init ipcomp6_init(void)
 		pr_info("%s: can't add xfrm type\n", __func__);
 		return -EAGAIN;
 	}
-	if (inet6_add_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0) {
+	if (xfrm6_protocol_register(&ipcomp6_protocol, IPPROTO_COMP) < 0) {
 		pr_info("%s: can't add protocol\n", __func__);
 		xfrm_unregister_type(&ipcomp6_type, AF_INET6);
 		return -EAGAIN;
@@ -209,7 +217,7 @@ static int __init ipcomp6_init(void)
 
 static void __exit ipcomp6_fini(void)
 {
-	if (inet6_del_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0)
+	if (xfrm6_protocol_deregister(&ipcomp6_protocol, IPPROTO_COMP) < 0)
 		pr_info("%s: can't remove protocol\n", __func__);
 	if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0)
 		pr_info("%s: can't remove xfrm type\n", __func__);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 06/12] vti6: Remove dst_entry caching
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (4 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 05/12] ipcomp6: " Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-03-03 10:58   ` Nicolas Dichtel
  2014-02-28 10:31 ` [PATCH RFC 07/12] vti6: Remove caching of flow informations Steffen Klassert
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

Unlike ip6_tunnel, vti6 can lookup multiple different dst entries,
dependent of the configured xfrm states. Therefore it does not make
sense to cache a dst_entry.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c |   44 +++++++++++++++++++-------------------------
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 8649143..3f337c7 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -278,7 +278,6 @@ static void vti6_dev_uninit(struct net_device *dev)
 		RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL);
 	else
 		vti6_tnl_unlink(ip6n, t);
-	ip6_tnl_dst_reset(t);
 	dev_put(dev);
 }
 
@@ -356,11 +355,10 @@ vti6_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
  **/
 static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net *net = dev_net(dev);
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net_device_stats *stats = &t->dev->stats;
-	struct dst_entry *dst = NULL, *ndst = NULL;
-	struct flowi6 fl6;
+	struct dst_entry *dst = skb_dst(skb);
+	struct flowi fl;
 	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 	struct net_device *tdev;
 	int err = -1;
@@ -369,21 +367,19 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
 	    !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h))
 		return err;
 
-	dst = ip6_tnl_dst_check(t);
-	if (!dst) {
-		memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
+	memset(&fl, 0, sizeof(fl));
+	skb->mark = be32_to_cpu(t->parms.o_key);
+	xfrm_decode_session(skb, &fl, AF_INET6);
 
-		ndst = ip6_route_output(net, NULL, &fl6);
+	if (!dst)
+		goto tx_err_link_failure;
 
-		if (ndst->error)
-			goto tx_err_link_failure;
-		ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(&fl6), NULL, 0);
-		if (IS_ERR(ndst)) {
-			err = PTR_ERR(ndst);
-			ndst = NULL;
-			goto tx_err_link_failure;
-		}
-		dst = ndst;
+	dst_hold(dst);
+	dst = xfrm_lookup(t->net, dst, &fl, NULL, 0);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
+		dst = NULL;
+		goto tx_err_link_failure;
 	}
 
 	if (!dst->xfrm || dst->xfrm->props.mode != XFRM_MODE_TUNNEL)
@@ -399,21 +395,19 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 
-	skb_dst_drop(skb);
-	skb_dst_set_noref(skb, dst);
+	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+	skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
+	skb_dst_set(skb, dst);
+	skb->dev = skb_dst(skb)->dev;
 
 	ip6tunnel_xmit(skb, dev);
-	if (ndst) {
-		dev->mtu = dst_mtu(ndst);
-		ip6_tnl_dst_store(t, ndst);
-	}
 
 	return 0;
 tx_err_link_failure:
 	stats->tx_carrier_errors++;
 	dst_link_failure(skb);
 tx_err_dst_release:
-	dst_release(ndst);
+	dst_release(dst);
 	return err;
 }
 
@@ -997,7 +991,7 @@ static int __init vti6_tunnel_init(void)
 	if (err < 0)
 		goto out_pernet;
 
-	err = xfrm6_mode_tunnel_input_register(&vti6_handler);
+	 err = xfrm6_mode_tunnel_input_register(&vti6_handler);
 	if (err < 0) {
 		pr_err("%s: can't register vti6\n", __func__);
 		goto out;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 07/12] vti6: Remove caching of flow informations.
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (5 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 06/12] vti6: Remove dst_entry caching Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 08/12] vti6: Update the ipv6 side to use it's own receive hook Steffen Klassert
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

Unlike ip6_tunnel, vti6 does not use the the tunnel
endpoint addresses to do route and xfrm lookups.
So no need to cache the flow informations. It also
does not make sense to calculate the mtu based on
such flow informations, so remove this too.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c |   31 -------------------------------
 1 file changed, 31 deletions(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 3f337c7..596327d 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -443,19 +443,10 @@ static void vti6_link_config(struct ip6_tnl *t)
 	struct dst_entry *dst;
 	struct net_device *dev = t->dev;
 	struct __ip6_tnl_parm *p = &t->parms;
-	struct flowi6 *fl6 = &t->fl.u.ip6;
 
 	memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
 	memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
 
-	/* Set up flowi template */
-	fl6->saddr = p->laddr;
-	fl6->daddr = p->raddr;
-	fl6->flowi6_oif = p->link;
-	fl6->flowi6_mark = be32_to_cpu(p->i_key);
-	fl6->flowi6_proto = p->proto;
-	fl6->flowlabel = 0;
-
 	p->flags &= ~(IP6_TNL_F_CAP_XMIT | IP6_TNL_F_CAP_RCV |
 		      IP6_TNL_F_CAP_PER_PACKET);
 	p->flags |= ip6_tnl_get_cap(t, &p->laddr, &p->raddr);
@@ -466,28 +457,6 @@ static void vti6_link_config(struct ip6_tnl *t)
 		dev->flags &= ~IFF_POINTOPOINT;
 
 	dev->iflink = p->link;
-
-	if (p->flags & IP6_TNL_F_CAP_XMIT) {
-
-		dst = ip6_route_output(dev_net(dev), NULL, fl6);
-		if (dst->error)
-			return;
-
-		dst = xfrm_lookup(dev_net(dev), dst, flowi6_to_flowi(fl6),
-				  NULL, 0);
-		if (IS_ERR(dst))
-			return;
-
-		if (dst->dev) {
-			dev->hard_header_len = dst->dev->hard_header_len;
-
-			dev->mtu = dst_mtu(dst);
-
-			if (dev->mtu < IPV6_MIN_MTU)
-				dev->mtu = IPV6_MIN_MTU;
-		}
-		dst_release(dst);
-	}
 }
 
 /**
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 08/12] vti6: Update the ipv6 side to use it's own receive hook.
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (6 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 07/12] vti6: Remove caching of flow informations Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-03-03  1:12   ` David Miller
  2014-02-28 10:31 ` [PATCH RFC 09/12] xfrm6: Remove xfrm_tunnel_notifier Steffen Klassert
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

With this patch, vti6 uses the IPsec protocol multiplexer to
register it's own receive side hooks for ESP, AH and IPCOMP.

Vti6 now does the following on receive side:

1. Do an input policy check for the IPsec packet we received.
   This is required because this packet could be already
   prosecces by IPsec, so an inbuond policy check is needed.

2. Mark the packet with the i_key. The policy and the state
   must match this key now. Policy and state belong to the vti
   namespace and policy enforcement is done at the further layers.

3. Call the generic xfrm layer to do decryption and decapsulation.

4. Wait for a callback from the xfrm layer to properly clean the
   skb to not leak informations on namespace transitions and
    update the device statistics.

On transmit side:

1. Mark the packet with the o_key. The policy and the state
   must match this key now.

2. Do a xfrm_lookup on the original packet with the mark applied.

3. Check if we got an IPsec route.

4. Clean the skb to not leak informations on namespace
   transitions.

5. Attach the dst_enty we got from the xfrm_lookup to the skb.

6. Call dst_output to do the IPsec processing.

7. Do the device statistics.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c |  175 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 149 insertions(+), 26 deletions(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 596327d..6b919bc 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -287,10 +287,8 @@ static int vti6_rcv(struct sk_buff *skb)
 	const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 
 	rcu_read_lock();
-
 	if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
 				 &ipv6h->daddr)) != NULL) {
-		struct pcpu_sw_netstats *tstats;
 
 		if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) {
 			rcu_read_unlock();
@@ -308,27 +306,58 @@ static int vti6_rcv(struct sk_buff *skb)
 			goto discard;
 		}
 
-		tstats = this_cpu_ptr(t->dev->tstats);
-		u64_stats_update_begin(&tstats->syncp);
-		tstats->rx_packets++;
-		tstats->rx_bytes += skb->len;
-		u64_stats_update_end(&tstats->syncp);
-
-		skb->mark = 0;
-		secpath_reset(skb);
-		skb->dev = t->dev;
+		XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
+		skb->mark = be32_to_cpu(t->parms.i_key);
 
 		rcu_read_unlock();
-		return 0;
+
+		return xfrm6_rcv(skb);
 	}
 	rcu_read_unlock();
-	return 1;
-
+	return -EINVAL;
 discard:
 	kfree_skb(skb);
 	return 0;
 }
 
+static int vti6_rcv_cb(struct sk_buff *skb, int err)
+{
+	unsigned short family;
+	struct net_device *dev;
+	struct pcpu_sw_netstats *tstats;
+	struct xfrm_state *x;
+	struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
+
+	if (!t)
+		return 1;
+
+	dev = t->dev;
+
+	if (err) {
+		dev->stats.rx_errors++;
+		dev->stats.rx_dropped++;
+
+		return 0;
+	}
+
+	x = xfrm_input_state(skb);
+	family = x->inner_mode->afinfo->family;
+
+	if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+		return -EPERM;
+
+	skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev)));
+	skb->dev = dev;
+
+	tstats = this_cpu_ptr(dev->tstats);
+	u64_stats_update_begin(&tstats->syncp);
+	tstats->rx_packets++;
+	tstats->rx_bytes += skb->len;
+	u64_stats_update_end(&tstats->syncp);
+
+	return 0;
+}
+
 /**
  * vti6_addr_conflict - compare packet addresses to tunnel's own
  *   @t: the outgoing tunnel device
@@ -394,7 +423,6 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto tx_err_dst_release;
 	}
 
-
 	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
 	skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
 	skb_dst_set(skb, dst);
@@ -438,9 +466,60 @@ tx_err:
 	return NETDEV_TX_OK;
 }
 
+static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+		    u8 type, u8 code, int offset, __be32 info)
+{
+	__be32 spi;
+	struct xfrm_state *x;
+	struct ip6_tnl *t;
+	struct ip_esp_hdr *esph;
+	struct ip_auth_hdr *ah ;
+	struct ip_comp_hdr *ipch;
+	struct net *net = dev_net(skb->dev);
+	const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
+	int protocol = iph->nexthdr;
+
+	t = vti6_tnl_lookup(dev_net(skb->dev), &iph->daddr, &iph->saddr);
+	if (!t)
+		return -1;
+
+	switch (protocol) {
+	case IPPROTO_ESP:
+		esph = (struct ip_esp_hdr *)(skb->data + offset);
+		spi = esph->spi;
+		break;
+	case IPPROTO_AH:
+		ah = (struct ip_auth_hdr *)(skb->data + offset);
+		spi = ah->spi;
+		break;
+	case IPPROTO_COMP:
+		ipch = (struct ip_comp_hdr *)(skb->data + offset);
+		spi = htonl(ntohs(ipch->cpi));
+		break;
+	default:
+		return 0;
+	}
+
+	if (type != ICMPV6_PKT_TOOBIG &&
+	    type != NDISC_REDIRECT)
+		return 0;
+
+	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+			      spi, protocol, AF_INET6);
+	if (!x)
+		return 0;
+
+	if (type == NDISC_REDIRECT)
+		ip6_redirect(skb, net, skb->dev->ifindex, 0);
+	else
+		ip6_update_pmtu(skb, net, info, 0, 0);
+	xfrm_state_put(x);
+
+	return 0;
+}
+
 static void vti6_link_config(struct ip6_tnl *t)
 {
-	struct dst_entry *dst;
 	struct net_device *dev = t->dev;
 	struct __ip6_tnl_parm *p = &t->parms;
 
@@ -871,11 +950,6 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = {
 	.fill_info	= vti6_fill_info,
 };
 
-static struct xfrm_tunnel_notifier vti6_handler __read_mostly = {
-	.handler	= vti6_rcv,
-	.priority	=	1,
-};
-
 static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n)
 {
 	int h;
@@ -947,6 +1021,27 @@ static struct pernet_operations vti6_net_ops = {
 	.size = sizeof(struct vti6_net),
 };
 
+static struct xfrm6_protocol vti_esp6_protocol __read_mostly = {
+	.handler	=	vti6_rcv,
+	.cb_handler	=	vti6_rcv_cb,
+	.err_handler	=	vti6_err,
+	.priority	=	100,
+};
+
+static struct xfrm6_protocol vti_ah6_protocol __read_mostly = {
+	.handler	=	vti6_rcv,
+	.cb_handler	=	vti6_rcv_cb,
+	.err_handler	=	vti6_err,
+	.priority	=	100,
+};
+
+static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = {
+	.handler	=	vti6_rcv,
+	.cb_handler	=	vti6_rcv_cb,
+	.err_handler	=	vti6_err,
+	.priority	=	100,
+};
+
 /**
  * vti6_tunnel_init - register protocol and reserve needed resources
  *
@@ -960,11 +1055,33 @@ static int __init vti6_tunnel_init(void)
 	if (err < 0)
 		goto out_pernet;
 
-	 err = xfrm6_mode_tunnel_input_register(&vti6_handler);
+	err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP);
 	if (err < 0) {
-		pr_err("%s: can't register vti6\n", __func__);
+		unregister_pernet_device(&vti6_net_ops);
+		pr_err("%s: can't register vti6 protocol\n", __func__);
+
 		goto out;
 	}
+
+	err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH);
+	if (err < 0) {
+		xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
+		unregister_pernet_device(&vti6_net_ops);
+		pr_err("%s: can't register vti6 protocol\n", __func__);
+
+		goto out;
+	}
+
+	err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP);
+	if (err < 0) {
+		xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
+		xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
+		unregister_pernet_device(&vti6_net_ops);
+		pr_err("%s: can't register vti6 protocol\n", __func__);
+
+		goto out;
+	}
+
 	err = rtnl_link_register(&vti6_link_ops);
 	if (err < 0)
 		goto rtnl_link_failed;
@@ -972,7 +1089,9 @@ static int __init vti6_tunnel_init(void)
 	return 0;
 
 rtnl_link_failed:
-	xfrm6_mode_tunnel_input_deregister(&vti6_handler);
+	xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP);
+	xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
+	xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
 out:
 	unregister_pernet_device(&vti6_net_ops);
 out_pernet:
@@ -985,8 +1104,12 @@ out_pernet:
 static void __exit vti6_tunnel_cleanup(void)
 {
 	rtnl_link_unregister(&vti6_link_ops);
-	if (xfrm6_mode_tunnel_input_deregister(&vti6_handler))
-		pr_info("%s: can't deregister vti6\n", __func__);
+	if (xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP))
+		pr_info("%s: can't deregister protocol\n", __func__);
+	if (xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH))
+		pr_info("%s: can't deregister protocol\n", __func__);
+	if (xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP))
+		pr_info("%s: can't deregister protocol\n", __func__);
 
 	unregister_pernet_device(&vti6_net_ops);
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 09/12] xfrm6: Remove xfrm_tunnel_notifier
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (7 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 08/12] vti6: Update the ipv6 side to use it's own receive hook Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 10/12] vti6: Support inter address family tunneling Steffen Klassert
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

This was used from vti and is replaced by the IPsec protocol
multiplexer hooks. It is now unused, so remove it.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 include/net/xfrm.h           |    8 ------
 net/ipv6/xfrm6_mode_tunnel.c |   63 ------------------------------------------
 2 files changed, 71 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 60df20a..cb795f1 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1393,12 +1393,6 @@ struct xfrm_tunnel {
 	int priority;
 };
 
-struct xfrm_tunnel_notifier {
-	int (*handler)(struct sk_buff *skb);
-	struct xfrm_tunnel_notifier __rcu *next;
-	int priority;
-};
-
 struct xfrm6_tunnel {
 	int (*handler)(struct sk_buff *skb);
 	int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -1554,8 +1548,6 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char prot
 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
-int xfrm6_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
-int xfrm6_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
 int xfrm6_extract_header(struct sk_buff *skb);
 int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index cb04f7a..901ef6f 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -18,65 +18,6 @@
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-/* Informational hook. The decap is still done here. */
-static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly;
-static DEFINE_MUTEX(xfrm6_mode_tunnel_input_mutex);
-
-int xfrm6_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler)
-{
-	struct xfrm_tunnel_notifier __rcu **pprev;
-	struct xfrm_tunnel_notifier *t;
-	int ret = -EEXIST;
-	int priority = handler->priority;
-
-	mutex_lock(&xfrm6_mode_tunnel_input_mutex);
-
-	for (pprev = &rcv_notify_handlers;
-	     (t = rcu_dereference_protected(*pprev,
-	     lockdep_is_held(&xfrm6_mode_tunnel_input_mutex))) != NULL;
-	     pprev = &t->next) {
-		if (t->priority > priority)
-			break;
-		if (t->priority == priority)
-			goto err;
-
-	}
-
-	handler->next = *pprev;
-	rcu_assign_pointer(*pprev, handler);
-
-	ret = 0;
-
-err:
-	mutex_unlock(&xfrm6_mode_tunnel_input_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(xfrm6_mode_tunnel_input_register);
-
-int xfrm6_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler)
-{
-	struct xfrm_tunnel_notifier __rcu **pprev;
-	struct xfrm_tunnel_notifier *t;
-	int ret = -ENOENT;
-
-	mutex_lock(&xfrm6_mode_tunnel_input_mutex);
-	for (pprev = &rcv_notify_handlers;
-	     (t = rcu_dereference_protected(*pprev,
-	     lockdep_is_held(&xfrm6_mode_tunnel_input_mutex))) != NULL;
-	     pprev = &t->next) {
-		if (t == handler) {
-			*pprev = handler->next;
-			ret = 0;
-			break;
-		}
-	}
-	mutex_unlock(&xfrm6_mode_tunnel_input_mutex);
-	synchronize_net();
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(xfrm6_mode_tunnel_input_deregister);
-
 static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
 {
 	const struct ipv6hdr *outer_iph = ipv6_hdr(skb);
@@ -130,7 +71,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 
 static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	struct xfrm_tunnel_notifier *handler;
 	int err = -EINVAL;
 
 	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
@@ -138,9 +78,6 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 		goto out;
 
-	for_each_input_rcu(rcv_notify_handlers, handler)
-		handler->handler(skb);
-
 	err = skb_unclone(skb, GFP_ATOMIC);
 	if (err)
 		goto out;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 10/12] vti6: Support inter address family tunneling.
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (8 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 09/12] xfrm6: Remove xfrm_tunnel_notifier Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-03-03  1:13   ` David Miller
  2014-02-28 10:31 ` [PATCH RFC 11/12] vti6: Check the tunnel endpoints of the xfrm state and the vti interface Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 12/12] vti6: Enable namespace changing Steffen Klassert
  11 siblings, 1 reply; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

With this patch we can tunnel ipv4 traffic via a vti6
interface. A vti6 interface can now have an ipv4 address
and ipv4 traffic can be routed via a vti6 interface.
The resulting traffic is xfrm transformed and tunneled
through ipv6 if matching IPsec policies and states are
present.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c |   48 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 6b919bc..6193e44 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -381,30 +381,22 @@ vti6_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
  * vti6_xmit - send a packet
  *   @skb: the outgoing socket buffer
  *   @dev: the outgoing tunnel device
+ *   @fl: the flow informations for the xfrm_lookup
  **/
-static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
+static int
+vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net_device_stats *stats = &t->dev->stats;
 	struct dst_entry *dst = skb_dst(skb);
-	struct flowi fl;
-	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 	struct net_device *tdev;
 	int err = -1;
 
-	if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) ||
-	    !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h))
-		return err;
-
-	memset(&fl, 0, sizeof(fl));
-	skb->mark = be32_to_cpu(t->parms.o_key);
-	xfrm_decode_session(skb, &fl, AF_INET6);
-
 	if (!dst)
 		goto tx_err_link_failure;
 
 	dst_hold(dst);
-	dst = xfrm_lookup(t->net, dst, &fl, NULL, 0);
+	dst = xfrm_lookup(t->net, dst, fl, NULL, 0);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		dst = NULL;
@@ -423,12 +415,21 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto tx_err_dst_release;
 	}
 
-	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
 	skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
 	skb_dst_set(skb, dst);
 	skb->dev = skb_dst(skb)->dev;
 
-	ip6tunnel_xmit(skb, dev);
+	err = dst_output(skb);
+	if (net_xmit_eval(err) == 0) {
+		struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
+		u64_stats_update_begin(&tstats->syncp);
+		tstats->tx_bytes += skb->len;
+		tstats->tx_packets++;
+		u64_stats_update_end(&tstats->syncp);
+	} else {
+		stats->tx_errors++;
+		stats->tx_aborted_errors++;
+	}
 
 	return 0;
 tx_err_link_failure:
@@ -444,16 +445,33 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net_device_stats *stats = &t->dev->stats;
+	struct ipv6hdr *ipv6h;
+	struct flowi fl;
 	int ret;
 
+	memset(&fl, 0, sizeof(fl));
+	skb->mark = be32_to_cpu(t->parms.o_key);
+
 	switch (skb->protocol) {
 	case htons(ETH_P_IPV6):
-		ret = vti6_xmit(skb, dev);
+		ipv6h = ipv6_hdr(skb);
+
+		if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) ||
+		    !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h))
+			goto tx_err;
+
+		xfrm_decode_session(skb, &fl, AF_INET6);
+		memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+		break;
+	case htons(ETH_P_IP):
+		xfrm_decode_session(skb, &fl, AF_INET);
+		memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 		break;
 	default:
 		goto tx_err;
 	}
 
+	ret = vti6_xmit(skb, dev, &fl);
 	if (ret < 0)
 		goto tx_err;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 11/12] vti6: Check the tunnel endpoints of the xfrm state and the vti interface
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (9 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 10/12] vti6: Support inter address family tunneling Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  2014-02-28 10:31 ` [PATCH RFC 12/12] vti6: Enable namespace changing Steffen Klassert
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

The tunnel endpoints of the xfrm_state we got from the xfrm_lookup
must match the tunnel endpoints of the vti interface. This patch
ensures this matching.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 6193e44..ee4c477 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -377,6 +377,29 @@ vti6_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
 	return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
 }
 
+static bool vti6_state_check(const struct xfrm_state *x,
+			     const struct in6_addr *dst,
+			     const struct in6_addr *src)
+{
+	xfrm_address_t *daddr = (xfrm_address_t *)dst;
+	xfrm_address_t *saddr = (xfrm_address_t *)src;
+
+	/* if there is no transform then this tunnel is not functional.
+	 * Or if the xfrm is not mode tunnel.
+	 */
+	if (!x || x->props.mode != XFRM_MODE_TUNNEL ||
+	    x->props.family != AF_INET6)
+		return false;
+
+	if (ipv6_addr_any(dst))
+		return xfrm_addr_equal(saddr, &x->props.saddr, AF_INET6);
+
+	if (!xfrm_state_addr_check(x, daddr, saddr, AF_INET6))
+		return false;
+
+	return true;
+}
+
 /**
  * vti6_xmit - send a packet
  *   @skb: the outgoing socket buffer
@@ -403,7 +426,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
 		goto tx_err_link_failure;
 	}
 
-	if (!dst->xfrm || dst->xfrm->props.mode != XFRM_MODE_TUNNEL)
+	if (!vti6_state_check(dst->xfrm, &t->parms.raddr, &t->parms.laddr))
 		goto tx_err_link_failure;
 
 	tdev = dst->dev;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH RFC 12/12] vti6: Enable namespace changing
  2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
                   ` (10 preceding siblings ...)
  2014-02-28 10:31 ` [PATCH RFC 11/12] vti6: Check the tunnel endpoints of the xfrm state and the vti interface Steffen Klassert
@ 2014-02-28 10:31 ` Steffen Klassert
  11 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-02-28 10:31 UTC (permalink / raw)
  To: netdev; +Cc: Steffen Klassert, Christophe Gouault

vti6 is now fully namespace aware, so allow namespace changing
for vti devices.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index ee4c477..ad0dd37 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -803,7 +803,6 @@ static void vti6_dev_setup(struct net_device *dev)
 	t = netdev_priv(dev);
 	dev->flags |= IFF_NOARP;
 	dev->addr_len = sizeof(struct in6_addr);
-	dev->features |= NETIF_F_NETNS_LOCAL;
 	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 }
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly
  2014-02-28 10:31 ` [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly Steffen Klassert
@ 2014-03-03  1:09   ` David Miller
  2014-03-05 12:24     ` Steffen Klassert
  0 siblings, 1 reply; 18+ messages in thread
From: David Miller @ 2014-03-03  1:09 UTC (permalink / raw)
  To: steffen.klassert; +Cc: netdev, christophe.gouault

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 28 Feb 2014 11:31:11 +0100

> +	int err = 0;
> +	if (unlikely(afinfo == NULL))
> +		return -EINVAL;

A newline between local variable declarations and code, please.

> +	int err = 0;
> +	if (unlikely(afinfo == NULL))
> +		return -EINVAL;

Likewise.

> +	struct xfrm_input_afinfo *afinfo;
> +	if (unlikely(family >= NPROTO))
> +		return NULL;

Likewise.

> +	int ret;
> +	struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family);
> +	if (!afinfo)
> +		return -EAFNOSUPPORT;

Likewise.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH RFC 08/12] vti6: Update the ipv6 side to use it's own receive hook.
  2014-02-28 10:31 ` [PATCH RFC 08/12] vti6: Update the ipv6 side to use it's own receive hook Steffen Klassert
@ 2014-03-03  1:12   ` David Miller
  0 siblings, 0 replies; 18+ messages in thread
From: David Miller @ 2014-03-03  1:12 UTC (permalink / raw)
  To: steffen.klassert; +Cc: netdev, christophe.gouault

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 28 Feb 2014 11:31:18 +0100

>  	if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
>  				 &ipv6h->daddr)) != NULL) {
> -		struct pcpu_sw_netstats *tstats;
>  
>  		if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) {

Since you're removing all local variable declarations in this basic
block, you should remove the empty line as well.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH RFC 10/12] vti6: Support inter address family tunneling.
  2014-02-28 10:31 ` [PATCH RFC 10/12] vti6: Support inter address family tunneling Steffen Klassert
@ 2014-03-03  1:13   ` David Miller
  0 siblings, 0 replies; 18+ messages in thread
From: David Miller @ 2014-03-03  1:13 UTC (permalink / raw)
  To: steffen.klassert; +Cc: netdev, christophe.gouault

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 28 Feb 2014 11:31:20 +0100

> +	if (net_xmit_eval(err) == 0) {
> +		struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
> +		u64_stats_update_begin(&tstats->syncp);

Empty line between local variable declaration and code, please.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH RFC 06/12] vti6: Remove dst_entry caching
  2014-02-28 10:31 ` [PATCH RFC 06/12] vti6: Remove dst_entry caching Steffen Klassert
@ 2014-03-03 10:58   ` Nicolas Dichtel
  0 siblings, 0 replies; 18+ messages in thread
From: Nicolas Dichtel @ 2014-03-03 10:58 UTC (permalink / raw)
  To: Steffen Klassert, netdev; +Cc: Christophe Gouault

Le 28/02/2014 11:31, Steffen Klassert a écrit :
> Unlike ip6_tunnel, vti6 can lookup multiple different dst entries,
> dependent of the configured xfrm states. Therefore it does not make
> sense to cache a dst_entry.
>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> ---
>   net/ipv6/ip6_vti.c |   44 +++++++++++++++++++-------------------------
>   1 file changed, 19 insertions(+), 25 deletions(-)
>
> diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
> index 8649143..3f337c7 100644
> --- a/net/ipv6/ip6_vti.c
> +++ b/net/ipv6/ip6_vti.c
> @@ -278,7 +278,6 @@ static void vti6_dev_uninit(struct net_device *dev)
>   		RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL);
>   	else
>   		vti6_tnl_unlink(ip6n, t);
> -	ip6_tnl_dst_reset(t);
>   	dev_put(dev);
>   }
>
> @@ -356,11 +355,10 @@ vti6_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
>    **/
>   static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
>   {
> -	struct net *net = dev_net(dev);
>   	struct ip6_tnl *t = netdev_priv(dev);
>   	struct net_device_stats *stats = &t->dev->stats;
> -	struct dst_entry *dst = NULL, *ndst = NULL;
> -	struct flowi6 fl6;
> +	struct dst_entry *dst = skb_dst(skb);
> +	struct flowi fl;
>   	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
>   	struct net_device *tdev;
>   	int err = -1;
> @@ -369,21 +367,19 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
>   	    !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h))
>   		return err;
>
> -	dst = ip6_tnl_dst_check(t);
> -	if (!dst) {
> -		memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
> +	memset(&fl, 0, sizeof(fl));
> +	skb->mark = be32_to_cpu(t->parms.o_key);
> +	xfrm_decode_session(skb, &fl, AF_INET6);
>
> -		ndst = ip6_route_output(net, NULL, &fl6);
> +	if (!dst)
> +		goto tx_err_link_failure;
>
> -		if (ndst->error)
> -			goto tx_err_link_failure;
> -		ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(&fl6), NULL, 0);
> -		if (IS_ERR(ndst)) {
> -			err = PTR_ERR(ndst);
> -			ndst = NULL;
> -			goto tx_err_link_failure;
> -		}
> -		dst = ndst;
> +	dst_hold(dst);
> +	dst = xfrm_lookup(t->net, dst, &fl, NULL, 0);
> +	if (IS_ERR(dst)) {
> +		err = PTR_ERR(dst);
> +		dst = NULL;
> +		goto tx_err_link_failure;
>   	}
>
>   	if (!dst->xfrm || dst->xfrm->props.mode != XFRM_MODE_TUNNEL)
> @@ -399,21 +395,19 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
>   	}
>
>
> -	skb_dst_drop(skb);
> -	skb_dst_set_noref(skb, dst);
> +	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
> +	skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
> +	skb_dst_set(skb, dst);
> +	skb->dev = skb_dst(skb)->dev;
>
>   	ip6tunnel_xmit(skb, dev);
> -	if (ndst) {
> -		dev->mtu = dst_mtu(ndst);
> -		ip6_tnl_dst_store(t, ndst);
> -	}
>
>   	return 0;
>   tx_err_link_failure:
>   	stats->tx_carrier_errors++;
>   	dst_link_failure(skb);
>   tx_err_dst_release:
> -	dst_release(ndst);
> +	dst_release(dst);
>   	return err;
>   }
>
> @@ -997,7 +991,7 @@ static int __init vti6_tunnel_init(void)
>   	if (err < 0)
>   		goto out_pernet;
>
> -	err = xfrm6_mode_tunnel_input_register(&vti6_handler);
> +	 err = xfrm6_mode_tunnel_input_register(&vti6_handler);
There is no difference in this line, except the space after the tab.

>   	if (err < 0) {
>   		pr_err("%s: can't register vti6\n", __func__);
>   		goto out;
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly
  2014-03-03  1:09   ` David Miller
@ 2014-03-05 12:24     ` Steffen Klassert
  0 siblings, 0 replies; 18+ messages in thread
From: Steffen Klassert @ 2014-03-05 12:24 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, christophe.gouault

On Sun, Mar 02, 2014 at 08:09:23PM -0500, David Miller wrote:
> From: Steffen Klassert <steffen.klassert@secunet.com>
> Date: Fri, 28 Feb 2014 11:31:11 +0100
> 
> > +	int err = 0;
> > +	if (unlikely(afinfo == NULL))
> > +		return -EINVAL;
> 
> A newline between local variable declarations and code, please.
> 

This was a copy and paste from xfrm_state_register_afinfo :)

I've incorporated your feedback into the next version of
this patchset. Thanks for the review!

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-03-05 12:24 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-28 10:31 [PATCH RFC 0/12] vti6: prepare namespace and interfamily support Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 01/12] xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly Steffen Klassert
2014-03-03  1:09   ` David Miller
2014-03-05 12:24     ` Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 02/12] xfrm6: Add IPsec protocol multiplexer Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 03/12] esp6: Use the IPsec protocol multiplexer API Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 04/12] ah6: " Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 05/12] ipcomp6: " Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 06/12] vti6: Remove dst_entry caching Steffen Klassert
2014-03-03 10:58   ` Nicolas Dichtel
2014-02-28 10:31 ` [PATCH RFC 07/12] vti6: Remove caching of flow informations Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 08/12] vti6: Update the ipv6 side to use it's own receive hook Steffen Klassert
2014-03-03  1:12   ` David Miller
2014-02-28 10:31 ` [PATCH RFC 09/12] xfrm6: Remove xfrm_tunnel_notifier Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 10/12] vti6: Support inter address family tunneling Steffen Klassert
2014-03-03  1:13   ` David Miller
2014-02-28 10:31 ` [PATCH RFC 11/12] vti6: Check the tunnel endpoints of the xfrm state and the vti interface Steffen Klassert
2014-02-28 10:31 ` [PATCH RFC 12/12] vti6: Enable namespace changing Steffen Klassert

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.