Commit 0c09e89f authored by Paolo Abeni's avatar Paolo Abeni Committed by Jakub Kicinski
Browse files

geneve: expose gso partial features for tunnel offload



GSO partial features for tunnels do not require any kind of support from
the underlying device: we can safely add them to the geneve UDP tunnel.

The only point of attention is the skb required features propagation in
the device xmit op: partial features must be stripped, except for
UDP_TUNNEL*.

Keep partial features disabled by default.

Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/d851ca8e928cf05d68310bcbaeaa5e9e0b01e058.1769011015.git.pabeni@redhat.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 31c5a71d
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -774,6 +774,7 @@ static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
	bool udp_sum = test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags);
	struct genevehdr *gnvh;
	__be16 inner_proto;
	bool double_encap;
	int min_headroom;
	int err;

@@ -786,6 +787,7 @@ static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
	if (unlikely(err))
		goto free_dst;

	double_encap = udp_tunnel_handle_partial(skb);
	err = udp_tunnel_handle_offloads(skb, udp_sum);
	if (err)
		goto free_dst;
@@ -793,7 +795,7 @@ static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
	gnvh = __skb_push(skb, sizeof(*gnvh) + info->options_len);
	inner_proto = inner_proto_inherit ? skb->protocol : htons(ETH_P_TEB);
	geneve_build_header(gnvh, info, inner_proto);
	skb_set_inner_protocol(skb, inner_proto);
	udp_tunnel_set_inner_protocol(skb, double_encap, inner_proto);
	return 0;

free_dst:
@@ -1211,9 +1213,16 @@ static void geneve_setup(struct net_device *dev)
	dev->features    |= NETIF_F_RXCSUM;
	dev->features    |= NETIF_F_GSO_SOFTWARE;

	/* Partial features are disabled by default. */
	dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
	dev->hw_features |= NETIF_F_RXCSUM;
	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
	dev->hw_features |= UDP_TUNNEL_PARTIAL_FEATURES;
	dev->hw_features |= NETIF_F_GSO_PARTIAL;

	dev->hw_enc_features = dev->hw_features;
	dev->gso_partial_features = UDP_TUNNEL_PARTIAL_FEATURES;
	dev->mangleid_features = NETIF_F_GSO_PARTIAL;

	dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
	/* MTU range: 68 - (something less than 65535) */
+32 −0
Original line number Diff line number Diff line
@@ -10,6 +10,11 @@
#include <net/ipv6_stubs.h>
#endif

#define UDP_TUNNEL_PARTIAL_FEATURES	NETIF_F_GSO_ENCAP_ALL
#define UDP_TUNNEL_STRIPPED_GSO_TYPES	((UDP_TUNNEL_PARTIAL_FEATURES |	\
					  NETIF_F_GSO_PARTIAL) >>	\
					 NETIF_F_GSO_SHIFT)

struct udp_port_cfg {
	u8			family;

@@ -145,6 +150,33 @@ void udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
			  __be16 src_port, __be16 dst_port, bool nocheck,
			  u16 ip6cb_flags);

static inline bool udp_tunnel_handle_partial(struct sk_buff *skb)
{
	bool double_encap = !!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL);

	/*
	 * If the skb went through partial segmentation, lower devices
	 * will not need to offload the related features - except for
	 * UDP_TUNNEL, that will be re-added by the later
	 * udp_tunnel_handle_offloads().
	 */
	if (double_encap)
		skb_shinfo(skb)->gso_type &= ~UDP_TUNNEL_STRIPPED_GSO_TYPES;
	return double_encap;
}

static inline void udp_tunnel_set_inner_protocol(struct sk_buff *skb,
						 bool double_encap,
						 __be16 inner_proto)
{
	/*
	 * The inner protocol has been set by the nested tunnel, don't
	 * overraid it.
	 */
	if (!double_encap)
		skb_set_inner_protocol(skb, inner_proto);
}

void udp_tunnel_sock_release(struct socket *sock);

struct rtable *udp_tunnel_dst_lookup(struct sk_buff *skb,