Commit 014c607f authored by Ankit Garg's avatar Ankit Garg Committed by Jakub Kicinski
Browse files

gve: add support for UDP GSO for DQO format



Enable support for UDP GSO when using DQO format. Advertise the feature
flag during device initialization and enable offload by default.

Signed-off-by: default avatarAnkit Garg <nktgrg@google.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarHarshitha Ramamurthy <hramamurthy@google.com>
Link: https://patch.msgid.link/20260306224816.3391551-1-hramamurthy@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent dc9c9193
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -1117,10 +1117,12 @@ int gve_adminq_describe_device(struct gve_priv *priv)

	gve_set_default_rss_sizes(priv);

	/* DQO supports HW-GRO. */
	/* DQO supports HW-GRO and UDP_GSO */
	if (gve_is_dqo(priv)) {
		priv->dev->hw_features |= NETIF_F_GRO_HW;
		priv->dev->features |= NETIF_F_GRO_HW;
		u64 additional_features = NETIF_F_GRO_HW | NETIF_F_GSO_UDP_L4;

		priv->dev->hw_features |= additional_features;
		priv->dev->features |= additional_features;
	}

	priv->max_registered_pages =
+24 −9
Original line number Diff line number Diff line
@@ -570,9 +570,11 @@ static void gve_tx_fill_pkt_desc_dqo(struct gve_tx_ring *tx, u32 *desc_idx,
 */
static int gve_prep_tso(struct sk_buff *skb)
{
	struct skb_shared_info *shinfo = skb_shinfo(skb);
	u32 paylen, l4_start;
	struct tcphdr *tcp;
	struct udphdr *udp;
	int header_len;
	u32 paylen;
	int err;

	/* Note: HW requires MSS (gso_size) to be <= 9728 and the total length
@@ -583,21 +585,34 @@ static int gve_prep_tso(struct sk_buff *skb)
	 * - Kernel will not produce a TSO larger than 64k
	 */

	if (unlikely(skb_shinfo(skb)->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
	if (unlikely(shinfo->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
		return -1;

	if (!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
		return -EINVAL;

	/* Needed because we will modify header. */
	err = skb_cow_head(skb, 0);
	if (err < 0)
		return err;

	l4_start = skb_transport_offset(skb);
	paylen = skb->len - l4_start;

	switch (shinfo->gso_type) {
	case SKB_GSO_TCPV4:
	case SKB_GSO_TCPV6:
		tcp = tcp_hdr(skb);
	paylen = skb->len - skb_transport_offset(skb);
	csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen));
		csum_replace_by_diff(&tcp->check,
				     (__force __wsum)htonl(paylen));
		header_len = skb_tcp_all_headers(skb);
		break;
	case SKB_GSO_UDP_L4:
		udp = udp_hdr(skb);
		csum_replace_by_diff(&udp->check,
				     (__force __wsum)htonl(paylen));
		header_len = sizeof(struct udphdr) + l4_start;
		break;
	default:
		return -EINVAL;
	}

	if (unlikely(header_len > GVE_TX_MAX_HDR_SIZE_DQO))
		return -EINVAL;