netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode
@ 2020-03-26  9:02 Xin Long
  2020-03-26  9:02 ` [PATCH ipsec-next 1/3] esp4: add gso_segment for esp4 " Xin Long
  2020-03-27  7:51 ` [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode Steffen Klassert
  0 siblings, 2 replies; 5+ messages in thread
From: Xin Long @ 2020-03-26  9:02 UTC (permalink / raw)
  To: netdev
  Cc: Steffen Klassert, Herbert Xu, David S. Miller, Florian Westphal,
	Sabrina Dubroca

This patchset is to add gso_segment functions for esp4 and esp6
beet mode, and prep function for both, and tested with 6 cases:

  1. IPv4 INNER ADDRESSES
     - OUTER v4 ADDRESSES
     - OUTER v6 ADDRESSES

  2. IPv4 INNER ADDRESSES with options
     - OUTER v4 ADDRESSES
     - OUTER v6 ADDRESSES

  3. IPv6 INNER ADDRESSES
     - OUTER v4 ADDRESSES
     - OUTER v6 ADDRESSES

With this patchset, an esp beet mode skb would be segmented and
encryped until it arrives in dev_queue_xmit()/validate_xmit_skb().

Xin Long (3):
  esp4: add gso_segment for esp4 beet mode
  esp6: add gso_segment for esp6 beet mode
  xfrm: add prep for esp beet mode offload

 net/ipv4/esp4_offload.c | 32 ++++++++++++++++++++++++++++++++
 net/ipv6/esp6_offload.c | 36 ++++++++++++++++++++++++++++++++++++
 net/xfrm/xfrm_device.c  | 28 +++++++++++++++++++++++++++-
 3 files changed, 95 insertions(+), 1 deletion(-)

-- 
2.1.0


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

* [PATCH ipsec-next 1/3] esp4: add gso_segment for esp4 beet mode
  2020-03-26  9:02 [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode Xin Long
@ 2020-03-26  9:02 ` Xin Long
  2020-03-26  9:02   ` [PATCH ipsec-next 2/3] esp6: add gso_segment for esp6 " Xin Long
  2020-03-27  7:51 ` [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode Steffen Klassert
  1 sibling, 1 reply; 5+ messages in thread
From: Xin Long @ 2020-03-26  9:02 UTC (permalink / raw)
  To: netdev
  Cc: Steffen Klassert, Herbert Xu, David S. Miller, Florian Westphal,
	Sabrina Dubroca

Similar to xfrm4_tunnel/transport_gso_segment(), _gso_segment()
is added to do gso_segment for esp4 beet mode. Before calling
inet_offloads[proto]->callbacks.gso_segment, it needs to do:

  - Get the upper proto from ph header to get its gso_segment
    when xo->proto is IPPROTO_BEETPH.

  - Add SKB_GSO_TCPV4 to gso_type if x->sel.family == AF_INET6
    and the proto == IPPROTO_TCP, so that the current tcp ipv4
    packet can be segmented.

  - Calculate a right value for skb->transport_header and move
    skb->data to the transport header position.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/ipv4/esp4_offload.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index e2e219c..731022c 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -132,6 +132,36 @@ static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 	return segs;
 }
 
+static struct sk_buff *xfrm4_beet_gso_segment(struct xfrm_state *x,
+					      struct sk_buff *skb,
+					      netdev_features_t features)
+{
+	struct xfrm_offload *xo = xfrm_offload(skb);
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	const struct net_offload *ops;
+	int proto = xo->proto;
+
+	skb->transport_header += x->props.header_len;
+
+	if (proto == IPPROTO_BEETPH) {
+		struct ip_beet_phdr *ph = (struct ip_beet_phdr *)skb->data;
+
+		skb->transport_header += ph->hdrlen * 8;
+		proto = ph->nexthdr;
+	} else if (x->sel.family != AF_INET6) {
+		skb->transport_header -= IPV4_BEET_PHMAXLEN;
+	} else if (proto == IPPROTO_TCP) {
+		skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
+	}
+
+	__skb_pull(skb, skb_transport_offset(skb));
+	ops = rcu_dereference(inet_offloads[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)
@@ -141,6 +171,8 @@ static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
 		return xfrm4_tunnel_gso_segment(x, skb, features);
 	case XFRM_MODE_TRANSPORT:
 		return xfrm4_transport_gso_segment(x, skb, features);
+	case XFRM_MODE_BEET:
+		return xfrm4_beet_gso_segment(x, skb, features);
 	}
 
 	return ERR_PTR(-EOPNOTSUPP);
-- 
2.1.0


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

* [PATCH ipsec-next 2/3] esp6: add gso_segment for esp6 beet mode
  2020-03-26  9:02 ` [PATCH ipsec-next 1/3] esp4: add gso_segment for esp4 " Xin Long
@ 2020-03-26  9:02   ` Xin Long
  2020-03-26  9:02     ` [PATCH ipsec-next 3/3] xfrm: add prep for esp beet mode offload Xin Long
  0 siblings, 1 reply; 5+ messages in thread
From: Xin Long @ 2020-03-26  9:02 UTC (permalink / raw)
  To: netdev
  Cc: Steffen Klassert, Herbert Xu, David S. Miller, Florian Westphal,
	Sabrina Dubroca

Similar to xfrm6_tunnel/transport_gso_segment(), _gso_segment()
is added to do gso_segment for esp6 beet mode. Before calling
inet6_offloads[proto]->callbacks.gso_segment, it needs to do:

  - Get the upper proto from ph header to get its gso_segment
    when xo->proto is IPPROTO_BEETPH.

  - Add SKB_GSO_TCPV6 to gso_type if x->sel.family != AF_INET6
    and the proto == IPPROTO_TCP, so that the current tcp ipv6
    packet can be segmented.

  - Calculate a right value for skb->transport_header and move
    skb->data to the transport header position.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/ipv6/esp6_offload.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index fd53505..8eab2c8 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -159,6 +159,40 @@ static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,
 	return segs;
 }
 
+static struct sk_buff *xfrm6_beet_gso_segment(struct xfrm_state *x,
+					      struct sk_buff *skb,
+					      netdev_features_t features)
+{
+	struct xfrm_offload *xo = xfrm_offload(skb);
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	const struct net_offload *ops;
+	int proto = xo->proto;
+
+	skb->transport_header += x->props.header_len;
+
+	if (proto == IPPROTO_BEETPH) {
+		struct ip_beet_phdr *ph = (struct ip_beet_phdr *)skb->data;
+
+		skb->transport_header += ph->hdrlen * 8;
+		proto = ph->nexthdr;
+	}
+
+	if (x->sel.family != AF_INET6) {
+		skb->transport_header -=
+			(sizeof(struct ipv6hdr) - sizeof(struct iphdr));
+
+		if (proto == IPPROTO_TCP)
+			skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV6;
+	}
+
+	__skb_pull(skb, skb_transport_offset(skb));
+	ops = rcu_dereference(inet6_offloads[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)
@@ -168,6 +202,8 @@ static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
 		return xfrm6_tunnel_gso_segment(x, skb, features);
 	case XFRM_MODE_TRANSPORT:
 		return xfrm6_transport_gso_segment(x, skb, features);
+	case XFRM_MODE_BEET:
+		return xfrm6_beet_gso_segment(x, skb, features);
 	}
 
 	return ERR_PTR(-EOPNOTSUPP);
-- 
2.1.0


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

* [PATCH ipsec-next 3/3] xfrm: add prep for esp beet mode offload
  2020-03-26  9:02   ` [PATCH ipsec-next 2/3] esp6: add gso_segment for esp6 " Xin Long
@ 2020-03-26  9:02     ` Xin Long
  0 siblings, 0 replies; 5+ messages in thread
From: Xin Long @ 2020-03-26  9:02 UTC (permalink / raw)
  To: netdev
  Cc: Steffen Klassert, Herbert Xu, David S. Miller, Florian Westphal,
	Sabrina Dubroca

Like __xfrm_transport/mode_tunnel_prep(), this patch is to add
__xfrm_mode_beet_prep() to fix the transport_header for gso
segments, and reset skb mac_len, and pull skb data to the
proto inside esp.

This patch also fixes a panic, reported by ltp:

  # modprobe esp4_offload
  # runltp -f net_stress.ipsec_tcp

  [ 2452.780511] kernel BUG at net/core/skbuff.c:109!
  [ 2452.799851] Call Trace:
  [ 2452.800298]  <IRQ>
  [ 2452.800705]  skb_push.cold.98+0x14/0x20
  [ 2452.801396]  esp_xmit+0x17b/0x270 [esp4_offload]
  [ 2452.802799]  validate_xmit_xfrm+0x22f/0x2e0
  [ 2452.804285]  __dev_queue_xmit+0x589/0x910
  [ 2452.806264]  __neigh_update+0x3d7/0xa50
  [ 2452.806958]  arp_process+0x259/0x810
  [ 2452.807589]  arp_rcv+0x18a/0x1c

It was caused by the skb going to esp_xmit with a wrong transport
header.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/xfrm/xfrm_device.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 50f567a..fa2a506 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -46,6 +46,25 @@ static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
 	pskb_pull(skb, skb->mac_len + x->props.header_len);
 }
 
+static void __xfrm_mode_beet_prep(struct xfrm_state *x, struct sk_buff *skb,
+				  unsigned int hsize)
+{
+	struct xfrm_offload *xo = xfrm_offload(skb);
+	int phlen = 0;
+
+	if (xo->flags & XFRM_GSO_SEGMENT)
+		skb->transport_header = skb->network_header + hsize;
+
+	skb_reset_mac_len(skb);
+	if (x->sel.family != AF_INET6) {
+		phlen = IPV4_BEET_PHMAXLEN;
+		if (x->outer_mode.family == AF_INET6)
+			phlen += sizeof(struct ipv6hdr) - sizeof(struct iphdr);
+	}
+
+	pskb_pull(skb, skb->mac_len + hsize + (x->props.header_len - phlen));
+}
+
 /* 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)
 {
@@ -66,9 +85,16 @@ static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
 			return __xfrm_transport_prep(x, skb,
 						     sizeof(struct ipv6hdr));
 		break;
+	case XFRM_MODE_BEET:
+		if (x->outer_mode.family == AF_INET)
+			return __xfrm_mode_beet_prep(x, skb,
+						     sizeof(struct iphdr));
+		if (x->outer_mode.family == AF_INET6)
+			return __xfrm_mode_beet_prep(x, skb,
+						     sizeof(struct ipv6hdr));
+		break;
 	case XFRM_MODE_ROUTEOPTIMIZATION:
 	case XFRM_MODE_IN_TRIGGER:
-	case XFRM_MODE_BEET:
 		break;
 	}
 }
-- 
2.1.0


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

* Re: [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode
  2020-03-26  9:02 [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode Xin Long
  2020-03-26  9:02 ` [PATCH ipsec-next 1/3] esp4: add gso_segment for esp4 " Xin Long
@ 2020-03-27  7:51 ` Steffen Klassert
  1 sibling, 0 replies; 5+ messages in thread
From: Steffen Klassert @ 2020-03-27  7:51 UTC (permalink / raw)
  To: Xin Long
  Cc: netdev, Herbert Xu, David S. Miller, Florian Westphal, Sabrina Dubroca

On Thu, Mar 26, 2020 at 05:02:28PM +0800, Xin Long wrote:
> This patchset is to add gso_segment functions for esp4 and esp6
> beet mode, and prep function for both, and tested with 6 cases:
> 
>   1. IPv4 INNER ADDRESSES
>      - OUTER v4 ADDRESSES
>      - OUTER v6 ADDRESSES
> 
>   2. IPv4 INNER ADDRESSES with options
>      - OUTER v4 ADDRESSES
>      - OUTER v6 ADDRESSES
> 
>   3. IPv6 INNER ADDRESSES
>      - OUTER v4 ADDRESSES
>      - OUTER v6 ADDRESSES
> 
> With this patchset, an esp beet mode skb would be segmented and
> encryped until it arrives in dev_queue_xmit()/validate_xmit_skb().
> 
> Xin Long (3):
>   esp4: add gso_segment for esp4 beet mode
>   esp6: add gso_segment for esp6 beet mode
>   xfrm: add prep for esp beet mode offload

Series applied to ipsec-next, thanks a lot Xin!

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

end of thread, other threads:[~2020-03-27  7:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-26  9:02 [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode Xin Long
2020-03-26  9:02 ` [PATCH ipsec-next 1/3] esp4: add gso_segment for esp4 " Xin Long
2020-03-26  9:02   ` [PATCH ipsec-next 2/3] esp6: add gso_segment for esp6 " Xin Long
2020-03-26  9:02     ` [PATCH ipsec-next 3/3] xfrm: add prep for esp beet mode offload Xin Long
2020-03-27  7:51 ` [PATCH ipsec-next 0/3] xfrm: add offload support for esp beet mode Steffen Klassert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).