Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b17f709a authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller
Browse files

gue: TX support for using remote checksum offload option



Add if_tunnel flag TUNNEL_ENCAP_FLAG_REMCSUM to configure
remote checksum offload on an IP tunnel. Add logic in gue_build_header
to insert remote checksum offload option.

Signed-off-by: default avatarTom Herbert <therbert@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c1aa8347
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -20,7 +20,19 @@ static size_t fou_encap_hlen(struct ip_tunnel_encap *e)

static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
{
	return sizeof(struct udphdr) + sizeof(struct guehdr);
	size_t len;
	bool need_priv = false;

	len = sizeof(struct udphdr) + sizeof(struct guehdr);

	if (e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) {
		len += GUE_PLEN_REMCSUM;
		need_priv = true;
	}

	len += need_priv ? GUE_LEN_PRIV : 0;

	return len;
}

#endif
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ enum tunnel_encap_types {

#define TUNNEL_ENCAP_FLAG_CSUM		(1<<0)
#define TUNNEL_ENCAP_FLAG_CSUM6		(1<<1)
#define TUNNEL_ENCAP_FLAG_REMCSUM	(1<<2)

/* SIT-mode i_flags */
#define	SIT_ISATAP	0x0001
+32 −3
Original line number Diff line number Diff line
@@ -562,11 +562,19 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
	bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
	int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
	struct guehdr *guehdr;
	size_t optlen = 0;
	size_t hdrlen, optlen = 0;
	__be16 sport;
	void *data;
	bool need_priv = false;

	if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) &&
	    skb->ip_summed == CHECKSUM_PARTIAL) {
		csum = false;
		optlen += GUE_PLEN_REMCSUM;
		type |= SKB_GSO_TUNNEL_REMCSUM;
		need_priv = true;
	}

	optlen += need_priv ? GUE_LEN_PRIV : 0;

	skb = iptunnel_handle_offloads(skb, csum, type);
@@ -578,7 +586,9 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
	sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
					       skb, 0, 0, false);

	skb_push(skb, sizeof(struct guehdr) + optlen);
	hdrlen = sizeof(struct guehdr) + optlen;

	skb_push(skb, hdrlen);

	guehdr = (struct guehdr *)skb->data;

@@ -597,7 +607,26 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
		*flags = 0;
		data += GUE_LEN_PRIV;

		/* Add private flags */
		if (type & SKB_GSO_TUNNEL_REMCSUM) {
			u16 csum_start = skb_checksum_start_offset(skb);
			__be16 *pd = data;

			if (csum_start < hdrlen)
				return -EINVAL;

			csum_start -= hdrlen;
			pd[0] = htons(csum_start);
			pd[1] = htons(csum_start + skb->csum_offset);

			if (!skb_is_gso(skb)) {
				skb->ip_summed = CHECKSUM_NONE;
				skb->encapsulation = 0;
			}

			*flags |= GUE_PFLAG_REMCSUM;
			data += GUE_PLEN_REMCSUM;
		}

	}

	fou_build_udp(skb, e, fl4, protocol, sport);