All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections
@ 2019-03-27 17:31 Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 01/11] xfrm: place af number into xfrm_mode struct Florian Westphal
                   ` (11 more replies)
  0 siblings, 12 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert

This series removes all function pointers from the xfrm_mode struct.
They are either replaced by direct calls or a static helper.

This also reduces code size: even merging all xfrm{4,6}_,mode* modules
into the core reduces total size, as the infrastructure to maintain
dynamic (un)register can be removed.

There are more opportunities for indirection avoidance, e.g. in
xfrm_type.

I plan to follow up once/if this series is accepted.
This is quite some code churn, but I think its worth doing.

Tested with xfrm tunnel mode via netns with esp/aead.

Florian Westphal (11):
      xfrm: place af number into xfrm_mode struct
      xfrm: prefer family stored in xfrm_mode struct
      xfrm: remove input indirection from xfrm_mode
      xfrm: remove output indirection from xfrm_mode
      xfrm: remove xmit indirection from xfrm_mode
      xfrm: remove gso_segment indirection from xfrm_mode
      xfrm: remove input2 indirection from xfrm_mode
      xfrm: remove output2 indirection from xfrm_mode
      xfrm: remove afinfo pointer from xfrm_mode
      xfrm: make xfrm modes builtin
      xfrm: store xfrm_mode directly, not its address

 include/net/xfrm.h                 |  105 ++--------
 net/core/pktgen.c                  |    2 
 net/ipv4/Kconfig                   |   29 --
 net/ipv4/Makefile                  |    3 
 net/ipv4/esp4_offload.c            |   40 +++
 net/ipv4/ip_vti.c                  |    6 
 net/ipv4/xfrm4_output.c            |   26 --
 net/ipv6/Kconfig                   |   35 ---
 net/ipv6/Makefile                  |    4 
 net/ipv6/esp6_offload.c            |   40 +++
 net/ipv6/ip6_vti.c                 |    6 
 net/ipv6/xfrm6_output.c            |   36 +--
 net/xfrm/xfrm_device.c             |   58 +++++
 net/xfrm/xfrm_inout.h              |   38 +++
 net/xfrm/xfrm_input.c              |  283 ++++++++++++++++++++++++++-
 net/xfrm/xfrm_interface.c          |    6 
 net/xfrm/xfrm_output.c             |  359 ++++++++++++++++++++++++++++++++++-
 net/xfrm/xfrm_policy.c             |   11 -
 net/xfrm/xfrm_state.c              |  181 ++++++-----------
 tools/testing/selftests/net/config |    2 
 net/ipv4/xfrm4_mode_beet.c         |  155 ---------------
 net/ipv4/xfrm4_mode_transport.c    |  114 -----------
 net/ipv4/xfrm4_mode_tunnel.c       |  152 --------------
 net/ipv6/xfrm6_mode_beet.c         |  131 ------------
 net/ipv6/xfrm6_mode_ro.c           |   85 --------
 net/ipv6/xfrm6_mode_transport.c    |  121 -----------
 net/ipv6/xfrm6_mode_tunnel.c       |  151 --------------
 27 files changed, 937 insertions(+), 1242 deletions(-)


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

* [PATCH ipsec-next 01/11] xfrm: place af number into xfrm_mode struct
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 02/11] xfrm: prefer family stored in " Florian Westphal
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

This will be useful to know if we're supposed to decode ipv4 or ipv6.

While at it, make the unregister function return void, all module_exit
functions did just BUG(); there is never a point in doing error checks
if there is no way to handle such error.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h              |  9 +++++----
 net/ipv4/xfrm4_mode_beet.c      |  8 +++-----
 net/ipv4/xfrm4_mode_transport.c |  8 +++-----
 net/ipv4/xfrm4_mode_tunnel.c    |  8 +++-----
 net/ipv6/xfrm6_mode_beet.c      |  8 +++-----
 net/ipv6/xfrm6_mode_ro.c        |  8 +++-----
 net/ipv6/xfrm6_mode_transport.c |  8 +++-----
 net/ipv6/xfrm6_mode_tunnel.c    |  8 +++-----
 net/xfrm/xfrm_state.c           | 19 ++++++-------------
 9 files changed, 32 insertions(+), 52 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 85386becbaea..9a155063c25f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -482,8 +482,9 @@ struct xfrm_mode {
 
 	struct xfrm_state_afinfo *afinfo;
 	struct module *owner;
-	unsigned int encap;
-	int flags;
+	u8 encap;
+	u8 family;
+	u8 flags;
 };
 
 /* Flags for xfrm_mode. */
@@ -491,8 +492,8 @@ enum {
 	XFRM_MODE_FLAG_TUNNEL = 1,
 };
 
-int xfrm_register_mode(struct xfrm_mode *mode, int family);
-int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+int xfrm_register_mode(struct xfrm_mode *mode);
+void xfrm_unregister_mode(struct xfrm_mode *mode);
 
 static inline int xfrm_af2proto(unsigned int family)
 {
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 856d2dfdb44b..a2e3b52ae46c 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -134,19 +134,17 @@ static struct xfrm_mode xfrm4_beet_mode = {
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
+	.family = AF_INET,
 };
 
 static int __init xfrm4_beet_init(void)
 {
-	return xfrm_register_mode(&xfrm4_beet_mode, AF_INET);
+	return xfrm_register_mode(&xfrm4_beet_mode);
 }
 
 static void __exit xfrm4_beet_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm4_beet_mode, AF_INET);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm4_beet_mode);
 }
 
 module_init(xfrm4_beet_init);
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index 1ad2c2c4e250..7c5443f797cf 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -93,19 +93,17 @@ static struct xfrm_mode xfrm4_transport_mode = {
 	.xmit = xfrm4_transport_xmit,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TRANSPORT,
+	.family = AF_INET,
 };
 
 static int __init xfrm4_transport_init(void)
 {
-	return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
+	return xfrm_register_mode(&xfrm4_transport_mode);
 }
 
 static void __exit xfrm4_transport_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm4_transport_mode);
 }
 
 module_init(xfrm4_transport_init);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 2a9764bd1719..cfc6b6d39755 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -131,19 +131,17 @@ static struct xfrm_mode xfrm4_tunnel_mode = {
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
+	.family = AF_INET,
 };
 
 static int __init xfrm4_mode_tunnel_init(void)
 {
-	return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
+	return xfrm_register_mode(&xfrm4_tunnel_mode);
 }
 
 static void __exit xfrm4_mode_tunnel_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm4_tunnel_mode);
 }
 
 module_init(xfrm4_mode_tunnel_init);
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 57fd314ec2b8..0d440e3a13f8 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -110,19 +110,17 @@ static struct xfrm_mode xfrm6_beet_mode = {
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
+	.family = AF_INET6,
 };
 
 static int __init xfrm6_beet_init(void)
 {
-	return xfrm_register_mode(&xfrm6_beet_mode, AF_INET6);
+	return xfrm_register_mode(&xfrm6_beet_mode);
 }
 
 static void __exit xfrm6_beet_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm6_beet_mode, AF_INET6);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm6_beet_mode);
 }
 
 module_init(xfrm6_beet_init);
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index da28e4407b8f..0408547d01ab 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -64,19 +64,17 @@ static struct xfrm_mode xfrm6_ro_mode = {
 	.output = xfrm6_ro_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_ROUTEOPTIMIZATION,
+	.family = AF_INET6,
 };
 
 static int __init xfrm6_ro_init(void)
 {
-	return xfrm_register_mode(&xfrm6_ro_mode, AF_INET6);
+	return xfrm_register_mode(&xfrm6_ro_mode);
 }
 
 static void __exit xfrm6_ro_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm6_ro_mode, AF_INET6);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm6_ro_mode);
 }
 
 module_init(xfrm6_ro_init);
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 3c29da5defe6..66ae79218bdf 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -100,19 +100,17 @@ static struct xfrm_mode xfrm6_transport_mode = {
 	.xmit = xfrm6_transport_xmit,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TRANSPORT,
+	.family = AF_INET6,
 };
 
 static int __init xfrm6_transport_init(void)
 {
-	return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6);
+	return xfrm_register_mode(&xfrm6_transport_mode);
 }
 
 static void __exit xfrm6_transport_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm6_transport_mode);
 }
 
 module_init(xfrm6_transport_init);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index de1b0b8c53b0..6cf12e961ea5 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -130,19 +130,17 @@ static struct xfrm_mode xfrm6_tunnel_mode = {
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
+	.family = AF_INET6,
 };
 
 static int __init xfrm6_mode_tunnel_init(void)
 {
-	return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6);
+	return xfrm_register_mode(&xfrm6_tunnel_mode);
 }
 
 static void __exit xfrm6_mode_tunnel_exit(void)
 {
-	int err;
-
-	err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6);
-	BUG_ON(err);
+	xfrm_unregister_mode(&xfrm6_tunnel_mode);
 }
 
 module_init(xfrm6_mode_tunnel_init);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1bb971f46fc6..c32394b59776 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -331,7 +331,7 @@ static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
 }
 
 static DEFINE_SPINLOCK(xfrm_mode_lock);
-int xfrm_register_mode(struct xfrm_mode *mode, int family)
+int xfrm_register_mode(struct xfrm_mode *mode)
 {
 	struct xfrm_state_afinfo *afinfo;
 	struct xfrm_mode **modemap;
@@ -340,7 +340,7 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
 	if (unlikely(mode->encap >= XFRM_MODE_MAX))
 		return -EINVAL;
 
-	afinfo = xfrm_state_get_afinfo(family);
+	afinfo = xfrm_state_get_afinfo(mode->family);
 	if (unlikely(afinfo == NULL))
 		return -EAFNOSUPPORT;
 
@@ -365,31 +365,24 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
 }
 EXPORT_SYMBOL(xfrm_register_mode);
 
-int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
+void xfrm_unregister_mode(struct xfrm_mode *mode)
 {
 	struct xfrm_state_afinfo *afinfo;
 	struct xfrm_mode **modemap;
-	int err;
-
-	if (unlikely(mode->encap >= XFRM_MODE_MAX))
-		return -EINVAL;
 
-	afinfo = xfrm_state_get_afinfo(family);
-	if (unlikely(afinfo == NULL))
-		return -EAFNOSUPPORT;
+	afinfo = xfrm_state_get_afinfo(mode->family);
+	if (WARN_ON_ONCE(!afinfo))
+		return;
 
-	err = -ENOENT;
 	modemap = afinfo->mode_map;
 	spin_lock_bh(&xfrm_mode_lock);
 	if (likely(modemap[mode->encap] == mode)) {
 		modemap[mode->encap] = NULL;
 		module_put(mode->afinfo->owner);
-		err = 0;
 	}
 
 	spin_unlock_bh(&xfrm_mode_lock);
 	rcu_read_unlock();
-	return err;
 }
 EXPORT_SYMBOL(xfrm_unregister_mode);
 
-- 
2.19.2


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

* [PATCH ipsec-next 02/11] xfrm: prefer family stored in xfrm_mode struct
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 01/11] xfrm: place af number into xfrm_mode struct Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode Florian Westphal
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

Now that we have the family available directly in the
xfrm_mode struct, we can use that and avoid one extra dereference.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/ipv4/ip_vti.c         | 2 +-
 net/ipv6/ip6_vti.c        | 2 +-
 net/xfrm/xfrm_input.c     | 4 ++--
 net/xfrm/xfrm_interface.c | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index a8474799fb79..3f3f6d6be318 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -137,7 +137,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
 		}
 	}
 
-	family = inner_mode->afinfo->family;
+	family = inner_mode->family;
 
 	skb->mark = be32_to_cpu(tunnel->parms.i_key);
 	ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 8b6eefff2f7e..369803c581b7 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -372,7 +372,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
 		}
 	}
 
-	family = inner_mode->afinfo->family;
+	family = inner_mode->family;
 
 	skb->mark = be32_to_cpu(t->parms.i_key);
 	ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index b3b613660d44..ea5ac053c15d 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -216,7 +216,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 			goto drop;
 		}
 
-		family = x->outer_mode->afinfo->family;
+		family = x->outer_mode->family;
 
 		/* An encap_type of -1 indicates async resumption. */
 		if (encap_type == -1) {
@@ -425,7 +425,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		 * transport mode so the outer address is identical.
 		 */
 		daddr = &x->id.daddr;
-		family = x->outer_mode->afinfo->family;
+		family = x->outer_mode->family;
 
 		err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
 		if (err < 0) {
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index dbb3c1945b5c..93efb0965e7d 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -285,7 +285,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
 		}
 
 		if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
-				       inner_mode->afinfo->family))
+				       inner_mode->family))
 			return -EPERM;
 	}
 
-- 
2.19.2


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

* [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 01/11] xfrm: place af number into xfrm_mode struct Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 02/11] xfrm: prefer family stored in " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-28 11:39   ` Sabrina Dubroca
  2019-03-29 17:10   ` Eyal Birger
  2019-03-27 17:31 ` [PATCH ipsec-next 04/11] xfrm: remove output " Florian Westphal
                   ` (8 subsequent siblings)
  11 siblings, 2 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

No need for any indirection or abstraction here, both functions
are pretty much the same and quite small, they also have no external
dependencies.

With allmodconfig build, size increase of vmlinux is 25 byte:

Before:
   text   data     bss     dec      filename
15730207  6936924 4046908 26714039  vmlinux

After:
15730208  6936948 4046908 26714064 vmlinux

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h              | 10 -----
 net/ipv4/xfrm4_mode_beet.c      |  1 -
 net/ipv4/xfrm4_mode_transport.c | 23 -----------
 net/ipv4/xfrm4_mode_tunnel.c    |  1 -
 net/ipv6/xfrm6_mode_beet.c      |  1 -
 net/ipv6/xfrm6_mode_transport.c | 25 ------------
 net/ipv6/xfrm6_mode_tunnel.c    |  1 -
 net/xfrm/xfrm_input.c           | 70 ++++++++++++++++++++++++++++++++-
 8 files changed, 69 insertions(+), 63 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 9a155063c25f..de5e56828e75 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -436,16 +436,6 @@ struct xfrm_mode {
 	 */
 	int (*input2)(struct xfrm_state *x, struct sk_buff *skb);
 
-	/*
-	 * This is the actual input entry point.
-	 *
-	 * For transport mode and equivalent this would be identical to
-	 * input2 (which does not need to be set).  While tunnel mode
-	 * and equivalent would set this to the tunnel encapsulation function
-	 * xfrm4_prepare_input that would in turn call input2.
-	 */
-	int (*input)(struct xfrm_state *x, struct sk_buff *skb);
-
 	/*
 	 * Add encapsulation header.
 	 *
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index a2e3b52ae46c..264c4c9e2473 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -128,7 +128,6 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 
 static struct xfrm_mode xfrm4_beet_mode = {
 	.input2 = xfrm4_beet_input,
-	.input = xfrm_prepare_input,
 	.output2 = xfrm4_beet_output,
 	.output = xfrm4_prepare_output,
 	.owner = THIS_MODULE,
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index 7c5443f797cf..c943d710f302 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -35,28 +35,6 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 	return 0;
 }
 
-/* Remove encapsulation header.
- *
- * The IP header will be moved over the top of the encapsulation header.
- *
- * On entry, skb->h shall point to where the IP header should be and skb->nh
- * shall be set to where the IP header currently is.  skb->data shall point
- * to the start of the payload.
- */
-static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-	int ihl = skb->data - skb_transport_header(skb);
-
-	if (skb->transport_header != skb->network_header) {
-		memmove(skb_transport_header(skb),
-			skb_network_header(skb), ihl);
-		skb->network_header = skb->transport_header;
-	}
-	ip_hdr(skb)->tot_len = htons(skb->len + ihl);
-	skb_reset_transport_header(skb);
-	return 0;
-}
-
 static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 						   struct sk_buff *skb,
 						   netdev_features_t features)
@@ -87,7 +65,6 @@ static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
 }
 
 static struct xfrm_mode xfrm4_transport_mode = {
-	.input = xfrm4_transport_input,
 	.output = xfrm4_transport_output,
 	.gso_segment = xfrm4_transport_gso_segment,
 	.xmit = xfrm4_transport_xmit,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index cfc6b6d39755..678b91754b5e 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -123,7 +123,6 @@ static void xfrm4_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
 
 static struct xfrm_mode xfrm4_tunnel_mode = {
 	.input2 = xfrm4_mode_tunnel_input,
-	.input = xfrm_prepare_input,
 	.output2 = xfrm4_mode_tunnel_output,
 	.output = xfrm4_prepare_output,
 	.gso_segment = xfrm4_mode_tunnel_gso_segment,
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 0d440e3a13f8..eadacaddfcae 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -104,7 +104,6 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 
 static struct xfrm_mode xfrm6_beet_mode = {
 	.input2 = xfrm6_beet_input,
-	.input = xfrm_prepare_input,
 	.output2 = xfrm6_beet_output,
 	.output = xfrm6_prepare_output,
 	.owner = THIS_MODULE,
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 66ae79218bdf..4c306bb99284 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -40,29 +40,6 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 	return 0;
 }
 
-/* Remove encapsulation header.
- *
- * The IP header will be moved over the top of the encapsulation header.
- *
- * On entry, skb->h shall point to where the IP header should be and skb->nh
- * shall be set to where the IP header currently is.  skb->data shall point
- * to the start of the payload.
- */
-static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-	int ihl = skb->data - skb_transport_header(skb);
-
-	if (skb->transport_header != skb->network_header) {
-		memmove(skb_transport_header(skb),
-			skb_network_header(skb), ihl);
-		skb->network_header = skb->transport_header;
-	}
-	ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
-					   sizeof(struct ipv6hdr));
-	skb_reset_transport_header(skb);
-	return 0;
-}
-
 static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 						   struct sk_buff *skb,
 						   netdev_features_t features)
@@ -92,9 +69,7 @@ static void xfrm6_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
 	}
 }
 
-
 static struct xfrm_mode xfrm6_transport_mode = {
-	.input = xfrm6_transport_input,
 	.output = xfrm6_transport_output,
 	.gso_segment = xfrm4_transport_gso_segment,
 	.xmit = xfrm6_transport_xmit,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 6cf12e961ea5..1e9677fd6559 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -122,7 +122,6 @@ static void xfrm6_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
 
 static struct xfrm_mode xfrm6_tunnel_mode = {
 	.input2 = xfrm6_mode_tunnel_input,
-	.input = xfrm_prepare_input,
 	.output2 = xfrm6_mode_tunnel_output,
 	.output = xfrm6_prepare_output,
 	.gso_segment = xfrm6_mode_tunnel_gso_segment,
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index ea5ac053c15d..e3c7edd11e77 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -186,6 +186,74 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(xfrm_prepare_input);
 
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET4_XFRM_MODE_TRANSPORT)
+	int ihl = skb->data - skb_transport_header(skb);
+
+	if (skb->transport_header != skb->network_header) {
+		memmove(skb_transport_header(skb),
+			skb_network_header(skb), ihl);
+		skb->network_header = skb->transport_header;
+	}
+	ip_hdr(skb)->tot_len = htons(skb->len + ihl);
+	skb_reset_transport_header(skb);
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+
+static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
+	int ihl = skb->data - skb_transport_header(skb);
+
+	if (skb->transport_header != skb->network_header) {
+		memmove(skb_transport_header(skb),
+			skb_network_header(skb), ihl);
+		skb->network_header = skb->transport_header;
+	}
+	ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
+					   sizeof(struct ipv6hdr));
+	skb_reset_transport_header(skb);
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+
+static int xfrm_inner_mode_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	switch (x->inner_mode->encap) {
+	case XFRM_MODE_BEET:
+	case XFRM_MODE_TUNNEL:
+		return xfrm_prepare_input(x, skb);
+	case XFRM_MODE_TRANSPORT:
+		if (x->inner_mode->family == AF_INET)
+			return xfrm4_transport_input(x, skb);
+		if (x->inner_mode->family == AF_INET6)
+			return xfrm6_transport_input(x, skb);
+		break;
+	case XFRM_MODE_ROUTEOPTIMIZATION:
+		WARN_ON_ONCE(1);
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 {
 	struct net *net = dev_net(skb->dev);
@@ -410,7 +478,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 			}
 		}
 
-		if (inner_mode->input(x, skb)) {
+		if (xfrm_inner_mode_input(x, skb)) {
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
 			goto drop;
 		}
-- 
2.19.2


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

* [PATCH ipsec-next 04/11] xfrm: remove output indirection from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (2 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-28 11:12   ` Sabrina Dubroca
  2019-03-27 17:31 ` [PATCH ipsec-next 05/11] xfrm: remove xmit " Florian Westphal
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

Same is input indirection.  Only exception: we need to export
xfrm_outer_mode_output for pktgen.

Increases size of vmlinux by about 163 byte:
Before:
   text    data     bss     dec      filename
15730208  6936948 4046908 26714064   vmlinux

After:
15730311  6937008 4046908 26714227   vmlinux

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h              |  18 ++--
 net/core/pktgen.c               |   2 +-
 net/ipv4/xfrm4_mode_beet.c      |   1 -
 net/ipv4/xfrm4_mode_transport.c |  22 -----
 net/ipv4/xfrm4_mode_tunnel.c    |   1 -
 net/ipv4/xfrm4_output.c         |  15 ----
 net/ipv6/xfrm6_mode_beet.c      |   1 -
 net/ipv6/xfrm6_mode_ro.c        |  28 ------
 net/ipv6/xfrm6_mode_transport.c |  26 ------
 net/ipv6/xfrm6_mode_tunnel.c    |   1 -
 net/ipv6/xfrm6_output.c         |  15 ----
 net/xfrm/xfrm_output.c          | 152 +++++++++++++++++++++++++++++++-
 12 files changed, 157 insertions(+), 125 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index de5e56828e75..cda319180b19 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -449,17 +449,6 @@ struct xfrm_mode {
 	 */
 	int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
 
-	/*
-	 * This is the actual output entry point.
-	 *
-	 * For transport mode and equivalent this would be identical to
-	 * output2 (which does not need to be set).  While tunnel mode
-	 * and equivalent would set this to a tunnel encapsulation function
-	 * (xfrm4_prepare_output or xfrm6_prepare_output) that would in turn
-	 * call output2.
-	 */
-	int (*output)(struct xfrm_state *x, struct sk_buff *skb);
-
 	/*
 	 * Adjust pointers into the packet and do GSO segmentation.
 	 */
@@ -1604,6 +1593,11 @@ int xfrm_trans_queue(struct sk_buff *skb,
 				   struct sk_buff *));
 int xfrm_output_resume(struct sk_buff *skb, int err);
 int xfrm_output(struct sock *sk, struct sk_buff *skb);
+
+#if IS_ENABLED(CONFIG_NET_PKTGEN)
+int pktgen_xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb);
+#endif
+
 int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 void xfrm_local_error(struct sk_buff *skb, int mtu);
 int xfrm4_extract_header(struct sk_buff *skb);
@@ -1623,7 +1617,6 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 }
 
 int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
-int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb);
 int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb);
 int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
@@ -1650,7 +1643,6 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
 __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
 __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
 int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
-int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb);
 int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb);
 int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index f3f5a78cd062..319ad5490fb3 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2521,7 +2521,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
 		skb->_skb_refdst = (unsigned long)&pkt_dev->xdst.u.dst | SKB_DST_NOREF;
 
 	rcu_read_lock_bh();
-	err = x->outer_mode->output(x, skb);
+	err = pktgen_xfrm_outer_mode_output(x, skb);
 	rcu_read_unlock_bh();
 	if (err) {
 		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 264c4c9e2473..f02cc8237d54 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -129,7 +129,6 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 static struct xfrm_mode xfrm4_beet_mode = {
 	.input2 = xfrm4_beet_input,
 	.output2 = xfrm4_beet_output,
-	.output = xfrm4_prepare_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index c943d710f302..6f8cf09ff0ef 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -14,27 +14,6 @@
 #include <net/xfrm.h>
 #include <net/protocol.h>
 
-/* Add encapsulation header.
- *
- * The IP header will be moved forward to make space for the encapsulation
- * header.
- */
-static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct iphdr *iph = ip_hdr(skb);
-	int ihl = iph->ihl * 4;
-
-	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
-
-	skb_set_network_header(skb, -x->props.header_len);
-	skb->mac_header = skb->network_header +
-			  offsetof(struct iphdr, protocol);
-	skb->transport_header = skb->network_header + ihl;
-	__skb_pull(skb, ihl);
-	memmove(skb_network_header(skb), iph, ihl);
-	return 0;
-}
-
 static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 						   struct sk_buff *skb,
 						   netdev_features_t features)
@@ -65,7 +44,6 @@ static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
 }
 
 static struct xfrm_mode xfrm4_transport_mode = {
-	.output = xfrm4_transport_output,
 	.gso_segment = xfrm4_transport_gso_segment,
 	.xmit = xfrm4_transport_xmit,
 	.owner = THIS_MODULE,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 678b91754b5e..823bc54b47de 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -124,7 +124,6 @@ static void xfrm4_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
 static struct xfrm_mode xfrm4_tunnel_mode = {
 	.input2 = xfrm4_mode_tunnel_input,
 	.output2 = xfrm4_mode_tunnel_output,
-	.output = xfrm4_prepare_output,
 	.gso_segment = xfrm4_mode_tunnel_gso_segment,
 	.xmit = xfrm4_mode_tunnel_xmit,
 	.owner = THIS_MODULE,
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index be980c195fc5..6802d1aee424 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -58,21 +58,6 @@ int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 	return xfrm4_extract_header(skb);
 }
 
-int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	int err;
-
-	err = xfrm_inner_extract_output(x, skb);
-	if (err)
-		return err;
-
-	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
-	skb->protocol = htons(ETH_P_IP);
-
-	return x->outer_mode->output2(x, skb);
-}
-EXPORT_SYMBOL(xfrm4_prepare_output);
-
 int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
 {
 	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index eadacaddfcae..6f35e24f0077 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -105,7 +105,6 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 static struct xfrm_mode xfrm6_beet_mode = {
 	.input2 = xfrm6_beet_input,
 	.output2 = xfrm6_beet_output,
-	.output = xfrm6_prepare_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 0408547d01ab..d0a6a4dbd689 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -33,35 +33,7 @@
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-/* Add route optimization header space.
- *
- * The IP header and mutable extension headers will be moved forward to make
- * space for the route optimization header.
- */
-static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct ipv6hdr *iph;
-	u8 *prevhdr;
-	int hdr_len;
-
-	iph = ipv6_hdr(skb);
-
-	hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
-	if (hdr_len < 0)
-		return hdr_len;
-	skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
-	skb_set_network_header(skb, -x->props.header_len);
-	skb->transport_header = skb->network_header + hdr_len;
-	__skb_pull(skb, hdr_len);
-	memmove(ipv6_hdr(skb), iph, hdr_len);
-
-	x->lastused = ktime_get_real_seconds();
-
-	return 0;
-}
-
 static struct xfrm_mode xfrm6_ro_mode = {
-	.output = xfrm6_ro_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_ROUTEOPTIMIZATION,
 	.family = AF_INET6,
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 4c306bb99284..1e7165a8481a 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -15,31 +15,6 @@
 #include <net/xfrm.h>
 #include <net/protocol.h>
 
-/* Add encapsulation header.
- *
- * The IP header and mutable extension headers will be moved forward to make
- * space for the encapsulation header.
- */
-static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct ipv6hdr *iph;
-	u8 *prevhdr;
-	int hdr_len;
-
-	iph = ipv6_hdr(skb);
-	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
-
-	hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
-	if (hdr_len < 0)
-		return hdr_len;
-	skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
-	skb_set_network_header(skb, -x->props.header_len);
-	skb->transport_header = skb->network_header + hdr_len;
-	__skb_pull(skb, hdr_len);
-	memmove(ipv6_hdr(skb), iph, hdr_len);
-	return 0;
-}
-
 static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 						   struct sk_buff *skb,
 						   netdev_features_t features)
@@ -70,7 +45,6 @@ static void xfrm6_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
 }
 
 static struct xfrm_mode xfrm6_transport_mode = {
-	.output = xfrm6_transport_output,
 	.gso_segment = xfrm4_transport_gso_segment,
 	.xmit = xfrm6_transport_xmit,
 	.owner = THIS_MODULE,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 1e9677fd6559..e1a129524dde 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -123,7 +123,6 @@ static void xfrm6_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
 static struct xfrm_mode xfrm6_tunnel_mode = {
 	.input2 = xfrm6_mode_tunnel_input,
 	.output2 = xfrm6_mode_tunnel_output,
-	.output = xfrm6_prepare_output,
 	.gso_segment = xfrm6_mode_tunnel_gso_segment,
 	.xmit = xfrm6_mode_tunnel_xmit,
 	.owner = THIS_MODULE,
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6a74080005cf..2b663d2ffdcd 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -111,21 +111,6 @@ int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 	return xfrm6_extract_header(skb);
 }
 
-int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	int err;
-
-	err = xfrm_inner_extract_output(x, skb);
-	if (err)
-		return err;
-
-	skb->ignore_df = 1;
-	skb->protocol = htons(ETH_P_IPV6);
-
-	return x->outer_mode->output2(x, skb);
-}
-EXPORT_SYMBOL(xfrm6_prepare_output);
-
 int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
 {
 	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 9333153bafda..01eb142ba6d0 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -50,6 +50,156 @@ static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 	return child;
 }
 
+/* Add encapsulation header.
+ *
+ * The IP header will be moved forward to make space for the encapsulation
+ * header.
+ */
+static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET_XFRM_MODE_TRANSPORT)
+	struct iphdr *iph = ip_hdr(skb);
+	int ihl = iph->ihl * 4;
+
+	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
+
+	skb_set_network_header(skb, -x->props.header_len);
+	skb->mac_header = skb->network_header +
+			  offsetof(struct iphdr, protocol);
+	skb->transport_header = skb->network_header + ihl;
+	__skb_pull(skb, ihl);
+	memmove(skb_network_header(skb), iph, ihl);
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+
+/* Add encapsulation header.
+ *
+ * The IP header and mutable extension headers will be moved forward to make
+ * space for the encapsulation header.
+ */
+static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
+	struct ipv6hdr *iph;
+	u8 *prevhdr;
+	int hdr_len;
+
+	iph = ipv6_hdr(skb);
+	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
+
+	hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+	if (hdr_len < 0)
+		return hdr_len;
+	skb_set_mac_header(skb,
+			   (prevhdr - x->props.header_len) - skb->data);
+	skb_set_network_header(skb, -x->props.header_len);
+	skb->transport_header = skb->network_header + hdr_len;
+	__skb_pull(skb, hdr_len);
+	memmove(ipv6_hdr(skb), iph, hdr_len);
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+
+/* Add route optimization header space.
+ *
+ * The IP header and mutable extension headers will be moved forward to make
+ * space for the route optimization header.
+ */
+static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION)
+	struct ipv6hdr *iph;
+	u8 *prevhdr;
+	int hdr_len;
+
+	iph = ipv6_hdr(skb);
+
+	hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+	if (hdr_len < 0)
+		return hdr_len;
+	skb_set_mac_header(skb,
+			   (prevhdr - x->props.header_len) - skb->data);
+	skb_set_network_header(skb, -x->props.header_len);
+	skb->transport_header = skb->network_header + hdr_len;
+	__skb_pull(skb, hdr_len);
+	memmove(ipv6_hdr(skb), iph, hdr_len);
+
+	x->lastused = ktime_get_real_seconds();
+
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+
+static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err;
+
+	err = xfrm_inner_extract_output(x, skb);
+	if (err)
+		return err;
+
+	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
+	skb->protocol = htons(ETH_P_IP);
+
+	return x->outer_mode->output2(x, skb);
+}
+
+static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err;
+
+	err = xfrm_inner_extract_output(x, skb);
+	if (err)
+		return err;
+
+	skb->ignore_df = 1;
+	skb->protocol = htons(ETH_P_IPV6);
+
+	return x->outer_mode->output2(x, skb);
+}
+
+static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+	switch (x->outer_mode->encap) {
+	case XFRM_MODE_BEET:
+	case XFRM_MODE_TUNNEL:
+		if (x->outer_mode->family == AF_INET)
+			return xfrm4_prepare_output(x, skb);
+		if (x->outer_mode->family == AF_INET6)
+			return xfrm6_prepare_output(x, skb);
+	case XFRM_MODE_TRANSPORT:
+		if (x->outer_mode->family == AF_INET)
+			return xfrm4_transport_output(x, skb);
+		if (x->outer_mode->family == AF_INET6)
+			return xfrm6_transport_output(x, skb);
+		break;
+	case XFRM_MODE_ROUTEOPTIMIZATION:
+		if (x->outer_mode->family == AF_INET6)
+			return xfrm6_ro_output(x, skb);
+		WARN_ON_ONCE(1);
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+#if IS_ENABLED(CONFIG_NET_PKTGEN)
+int pktgen_xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+	return xfrm_outer_mode_output(x, skb);
+}
+EXPORT_SYMBOL_GPL(pktgen_xfrm_outer_mode_output);
+#endif
+
 static int xfrm_output_one(struct sk_buff *skb, int err)
 {
 	struct dst_entry *dst = skb_dst(skb);
@@ -68,7 +218,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 
 		skb->mark = xfrm_smark_get(skb->mark, x);
 
-		err = x->outer_mode->output(x, skb);
+		err = xfrm_outer_mode_output(x, skb);
 		if (err) {
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
 			goto error_nolock;
-- 
2.19.2


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

* [PATCH ipsec-next 05/11] xfrm: remove xmit indirection from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (3 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 04/11] xfrm: remove output " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 06/11] xfrm: remove gso_segment " Florian Westphal
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

There are only two versions (tunnel and transport). The ip/ipv6 versions
are only differ in sizeof(iphdr) vs ipv6hdr.

Place this in the core and use x->outer_mode->encap type to call the
correct adjustment helper.

Before:
   text   data    bss     dec      filename
15730311  6937008 4046908 26714227 vmlinux

After:
15730428  6937008 4046908 26714344 vmlinux

(about 117 byte increase)

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h              |  5 ---
 net/ipv4/xfrm4_mode_transport.c | 14 --------
 net/ipv4/xfrm4_mode_tunnel.c    | 13 --------
 net/ipv6/xfrm6_mode_transport.c | 14 --------
 net/ipv6/xfrm6_mode_tunnel.c    | 12 -------
 net/xfrm/xfrm_device.c          | 58 +++++++++++++++++++++++++++++++--
 6 files changed, 56 insertions(+), 60 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index cda319180b19..bb19befd1a67 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -454,11 +454,6 @@ struct xfrm_mode {
 	 */
 	struct sk_buff *(*gso_segment)(struct xfrm_state *x, struct sk_buff *skb, netdev_features_t features);
 
-	/*
-	 * Adjust pointers into the packet when IPsec is done at layer2.
-	 */
-	void (*xmit)(struct xfrm_state *x, struct sk_buff *skb);
-
 	struct xfrm_state_afinfo *afinfo;
 	struct module *owner;
 	u8 encap;
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index 6f8cf09ff0ef..d4b34bb2de00 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -30,22 +30,8 @@ static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 	return segs;
 }
 
-static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct xfrm_offload *xo = xfrm_offload(skb);
-
-	skb_reset_mac_len(skb);
-	pskb_pull(skb, skb->mac_len + sizeof(struct iphdr) + x->props.header_len);
-
-	if (xo->flags & XFRM_GSO_SEGMENT) {
-		 skb_reset_transport_header(skb);
-		 skb->transport_header -= x->props.header_len;
-	}
-}
-
 static struct xfrm_mode xfrm4_transport_mode = {
 	.gso_segment = xfrm4_transport_gso_segment,
-	.xmit = xfrm4_transport_xmit,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TRANSPORT,
 	.family = AF_INET,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 823bc54b47de..8bd5112b3ee3 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -109,23 +109,10 @@ static struct sk_buff *xfrm4_mode_tunnel_gso_segment(struct xfrm_state *x,
 	return skb_mac_gso_segment(skb, features);
 }
 
-static void xfrm4_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct xfrm_offload *xo = xfrm_offload(skb);
-
-	if (xo->flags & XFRM_GSO_SEGMENT)
-		skb->transport_header = skb->network_header +
-					sizeof(struct iphdr);
-
-	skb_reset_mac_len(skb);
-	pskb_pull(skb, skb->mac_len + x->props.header_len);
-}
-
 static struct xfrm_mode xfrm4_tunnel_mode = {
 	.input2 = xfrm4_mode_tunnel_input,
 	.output2 = xfrm4_mode_tunnel_output,
 	.gso_segment = xfrm4_mode_tunnel_gso_segment,
-	.xmit = xfrm4_mode_tunnel_xmit,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 1e7165a8481a..6a72ff39bc05 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -31,22 +31,8 @@ static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 	return segs;
 }
 
-static void xfrm6_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct xfrm_offload *xo = xfrm_offload(skb);
-
-	skb_reset_mac_len(skb);
-	pskb_pull(skb, skb->mac_len + sizeof(struct ipv6hdr) + x->props.header_len);
-
-	if (xo->flags & XFRM_GSO_SEGMENT) {
-		 skb_reset_transport_header(skb);
-		 skb->transport_header -= x->props.header_len;
-	}
-}
-
 static struct xfrm_mode xfrm6_transport_mode = {
 	.gso_segment = xfrm4_transport_gso_segment,
-	.xmit = xfrm6_transport_xmit,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TRANSPORT,
 	.family = AF_INET6,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index e1a129524dde..7450dd87f27d 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -109,22 +109,10 @@ static struct sk_buff *xfrm6_mode_tunnel_gso_segment(struct xfrm_state *x,
 	return skb_mac_gso_segment(skb, features);
 }
 
-static void xfrm6_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct xfrm_offload *xo = xfrm_offload(skb);
-
-	if (xo->flags & XFRM_GSO_SEGMENT)
-		skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
-
-	skb_reset_mac_len(skb);
-	pskb_pull(skb, skb->mac_len + x->props.header_len);
-}
-
 static struct xfrm_mode xfrm6_tunnel_mode = {
 	.input2 = xfrm6_mode_tunnel_input,
 	.output2 = xfrm6_mode_tunnel_output,
 	.gso_segment = xfrm6_mode_tunnel_gso_segment,
-	.xmit = xfrm6_mode_tunnel_xmit,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index e437b60fba51..e37824a8652e 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -23,6 +23,60 @@
 #include <linux/notifier.h>
 
 #ifdef CONFIG_XFRM_OFFLOAD
+static void __xfrm_transport_prep(struct xfrm_state *x, struct sk_buff *skb,
+				  unsigned int hsize)
+{
+	struct xfrm_offload *xo = xfrm_offload(skb);
+
+	skb_reset_mac_len(skb);
+	pskb_pull(skb, skb->mac_len + hsize + x->props.header_len);
+
+	if (xo->flags & XFRM_GSO_SEGMENT) {
+		skb_reset_transport_header(skb);
+		skb->transport_header -= x->props.header_len;
+	}
+}
+
+static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
+				    unsigned int hsize)
+
+{
+	struct xfrm_offload *xo = xfrm_offload(skb);
+
+	if (xo->flags & XFRM_GSO_SEGMENT)
+		skb->transport_header = skb->network_header + hsize;
+
+	skb_reset_mac_len(skb);
+	pskb_pull(skb, skb->mac_len + x->props.header_len);
+}
+
+/* Adjust pointers into the packet when IPsec is done at layer2 */
+static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
+{
+	switch (x->outer_mode->encap) {
+	case XFRM_MODE_TUNNEL:
+		if (x->inner_mode->family == AF_INET)
+			return __xfrm_mode_tunnel_prep(x, skb,
+						       sizeof(struct iphdr));
+		if (x->inner_mode->family == AF_INET6)
+			return __xfrm_mode_tunnel_prep(x, skb,
+						       sizeof(struct ipv6hdr));
+		break;
+	case XFRM_MODE_TRANSPORT:
+		if (x->inner_mode->family == AF_INET)
+			return __xfrm_transport_prep(x, skb,
+						     sizeof(struct iphdr));
+		if (x->inner_mode->family == AF_INET6)
+			return __xfrm_transport_prep(x, skb,
+						     sizeof(struct ipv6hdr));
+		break;
+	case XFRM_MODE_ROUTEOPTIMIZATION:
+	case XFRM_MODE_IN_TRIGGER:
+	case XFRM_MODE_BEET:
+		break;
+	}
+}
+
 struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
 {
 	int err;
@@ -79,7 +133,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 
 	if (!skb->next) {
 		esp_features |= skb->dev->gso_partial_features;
-		x->outer_mode->xmit(x, skb);
+		xfrm_outer_mode_prep(x, skb);
 
 		xo->flags |= XFRM_DEV_RESUME;
 
@@ -109,7 +163,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 		xo = xfrm_offload(skb2);
 		xo->flags |= XFRM_DEV_RESUME;
 
-		x->outer_mode->xmit(x, skb2);
+		xfrm_outer_mode_prep(x, skb2);
 
 		err = x->type_offload->xmit(x, skb2, esp_features);
 		if (!err) {
-- 
2.19.2


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

* [PATCH ipsec-next 06/11] xfrm: remove gso_segment indirection from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (4 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 05/11] xfrm: remove xmit " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 07/11] xfrm: remove input2 " Florian Westphal
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

These functions are small and we only have versions for tunnel
and transport mode for ipv4 and ipv6 respectively.

Just place the 'transport or tunnel' conditional in the protocol
specific function instead of using an indirection.

Before:
    3226       12       0     3238   net/ipv4/esp4_offload.o
    7004      492       0     7496   net/ipv4/ip_vti.o
    3339       12       0     3351   net/ipv6/esp6_offload.o
   11294      460       0    11754   net/ipv6/ip6_vti.o
    1180       72       0     1252   net/ipv4/xfrm4_mode_beet.o
     428       48       0      476   net/ipv4/xfrm4_mode_transport.o
    1271       48       0     1319   net/ipv4/xfrm4_mode_tunnel.o
    1083       60       0     1143   net/ipv6/xfrm6_mode_beet.o
     172       48       0      220   net/ipv6/xfrm6_mode_ro.o
     429       48       0      477   net/ipv6/xfrm6_mode_transport.o
    1164       48       0     1212   net/ipv6/xfrm6_mode_tunnel.o
15730428  6937008 4046908 26714344   vmlinux

After:
    3461       12       0     3473   net/ipv4/esp4_offload.o
    7000      492       0     7492   net/ipv4/ip_vti.o
    3574       12       0     3586   net/ipv6/esp6_offload.o
   11295      460       0    11755   net/ipv6/ip6_vti.o
    1180       64       0     1244   net/ipv4/xfrm4_mode_beet.o
     171       40       0      211   net/ipv4/xfrm4_mode_transport.o
    1163       40       0     1203   net/ipv4/xfrm4_mode_tunnel.o
    1083       52       0     1135   net/ipv6/xfrm6_mode_beet.o
     172       40       0      212   net/ipv6/xfrm6_mode_ro.o
     172       40       0      212   net/ipv6/xfrm6_mode_transport.o
    1056       40       0     1096   net/ipv6/xfrm6_mode_tunnel.o
15730424  6937008 4046908 26714340   vmlinux

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h              |  5 -----
 net/ipv4/esp4_offload.c         | 40 ++++++++++++++++++++++++++++++++-
 net/ipv4/xfrm4_mode_transport.c | 17 --------------
 net/ipv4/xfrm4_mode_tunnel.c    |  9 --------
 net/ipv6/esp6_offload.c         | 40 ++++++++++++++++++++++++++++++++-
 net/ipv6/xfrm6_mode_transport.c | 17 --------------
 net/ipv6/xfrm6_mode_tunnel.c    |  8 -------
 7 files changed, 78 insertions(+), 58 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bb19befd1a67..437118b0e06e 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -449,11 +449,6 @@ struct xfrm_mode {
 	 */
 	int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
 
-	/*
-	 * Adjust pointers into the packet and do GSO segmentation.
-	 */
-	struct sk_buff *(*gso_segment)(struct xfrm_state *x, struct sk_buff *skb, netdev_features_t features);
-
 	struct xfrm_state_afinfo *afinfo;
 	struct module *owner;
 	u8 encap;
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index c6c84f2bc41c..74d59e0177a7 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -107,6 +107,44 @@ static void esp4_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
 	xo->proto = proto;
 }
 
+static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x,
+						struct sk_buff *skb,
+						netdev_features_t features)
+{
+	__skb_push(skb, skb->mac_len);
+	return skb_mac_gso_segment(skb, features);
+}
+
+static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
+						   struct sk_buff *skb,
+						   netdev_features_t features)
+{
+	const struct net_offload *ops;
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	struct xfrm_offload *xo = xfrm_offload(skb);
+
+	skb->transport_header += x->props.header_len;
+	ops = rcu_dereference(inet_offloads[xo->proto]);
+	if (likely(ops && ops->callbacks.gso_segment))
+		segs = ops->callbacks.gso_segment(skb, features);
+
+	return segs;
+}
+
+static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
+						    struct sk_buff *skb,
+						    netdev_features_t features)
+{
+	switch (x->outer_mode->encap) {
+	case XFRM_MODE_TUNNEL:
+		return xfrm4_tunnel_gso_segment(x, skb, features);
+	case XFRM_MODE_TRANSPORT:
+		return xfrm4_transport_gso_segment(x, skb, features);
+	}
+
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
 static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 				        netdev_features_t features)
 {
@@ -147,7 +185,7 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 
 	xo->flags |= XFRM_GSO_SEGMENT;
 
-	return x->outer_mode->gso_segment(x, skb, esp_features);
+	return xfrm4_outer_mode_gso_segment(x, skb, esp_features);
 }
 
 static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index d4b34bb2de00..397863ea762b 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -14,24 +14,7 @@
 #include <net/xfrm.h>
 #include <net/protocol.h>
 
-static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
-						   struct sk_buff *skb,
-						   netdev_features_t features)
-{
-	const struct net_offload *ops;
-	struct sk_buff *segs = ERR_PTR(-EINVAL);
-	struct xfrm_offload *xo = xfrm_offload(skb);
-
-	skb->transport_header += x->props.header_len;
-	ops = rcu_dereference(inet_offloads[xo->proto]);
-	if (likely(ops && ops->callbacks.gso_segment))
-		segs = ops->callbacks.gso_segment(skb, features);
-
-	return segs;
-}
-
 static struct xfrm_mode xfrm4_transport_mode = {
-	.gso_segment = xfrm4_transport_gso_segment,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TRANSPORT,
 	.family = AF_INET,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 8bd5112b3ee3..b5d4ba41758e 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -101,18 +101,9 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 	return err;
 }
 
-static struct sk_buff *xfrm4_mode_tunnel_gso_segment(struct xfrm_state *x,
-						     struct sk_buff *skb,
-						     netdev_features_t features)
-{
-	__skb_push(skb, skb->mac_len);
-	return skb_mac_gso_segment(skb, features);
-}
-
 static struct xfrm_mode xfrm4_tunnel_mode = {
 	.input2 = xfrm4_mode_tunnel_input,
 	.output2 = xfrm4_mode_tunnel_output,
-	.gso_segment = xfrm4_mode_tunnel_gso_segment,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index d46b4eb645c2..c793a2ace77d 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -134,6 +134,44 @@ static void esp6_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
 	xo->proto = proto;
 }
 
+static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x,
+						struct sk_buff *skb,
+						netdev_features_t features)
+{
+	__skb_push(skb, skb->mac_len);
+	return skb_mac_gso_segment(skb, features);
+}
+
+static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,
+						   struct sk_buff *skb,
+						   netdev_features_t features)
+{
+	const struct net_offload *ops;
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	struct xfrm_offload *xo = xfrm_offload(skb);
+
+	skb->transport_header += x->props.header_len;
+	ops = rcu_dereference(inet6_offloads[xo->proto]);
+	if (likely(ops && ops->callbacks.gso_segment))
+		segs = ops->callbacks.gso_segment(skb, features);
+
+	return segs;
+}
+
+static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
+						    struct sk_buff *skb,
+						    netdev_features_t features)
+{
+	switch (x->outer_mode->encap) {
+	case XFRM_MODE_TUNNEL:
+		return xfrm6_tunnel_gso_segment(x, skb, features);
+	case XFRM_MODE_TRANSPORT:
+		return xfrm6_transport_gso_segment(x, skb, features);
+	}
+
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
 static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 				        netdev_features_t features)
 {
@@ -172,7 +210,7 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 
 	xo->flags |= XFRM_GSO_SEGMENT;
 
-	return x->outer_mode->gso_segment(x, skb, esp_features);
+	return xfrm6_outer_mode_gso_segment(x, skb, esp_features);
 }
 
 static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 6a72ff39bc05..d90c934c2f1a 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -15,24 +15,7 @@
 #include <net/xfrm.h>
 #include <net/protocol.h>
 
-static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
-						   struct sk_buff *skb,
-						   netdev_features_t features)
-{
-	const struct net_offload *ops;
-	struct sk_buff *segs = ERR_PTR(-EINVAL);
-	struct xfrm_offload *xo = xfrm_offload(skb);
-
-	skb->transport_header += x->props.header_len;
-	ops = rcu_dereference(inet6_offloads[xo->proto]);
-	if (likely(ops && ops->callbacks.gso_segment))
-		segs = ops->callbacks.gso_segment(skb, features);
-
-	return segs;
-}
-
 static struct xfrm_mode xfrm6_transport_mode = {
-	.gso_segment = xfrm4_transport_gso_segment,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TRANSPORT,
 	.family = AF_INET6,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 7450dd87f27d..8e23a2fba617 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -101,18 +101,10 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 	return err;
 }
 
-static struct sk_buff *xfrm6_mode_tunnel_gso_segment(struct xfrm_state *x,
-						     struct sk_buff *skb,
-						     netdev_features_t features)
-{
-	__skb_push(skb, skb->mac_len);
-	return skb_mac_gso_segment(skb, features);
-}
 
 static struct xfrm_mode xfrm6_tunnel_mode = {
 	.input2 = xfrm6_mode_tunnel_input,
 	.output2 = xfrm6_mode_tunnel_output,
-	.gso_segment = xfrm6_mode_tunnel_gso_segment,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
-- 
2.19.2


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

* [PATCH ipsec-next 07/11] xfrm: remove input2 indirection from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (5 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 06/11] xfrm: remove gso_segment " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-27 17:31 ` [PATCH ipsec-next 08/11] xfrm: remove output2 " Florian Westphal
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

