Commit acc086bf authored by David S. Miller's avatar David S. Miller
Browse files


Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2020-03-28

1) Use kmem_cache_zalloc() instead of kmem_cache_alloc()
   in xfrm_state_alloc(). From Huang Zijiang.

2) esp_output_fill_trailer() is the same in IPv4 and IPv6,
   so share this function to avoide code duplcation.
   From Raed Salem.

3) Add offload support for esp beet mode.
   From Xin Long.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ee91a83e 30849175
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -11,6 +11,22 @@ static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
	return (struct ip_esp_hdr *)skb_transport_header(skb);
}

static inline void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
{
	/* Fill padding... */
	if (tfclen) {
		memset(tail, 0, tfclen);
		tail += tfclen;
	}
	do {
		int i;
		for (i = 0; i < plen - 2; i++)
			tail[i] = i + 1;
	} while (0);
	tail[plen - 2] = plen - 2;
	tail[plen - 1] = proto;
}

struct esp_info {
	struct	ip_esp_hdr *esph;
	__be64	seqno;
+0 −16
Original line number Diff line number Diff line
@@ -341,22 +341,6 @@ static void esp_output_done_esn(struct crypto_async_request *base, int err)
	esp_output_done(base, err);
}

static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
{
	/* Fill padding... */
	if (tfclen) {
		memset(tail, 0, tfclen);
		tail += tfclen;
	}
	do {
		int i;
		for (i = 0; i < plen - 2; i++)
			tail[i] = i + 1;
	} while (0);
	tail[plen - 2] = plen - 2;
	tail[plen - 1] = proto;
}

static struct ip_esp_hdr *esp_output_udp_encap(struct sk_buff *skb,
					       int encap_type,
					       struct esp_info *esp,
+32 −0
Original line number Diff line number Diff line
@@ -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);
+0 −16
Original line number Diff line number Diff line
@@ -207,22 +207,6 @@ static void esp_output_done_esn(struct crypto_async_request *base, int err)
	esp_output_done(base, err);
}

static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
{
	/* Fill padding... */
	if (tfclen) {
		memset(tail, 0, tfclen);
		tail += tfclen;
	}
	do {
		int i;
		for (i = 0; i < plen - 2; i++)
			tail[i] = i + 1;
	} while (0);
	tail[plen - 2] = plen - 2;
	tail[plen - 1] = proto;
}

int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
{
	u8 *tail;
+36 −0
Original line number Diff line number Diff line
@@ -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);
Loading