No external dependencies on any module, place this in the core.
Increase is about 1800 byte for xfrm_input.o.

The beet helpers get added to internal header, as they can be reused
from xfrm_output.c in the next patch (kernel contains several
copies of them in the xfrm{4,6}_mode_beet.c files).

Before:
   text    data     bss     dec filename
   5578     176    2364    8118 net/xfrm/xfrm_input.o
   1180      64       0    1244 net/ipv4/xfrm4_mode_beet.o
    171      40       0     211 net/ipv4/xfrm4_mode_transport.o
   1163      40       0    1203 net/ipv4/xfrm4_mode_tunnel.o
   1083      52       0    1135 net/ipv6/xfrm6_mode_beet.o
    172      40       0     212 net/ipv6/xfrm6_mode_ro.o
    172      40       0     212 net/ipv6/xfrm6_mode_transport.o
   1056      40       0    1096 net/ipv6/xfrm6_mode_tunnel.o

After:
   text    data     bss     dec filename
   7373     200    2364    9937 net/xfrm/xfrm_input.o
    587      44       0     631 net/ipv4/xfrm4_mode_beet.o
    171      32       0     203 net/ipv4/xfrm4_mode_transport.o
    649      32       0     681 net/ipv4/xfrm4_mode_tunnel.o
    625      44       0     669 net/ipv6/xfrm6_mode_beet.o
    172      32       0     204 net/ipv6/xfrm6_mode_ro.o
    172      32       0     204 net/ipv6/xfrm6_mode_transport.o
    599      32       0     631 net/ipv6/xfrm6_mode_tunnel.o

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h           |  13 ---
 net/ipv4/xfrm4_mode_beet.c   |  47 ---------
 net/ipv4/xfrm4_mode_tunnel.c |  39 --------
 net/ipv6/xfrm6_mode_beet.c   |  27 ------
 net/ipv6/xfrm6_mode_tunnel.c |  46 ---------
 net/xfrm/xfrm_inout.h        |  38 ++++++++
 net/xfrm/xfrm_input.c        | 183 ++++++++++++++++++++++++++++++++++-
 7 files changed, 220 insertions(+), 173 deletions(-)
 create mode 100644 net/xfrm/xfrm_inout.h

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 437118b0e06e..bb2047d774b3 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -423,19 +423,6 @@ int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned sh
 int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 
 struct xfrm_mode {
-	/*
-	 * Remove encapsulation header.
-	 *
-	 * The IP header will be moved over the top of the encapsulation
-	 * header.
-	 *
-	 * On entry, the transport header shall point to where the IP header
-	 * should be and the network header shall be set to where the IP
-	 * header currently is.  skb->data shall point to the start of the
-	 * payload.
-	 */
-	int (*input2)(struct xfrm_state *x, struct sk_buff *skb);
-
 	/*
 	 * Add encapsulation header.
 	 *
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index f02cc8237d54..500960172933 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -80,54 +80,7 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
 	return 0;
 }
 
-static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct iphdr *iph;
-	int optlen = 0;
-	int err = -EINVAL;
-
-	if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
-		struct ip_beet_phdr *ph;
-		int phlen;
-
-		if (!pskb_may_pull(skb, sizeof(*ph)))
-			goto out;
-
-		ph = (struct ip_beet_phdr *)skb->data;
-
-		phlen = sizeof(*ph) + ph->padlen;
-		optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
-		if (optlen < 0 || optlen & 3 || optlen > 250)
-			goto out;
-
-		XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;
-
-		if (!pskb_may_pull(skb, phlen))
-			goto out;
-		__skb_pull(skb, phlen);
-	}
-
-	skb_push(skb, sizeof(*iph));
-	skb_reset_network_header(skb);
-	skb_mac_header_rebuild(skb);
-
-	xfrm4_beet_make_header(skb);
-
-	iph = ip_hdr(skb);
-
-	iph->ihl += optlen / 4;
-	iph->tot_len = htons(skb->len);
-	iph->daddr = x->sel.daddr.a4;
-	iph->saddr = x->sel.saddr.a4;
-	iph->check = 0;
-	iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
-	err = 0;
-out:
-	return err;
-}
-
 static struct xfrm_mode xfrm4_beet_mode = {
-	.input2 = xfrm4_beet_input,
 	.output2 = xfrm4_beet_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index b5d4ba41758e..31645319aaeb 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -15,14 +15,6 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 
-static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
-{
-	struct iphdr *inner_iph = ipip_hdr(skb);
-
-	if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
-		IP_ECN_set_ce(inner_iph);
-}
-
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per RFC 2401.
@@ -71,38 +63,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 	return 0;
 }
 
-static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-	int err = -EINVAL;
-
-	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
-		goto out;
-
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		goto out;
-
-	err = skb_unclone(skb, GFP_ATOMIC);
-	if (err)
-		goto out;
-
-	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-		ipv4_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipip_hdr(skb));
-	if (!(x->props.flags & XFRM_STATE_NOECN))
-		ipip_ecn_decapsulate(skb);
-
-	skb_reset_network_header(skb);
-	skb_mac_header_rebuild(skb);
-	if (skb->mac_len)
-		eth_hdr(skb)->h_proto = skb->protocol;
-
-	err = 0;
-
-out:
-	return err;
-}
-
 static struct xfrm_mode xfrm4_tunnel_mode = {
-	.input2 = xfrm4_mode_tunnel_input,
 	.output2 = xfrm4_mode_tunnel_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 6f35e24f0077..a0537b4f62f8 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -76,34 +76,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
 	top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
 	return 0;
 }
-
-static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct ipv6hdr *ip6h;
-	int size = sizeof(struct ipv6hdr);
-	int err;
-
-	err = skb_cow_head(skb, size + skb->mac_len);
-	if (err)
-		goto out;
-
-	__skb_push(skb, size);
-	skb_reset_network_header(skb);
-	skb_mac_header_rebuild(skb);
-
-	xfrm6_beet_make_header(skb);
-
-	ip6h = ipv6_hdr(skb);
-	ip6h->payload_len = htons(skb->len - size);
-	ip6h->daddr = x->sel.daddr.in6;
-	ip6h->saddr = x->sel.saddr.in6;
-	err = 0;
-out:
-	return err;
-}
-
 static struct xfrm_mode xfrm6_beet_mode = {
-	.input2 = xfrm6_beet_input,
 	.output2 = xfrm6_beet_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 8e23a2fba617..79c57decb472 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -18,14 +18,6 @@
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
-{
-	struct ipv6hdr *inner_iph = ipipv6_hdr(skb);
-
-	if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
-		IP6_ECN_set_ce(skb, inner_iph);
-}
-
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per RFC 2401.
@@ -65,45 +57,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 	return 0;
 }
 
-#define for_each_input_rcu(head, handler)	\
-	for (handler = rcu_dereference(head);	\
-	     handler != NULL;			\
-	     handler = rcu_dereference(handler->next))
-
-
-static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-	int err = -EINVAL;
-
-	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
-		goto out;
-	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
-		goto out;
-
-	err = skb_unclone(skb, GFP_ATOMIC);
-	if (err)
-		goto out;
-
-	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-		ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)),
-			       ipipv6_hdr(skb));
-	if (!(x->props.flags & XFRM_STATE_NOECN))
-		ipip6_ecn_decapsulate(skb);
-
-	skb_reset_network_header(skb);
-	skb_mac_header_rebuild(skb);
-	if (skb->mac_len)
-		eth_hdr(skb)->h_proto = skb->protocol;
-
-	err = 0;
-
-out:
-	return err;
-}
-
-
 static struct xfrm_mode xfrm6_tunnel_mode = {
-	.input2 = xfrm6_mode_tunnel_input,
 	.output2 = xfrm6_mode_tunnel_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
diff --git a/net/xfrm/xfrm_inout.h b/net/xfrm/xfrm_inout.h
new file mode 100644
index 000000000000..c7b0318938e2
--- /dev/null
+++ b/net/xfrm/xfrm_inout.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/ipv6.h>
+#include <net/dsfield.h>
+#include <net/xfrm.h>
+
+#ifndef XFRM_INOUT_H
+#define XFRM_INOUT_H 1
+
+static inline void xfrm6_beet_make_header(struct sk_buff *skb)
+{
+	struct ipv6hdr *iph = ipv6_hdr(skb);
+
+	iph->version = 6;
+
+	memcpy(iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
+	       sizeof(iph->flow_lbl));
+	iph->nexthdr = XFRM_MODE_SKB_CB(skb)->protocol;
+
+	ipv6_change_dsfield(iph, 0, XFRM_MODE_SKB_CB(skb)->tos);
+	iph->hop_limit = XFRM_MODE_SKB_CB(skb)->ttl;
+}
+
+static inline void xfrm4_beet_make_header(struct sk_buff *skb)
+{
+	struct iphdr *iph = ip_hdr(skb);
+
+	iph->ihl = 5;
+	iph->version = 4;
+
+	iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
+	iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
+
+	iph->id = XFRM_MODE_SKB_CB(skb)->id;
+	iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
+	iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
+}
+
+#endif
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index e3c7edd11e77..065ace68b26a 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -21,6 +21,8 @@
 #include <net/ip_tunnels.h>
 #include <net/ip6_tunnel.h>
 
+#include "xfrm_inout.h"
+
 struct xfrm_trans_tasklet {
 	struct tasklet_struct tasklet;
 	struct sk_buff_head queue;
@@ -166,6 +168,185 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 }
 EXPORT_SYMBOL(xfrm_parse_spi);
 
+static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	int optlen = 0;
+	int err = -EINVAL;
+
+	if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
+		struct ip_beet_phdr *ph;
+		int phlen;
+
+		if (!pskb_may_pull(skb, sizeof(*ph)))
+			goto out;
+
+		ph = (struct ip_beet_phdr *)skb->data;
+
+		phlen = sizeof(*ph) + ph->padlen;
+		optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
+		if (optlen < 0 || optlen & 3 || optlen > 250)
+			goto out;
+
+		XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;
+
+		if (!pskb_may_pull(skb, phlen))
+			goto out;
+		__skb_pull(skb, phlen);
+	}
+
+	skb_push(skb, sizeof(*iph));
+	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+
+	xfrm4_beet_make_header(skb);
+
+	iph = ip_hdr(skb);
+
+	iph->ihl += optlen / 4;
+	iph->tot_len = htons(skb->len);
+	iph->daddr = x->sel.daddr.a4;
+	iph->saddr = x->sel.saddr.a4;
+	iph->check = 0;
+	iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
+	err = 0;
+out:
+	return err;
+}
+
+static void ipip_ecn_decapsulate(struct sk_buff *skb)
+{
+	struct iphdr *inner_iph = ipip_hdr(skb);
+
+	if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
+		IP_ECN_set_ce(inner_iph);
+}
+
+static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err = -EINVAL;
+
+	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
+		goto out;
+
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto out;
+
+	err = skb_unclone(skb, GFP_ATOMIC);
+	if (err)
+		goto out;
+
+	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+		ipv4_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipip_hdr(skb));
+	if (!(x->props.flags & XFRM_STATE_NOECN))
+		ipip_ecn_decapsulate(skb);
+
+	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+	if (skb->mac_len)
+		eth_hdr(skb)->h_proto = skb->protocol;
+
+	err = 0;
+
+out:
+	return err;
+}
+
+static void ipip6_ecn_decapsulate(struct sk_buff *skb)
+{
+	struct ipv6hdr *inner_iph = ipipv6_hdr(skb);
+
+	if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
+		IP6_ECN_set_ce(skb, inner_iph);
+}
+
+static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err = -EINVAL;
+
+	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
+		goto out;
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+		goto out;
+
+	err = skb_unclone(skb, GFP_ATOMIC);
+	if (err)
+		goto out;
+
+	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+		ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)),
+			       ipipv6_hdr(skb));
+	if (!(x->props.flags & XFRM_STATE_NOECN))
+		ipip6_ecn_decapsulate(skb);
+
+	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+	if (skb->mac_len)
+		eth_hdr(skb)->h_proto = skb->protocol;
+
+	err = 0;
+
+out:
+	return err;
+}
+
+static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct ipv6hdr *ip6h;
+	int size = sizeof(struct ipv6hdr);
+	int err;
+
+	err = skb_cow_head(skb, size + skb->mac_len);
+	if (err)
+		goto out;
+
+	__skb_push(skb, size);
+	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+
+	xfrm6_beet_make_header(skb);
+
+	ip6h = ipv6_hdr(skb);
+	ip6h->payload_len = htons(skb->len - size);
+	ip6h->daddr = x->sel.daddr.in6;
+	ip6h->saddr = x->sel.saddr.in6;
+	err = 0;
+out:
+	return err;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation
+ * header.
+ *
+ * On entry, the transport header shall point to where the IP header
+ * should be and the network header shall be set to where the IP
+ * header currently is.  skb->data shall point to the start of the
+ * payload.
+ */
+static int
+xfrm_inner_mode_encap_remove(struct xfrm_state *x, struct sk_buff *skb)
+{
+	switch (x->inner_mode->encap) {
+	case XFRM_MODE_BEET:
+		if (x->inner_mode->family == AF_INET)
+			return xfrm4_remove_beet_encap(x, skb);
+		if (x->inner_mode->family == AF_INET6)
+			return xfrm6_remove_beet_encap(x, skb);
+		break;
+	case XFRM_MODE_TUNNEL:
+		if (x->inner_mode->family == AF_INET)
+			return xfrm4_remove_tunnel_encap(x, skb);
+		if (x->inner_mode->family == AF_INET6)
+			return xfrm6_remove_tunnel_encap(x, skb);
+		break;
+	}
+
+	WARN_ON_ONCE(1);
+	return -EOPNOTSUPP;
+}
+
 int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct xfrm_mode *inner_mode = x->inner_mode;
@@ -182,7 +363,7 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
 	}
 
 	skb->protocol = inner_mode->afinfo->eth_proto;
-	return inner_mode->input2(x, skb);
+	return xfrm_inner_mode_encap_remove(x, skb);
 }
 EXPORT_SYMBOL(xfrm_prepare_input);
 
-- 
2.19.2


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

* [PATCH ipsec-next 08/11] xfrm: remove output2 indirection from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (6 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 07/11] xfrm: remove input2 " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-28 22:28   ` kbuild test robot
  2019-03-29  2:15   ` kbuild test robot
  2019-03-27 17:31 ` [PATCH ipsec-next 09/11] xfrm: remove afinfo pointer " Florian Westphal
                   ` (3 subsequent siblings)
  11 siblings, 2 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

similar to previous patch: no external module dependencies,
so we can avoid the indirection by placing this in the core.

This change removes the last indirection from xfrm_mode and the
xfrm4|6_mode_{beet,tunnel}.c modules contain (almost) no code anymore.

Before:
   text    data     bss     dec     hex filename
   3957     136       0    4093     ffd net/xfrm/xfrm_output.o
    587      44       0     631     277 net/ipv4/xfrm4_mode_beet.o
    649      32       0     681     2a9 net/ipv4/xfrm4_mode_tunnel.o
    625      44       0     669     29d net/ipv6/xfrm6_mode_beet.o
    599      32       0     631     277 net/ipv6/xfrm6_mode_tunnel.o
After:
   text    data     bss     dec     hex filename
   5359     184       0    5543    15a7 net/xfrm/xfrm_output.o
    171      24       0     195      c3 net/ipv4/xfrm4_mode_beet.o
    171      24       0     195      c3 net/ipv4/xfrm4_mode_tunnel.o
    172      24       0     196      c4 net/ipv6/xfrm6_mode_beet.o
    172      24       0     196      c4 net/ipv6/xfrm6_mode_tunnel.o

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h           |  13 ---
 net/ipv4/xfrm4_mode_beet.c   |  63 -----------
 net/ipv4/xfrm4_mode_tunnel.c |  49 ---------
 net/ipv6/xfrm6_mode_beet.c   |  58 ----------
 net/ipv6/xfrm6_mode_tunnel.c |  36 ------
 net/xfrm/xfrm_output.c       | 205 ++++++++++++++++++++++++++++++++++-
 6 files changed, 203 insertions(+), 221 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bb2047d774b3..6249d44997e0 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -423,19 +423,6 @@ int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned sh
 int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 
 struct xfrm_mode {
-	/*
-	 * Add encapsulation header.
-	 *
-	 * On exit, the transport header will be set to the start of the
-	 * encapsulation header to be filled in by x->type->output and
-	 * the mac header will be set to the nextheader (protocol for
-	 * IPv4) field of the extension header directly preceding the
-	 * encapsulation header, or in its absence, that of the top IP
-	 * header.  The value of the network header will always point
-	 * to the top IP header while skb->data will point to the payload.
-	 */
-	int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
-
 	struct xfrm_state_afinfo *afinfo;
 	struct module *owner;
 	u8 encap;
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 500960172933..ba84b278e627 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -17,71 +17,8 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 
-static void xfrm4_beet_make_header(struct sk_buff *skb)
-{
-	struct iphdr *iph = ip_hdr(skb);
-
-	iph->ihl = 5;
-	iph->version = 4;
-
-	iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
-	iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
-
-	iph->id = XFRM_MODE_SKB_CB(skb)->id;
-	iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
-	iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
-}
-
-/* Add encapsulation header.
- *
- * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
- */
-static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct ip_beet_phdr *ph;
-	struct iphdr *top_iph;
-	int hdrlen, optlen;
-
-	hdrlen = 0;
-	optlen = XFRM_MODE_SKB_CB(skb)->optlen;
-	if (unlikely(optlen))
-		hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
-
-	skb_set_network_header(skb, -x->props.header_len -
-				    hdrlen + (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
-	if (x->sel.family != AF_INET6)
-		skb->network_header += IPV4_BEET_PHMAXLEN;
-	skb->mac_header = skb->network_header +
-			  offsetof(struct iphdr, protocol);
-	skb->transport_header = skb->network_header + sizeof(*top_iph);
-
-	xfrm4_beet_make_header(skb);
-
-	ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
-
-	top_iph = ip_hdr(skb);
-
-	if (unlikely(optlen)) {
-		BUG_ON(optlen < 0);
-
-		ph->padlen = 4 - (optlen & 4);
-		ph->hdrlen = optlen / 8;
-		ph->nexthdr = top_iph->protocol;
-		if (ph->padlen)
-			memset(ph + 1, IPOPT_NOP, ph->padlen);
-
-		top_iph->protocol = IPPROTO_BEETPH;
-		top_iph->ihl = sizeof(struct iphdr) / 4;
-	}
-
-	top_iph->saddr = x->props.saddr.a4;
-	top_iph->daddr = x->id.daddr.a4;
-
-	return 0;
-}
 
 static struct xfrm_mode xfrm4_beet_mode = {
-	.output2 = xfrm4_beet_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 31645319aaeb..b2b132c800fc 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -15,56 +15,7 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 
-/* Add encapsulation header.
- *
- * The top IP header will be constructed per RFC 2401.
- */
-static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct dst_entry *dst = skb_dst(skb);
-	struct iphdr *top_iph;
-	int flags;
-
-	skb_set_inner_network_header(skb, skb_network_offset(skb));
-	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
-
-	skb_set_network_header(skb, -x->props.header_len);
-	skb->mac_header = skb->network_header +
-			  offsetof(struct iphdr, protocol);
-	skb->transport_header = skb->network_header + sizeof(*top_iph);
-	top_iph = ip_hdr(skb);
-
-	top_iph->ihl = 5;
-	top_iph->version = 4;
-
-	top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
-
-	/* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
-	if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
-		top_iph->tos = 0;
-	else
-		top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
-	top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
-					    XFRM_MODE_SKB_CB(skb)->tos);
-
-	flags = x->props.flags;
-	if (flags & XFRM_STATE_NOECN)
-		IP_ECN_clear(top_iph);
-
-	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
-		0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
-
-	top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
-
-	top_iph->saddr = x->props.saddr.a4;
-	top_iph->daddr = x->id.daddr.a4;
-	ip_select_ident(dev_net(dst->dev), skb, NULL);
-
-	return 0;
-}
-
 static struct xfrm_mode xfrm4_tunnel_mode = {
-	.output2 = xfrm4_mode_tunnel_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index a0537b4f62f8..1c4a76bdd889 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -19,65 +19,7 @@
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static void xfrm6_beet_make_header(struct sk_buff *skb)
-{
-	struct ipv6hdr *iph = ipv6_hdr(skb);
-
-	iph->version = 6;
-
-	memcpy(iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
-	       sizeof(iph->flow_lbl));
-	iph->nexthdr = XFRM_MODE_SKB_CB(skb)->protocol;
-
-	ipv6_change_dsfield(iph, 0, XFRM_MODE_SKB_CB(skb)->tos);
-	iph->hop_limit = XFRM_MODE_SKB_CB(skb)->ttl;
-}
-
-/* Add encapsulation header.
- *
- * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
- */
-static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct ipv6hdr *top_iph;
-	struct ip_beet_phdr *ph;
-	int optlen, hdr_len;
-
-	hdr_len = 0;
-	optlen = XFRM_MODE_SKB_CB(skb)->optlen;
-	if (unlikely(optlen))
-		hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);
-
-	skb_set_network_header(skb, -x->props.header_len - hdr_len);
-	if (x->sel.family != AF_INET6)
-		skb->network_header += IPV4_BEET_PHMAXLEN;
-	skb->mac_header = skb->network_header +
-			  offsetof(struct ipv6hdr, nexthdr);
-	skb->transport_header = skb->network_header + sizeof(*top_iph);
-	ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdr_len);
-
-	xfrm6_beet_make_header(skb);
-
-	top_iph = ipv6_hdr(skb);
-	if (unlikely(optlen)) {
-
-		BUG_ON(optlen < 0);
-
-		ph->padlen = 4 - (optlen & 4);
-		ph->hdrlen = optlen / 8;
-		ph->nexthdr = top_iph->nexthdr;
-		if (ph->padlen)
-			memset(ph + 1, IPOPT_NOP, ph->padlen);
-
-		top_iph->nexthdr = IPPROTO_BEETPH;
-	}
-
-	top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
-	top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
-	return 0;
-}
 static struct xfrm_mode xfrm6_beet_mode = {
-	.output2 = xfrm6_beet_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_BEET,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 79c57decb472..e5c928dd70e3 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -22,43 +22,7 @@
  *
  * The top IP header will be constructed per RFC 2401.
  */
-static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-	struct dst_entry *dst = skb_dst(skb);
-	struct ipv6hdr *top_iph;
-	int dsfield;
-
-	skb_set_inner_network_header(skb, skb_network_offset(skb));
-	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
-
-	skb_set_network_header(skb, -x->props.header_len);
-	skb->mac_header = skb->network_header +
-			  offsetof(struct ipv6hdr, nexthdr);
-	skb->transport_header = skb->network_header + sizeof(*top_iph);
-	top_iph = ipv6_hdr(skb);
-
-	top_iph->version = 6;
-
-	memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
-	       sizeof(top_iph->flow_lbl));
-	top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
-
-	if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
-		dsfield = 0;
-	else
-		dsfield = XFRM_MODE_SKB_CB(skb)->tos;
-	dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
-	if (x->props.flags & XFRM_STATE_NOECN)
-		dsfield &= ~INET_ECN_MASK;
-	ipv6_change_dsfield(top_iph, 0, dsfield);
-	top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
-	top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
-	top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
-	return 0;
-}
-
 static struct xfrm_mode xfrm6_tunnel_mode = {
-	.output2 = xfrm6_mode_tunnel_output,
 	.owner = THIS_MODULE,
 	.encap = XFRM_MODE_TUNNEL,
 	.flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 01eb142ba6d0..1174c7babcce 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -17,8 +17,11 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <net/dst.h>
+#include <net/inet_ecn.h>
 #include <net/xfrm.h>
 
+#include "xfrm_inout.h"
+
 static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb);
 
 static int xfrm_skb_check_space(struct sk_buff *skb)
@@ -137,6 +140,204 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
 #endif
 }
 
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
+ */
+static int xfrm4_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct ip_beet_phdr *ph;
+	struct iphdr *top_iph;
+	int hdrlen, optlen;
+
+	hdrlen = 0;
+	optlen = XFRM_MODE_SKB_CB(skb)->optlen;
+	if (unlikely(optlen))
+		hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
+
+	skb_set_network_header(skb, -x->props.header_len - hdrlen +
+			       (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
+	if (x->sel.family != AF_INET6)
+		skb->network_header += IPV4_BEET_PHMAXLEN;
+	skb->mac_header = skb->network_header +
+			  offsetof(struct iphdr, protocol);
+	skb->transport_header = skb->network_header + sizeof(*top_iph);
+
+	xfrm4_beet_make_header(skb);
+
+	ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
+
+	top_iph = ip_hdr(skb);
+
+	if (unlikely(optlen)) {
+		if (WARN_ON(optlen < 0))
+			return -EINVAL;
+
+		ph->padlen = 4 - (optlen & 4);
+		ph->hdrlen = optlen / 8;
+		ph->nexthdr = top_iph->protocol;
+		if (ph->padlen)
+			memset(ph + 1, IPOPT_NOP, ph->padlen);
+
+		top_iph->protocol = IPPROTO_BEETPH;
+		top_iph->ihl = sizeof(struct iphdr) / 4;
+	}
+
+	top_iph->saddr = x->props.saddr.a4;
+	top_iph->daddr = x->id.daddr.a4;
+
+	return 0;
+}
+
+static int xfrm6_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct ipv6hdr *top_iph;
+	struct ip_beet_phdr *ph;
+	int optlen, hdr_len;
+
+	hdr_len = 0;
+	optlen = XFRM_MODE_SKB_CB(skb)->optlen;
+	if (unlikely(optlen))
+		hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);
+
+	skb_set_network_header(skb, -x->props.header_len - hdr_len);
+	if (x->sel.family != AF_INET6)
+		skb->network_header += IPV4_BEET_PHMAXLEN;
+	skb->mac_header = skb->network_header +
+			  offsetof(struct ipv6hdr, nexthdr);
+	skb->transport_header = skb->network_header + sizeof(*top_iph);
+	ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdr_len);
+
+	xfrm6_beet_make_header(skb);
+
+	top_iph = ipv6_hdr(skb);
+	if (unlikely(optlen)) {
+		if (WARN_ON(optlen < 0))
+			return -EINVAL;
+
+		ph->padlen = 4 - (optlen & 4);
+		ph->hdrlen = optlen / 8;
+		ph->nexthdr = top_iph->nexthdr;
+		if (ph->padlen)
+			memset(ph + 1, IPOPT_NOP, ph->padlen);
+
+		top_iph->nexthdr = IPPROTO_BEETPH;
+	}
+
+	top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
+	top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
+	return 0;
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.
+ */
+static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+	struct iphdr *top_iph;
+	int flags;
+
+	skb_set_inner_network_header(skb, skb_network_offset(skb));
+	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
+
+	skb_set_network_header(skb, -x->props.header_len);
+	skb->mac_header = skb->network_header +
+			  offsetof(struct iphdr, protocol);
+	skb->transport_header = skb->network_header + sizeof(*top_iph);
+	top_iph = ip_hdr(skb);
+
+	top_iph->ihl = 5;
+	top_iph->version = 4;
+
+	top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
+
+	/* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
+	if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
+		top_iph->tos = 0;
+	else
+		top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
+	top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
+					    XFRM_MODE_SKB_CB(skb)->tos);
+
+	flags = x->props.flags;
+	if (flags & XFRM_STATE_NOECN)
+		IP_ECN_clear(top_iph);
+
+	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+		0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
+
+	top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
+
+	top_iph->saddr = x->props.saddr.a4;
+	top_iph->daddr = x->id.daddr.a4;
+	ip_select_ident(dev_net(dst->dev), skb, NULL);
+
+	return 0;
+}
+
+static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+	struct ipv6hdr *top_iph;
+	int dsfield;
+
+	skb_set_inner_network_header(skb, skb_network_offset(skb));
+	skb_set_inner_transport_header(skb, skb_transport_offset(skb));
+
+	skb_set_network_header(skb, -x->props.header_len);
+	skb->mac_header = skb->network_header +
+			  offsetof(struct ipv6hdr, nexthdr);
+	skb->transport_header = skb->network_header + sizeof(*top_iph);
+	top_iph = ipv6_hdr(skb);
+
+	top_iph->version = 6;
+
+	memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
+	       sizeof(top_iph->flow_lbl));
+	top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
+
+	if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
+		dsfield = 0;
+	else
+		dsfield = XFRM_MODE_SKB_CB(skb)->tos;
+	dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
+	if (x->props.flags & XFRM_STATE_NOECN)
+		dsfield &= ~INET_ECN_MASK;
+	ipv6_change_dsfield(top_iph, 0, dsfield);
+	top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
+	top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
+	top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
+	return 0;
+}
+
+static int xfrm4_outer_encap_add(struct xfrm_state *x, struct sk_buff *skb)
+{
+	switch (x->inner_mode->encap) {
+	case XFRM_MODE_BEET:
+		return xfrm4_beet_encap_add(x, skb);
+	case XFRM_MODE_TUNNEL:
+		return xfrm4_tunnel_encap_add(x, skb);
+	}
+
+	WARN_ON_ONCE(1);
+	return -EOPNOTSUPP;
+}
+
+static int xfrm6_outer_encap_add(struct xfrm_state *x, struct sk_buff *skb)
+{
+	switch (x->inner_mode->encap) {
+	case XFRM_MODE_BEET:
+		return xfrm6_beet_encap_add(x, skb);
+	case XFRM_MODE_TUNNEL:
+		return xfrm6_tunnel_encap_add(x, skb);
+	}
+
+	WARN_ON_ONCE(1);
+	return -EOPNOTSUPP;
+}
+
 static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
@@ -148,7 +349,7 @@ static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
 	skb->protocol = htons(ETH_P_IP);
 
-	return x->outer_mode->output2(x, skb);
+	return xfrm4_outer_encap_add(x, skb);
 }
 
 static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
@@ -162,7 +363,7 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 	skb->ignore_df = 1;
 	skb->protocol = htons(ETH_P_IPV6);
 
-	return x->outer_mode->output2(x, skb);
+	return xfrm6_outer_encap_add(x, skb);
 }
 
 static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
-- 
2.19.2


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

* [PATCH ipsec-next 09/11] xfrm: remove afinfo pointer from xfrm_mode
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (7 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 08/11] xfrm: remove output2 " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-28 14:13   ` Sabrina Dubroca
  2019-03-27 17:31 ` [PATCH ipsec-next 10/11] xfrm: make xfrm modes builtin Florian Westphal
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

Adds an EXPORT_SYMBOL for afinfo_get_rcu, as it will now be called from
ipv6 in case of CONFIG_IPV6=m.

This change has virtually no effect on vmlinux size, but it reduces
afinfo size and allows followup patch to make xfrm modes const.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h      |  1 -
 net/ipv4/xfrm4_output.c | 11 ++++++++++-
 net/ipv6/xfrm6_output.c | 21 +++++++++++++++++++--
 net/xfrm/xfrm_input.c   | 28 ++++++++++++++++++++++------
 net/xfrm/xfrm_output.c  | 12 +++++++++++-
 net/xfrm/xfrm_policy.c  |  7 ++++++-
 net/xfrm/xfrm_state.c   |  4 ++--
 7 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 6249d44997e0..bbce45f5ca6d 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -423,7 +423,6 @@ int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned sh
 int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 
 struct xfrm_mode {
-	struct xfrm_state_afinfo *afinfo;
 	struct module *owner;
 	u8 encap;
 	u8 family;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 6802d1aee424..cff048ad8562 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -72,6 +72,8 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
 static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
 	struct xfrm_state *x = skb_dst(skb)->xfrm;
+	const struct xfrm_state_afinfo *afinfo;
+	int ret = -EAFNOSUPPORT;
 
 #ifdef CONFIG_NETFILTER
 	if (!x) {
@@ -80,7 +82,14 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 	}
 #endif
 
-	return x->outer_mode->afinfo->output_finish(sk, skb);
+	rcu_read_lock();
+	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
+	if (afinfo)
+		ret = afinfo->output_finish(sk, skb);
+	else
+		kfree_skb(skb);
+	rcu_read_unlock();
+	return ret;
 }
 
 int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 2b663d2ffdcd..82168de60e6b 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -122,11 +122,27 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
 	return xfrm_output(sk, skb);
 }
 
+static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk, struct sk_buff *skb)
+{
+	const struct xfrm_state_afinfo *afinfo;
+	int ret = -EAFNOSUPPORT;
+
+	rcu_read_lock();
+	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
+	if (afinfo)
+		ret = afinfo->output_finish(sk, skb);
+	else
+		kfree_skb(skb);
+	rcu_read_unlock();
+
+	return ret;
+}
+
 static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
 	struct xfrm_state *x = skb_dst(skb)->xfrm;
 
-	return x->outer_mode->afinfo->output_finish(sk, skb);
+	return __xfrm6_output_state_finish(x, sk, skb);
 }
 
 static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
@@ -168,7 +184,8 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 				    __xfrm6_output_finish);
 
 skip_frag:
-	return x->outer_mode->afinfo->output_finish(sk, skb);
+
+	return __xfrm6_output_state_finish(x, sk, skb);
 }
 
 int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 065ace68b26a..a6db51cee1cf 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -350,19 +350,29 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x, struct sk_buff *skb)
 int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct xfrm_mode *inner_mode = x->inner_mode;
-	int err;
+	const struct xfrm_state_afinfo *afinfo;
+	int err = -EAFNOSUPPORT;
 
-	err = x->outer_mode->afinfo->extract_input(x, skb);
-	if (err)
+	rcu_read_lock();
+	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
+	if (afinfo)
+		err = afinfo->extract_input(x, skb);
+
+	if (err) {
+		rcu_read_unlock();
 		return err;
+	}
 
 	if (x->sel.family == AF_UNSPEC) {
 		inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
-		if (inner_mode == NULL)
+		if (!inner_mode) {
+			rcu_read_unlock();
 			return -EAFNOSUPPORT;
+		}
 	}
 
-	skb->protocol = inner_mode->afinfo->eth_proto;
+	skb->protocol = afinfo->eth_proto;
+	rcu_read_unlock();
 	return xfrm_inner_mode_encap_remove(x, skb);
 }
 EXPORT_SYMBOL(xfrm_prepare_input);
@@ -437,6 +447,7 @@ static int xfrm_inner_mode_input(struct xfrm_state *x, struct sk_buff *skb)
 
 int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 {
+	const struct xfrm_state_afinfo *afinfo;
 	struct net *net = dev_net(skb->dev);
 	int err;
 	__be32 seq;
@@ -702,7 +713,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		if (xo)
 			xfrm_gro = xo->flags & XFRM_GRO;
 
-		err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);
+		err = -EAFNOSUPPORT;
+		rcu_read_lock();
+		afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode->family);
+		if (afinfo)
+			err = afinfo->transport_finish(skb, xfrm_gro || async);
+		rcu_read_unlock();
 		if (xfrm_gro) {
 			sp = skb_sec_path(skb);
 			if (sp)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 1174c7babcce..3e4b3fdf34a4 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -611,7 +611,10 @@ EXPORT_SYMBOL_GPL(xfrm_output);
 
 int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 {
+	const struct xfrm_state_afinfo *afinfo;
 	struct xfrm_mode *inner_mode;
+	int err = -EAFNOSUPPORT;
+
 	if (x->sel.family == AF_UNSPEC)
 		inner_mode = xfrm_ip2inner_mode(x,
 				xfrm_af2proto(skb_dst(skb)->ops->family));
@@ -620,7 +623,14 @@ int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 
 	if (inner_mode == NULL)
 		return -EAFNOSUPPORT;
-	return inner_mode->afinfo->extract_output(x, skb);
+
+	rcu_read_lock();
+	afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
+	if (afinfo)
+		err = afinfo->extract_output(x, skb);
+	rcu_read_unlock();
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(xfrm_inner_extract_output);
 
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8d1a898d0ba5..e82e022182ae 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2545,6 +2545,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 					    const struct flowi *fl,
 					    struct dst_entry *dst)
 {
+	const struct xfrm_state_afinfo *afinfo;
 	struct net *net = xp_net(policy);
 	unsigned long now = jiffies;
 	struct net_device *dev;
@@ -2622,7 +2623,11 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 		dst1->lastuse = now;
 
 		dst1->input = dst_discard;
-		dst1->output = inner_mode->afinfo->output;
+
+		rcu_read_lock();
+		afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
+		dst1->output = afinfo ? afinfo->output : dst_discard_out;
+		rcu_read_unlock();
 
 		xdst_prev = xdst;
 
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index c32394b59776..358b09f0d018 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -354,7 +354,6 @@ int xfrm_register_mode(struct xfrm_mode *mode)
 	if (!try_module_get(afinfo->owner))
 		goto out;
 
-	mode->afinfo = afinfo;
 	modemap[mode->encap] = mode;
 	err = 0;
 
@@ -378,7 +377,7 @@ void xfrm_unregister_mode(struct xfrm_mode *mode)
 	spin_lock_bh(&xfrm_mode_lock);
 	if (likely(modemap[mode->encap] == mode)) {
 		modemap[mode->encap] = NULL;
-		module_put(mode->afinfo->owner);
+		module_put(afinfo->owner);
 	}
 
 	spin_unlock_bh(&xfrm_mode_lock);
@@ -2188,6 +2187,7 @@ struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family)
 
 	return rcu_dereference(xfrm_state_afinfo[family]);
 }
+EXPORT_SYMBOL_GPL(xfrm_state_afinfo_get_rcu);
 
 struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
 {
-- 
2.19.2


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

* [PATCH ipsec-next 10/11] xfrm: make xfrm modes builtin
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (8 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 09/11] xfrm: remove afinfo pointer " Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-29  3:54   ` kbuild test robot
  2019-03-27 17:31 ` [PATCH ipsec-next 11/11] xfrm: store xfrm_mode directly, not its address Florian Westphal
  2019-03-28 11:42 ` [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Benedict Wong
  11 siblings, 1 reply; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

after previous changes, xfrm_mode contains no function pointers anymore
and all modules defining such struct contain no code except an init/exit
functions to register the xfrm_mode struct with the xfrm core.

Just place the xfrm modes core and remove the modules,
the run-time xfrm_mode register/unregister functionality is removed.

Before:

    text    data     bss      dec filename
    7523     200    2364    10087 net/xfrm/xfrm_input.o
   40003     628     440    41071 net/xfrm/xfrm_state.o
15730338 6937080 4046908 26714326 vmlinux

    7389     200    2364    9953  net/xfrm/xfrm_input.o
   40574     656     440   41670  net/xfrm/xfrm_state.o
15730084 6937068 4046908 26714060 vmlinux

The xfrm*_mode_{transport,tunnel,beet} modules are gone.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h                 |  13 +--
 net/ipv4/Kconfig                   |  29 +-----
 net/ipv4/Makefile                  |   3 -
 net/ipv4/ip_vti.c                  |   2 +-
 net/ipv4/xfrm4_mode_beet.c         |  41 --------
 net/ipv4/xfrm4_mode_transport.c    |  36 -------
 net/ipv4/xfrm4_mode_tunnel.c       |  38 -------
 net/ipv6/Kconfig                   |  35 +------
 net/ipv6/Makefile                  |   4 -
 net/ipv6/ip6_vti.c                 |   2 +-
 net/ipv6/xfrm6_mode_beet.c         |  42 --------
 net/ipv6/xfrm6_mode_ro.c           |  55 ----------
 net/ipv6/xfrm6_mode_transport.c    |  37 -------
 net/ipv6/xfrm6_mode_tunnel.c       |  45 --------
 net/xfrm/xfrm_input.c              |  12 +--
 net/xfrm/xfrm_interface.c          |   2 +-
 net/xfrm/xfrm_output.c             |  14 +--
 net/xfrm/xfrm_policy.c             |   2 +-
 net/xfrm/xfrm_state.c              | 158 +++++++++++------------------
 tools/testing/selftests/net/config |   2 -
 20 files changed, 74 insertions(+), 498 deletions(-)
 delete mode 100644 net/ipv4/xfrm4_mode_beet.c
 delete mode 100644 net/ipv4/xfrm4_mode_transport.c
 delete mode 100644 net/ipv4/xfrm4_mode_tunnel.c
 delete mode 100644 net/ipv6/xfrm6_mode_beet.c
 delete mode 100644 net/ipv6/xfrm6_mode_ro.c
 delete mode 100644 net/ipv6/xfrm6_mode_transport.c
 delete mode 100644 net/ipv6/xfrm6_mode_tunnel.c

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bbce45f5ca6d..940b670a7999 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -234,9 +234,9 @@ struct xfrm_state {
 	/* Reference to data common to all the instances of this
 	 * transformer. */
 	const struct xfrm_type	*type;
-	struct xfrm_mode	*inner_mode;
-	struct xfrm_mode	*inner_mode_iaf;
-	struct xfrm_mode	*outer_mode;
+	const struct xfrm_mode	*inner_mode;
+	const struct xfrm_mode	*inner_mode_iaf;
+	const struct xfrm_mode	*outer_mode;
 
 	const struct xfrm_type_offload	*type_offload;
 
@@ -347,7 +347,6 @@ struct xfrm_state_afinfo {
 	struct module			*owner;
 	const struct xfrm_type		*type_map[IPPROTO_MAX];
 	const struct xfrm_type_offload	*type_offload_map[IPPROTO_MAX];
-	struct xfrm_mode		*mode_map[XFRM_MODE_MAX];
 
 	int			(*init_flags)(struct xfrm_state *x);
 	void			(*init_tempsel)(struct xfrm_selector *sel,
@@ -423,7 +422,6 @@ int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned sh
 int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 
 struct xfrm_mode {
-	struct module *owner;
 	u8 encap;
 	u8 family;
 	u8 flags;
@@ -434,9 +432,6 @@ enum {
 	XFRM_MODE_FLAG_TUNNEL = 1,
 };
 
-int xfrm_register_mode(struct xfrm_mode *mode);
-void xfrm_unregister_mode(struct xfrm_mode *mode);
-
 static inline int xfrm_af2proto(unsigned int family)
 {
 	switch(family) {
@@ -449,7 +444,7 @@ static inline int xfrm_af2proto(unsigned int family)
 	}
 }
 
-static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
+static inline const struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
 {
 	if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
 	    (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 32cae39cdff6..8108e97d4285 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -304,7 +304,7 @@ config NET_IPVTI
 	tristate "Virtual (secure) IP: tunneling"
 	select INET_TUNNEL
 	select NET_IP_TUNNEL
-	depends on INET_XFRM_MODE_TUNNEL
+	select XFRM
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -396,33 +396,6 @@ config INET_TUNNEL
 	tristate
 	default n
 
-config INET_XFRM_MODE_TRANSPORT
-	tristate "IP: IPsec transport mode"
-	default y
-	select XFRM
-	---help---
-	  Support for IPsec transport mode.
-
-	  If unsure, say Y.
-
-config INET_XFRM_MODE_TUNNEL
-	tristate "IP: IPsec tunnel mode"
-	default y
-	select XFRM
-	---help---
-	  Support for IPsec tunnel mode.
-
-	  If unsure, say Y.
-
-config INET_XFRM_MODE_BEET
-	tristate "IP: IPsec BEET mode"
-	default y
-	select XFRM
-	---help---
-	  Support for IPsec BEET mode.
-
-	  If unsure, say Y.
-
 config INET_DIAG
 	tristate "INET: socket monitoring interface"
 	default y
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 58629314eae9..000a61994c8f 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -37,10 +37,7 @@ obj-$(CONFIG_INET_ESP) += esp4.o
 obj-$(CONFIG_INET_ESP_OFFLOAD) += esp4_offload.o
 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
 obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
-obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.o
 obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
-obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
-obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_NETFILTER)	+= netfilter.o netfilter/
 obj-$(CONFIG_INET_DIAG) += inet_diag.o
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 3f3f6d6be318..91926c9a3bc9 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -107,7 +107,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
 	struct net_device *dev;
 	struct pcpu_sw_netstats *tstats;
 	struct xfrm_state *x;
-	struct xfrm_mode *inner_mode;
+	const struct xfrm_mode *inner_mode;
 	struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
 	u32 orig_mark = skb->mark;
 	int ret;
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
deleted file mode 100644
index ba84b278e627..000000000000
--- a/net/ipv4/xfrm4_mode_beet.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * xfrm4_mode_beet.c - BEET mode encapsulation for IPv4.
- *
- * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com>
- *                    Miika Komu     <miika@iki.fi>
- *                    Herbert Xu     <herbert@gondor.apana.org.au>
- *                    Abhinav Pathak <abhinav.pathak@hiit.fi>
- *                    Jeff Ahrenholz <ahrenholz@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/stringify.h>
-#include <net/dst.h>
-#include <net/ip.h>
-#include <net/xfrm.h>
-
-
-static struct xfrm_mode xfrm4_beet_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_BEET,
-	.flags = XFRM_MODE_FLAG_TUNNEL,
-	.family = AF_INET,
-};
-
-static int __init xfrm4_beet_init(void)
-{
-	return xfrm_register_mode(&xfrm4_beet_mode);
-}
-
-static void __exit xfrm4_beet_exit(void)
-{
-	xfrm_unregister_mode(&xfrm4_beet_mode);
-}
-
-module_init(xfrm4_beet_init);
-module_exit(xfrm4_beet_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_BEET);
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
deleted file mode 100644
index 397863ea762b..000000000000
--- a/net/ipv4/xfrm4_mode_transport.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
- *
- * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/stringify.h>
-#include <net/dst.h>
-#include <net/ip.h>
-#include <net/xfrm.h>
-#include <net/protocol.h>
-
-static struct xfrm_mode xfrm4_transport_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_TRANSPORT,
-	.family = AF_INET,
-};
-
-static int __init xfrm4_transport_init(void)
-{
-	return xfrm_register_mode(&xfrm4_transport_mode);
-}
-
-static void __exit xfrm4_transport_exit(void)
-{
-	xfrm_unregister_mode(&xfrm4_transport_mode);
-}
-
-module_init(xfrm4_transport_init);
-module_exit(xfrm4_transport_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
deleted file mode 100644
index b2b132c800fc..000000000000
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
- *
- * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
- */
-
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/stringify.h>
-#include <net/dst.h>
-#include <net/inet_ecn.h>
-#include <net/ip.h>
-#include <net/xfrm.h>
-
-static struct xfrm_mode xfrm4_tunnel_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_TUNNEL,
-	.flags = XFRM_MODE_FLAG_TUNNEL,
-	.family = AF_INET,
-};
-
-static int __init xfrm4_mode_tunnel_init(void)
-{
-	return xfrm_register_mode(&xfrm4_tunnel_mode);
-}
-
-static void __exit xfrm4_mode_tunnel_exit(void)
-{
-	xfrm_unregister_mode(&xfrm4_tunnel_mode);
-}
-
-module_init(xfrm4_mode_tunnel_init);
-module_exit(xfrm4_mode_tunnel_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 613282c65a10..cd915e332c98 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -135,44 +135,11 @@ config INET6_TUNNEL
 	tristate
 	default n
 
-config INET6_XFRM_MODE_TRANSPORT
-	tristate "IPv6: IPsec transport mode"
-	default IPV6
-	select XFRM
-	---help---
-	  Support for IPsec transport mode.
-
-	  If unsure, say Y.
-
-config INET6_XFRM_MODE_TUNNEL
-	tristate "IPv6: IPsec tunnel mode"
-	default IPV6
-	select XFRM
-	---help---
-	  Support for IPsec tunnel mode.
-
-	  If unsure, say Y.
-
-config INET6_XFRM_MODE_BEET
-	tristate "IPv6: IPsec BEET mode"
-	default IPV6
-	select XFRM
-	---help---
-	  Support for IPsec BEET mode.
-
-	  If unsure, say Y.
-
-config INET6_XFRM_MODE_ROUTEOPTIMIZATION
-	tristate "IPv6: MIPv6 route optimization mode"
-	select XFRM
-	---help---
-	  Support for MIPv6 route optimization mode.
-
 config IPV6_VTI
 tristate "Virtual (secure) IPv6: tunneling"
 	select IPV6_TUNNEL
 	select NET_IP_TUNNEL
-	depends on INET6_XFRM_MODE_TUNNEL
+	select XFRM
 	---help---
 	Tunneling means encapsulating data of one protocol type within
 	another protocol and sending it over a channel that understands the
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index e0026fa1261b..8ccf35514015 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -35,10 +35,6 @@ obj-$(CONFIG_INET6_ESP_OFFLOAD) += esp6_offload.o
 obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
 obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
 obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
-obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
-obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
-obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
-obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
 obj-$(CONFIG_IPV6_MIP6) += mip6.o
 obj-$(CONFIG_IPV6_ILA) += ila/
 obj-$(CONFIG_NETFILTER)	+= netfilter/
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 369803c581b7..71ec5e60cf8f 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -342,7 +342,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
 	struct net_device *dev;
 	struct pcpu_sw_netstats *tstats;
 	struct xfrm_state *x;
-	struct xfrm_mode *inner_mode;
+	const struct xfrm_mode *inner_mode;
 	struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
 	u32 orig_mark = skb->mark;
 	int ret;
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
deleted file mode 100644
index 1c4a76bdd889..000000000000
--- a/net/ipv6/xfrm6_mode_beet.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * xfrm6_mode_beet.c - BEET mode encapsulation for IPv6.
- *
- * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com>
- *                    Miika Komu     <miika@iki.fi>
- *                    Herbert Xu     <herbert@gondor.apana.org.au>
- *                    Abhinav Pathak <abhinav.pathak@hiit.fi>
- *                    Jeff Ahrenholz <ahrenholz@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/stringify.h>
-#include <net/dsfield.h>
-#include <net/dst.h>
-#include <net/inet_ecn.h>
-#include <net/ipv6.h>
-#include <net/xfrm.h>
-
-static struct xfrm_mode xfrm6_beet_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_BEET,
-	.flags = XFRM_MODE_FLAG_TUNNEL,
-	.family = AF_INET6,
-};
-
-static int __init xfrm6_beet_init(void)
-{
-	return xfrm_register_mode(&xfrm6_beet_mode);
-}
-
-static void __exit xfrm6_beet_exit(void)
-{
-	xfrm_unregister_mode(&xfrm6_beet_mode);
-}
-
-module_init(xfrm6_beet_init);
-module_exit(xfrm6_beet_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_BEET);
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
deleted file mode 100644
index d0a6a4dbd689..000000000000
--- a/net/ipv6/xfrm6_mode_ro.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * xfrm6_mode_ro.c - Route optimization mode for IPv6.
- *
- * Copyright (C)2003-2006 Helsinki University of Technology
- * Copyright (C)2003-2006 USAGI/WIDE Project
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-/*
- * Authors:
- *	Noriaki TAKAMIYA @USAGI
- *	Masahide NAKAMURA @USAGI
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/stringify.h>
-#include <linux/time.h>
-#include <net/ipv6.h>
-#include <net/xfrm.h>
-
-static struct xfrm_mode xfrm6_ro_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_ROUTEOPTIMIZATION,
-	.family = AF_INET6,
-};
-
-static int __init xfrm6_ro_init(void)
-{
-	return xfrm_register_mode(&xfrm6_ro_mode);
-}
-
-static void __exit xfrm6_ro_exit(void)
-{
-	xfrm_unregister_mode(&xfrm6_ro_mode);
-}
-
-module_init(xfrm6_ro_init);
-module_exit(xfrm6_ro_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_ROUTEOPTIMIZATION);
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
deleted file mode 100644
index d90c934c2f1a..000000000000
--- a/net/ipv6/xfrm6_mode_transport.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6.
- *
- * Copyright (C) 2002 USAGI/WIDE Project
- * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/stringify.h>
-#include <net/dst.h>
-#include <net/ipv6.h>
-#include <net/xfrm.h>
-#include <net/protocol.h>
-
-static struct xfrm_mode xfrm6_transport_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_TRANSPORT,
-	.family = AF_INET6,
-};
-
-static int __init xfrm6_transport_init(void)
-{
-	return xfrm_register_mode(&xfrm6_transport_mode);
-}
-
-static void __exit xfrm6_transport_exit(void)
-{
-	xfrm_unregister_mode(&xfrm6_transport_mode);
-}
-
-module_init(xfrm6_transport_init);
-module_exit(xfrm6_transport_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
deleted file mode 100644
index e5c928dd70e3..000000000000
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6.
- *
- * Copyright (C) 2002 USAGI/WIDE Project
- * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
- */
-
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/stringify.h>
-#include <net/dsfield.h>
-#include <net/dst.h>
-#include <net/inet_ecn.h>
-#include <net/ip6_route.h>
-#include <net/ipv6.h>
-#include <net/xfrm.h>
-
-/* Add encapsulation header.
- *
- * The top IP header will be constructed per RFC 2401.
- */
-static struct xfrm_mode xfrm6_tunnel_mode = {
-	.owner = THIS_MODULE,
-	.encap = XFRM_MODE_TUNNEL,
-	.flags = XFRM_MODE_FLAG_TUNNEL,
-	.family = AF_INET6,
-};
-
-static int __init xfrm6_mode_tunnel_init(void)
-{
-	return xfrm_register_mode(&xfrm6_tunnel_mode);
-}
-
-static void __exit xfrm6_mode_tunnel_exit(void)
-{
-	xfrm_unregister_mode(&xfrm6_tunnel_mode);
-}
-
-module_init(xfrm6_mode_tunnel_init);
-module_exit(xfrm6_mode_tunnel_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index a6db51cee1cf..31c17fc8b49f 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -349,7 +349,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x, struct sk_buff *skb)
 
 int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	struct xfrm_mode *inner_mode = x->inner_mode;
+	const struct xfrm_mode *inner_mode = x->inner_mode;
 	const struct xfrm_state_afinfo *afinfo;
 	int err = -EAFNOSUPPORT;
 
@@ -387,7 +387,6 @@ EXPORT_SYMBOL(xfrm_prepare_input);
  */
 static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET4_XFRM_MODE_TRANSPORT)
 	int ihl = skb->data - skb_transport_header(skb);
 
 	if (skb->transport_header != skb->network_header) {
@@ -398,14 +397,10 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
 	ip_hdr(skb)->tot_len = htons(skb->len + ihl);
 	skb_reset_transport_header(skb);
 	return 0;
-#else
-	return -EOPNOTSUPP;
-#endif
 }
 
 static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
 	int ihl = skb->data - skb_transport_header(skb);
 
 	if (skb->transport_header != skb->network_header) {
@@ -417,9 +412,6 @@ static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
 					   sizeof(struct ipv6hdr));
 	skb_reset_transport_header(skb);
 	return 0;
-#else
-	return -EOPNOTSUPP;
-#endif
 }
 
 static int xfrm_inner_mode_input(struct xfrm_state *x, struct sk_buff *skb)
@@ -449,12 +441,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 {
 	const struct xfrm_state_afinfo *afinfo;
 	struct net *net = dev_net(skb->dev);
+	const struct xfrm_mode *inner_mode;
 	int err;
 	__be32 seq;
 	__be32 seq_hi;
 	struct xfrm_state *x = NULL;
 	xfrm_address_t *daddr;
-	struct xfrm_mode *inner_mode;
 	u32 mark = skb->mark;
 	unsigned int family = AF_UNSPEC;
 	int decaps = 0;
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 93efb0965e7d..4fc49dbf3edf 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -244,8 +244,8 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
 
 static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
 {
+	const struct xfrm_mode *inner_mode;
 	struct pcpu_sw_netstats *tstats;
-	struct xfrm_mode *inner_mode;
 	struct net_device *dev;
 	struct xfrm_state *x;
 	struct xfrm_if *xi;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 3e4b3fdf34a4..6eaaf762db8e 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -60,7 +60,6 @@ static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
  */
 static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET_XFRM_MODE_TRANSPORT)
 	struct iphdr *iph = ip_hdr(skb);
 	int ihl = iph->ihl * 4;
 
@@ -73,9 +72,6 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 	__skb_pull(skb, ihl);
 	memmove(skb_network_header(skb), iph, ihl);
 	return 0;
-#else
-	return -EOPNOTSUPP;
-#endif
 }
 
 /* Add encapsulation header.
@@ -85,7 +81,6 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
  */
 static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
 	struct ipv6hdr *iph;
 	u8 *prevhdr;
 	int hdr_len;
@@ -103,9 +98,6 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 	__skb_pull(skb, hdr_len);
 	memmove(ipv6_hdr(skb), iph, hdr_len);
 	return 0;
-#else
-	return -EOPNOTSUPP;
-#endif
 }
 
 /* Add route optimization header space.
@@ -115,7 +107,6 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
  */
 static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION)
 	struct ipv6hdr *iph;
 	u8 *prevhdr;
 	int hdr_len;
@@ -135,9 +126,6 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
 	x->lastused = ktime_get_real_seconds();
 
 	return 0;
-#else
-	return -EOPNOTSUPP;
-#endif
 }
 
 /* Add encapsulation header.
@@ -612,7 +600,7 @@ EXPORT_SYMBOL_GPL(xfrm_output);
 int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	const struct xfrm_state_afinfo *afinfo;
-	struct xfrm_mode *inner_mode;
+	const struct xfrm_mode *inner_mode;
 	int err = -EAFNOSUPPORT;
 
 	if (x->sel.family == AF_UNSPEC)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e82e022182ae..b5dce0c6bdcd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2546,10 +2546,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 					    struct dst_entry *dst)
 {
 	const struct xfrm_state_afinfo *afinfo;
+	const struct xfrm_mode *inner_mode;
 	struct net *net = xp_net(policy);
 	unsigned long now = jiffies;
 	struct net_device *dev;
-	struct xfrm_mode *inner_mode;
 	struct xfrm_dst *xdst_prev = NULL;
 	struct xfrm_dst *xdst0 = NULL;
 	int i = 0;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 358b09f0d018..ace26f6dc790 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -330,92 +330,67 @@ static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
 	module_put(type->owner);
 }
 
-static DEFINE_SPINLOCK(xfrm_mode_lock);
-int xfrm_register_mode(struct xfrm_mode *mode)
-{
-	struct xfrm_state_afinfo *afinfo;
-	struct xfrm_mode **modemap;
-	int err;
-
-	if (unlikely(mode->encap >= XFRM_MODE_MAX))
-		return -EINVAL;
-
-	afinfo = xfrm_state_get_afinfo(mode->family);
-	if (unlikely(afinfo == NULL))
-		return -EAFNOSUPPORT;
-
-	err = -EEXIST;
-	modemap = afinfo->mode_map;
-	spin_lock_bh(&xfrm_mode_lock);
-	if (modemap[mode->encap])
-		goto out;
-
-	err = -ENOENT;
-	if (!try_module_get(afinfo->owner))
-		goto out;
-
-	modemap[mode->encap] = mode;
-	err = 0;
-
-out:
-	spin_unlock_bh(&xfrm_mode_lock);
-	rcu_read_unlock();
-	return err;
-}
-EXPORT_SYMBOL(xfrm_register_mode);
-
-void xfrm_unregister_mode(struct xfrm_mode *mode)
-{
-	struct xfrm_state_afinfo *afinfo;
-	struct xfrm_mode **modemap;
-
-	afinfo = xfrm_state_get_afinfo(mode->family);
-	if (WARN_ON_ONCE(!afinfo))
-		return;
-
-	modemap = afinfo->mode_map;
-	spin_lock_bh(&xfrm_mode_lock);
-	if (likely(modemap[mode->encap] == mode)) {
-		modemap[mode->encap] = NULL;
-		module_put(afinfo->owner);
-	}
-
-	spin_unlock_bh(&xfrm_mode_lock);
-	rcu_read_unlock();
-}
-EXPORT_SYMBOL(xfrm_unregister_mode);
-
-static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
-{
-	struct xfrm_state_afinfo *afinfo;
-	struct xfrm_mode *mode;
-	int modload_attempted = 0;
+static const struct xfrm_mode xfrm4_mode_map[XFRM_MODE_MAX] = {
+	[XFRM_MODE_BEET] = {
+		.encap = XFRM_MODE_BEET,
+		.flags = XFRM_MODE_FLAG_TUNNEL,
+		.family = AF_INET,
+	},
+	[XFRM_MODE_TRANSPORT] = {
+		.encap = XFRM_MODE_TRANSPORT,
+		.family = AF_INET,
+	},
+	[XFRM_MODE_TUNNEL] = {
+		.encap = XFRM_MODE_TUNNEL,
+		.flags = XFRM_MODE_FLAG_TUNNEL,
+		.family = AF_INET,
+	},
+};
+
+static const struct xfrm_mode xfrm6_mode_map[XFRM_MODE_MAX] = {
+	[XFRM_MODE_BEET] = {
+		.encap = XFRM_MODE_BEET,
+		.flags = XFRM_MODE_FLAG_TUNNEL,
+		.family = AF_INET6,
+	},
+	[XFRM_MODE_ROUTEOPTIMIZATION] = {
+		.encap = XFRM_MODE_ROUTEOPTIMIZATION,
+		.family = AF_INET6,
+	},
+	[XFRM_MODE_TRANSPORT] = {
+		.encap = XFRM_MODE_TRANSPORT,
+		.family = AF_INET6,
+	},
+	[XFRM_MODE_TUNNEL] = {
+		.encap = XFRM_MODE_TUNNEL,
+		.flags = XFRM_MODE_FLAG_TUNNEL,
+		.family = AF_INET6,
+	},
+};
+
+static const struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
+{
+	const struct xfrm_mode *mode;
 
 	if (unlikely(encap >= XFRM_MODE_MAX))
 		return NULL;
 
-retry:
-	afinfo = xfrm_state_get_afinfo(family);
-	if (unlikely(afinfo == NULL))
-		return NULL;
-
-	mode = READ_ONCE(afinfo->mode_map[encap]);
-	if (unlikely(mode && !try_module_get(mode->owner)))
-		mode = NULL;
-
-	rcu_read_unlock();
-	if (!mode && !modload_attempted) {
-		request_module("xfrm-mode-%d-%d", family, encap);
-		modload_attempted = 1;
-		goto retry;
+	switch (family) {
+	case AF_INET:
+		mode = &xfrm4_mode_map[encap];
+		if (mode->family == family)
+			return mode;
+		break;
+	case AF_INET6:
+		mode = &xfrm6_mode_map[encap];
+		if (mode->family == family)
+			return mode;
+		break;
+	default:
+		break;
 	}
 
-	return mode;
-}
-
-static void xfrm_put_mode(struct xfrm_mode *mode)
-{
-	module_put(mode->owner);
+	return NULL;
 }
 
 void xfrm_state_free(struct xfrm_state *x)
@@ -436,12 +411,6 @@ static void ___xfrm_state_destroy(struct xfrm_state *x)
 	kfree(x->coaddr);
 	kfree(x->replay_esn);
 	kfree(x->preplay_esn);
-	if (x->inner_mode)
-		xfrm_put_mode(x->inner_mode);
-	if (x->inner_mode_iaf)
-		xfrm_put_mode(x->inner_mode_iaf);
-	if (x->outer_mode)
-		xfrm_put_mode(x->outer_mode);
 	if (x->type_offload)
 		xfrm_put_type_offload(x->type_offload);
 	if (x->type) {
@@ -2235,8 +2204,8 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 
 int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 {
-	struct xfrm_state_afinfo *afinfo;
-	struct xfrm_mode *inner_mode;
+	const struct xfrm_mode *inner_mode;
+	const struct xfrm_state_afinfo *afinfo;
 	int family = x->props.family;
 	int err;
 
@@ -2262,24 +2231,21 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 			goto error;
 
 		if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
-		    family != x->sel.family) {
-			xfrm_put_mode(inner_mode);
+		    family != x->sel.family)
 			goto error;
-		}
 
 		x->inner_mode = inner_mode;
 	} else {
-		struct xfrm_mode *inner_mode_iaf;
+		const struct xfrm_mode *inner_mode_iaf;
 		int iafamily = AF_INET;
 
 		inner_mode = xfrm_get_mode(x->props.mode, x->props.family);
 		if (inner_mode == NULL)
 			goto error;
 
-		if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) {
-			xfrm_put_mode(inner_mode);
+		if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL))
 			goto error;
-		}
+
 		x->inner_mode = inner_mode;
 
 		if (x->props.family == AF_INET)
@@ -2289,8 +2255,6 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 		if (inner_mode_iaf) {
 			if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)
 				x->inner_mode_iaf = inner_mode_iaf;
-			else
-				xfrm_put_mode(inner_mode_iaf);
 		}
 	}
 
diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config
index e9c860d00416..474040448601 100644
--- a/tools/testing/selftests/net/config
+++ b/tools/testing/selftests/net/config
@@ -7,9 +7,7 @@ CONFIG_NET_L3_MASTER_DEV=y
 CONFIG_IPV6=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_VETH=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_NET_IPVTI=y
-CONFIG_INET6_XFRM_MODE_TUNNEL=y
 CONFIG_IPV6_VTI=y
 CONFIG_DUMMY=y
 CONFIG_BRIDGE=y
-- 
2.19.2


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

* [PATCH ipsec-next 11/11] xfrm: store xfrm_mode directly, not its address
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (9 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 10/11] xfrm: make xfrm modes builtin Florian Westphal
@ 2019-03-27 17:31 ` Florian Westphal
  2019-03-28 11:42 ` [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Benedict Wong
  11 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-27 17:31 UTC (permalink / raw)
  To: netdev; +Cc: steffen.klassert, Florian Westphal

This structure is now only 4 bytes, so its more efficient
to cache a copy rather than its address.

No significant size difference in allmodconfig vmlinux.

With non-modular kernel that has all XFRM options enabled, this
series reduces vmlinux image size by ~11kb, all
all xfrm_mode indirections are gone and all xfrm modes are always
available.

master:
    text      data      bss         dec   filename
21071494   7233140 11104324    39408958   vmlinux.master

this series:
21066448   7226772 11104324    39397544   vmlinux.patched

With allmodconfig kernel:
    text      data      bss         dec   filename
15730198   6936912  4046908    26714018   vmlinux.master
this series:

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/xfrm.h        | 34 +++++++++++++++++-----------------
 net/ipv4/esp4_offload.c   |  2 +-
 net/ipv4/ip_vti.c         |  2 +-
 net/ipv4/xfrm4_output.c   |  2 +-
 net/ipv6/esp6_offload.c   |  2 +-
 net/ipv6/ip6_vti.c        |  2 +-
 net/ipv6/xfrm6_output.c   |  2 +-
 net/xfrm/xfrm_device.c    | 10 +++++-----
 net/xfrm/xfrm_input.c     | 30 +++++++++++++++---------------
 net/xfrm/xfrm_interface.c |  2 +-
 net/xfrm/xfrm_output.c    | 20 ++++++++++----------
 net/xfrm/xfrm_policy.c    |  2 +-
 net/xfrm/xfrm_state.c     | 16 ++++++++--------
 13 files changed, 63 insertions(+), 63 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 940b670a7999..dc7d4de1ba80 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -132,6 +132,17 @@ struct xfrm_state_offload {
 	u8			flags;
 };
 
+struct xfrm_mode {
+	u8 encap;
+	u8 family;
+	u8 flags;
+};
+
+/* Flags for xfrm_mode. */
+enum {
+	XFRM_MODE_FLAG_TUNNEL = 1,
+};
+
 /* Full description of state of transformer. */
 struct xfrm_state {
 	possible_net_t		xs_net;
@@ -234,9 +245,9 @@ struct xfrm_state {
 	/* Reference to data common to all the instances of this
 	 * transformer. */
 	const struct xfrm_type	*type;
-	const struct xfrm_mode	*inner_mode;
-	const struct xfrm_mode	*inner_mode_iaf;
-	const struct xfrm_mode	*outer_mode;
+	struct xfrm_mode	inner_mode;
+	struct xfrm_mode	inner_mode_iaf;
+	struct xfrm_mode	outer_mode;
 
 	const struct xfrm_type_offload	*type_offload;
 
@@ -421,17 +432,6 @@ struct xfrm_type_offload {
 int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 
-struct xfrm_mode {
-	u8 encap;
-	u8 family;
-	u8 flags;
-};
-
-/* Flags for xfrm_mode. */
-enum {
-	XFRM_MODE_FLAG_TUNNEL = 1,
-};
-
 static inline int xfrm_af2proto(unsigned int family)
 {
 	switch(family) {
@@ -448,9 +448,9 @@ static inline const struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, i
 {
 	if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
 	    (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
-		return x->inner_mode;
+		return &x->inner_mode;
 	else
-		return x->inner_mode_iaf;
+		return &x->inner_mode_iaf;
 }
 
 struct xfrm_tmpl {
@@ -1992,7 +1992,7 @@ static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
 			tunnel = true;
 		break;
 	}
-	if (tunnel && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL))
+	if (tunnel && !(x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL))
 		return -EINVAL;
 
 	return 0;
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 74d59e0177a7..b61a8ff558f9 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -135,7 +135,7 @@ static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
 						    struct sk_buff *skb,
 						    netdev_features_t features)
 {
-	switch (x->outer_mode->encap) {
+	switch (x->outer_mode.encap) {
 	case XFRM_MODE_TUNNEL:
 		return xfrm4_tunnel_gso_segment(x, skb, features);
 	case XFRM_MODE_TRANSPORT:
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 91926c9a3bc9..cc5d9c0a8a10 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -126,7 +126,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
 
 	x = xfrm_input_state(skb);
 
-	inner_mode = x->inner_mode;
+	inner_mode = &x->inner_mode;
 
 	if (x->sel.family == AF_UNSPEC) {
 		inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index cff048ad8562..eeca8dca0793 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -83,7 +83,7 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 #endif
 
 	rcu_read_lock();
-	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
+	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
 	if (afinfo)
 		ret = afinfo->output_finish(sk, skb);
 	else
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index c793a2ace77d..bff83279d76f 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -162,7 +162,7 @@ static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
 						    struct sk_buff *skb,
 						    netdev_features_t features)
 {
-	switch (x->outer_mode->encap) {
+	switch (x->outer_mode.encap) {
 	case XFRM_MODE_TUNNEL:
 		return xfrm6_tunnel_gso_segment(x, skb, features);
 	case XFRM_MODE_TRANSPORT:
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 71ec5e60cf8f..218a0dedc8f4 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -361,7 +361,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
 
 	x = xfrm_input_state(skb);
 
-	inner_mode = x->inner_mode;
+	inner_mode = &x->inner_mode;
 
 	if (x->sel.family == AF_UNSPEC) {
 		inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 82168de60e6b..667ee0cad98a 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -128,7 +128,7 @@ static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk, st
 	int ret = -EAFNOSUPPORT;
 
 	rcu_read_lock();
-	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
+	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
 	if (afinfo)
 		ret = afinfo->output_finish(sk, skb);
 	else
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index e37824a8652e..c8b21c634a9c 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -53,20 +53,20 @@ static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
 /* Adjust pointers into the packet when IPsec is done at layer2 */
 static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
 {
-	switch (x->outer_mode->encap) {
+	switch (x->outer_mode.encap) {
 	case XFRM_MODE_TUNNEL:
-		if (x->inner_mode->family == AF_INET)
+		if (x->inner_mode.family == AF_INET)
 			return __xfrm_mode_tunnel_prep(x, skb,
 						       sizeof(struct iphdr));
-		if (x->inner_mode->family == AF_INET6)
+		if (x->inner_mode.family == AF_INET6)
 			return __xfrm_mode_tunnel_prep(x, skb,
 						       sizeof(struct ipv6hdr));
 		break;
 	case XFRM_MODE_TRANSPORT:
-		if (x->inner_mode->family == AF_INET)
+		if (x->inner_mode.family == AF_INET)
 			return __xfrm_transport_prep(x, skb,
 						     sizeof(struct iphdr));
-		if (x->inner_mode->family == AF_INET6)
+		if (x->inner_mode.family == AF_INET6)
 			return __xfrm_transport_prep(x, skb,
 						     sizeof(struct ipv6hdr));
 		break;
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 31c17fc8b49f..1b7055cb32c3 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -328,17 +328,17 @@ static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
 static int
 xfrm_inner_mode_encap_remove(struct xfrm_state *x, struct sk_buff *skb)
 {
-	switch (x->inner_mode->encap) {
+	switch (x->inner_mode.encap) {
 	case XFRM_MODE_BEET:
-		if (x->inner_mode->family == AF_INET)
+		if (x->inner_mode.family == AF_INET)
 			return xfrm4_remove_beet_encap(x, skb);
-		if (x->inner_mode->family == AF_INET6)
+		if (x->inner_mode.family == AF_INET6)
 			return xfrm6_remove_beet_encap(x, skb);
 		break;
 	case XFRM_MODE_TUNNEL:
-		if (x->inner_mode->family == AF_INET)
+		if (x->inner_mode.family == AF_INET)
 			return xfrm4_remove_tunnel_encap(x, skb);
-		if (x->inner_mode->family == AF_INET6)
+		if (x->inner_mode.family == AF_INET6)
 			return xfrm6_remove_tunnel_encap(x, skb);
 		break;
 	}
@@ -349,12 +349,12 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x, struct sk_buff *skb)
 
 int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	const struct xfrm_mode *inner_mode = x->inner_mode;
+	const struct xfrm_mode *inner_mode = &x->inner_mode;
 	const struct xfrm_state_afinfo *afinfo;
 	int err = -EAFNOSUPPORT;
 
 	rcu_read_lock();
-	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
+	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
 	if (afinfo)
 		err = afinfo->extract_input(x, skb);
 
@@ -416,14 +416,14 @@ static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
 
 static int xfrm_inner_mode_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	switch (x->inner_mode->encap) {
+	switch (x->inner_mode.encap) {
 	case XFRM_MODE_BEET:
 	case XFRM_MODE_TUNNEL:
 		return xfrm_prepare_input(x, skb);
 	case XFRM_MODE_TRANSPORT:
-		if (x->inner_mode->family == AF_INET)
+		if (x->inner_mode.family == AF_INET)
 			return xfrm4_transport_input(x, skb);
-		if (x->inner_mode->family == AF_INET6)
+		if (x->inner_mode.family == AF_INET6)
 			return xfrm6_transport_input(x, skb);
 		break;
 	case XFRM_MODE_ROUTEOPTIMIZATION:
@@ -468,7 +468,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 			goto drop;
 		}
 
-		family = x->outer_mode->family;
+		family = x->outer_mode.family;
 
 		/* An encap_type of -1 indicates async resumption. */
 		if (encap_type == -1) {
@@ -652,7 +652,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 
 		XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
 
-		inner_mode = x->inner_mode;
+		inner_mode = &x->inner_mode;
 
 		if (x->sel.family == AF_UNSPEC) {
 			inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
@@ -667,7 +667,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 			goto drop;
 		}
 
-		if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+		if (x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL) {
 			decaps = 1;
 			break;
 		}
@@ -677,7 +677,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		 * transport mode so the outer address is identical.
 		 */
 		daddr = &x->id.daddr;
-		family = x->outer_mode->family;
+		family = x->outer_mode.family;
 
 		err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
 		if (err < 0) {
@@ -707,7 +707,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 
 		err = -EAFNOSUPPORT;
 		rcu_read_lock();
-		afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode->family);
+		afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode.family);
 		if (afinfo)
 			err = afinfo->transport_finish(skb, xfrm_gro || async);
 		rcu_read_unlock();
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 4fc49dbf3edf..b9f118530db6 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -273,7 +273,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
 	xnet = !net_eq(xi->net, dev_net(skb->dev));
 
 	if (xnet) {
-		inner_mode = x->inner_mode;
+		inner_mode = &x->inner_mode;
 
 		if (x->sel.family == AF_UNSPEC) {
 			inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 6eaaf762db8e..877530f0d4af 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -302,7 +302,7 @@ static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
 
 static int xfrm4_outer_encap_add(struct xfrm_state *x, struct sk_buff *skb)
 {
-	switch (x->inner_mode->encap) {
+	switch (x->inner_mode.encap) {
 	case XFRM_MODE_BEET:
 		return xfrm4_beet_encap_add(x, skb);
 	case XFRM_MODE_TUNNEL:
@@ -315,7 +315,7 @@ static int xfrm4_outer_encap_add(struct xfrm_state *x, struct sk_buff *skb)
 
 static int xfrm6_outer_encap_add(struct xfrm_state *x, struct sk_buff *skb)
 {
-	switch (x->inner_mode->encap) {
+	switch (x->inner_mode.encap) {
 	case XFRM_MODE_BEET:
 		return xfrm6_beet_encap_add(x, skb);
 	case XFRM_MODE_TUNNEL:
@@ -356,21 +356,21 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 
 static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-	switch (x->outer_mode->encap) {
+	switch (x->outer_mode.encap) {
 	case XFRM_MODE_BEET:
 	case XFRM_MODE_TUNNEL:
-		if (x->outer_mode->family == AF_INET)
+		if (x->outer_mode.family == AF_INET)
 			return xfrm4_prepare_output(x, skb);
-		if (x->outer_mode->family == AF_INET6)
+		if (x->outer_mode.family == AF_INET6)
 			return xfrm6_prepare_output(x, skb);
 	case XFRM_MODE_TRANSPORT:
-		if (x->outer_mode->family == AF_INET)
+		if (x->outer_mode.family == AF_INET)
 			return xfrm4_transport_output(x, skb);
-		if (x->outer_mode->family == AF_INET6)
+		if (x->outer_mode.family == AF_INET6)
 			return xfrm6_transport_output(x, skb);
 		break;
 	case XFRM_MODE_ROUTEOPTIMIZATION:
-		if (x->outer_mode->family == AF_INET6)
+		if (x->outer_mode.family == AF_INET6)
 			return xfrm6_ro_output(x, skb);
 		WARN_ON_ONCE(1);
 	default:
@@ -470,7 +470,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 		}
 		skb_dst_set(skb, dst);
 		x = dst->xfrm;
-	} while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
+	} while (x && !(x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL));
 
 	return 0;
 
@@ -607,7 +607,7 @@ int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 		inner_mode = xfrm_ip2inner_mode(x,
 				xfrm_af2proto(skb_dst(skb)->ops->family));
 	else
-		inner_mode = x->inner_mode;
+		inner_mode = &x->inner_mode;
 
 	if (inner_mode == NULL)
 		return -EAFNOSUPPORT;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b5dce0c6bdcd..c5b3203d4e12 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2595,7 +2595,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 				goto put_states;
 			}
 		} else
-			inner_mode = xfrm[i]->inner_mode;
+			inner_mode = &xfrm[i]->inner_mode;
 
 		xdst->route = dst;
 		dst_copy_metrics(dst1, dst);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index ace26f6dc790..d3d87c409f44 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -551,8 +551,6 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
 		x->lft.hard_packet_limit = XFRM_INF;
 		x->replay_maxage = 0;
 		x->replay_maxdiff = 0;
-		x->inner_mode = NULL;
-		x->inner_mode_iaf = NULL;
 		spin_lock_init(&x->lock);
 	}
 	return x;
@@ -2204,8 +2202,9 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 
 int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 {
-	const struct xfrm_mode *inner_mode;
 	const struct xfrm_state_afinfo *afinfo;
+	const struct xfrm_mode *inner_mode;
+	const struct xfrm_mode *outer_mode;
 	int family = x->props.family;
 	int err;
 
@@ -2234,7 +2233,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 		    family != x->sel.family)
 			goto error;
 
-		x->inner_mode = inner_mode;
+		x->inner_mode = *inner_mode;
 	} else {
 		const struct xfrm_mode *inner_mode_iaf;
 		int iafamily = AF_INET;
@@ -2246,7 +2245,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 		if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL))
 			goto error;
 
-		x->inner_mode = inner_mode;
+		x->inner_mode = *inner_mode;
 
 		if (x->props.family == AF_INET)
 			iafamily = AF_INET6;
@@ -2254,7 +2253,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 		inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily);
 		if (inner_mode_iaf) {
 			if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)
-				x->inner_mode_iaf = inner_mode_iaf;
+				x->inner_mode_iaf = *inner_mode_iaf;
 		}
 	}
 
@@ -2268,12 +2267,13 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
 	if (err)
 		goto error;
 
-	x->outer_mode = xfrm_get_mode(x->props.mode, family);
-	if (x->outer_mode == NULL) {
+	outer_mode = xfrm_get_mode(x->props.mode, family);
+	if (!outer_mode) {
 		err = -EPROTONOSUPPORT;
 		goto error;
 	}
 
+	x->outer_mode = *outer_mode;
 	if (init_replay) {
 		err = xfrm_init_replay(x);
 		if (err)
-- 
2.19.2


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

* Re: [PATCH ipsec-next 04/11] xfrm: remove output indirection from xfrm_mode
  2019-03-27 17:31 ` [PATCH ipsec-next 04/11] xfrm: remove output " Florian Westphal
@ 2019-03-28 11:12   ` Sabrina Dubroca
  2019-03-28 11:27     ` Florian Westphal
  0 siblings, 1 reply; 25+ messages in thread
From: Sabrina Dubroca @ 2019-03-28 11:12 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, steffen.klassert

Hi Florian,

2019-03-27, 18:31:33 +0100, Florian Westphal wrote:
> diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
> index 9333153bafda..01eb142ba6d0 100644
> --- a/net/xfrm/xfrm_output.c
> +++ b/net/xfrm/xfrm_output.c
[snip]
> +static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
> +{

Why no #if IS_ENABLED here? (and in xfrm6_prepare_output)

> +	int err;
> +
> +	err = xfrm_inner_extract_output(x, skb);
> +	if (err)
> +		return err;
> +
> +	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
> +	skb->protocol = htons(ETH_P_IP);
> +
> +	return x->outer_mode->output2(x, skb);
> +}
> +
> +static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
> +{
> +	int err;
> +
> +	err = xfrm_inner_extract_output(x, skb);
> +	if (err)
> +		return err;
> +
> +	skb->ignore_df = 1;
> +	skb->protocol = htons(ETH_P_IPV6);
> +
> +	return x->outer_mode->output2(x, skb);
> +}
> +
> +static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
> +{
> +	switch (x->outer_mode->encap) {
> +	case XFRM_MODE_BEET:
> +	case XFRM_MODE_TUNNEL:
> +		if (x->outer_mode->family == AF_INET)
> +			return xfrm4_prepare_output(x, skb);
> +		if (x->outer_mode->family == AF_INET6)
> +			return xfrm6_prepare_output(x, skb);

Missing "break;" here?

> +	case XFRM_MODE_TRANSPORT:
> +		if (x->outer_mode->family == AF_INET)
> +			return xfrm4_transport_output(x, skb);
> +		if (x->outer_mode->family == AF_INET6)
> +			return xfrm6_transport_output(x, skb);
> +		break;
> +	case XFRM_MODE_ROUTEOPTIMIZATION:
> +		if (x->outer_mode->family == AF_INET6)
> +			return xfrm6_ro_output(x, skb);
> +		WARN_ON_ONCE(1);

Missing "break;" here too?

> +	default:
> +		WARN_ON_ONCE(1);
> +		break;
> +	}
> +
> +	return -EOPNOTSUPP;
> +}

-- 
Sabrina

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

* Re: [PATCH ipsec-next 04/11] xfrm: remove output indirection from xfrm_mode
  2019-03-28 11:12   ` Sabrina Dubroca
@ 2019-03-28 11:27     ` Florian Westphal
  2019-03-28 11:35       ` Sabrina Dubroca
  0 siblings, 1 reply; 25+ messages in thread
From: Florian Westphal @ 2019-03-28 11:27 UTC (permalink / raw)
  To: Sabrina Dubroca; +Cc: Florian Westphal, netdev, steffen.klassert

Sabrina Dubroca <sd@queasysnail.net> wrote:
> Hi Florian,
> 
> 2019-03-27, 18:31:33 +0100, Florian Westphal wrote:
> > diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
> > index 9333153bafda..01eb142ba6d0 100644
> > --- a/net/xfrm/xfrm_output.c
> > +++ b/net/xfrm/xfrm_output.c
> [snip]
> > +static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
> > +{
> 
> Why no #if IS_ENABLED here? (and in xfrm6_prepare_output)

I don't know what IS_ENABLED() conditional makes sense here.

This is coming from xfrm4_output.c which only depends on CONFIG_XFRM.
I'll add IS_ENABLED(CONFIG_IPV6) for xfrm6_prepare_output in v2.

> > +static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
> > +{
> > +	switch (x->outer_mode->encap) {
> > +	case XFRM_MODE_BEET:
> > +	case XFRM_MODE_TUNNEL:
> > +		if (x->outer_mode->family == AF_INET)
> > +			return xfrm4_prepare_output(x, skb);
> > +		if (x->outer_mode->family == AF_INET6)
> > +			return xfrm6_prepare_output(x, skb);
> 
> Missing "break;" here?
[..]
> Missing "break;" here too?

Indeed, added, thanks.

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

* Re: [PATCH ipsec-next 04/11] xfrm: remove output indirection from xfrm_mode
  2019-03-28 11:27     ` Florian Westphal
@ 2019-03-28 11:35       ` Sabrina Dubroca
  0 siblings, 0 replies; 25+ messages in thread
From: Sabrina Dubroca @ 2019-03-28 11:35 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, steffen.klassert

2019-03-28, 12:27:18 +0100, Florian Westphal wrote:
> Sabrina Dubroca <sd@queasysnail.net> wrote:
> > Hi Florian,
> > 
> > 2019-03-27, 18:31:33 +0100, Florian Westphal wrote:
> > > diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
> > > index 9333153bafda..01eb142ba6d0 100644
> > > --- a/net/xfrm/xfrm_output.c
> > > +++ b/net/xfrm/xfrm_output.c
> > [snip]
> > > +static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
> > > +{
> > 
> > Why no #if IS_ENABLED here? (and in xfrm6_prepare_output)
> 
> I don't know what IS_ENABLED() conditional makes sense here.

I was thinking of INET_XFRM_MODE_BEET || INET_XFRM_MODE_TUNNEL, to
match the check you added in xfrm4_transport_output, but anyway you're
getting rid of them at the end of the series. Probably not worth
bothering.

> This is coming from xfrm4_output.c which only depends on CONFIG_XFRM.
> I'll add IS_ENABLED(CONFIG_IPV6) for xfrm6_prepare_output in v2.

Oh, I didn't think of that one, nice.

> > > +static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
> > > +{
> > > +	switch (x->outer_mode->encap) {
> > > +	case XFRM_MODE_BEET:
> > > +	case XFRM_MODE_TUNNEL:
> > > +		if (x->outer_mode->family == AF_INET)
> > > +			return xfrm4_prepare_output(x, skb);
> > > +		if (x->outer_mode->family == AF_INET6)
> > > +			return xfrm6_prepare_output(x, skb);
> > 
> > Missing "break;" here?
> [..]
> > Missing "break;" here too?
> 
> Indeed, added, thanks.

Thanks.

-- 
Sabrina

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

* Re: [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode
  2019-03-27 17:31 ` [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode Florian Westphal
@ 2019-03-28 11:39   ` Sabrina Dubroca
  2019-03-28 11:46     ` Florian Westphal
  2019-03-29 17:10   ` Eyal Birger
  1 sibling, 1 reply; 25+ messages in thread
From: Sabrina Dubroca @ 2019-03-28 11:39 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, steffen.klassert

2019-03-27, 18:31:32 +0100, Florian Westphal wrote:
> diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
> index ea5ac053c15d..e3c7edd11e77 100644
> --- a/net/xfrm/xfrm_input.c
> +++ b/net/xfrm/xfrm_input.c
> @@ -186,6 +186,74 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
>  }
>  EXPORT_SYMBOL(xfrm_prepare_input);
>  
> +/* Remove encapsulation header.
> + *
> + * The IP header will be moved over the top of the encapsulation header.
> + *
> + * On entry, skb->h shall point to where the IP header should be and skb->nh
> + * shall be set to where the IP header currently is.  skb->data shall point
> + * to the start of the payload.
> + */
> +static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
> +{
> +#if IS_ENABLED(CONFIG_INET4_XFRM_MODE_TRANSPORT)

Nit: that should be CONFIG_INET_XFRM_MODE_TRANSPORT (without 4), and
in patch 10.

> +	int ihl = skb->data - skb_transport_header(skb);
> +
> +	if (skb->transport_header != skb->network_header) {
> +		memmove(skb_transport_header(skb),
> +			skb_network_header(skb), ihl);
> +		skb->network_header = skb->transport_header;
> +	}
> +	ip_hdr(skb)->tot_len = htons(skb->len + ihl);
> +	skb_reset_transport_header(skb);
> +	return 0;
> +#else
> +	return -EOPNOTSUPP;
> +#endif
> +}

-- 
Sabrina

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

* Re: [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections
  2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
                   ` (10 preceding siblings ...)
  2019-03-27 17:31 ` [PATCH ipsec-next 11/11] xfrm: store xfrm_mode directly, not its address Florian Westphal
@ 2019-03-28 11:42 ` Benedict Wong
  2019-03-28 11:48   ` Florian Westphal
  11 siblings, 1 reply; 25+ messages in thread
From: Benedict Wong @ 2019-03-28 11:42 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, Steffen Klassert

Hi Florian,

I ran the Android unit tests on these patches, based off ipsec-next,
and am encountering some new errors. I'll take another look to try and
isolate which patches might be causing the failures.

Best Regards,

Benedict Wong

On Wed, Mar 27, 2019 at 6:30 PM Florian Westphal <fw@strlen.de> wrote:
>
> This series removes all function pointers from the xfrm_mode struct.
> They are either replaced by direct calls or a static helper.
>
> This also reduces code size: even merging all xfrm{4,6}_,mode* modules
> into the core reduces total size, as the infrastructure to maintain
> dynamic (un)register can be removed.
>
> There are more opportunities for indirection avoidance, e.g. in
> xfrm_type.
>
> I plan to follow up once/if this series is accepted.
> This is quite some code churn, but I think its worth doing.
>
> Tested with xfrm tunnel mode via netns with esp/aead.
>
> Florian Westphal (11):
>       xfrm: place af number into xfrm_mode struct
>       xfrm: prefer family stored in xfrm_mode struct
>       xfrm: remove input indirection from xfrm_mode
>       xfrm: remove output indirection from xfrm_mode
>       xfrm: remove xmit indirection from xfrm_mode
>       xfrm: remove gso_segment indirection from xfrm_mode
>       xfrm: remove input2 indirection from xfrm_mode
>       xfrm: remove output2 indirection from xfrm_mode
>       xfrm: remove afinfo pointer from xfrm_mode
>       xfrm: make xfrm modes builtin
>       xfrm: store xfrm_mode directly, not its address
>
>  include/net/xfrm.h                 |  105 ++--------
>  net/core/pktgen.c                  |    2
>  net/ipv4/Kconfig                   |   29 --
>  net/ipv4/Makefile                  |    3
>  net/ipv4/esp4_offload.c            |   40 +++
>  net/ipv4/ip_vti.c                  |    6
>  net/ipv4/xfrm4_output.c            |   26 --
>  net/ipv6/Kconfig                   |   35 ---
>  net/ipv6/Makefile                  |    4
>  net/ipv6/esp6_offload.c            |   40 +++
>  net/ipv6/ip6_vti.c                 |    6
>  net/ipv6/xfrm6_output.c            |   36 +--
>  net/xfrm/xfrm_device.c             |   58 +++++
>  net/xfrm/xfrm_inout.h              |   38 +++
>  net/xfrm/xfrm_input.c              |  283 ++++++++++++++++++++++++++-
>  net/xfrm/xfrm_interface.c          |    6
>  net/xfrm/xfrm_output.c             |  359 ++++++++++++++++++++++++++++++++++-
>  net/xfrm/xfrm_policy.c             |   11 -
>  net/xfrm/xfrm_state.c              |  181 ++++++-----------
>  tools/testing/selftests/net/config |    2
>  net/ipv4/xfrm4_mode_beet.c         |  155 ---------------
>  net/ipv4/xfrm4_mode_transport.c    |  114 -----------
>  net/ipv4/xfrm4_mode_tunnel.c       |  152 --------------
>  net/ipv6/xfrm6_mode_beet.c         |  131 ------------
>  net/ipv6/xfrm6_mode_ro.c           |   85 --------
>  net/ipv6/xfrm6_mode_transport.c    |  121 -----------
>  net/ipv6/xfrm6_mode_tunnel.c       |  151 --------------
>  27 files changed, 937 insertions(+), 1242 deletions(-)
>

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

* Re: [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode
  2019-03-28 11:39   ` Sabrina Dubroca
@ 2019-03-28 11:46     ` Florian Westphal
  0 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-28 11:46 UTC (permalink / raw)
  To: Sabrina Dubroca; +Cc: Florian Westphal, netdev, steffen.klassert

Sabrina Dubroca <sd@queasysnail.net> wrote:
> 2019-03-27, 18:31:32 +0100, Florian Westphal wrote:
> > diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
> > index ea5ac053c15d..e3c7edd11e77 100644
> > --- a/net/xfrm/xfrm_input.c
> > +++ b/net/xfrm/xfrm_input.c
> > @@ -186,6 +186,74 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
> >  }
> >  EXPORT_SYMBOL(xfrm_prepare_input);
> >  
> > +/* Remove encapsulation header.
> > + *
> > + * The IP header will be moved over the top of the encapsulation header.
> > + *
> > + * On entry, skb->h shall point to where the IP header should be and skb->nh
> > + * shall be set to where the IP header currently is.  skb->data shall point
> > + * to the start of the payload.
> > + */
> > +static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
> > +{
> > +#if IS_ENABLED(CONFIG_INET4_XFRM_MODE_TRANSPORT)
> 
> Nit: that should be CONFIG_INET_XFRM_MODE_TRANSPORT (without 4), and
> in patch 10.

Urgh.  Thanks, I'll fix both.

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

* Re: [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections
  2019-03-28 11:42 ` [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Benedict Wong
@ 2019-03-28 11:48   ` Florian Westphal
  0 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-28 11:48 UTC (permalink / raw)
  To: Benedict Wong; +Cc: Florian Westphal, netdev, Steffen Klassert

Benedict Wong <benedictwong@google.com> wrote:
> Hi Florian,
> 
> I ran the Android unit tests on these patches, based off ipsec-next,
> and am encountering some new errors. I'll take another look to try and
> isolate which patches might be causing the failures.

Thanks a lot, but you can hold off for v1, Sabrina already found two
bugs that break transport mode for sure.

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

* Re: [PATCH ipsec-next 09/11] xfrm: remove afinfo pointer from xfrm_mode
  2019-03-27 17:31 ` [PATCH ipsec-next 09/11] xfrm: remove afinfo pointer " Florian Westphal
@ 2019-03-28 14:13   ` Sabrina Dubroca
  0 siblings, 0 replies; 25+ messages in thread
From: Sabrina Dubroca @ 2019-03-28 14:13 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, steffen.klassert

(just a couple of checkpatch-like comments)

2019-03-27, 18:31:38 +0100, Florian Westphal wrote:
> diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
> index 6802d1aee424..cff048ad8562 100644
> --- a/net/ipv4/xfrm4_output.c
> +++ b/net/ipv4/xfrm4_output.c
> @@ -72,6 +72,8 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
>  static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
>  {
>  	struct xfrm_state *x = skb_dst(skb)->xfrm;
> +	const struct xfrm_state_afinfo *afinfo;
> +	int ret = -EAFNOSUPPORT;
>  
>  #ifdef CONFIG_NETFILTER
>  	if (!x) {
> @@ -80,7 +82,14 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
>  	}
>  #endif
>  
> -	return x->outer_mode->afinfo->output_finish(sk, skb);
> +	rcu_read_lock();
> +	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
> +	if (afinfo)
> +		ret = afinfo->output_finish(sk, skb);
> +	else
> +		kfree_skb(skb);
> +	rcu_read_unlock();

Maybe add a blank line before the return, like you did in __xfrm6_output_state_finish().

> +	return ret;
>  }
>  
>  int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
> diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
> index 2b663d2ffdcd..82168de60e6b 100644
> --- a/net/ipv6/xfrm6_output.c
> +++ b/net/ipv6/xfrm6_output.c
> @@ -122,11 +122,27 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
>  	return xfrm_output(sk, skb);
>  }
>  
> +static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk, struct sk_buff *skb)

Over 80 chars.

> +{
> +	const struct xfrm_state_afinfo *afinfo;
> +	int ret = -EAFNOSUPPORT;
> +
> +	rcu_read_lock();
> +	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
> +	if (afinfo)
> +		ret = afinfo->output_finish(sk, skb);
> +	else
> +		kfree_skb(skb);
> +	rcu_read_unlock();
> +
> +	return ret;
> +}
> +
>  static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
>  {
>  	struct xfrm_state *x = skb_dst(skb)->xfrm;
>  
> -	return x->outer_mode->afinfo->output_finish(sk, skb);
> +	return __xfrm6_output_state_finish(x, sk, skb);
>  }
>  
>  static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
> @@ -168,7 +184,8 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
>  				    __xfrm6_output_finish);
>  
>  skip_frag:
> -	return x->outer_mode->afinfo->output_finish(sk, skb);
> +

You could skip the extra blank line.

> +	return __xfrm6_output_state_finish(x, sk, skb);
>  }
>  
>  int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)

-- 
Sabrina

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

* Re: [PATCH ipsec-next 08/11] xfrm: remove output2 indirection from xfrm_mode
  2019-03-27 17:31 ` [PATCH ipsec-next 08/11] xfrm: remove output2 " Florian Westphal
@ 2019-03-28 22:28   ` kbuild test robot
  2019-03-29  2:15   ` kbuild test robot
  1 sibling, 0 replies; 25+ messages in thread
From: kbuild test robot @ 2019-03-28 22:28 UTC (permalink / raw)
  To: Florian Westphal; +Cc: kbuild-all, netdev, steffen.klassert, Florian Westphal

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

Hi Florian,

I love your patch! Yet something to improve:

[auto build test ERROR on ipsec-next/master]

url:    https://github.com/0day-ci/linux/commits/Florian-Westphal/xfrm-remove-xfrm_mode-indirections/20190329-041949
base:   https://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git master
config: powerpc-defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   powerpc64-linux-gnu-ld: warning: orphan section `.gnu.hash' from `linker stubs' being placed in section `.gnu.hash'.
   net/xfrm/xfrm_output.o: In function `.xfrm_output_resume':
>> (.text+0xdec): undefined reference to `.ip6_dst_hoplimit'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 24312 bytes --]

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

* Re: [PATCH ipsec-next 08/11] xfrm: remove output2 indirection from xfrm_mode
  2019-03-27 17:31 ` [PATCH ipsec-next 08/11] xfrm: remove output2 " Florian Westphal
  2019-03-28 22:28   ` kbuild test robot
@ 2019-03-29  2:15   ` kbuild test robot
  1 sibling, 0 replies; 25+ messages in thread
From: kbuild test robot @ 2019-03-29  2:15 UTC (permalink / raw)
  To: Florian Westphal; +Cc: kbuild-all, netdev, steffen.klassert, Florian Westphal

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

Hi Florian,

I love your patch! Yet something to improve:

[auto build test ERROR on ipsec-next/master]

url:    https://github.com/0day-ci/linux/commits/Florian-Westphal/xfrm-remove-xfrm_mode-indirections/20190329-041949
base:   https://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git master
config: powerpc-g5_defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   net/xfrm/xfrm_output.o: In function `.xfrm_output_resume':
>> xfrm_output.c:(.text+0xd7c): undefined reference to `.ip6_dst_hoplimit'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20745 bytes --]

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

* Re: [PATCH ipsec-next 10/11] xfrm: make xfrm modes builtin
  2019-03-27 17:31 ` [PATCH ipsec-next 10/11] xfrm: make xfrm modes builtin Florian Westphal
@ 2019-03-29  3:54   ` kbuild test robot
  0 siblings, 0 replies; 25+ messages in thread
From: kbuild test robot @ 2019-03-29  3:54 UTC (permalink / raw)
  To: Florian Westphal; +Cc: kbuild-all, netdev, steffen.klassert, Florian Westphal

Hi Florian,

I love your patch! Perhaps something to improve:

[auto build test WARNING on ipsec-next/master]

url:    https://github.com/0day-ci/linux/commits/Florian-Westphal/xfrm-remove-xfrm_mode-indirections/20190329-041949
base:   https://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git master
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'


sparse warnings: (new ones prefixed by >>)

   net/xfrm/xfrm_state.c:928:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:928:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:928:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:928:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:928:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:945:9: sparse: cast removes address space of expression
   net/xfrm/xfrm_state.c:1003:77: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1003:77:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1003:77:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1005:77: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1005:77:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1005:77:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1008:85: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1008:85:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1008:85:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1024:42: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct xfrm_state [noderef] <asn:4>*x @@    got  xfrm_state [noderef] <asn:4>*x @@
   net/xfrm/xfrm_state.c:1024:42:    expected struct xfrm_state [noderef] <asn:4>*x
   net/xfrm/xfrm_state.c:1024:42:    got struct xfrm_state *[assigned] x
   net/xfrm/xfrm_state.c:52:39: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct refcount_struct [usertype] *r @@    got structstruct refcount_struct [usertype] *r @@
   net/xfrm/xfrm_state.c:52:39:    expected struct refcount_struct [usertype] *r
   net/xfrm/xfrm_state.c:52:39:    got struct refcount_struct [noderef] <asn:4>*<noident>
   net/xfrm/xfrm_state.c:1111:61: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1111:61:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1111:61:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1114:61: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1114:61:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1114:61:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1120:69: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1120:69:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1120:69:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1232:69: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1232:69:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1232:69:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1234:69: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1234:69:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1234:69:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:1789:69: sparse: incorrect type in argument 2 (different address spaces) @@    expected struct hlist_head *h @@    got struct hlist_headstruct hlist_head *h @@
   net/xfrm/xfrm_state.c:1789:69:    expected struct hlist_head *h
   net/xfrm/xfrm_state.c:1789:69:    got struct hlist_head [noderef] <asn:4>*
   net/xfrm/xfrm_state.c:2314:31: sparse: incorrect type in assignment (different address spaces) @@    expected struct hlist_head [noderef] <asn:4>*state_bydst @@    got  [noderef] <asn:4>*state_bydst @@
   net/xfrm/xfrm_state.c:2314:31:    expected struct hlist_head [noderef] <asn:4>*state_bydst
   net/xfrm/xfrm_state.c:2314:31:    got struct hlist_head *
   net/xfrm/xfrm_state.c:2317:31: sparse: incorrect type in assignment (different address spaces) @@    expected struct hlist_head [noderef] <asn:4>*state_bysrc @@    got  [noderef] <asn:4>*state_bysrc @@
   net/xfrm/xfrm_state.c:2317:31:    expected struct hlist_head [noderef] <asn:4>*state_bysrc
   net/xfrm/xfrm_state.c:2317:31:    got struct hlist_head *
   net/xfrm/xfrm_state.c:2320:31: sparse: incorrect type in assignment (different address spaces) @@    expected struct hlist_head [noderef] <asn:4>*state_byspi @@    got  [noderef] <asn:4>*state_byspi @@
   net/xfrm/xfrm_state.c:2320:31:    expected struct hlist_head [noderef] <asn:4>*state_byspi
   net/xfrm/xfrm_state.c:2320:31:    got struct hlist_head *
   net/xfrm/xfrm_state.c:2331:33: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head *n @@    got struct hlist_headstruct hlist_head *n @@
   net/xfrm/xfrm_state.c:2331:33:    expected struct hlist_head *n
   net/xfrm/xfrm_state.c:2331:33:    got struct hlist_head [noderef] <asn:4>*state_bysrc
   net/xfrm/xfrm_state.c:2333:33: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head *n @@    got struct hlist_headstruct hlist_head *n @@
   net/xfrm/xfrm_state.c:2333:33:    expected struct hlist_head *n
   net/xfrm/xfrm_state.c:2333:33:    got struct hlist_head [noderef] <asn:4>*state_bydst
   net/xfrm/xfrm_state.c:2349:9: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head const *h @@    got struct hlisstruct hlist_head const *h @@
   net/xfrm/xfrm_state.c:2349:9:    expected struct hlist_head const *h
   net/xfrm/xfrm_state.c:2349:9:    got struct hlist_head [noderef] <asn:4>*state_byspi
   net/xfrm/xfrm_state.c:2350:33: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head *n @@    got struct hlist_headstruct hlist_head *n @@
   net/xfrm/xfrm_state.c:2350:33:    expected struct hlist_head *n
   net/xfrm/xfrm_state.c:2350:33:    got struct hlist_head [noderef] <asn:4>*state_byspi
   net/xfrm/xfrm_state.c:2351:9: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head const *h @@    got struct hlisstruct hlist_head const *h @@
   net/xfrm/xfrm_state.c:2351:9:    expected struct hlist_head const *h
   net/xfrm/xfrm_state.c:2351:9:    got struct hlist_head [noderef] <asn:4>*state_bysrc
   net/xfrm/xfrm_state.c:2352:33: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head *n @@    got struct hlist_headstruct hlist_head *n @@
   net/xfrm/xfrm_state.c:2352:33:    expected struct hlist_head *n
   net/xfrm/xfrm_state.c:2352:33:    got struct hlist_head [noderef] <asn:4>*state_bysrc
   net/xfrm/xfrm_state.c:2353:9: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head const *h @@    got struct hlisstruct hlist_head const *h @@
   net/xfrm/xfrm_state.c:2353:9:    expected struct hlist_head const *h
   net/xfrm/xfrm_state.c:2353:9:    got struct hlist_head [noderef] <asn:4>*state_bydst
   net/xfrm/xfrm_state.c:2354:33: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct hlist_head *n @@    got struct hlist_headstruct hlist_head *n @@
   net/xfrm/xfrm_state.c:2354:33:    expected struct hlist_head *n
   net/xfrm/xfrm_state.c:2354:33:    got struct hlist_head [noderef] <asn:4>*state_bydst
   include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_register_type' - unexpected unlock
   include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_unregister_type' - unexpected unlock
   include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_get_type' - unexpected unlock
   include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_register_type_offload' - unexpected unlock
   include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_unregister_type_offload' - unexpected unlock
   include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_get_type_offload' - unexpected unlock
   net/xfrm/xfrm_state.c:629:17: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:690:17: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:650:17: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:734:17: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:1056:9: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:1144:9: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:1179:9: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:1407:17: sparse: dereference of noderef expression
   net/xfrm/xfrm_state.c:1424:17: sparse: dereference of noderef expression
>> include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_tmpl_sort' - unexpected unlock
>> include/linux/rcupdate.h:647:9: sparse: context imbalance in 'xfrm_state_sort' - unexpected unlock
   net/xfrm/xfrm_state.c:1687:17: sparse: too many warnings

vim +/xfrm_tmpl_sort +647 include/linux/rcupdate.h

^1da177e4 Linus Torvalds      2005-04-16  599  
^1da177e4 Linus Torvalds      2005-04-16  600  /*
^1da177e4 Linus Torvalds      2005-04-16  601   * So where is rcu_write_lock()?  It does not exist, as there is no
^1da177e4 Linus Torvalds      2005-04-16  602   * way for writers to lock out RCU readers.  This is a feature, not
^1da177e4 Linus Torvalds      2005-04-16  603   * a bug -- this property is what provides RCU's performance benefits.
^1da177e4 Linus Torvalds      2005-04-16  604   * Of course, writers must coordinate with each other.  The normal
^1da177e4 Linus Torvalds      2005-04-16  605   * spinlock primitives work well for this, but any other technique may be
^1da177e4 Linus Torvalds      2005-04-16  606   * used as well.  RCU does not care how the writers keep out of each
^1da177e4 Linus Torvalds      2005-04-16  607   * others' way, as long as they do so.
^1da177e4 Linus Torvalds      2005-04-16  608   */
3d76c0829 Paul E. McKenney    2009-09-28  609  
3d76c0829 Paul E. McKenney    2009-09-28  610  /**
ca5ecddfa Paul E. McKenney    2010-04-28  611   * rcu_read_unlock() - marks the end of an RCU read-side critical section.
3d76c0829 Paul E. McKenney    2009-09-28  612   *
f27bc4873 Paul E. McKenney    2014-05-04  613   * In most situations, rcu_read_unlock() is immune from deadlock.
f27bc4873 Paul E. McKenney    2014-05-04  614   * However, in kernels built with CONFIG_RCU_BOOST, rcu_read_unlock()
f27bc4873 Paul E. McKenney    2014-05-04  615   * is responsible for deboosting, which it does via rt_mutex_unlock().
f27bc4873 Paul E. McKenney    2014-05-04  616   * Unfortunately, this function acquires the scheduler's runqueue and
f27bc4873 Paul E. McKenney    2014-05-04  617   * priority-inheritance spinlocks.  This means that deadlock could result
f27bc4873 Paul E. McKenney    2014-05-04  618   * if the caller of rcu_read_unlock() already holds one of these locks or
ec84b27f9 Anna-Maria Gleixner 2018-05-25  619   * any lock that is ever acquired while holding them.
f27bc4873 Paul E. McKenney    2014-05-04  620   *
f27bc4873 Paul E. McKenney    2014-05-04  621   * That said, RCU readers are never priority boosted unless they were
f27bc4873 Paul E. McKenney    2014-05-04  622   * preempted.  Therefore, one way to avoid deadlock is to make sure
f27bc4873 Paul E. McKenney    2014-05-04  623   * that preemption never happens within any RCU read-side critical
f27bc4873 Paul E. McKenney    2014-05-04  624   * section whose outermost rcu_read_unlock() is called with one of
f27bc4873 Paul E. McKenney    2014-05-04  625   * rt_mutex_unlock()'s locks held.  Such preemption can be avoided in
f27bc4873 Paul E. McKenney    2014-05-04  626   * a number of ways, for example, by invoking preempt_disable() before
f27bc4873 Paul E. McKenney    2014-05-04  627   * critical section's outermost rcu_read_lock().
f27bc4873 Paul E. McKenney    2014-05-04  628   *
f27bc4873 Paul E. McKenney    2014-05-04  629   * Given that the set of locks acquired by rt_mutex_unlock() might change
f27bc4873 Paul E. McKenney    2014-05-04  630   * at any time, a somewhat more future-proofed approach is to make sure
f27bc4873 Paul E. McKenney    2014-05-04  631   * that that preemption never happens within any RCU read-side critical
f27bc4873 Paul E. McKenney    2014-05-04  632   * section whose outermost rcu_read_unlock() is called with irqs disabled.
f27bc4873 Paul E. McKenney    2014-05-04  633   * This approach relies on the fact that rt_mutex_unlock() currently only
f27bc4873 Paul E. McKenney    2014-05-04  634   * acquires irq-disabled locks.
f27bc4873 Paul E. McKenney    2014-05-04  635   *
f27bc4873 Paul E. McKenney    2014-05-04  636   * The second of these two approaches is best in most situations,
f27bc4873 Paul E. McKenney    2014-05-04  637   * however, the first approach can also be useful, at least to those
f27bc4873 Paul E. McKenney    2014-05-04  638   * developers willing to keep abreast of the set of locks acquired by
f27bc4873 Paul E. McKenney    2014-05-04  639   * rt_mutex_unlock().
f27bc4873 Paul E. McKenney    2014-05-04  640   *
3d76c0829 Paul E. McKenney    2009-09-28  641   * See rcu_read_lock() for more information.
3d76c0829 Paul E. McKenney    2009-09-28  642   */
bc33f24bd Paul E. McKenney    2009-08-22  643  static inline void rcu_read_unlock(void)
bc33f24bd Paul E. McKenney    2009-08-22  644  {
f78f5b90c Paul E. McKenney    2015-06-18  645  	RCU_LOCKDEP_WARN(!rcu_is_watching(),
bde23c689 Heiko Carstens      2012-02-01  646  			 "rcu_read_unlock() used illegally while idle");
bc33f24bd Paul E. McKenney    2009-08-22 @647  	__release(RCU);
bc33f24bd Paul E. McKenney    2009-08-22  648  	__rcu_read_unlock();
d24209bb6 Paul E. McKenney    2015-01-21  649  	rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */
bc33f24bd Paul E. McKenney    2009-08-22  650  }
^1da177e4 Linus Torvalds      2005-04-16  651  

:::::: The code at line 647 was first introduced by commit
:::::: bc33f24bdca8b6e97376e3a182ab69e6cdefa989 rcu: Consolidate sparse and lockdep declarations in include/linux/rcupdate.h

:::::: TO: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
:::::: CC: Ingo Molnar <mingo@elte.hu>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

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

* Re: [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode
  2019-03-27 17:31 ` [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode Florian Westphal
  2019-03-28 11:39   ` Sabrina Dubroca
@ 2019-03-29 17:10   ` Eyal Birger
  2019-03-29 17:19     ` Florian Westphal
  1 sibling, 1 reply; 25+ messages in thread
From: Eyal Birger @ 2019-03-29 17:10 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Linux Kernel Network Developers, Steffen Klassert

Hi Florian,

On Wed, Mar 27, 2019 at 7:31 PM Florian Westphal <fw@strlen.de> wrote:
>
> No need for any indirection or abstraction here, both functions
> are pretty much the same and quite small, they also have no external
> dependencies.
>.
> diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
> index ea5ac053c15d..e3c7edd11e77 100644
> --- a/net/xfrm/xfrm_input.c
> +++ b/net/xfrm/xfrm_input.c
> @@ -186,6 +186,74 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
>  }
>  EXPORT_SYMBOL(xfrm_prepare_input);

nit: looks like xfrm_prepare_input() should be static now, no?

Eyal.

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

* Re: [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode
  2019-03-29 17:10   ` Eyal Birger
@ 2019-03-29 17:19     ` Florian Westphal
  0 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2019-03-29 17:19 UTC (permalink / raw)
  To: Eyal Birger
  Cc: Florian Westphal, Linux Kernel Network Developers, Steffen Klassert

Eyal Birger <eyal.birger@gmail.com> wrote:
> > diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
> > index ea5ac053c15d..e3c7edd11e77 100644
> > --- a/net/xfrm/xfrm_input.c
> > +++ b/net/xfrm/xfrm_input.c
> > @@ -186,6 +186,74 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
> >  }
> >  EXPORT_SYMBOL(xfrm_prepare_input);
> 
> nit: looks like xfrm_prepare_input() should be static now, no?

Indeed, I've fixed this up, thanks Eyal.

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

end of thread, other threads:[~2019-03-29 17:19 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-27 17:31 [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 01/11] xfrm: place af number into xfrm_mode struct Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 02/11] xfrm: prefer family stored in " Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 03/11] xfrm: remove input indirection from xfrm_mode Florian Westphal
2019-03-28 11:39   ` Sabrina Dubroca
2019-03-28 11:46     ` Florian Westphal
2019-03-29 17:10   ` Eyal Birger
2019-03-29 17:19     ` Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 04/11] xfrm: remove output " Florian Westphal
2019-03-28 11:12   ` Sabrina Dubroca
2019-03-28 11:27     ` Florian Westphal
2019-03-28 11:35       ` Sabrina Dubroca
2019-03-27 17:31 ` [PATCH ipsec-next 05/11] xfrm: remove xmit " Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 06/11] xfrm: remove gso_segment " Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 07/11] xfrm: remove input2 " Florian Westphal
2019-03-27 17:31 ` [PATCH ipsec-next 08/11] xfrm: remove output2 " Florian Westphal
2019-03-28 22:28   ` kbuild test robot
2019-03-29  2:15   ` kbuild test robot
2019-03-27 17:31 ` [PATCH ipsec-next 09/11] xfrm: remove afinfo pointer " Florian Westphal
2019-03-28 14:13   ` Sabrina Dubroca
2019-03-27 17:31 ` [PATCH ipsec-next 10/11] xfrm: make xfrm modes builtin Florian Westphal
2019-03-29  3:54   ` kbuild test robot
2019-03-27 17:31 ` [PATCH ipsec-next 11/11] xfrm: store xfrm_mode directly, not its address Florian Westphal
2019-03-28 11:42 ` [PATCH ipsec-next 00/11] xfrm: remove xfrm_mode indirections Benedict Wong
2019-03-28 11:48   ` Florian Westphal

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.