Commit 83769c23fb18 for kernel

commit 83769c23fb1879edc916a526ba424285033baf2d
Author: Eric Dumazet <edumazet@google.com>
Date:   Wed Sep 23 14:59:42 2026 +0000

    gve: DQO: fix header length used by gve_can_send_tso() for UDP GSO

    gve_can_send_tso() computes how many buffers each segment of a GSO
    packet would span, and for this it needs the length of the headers
    that the device replicates in front of every segment.

    It unconditionally uses skb_tcp_all_headers(), which reads the doff
    field of the TCP header. SKB_GSO_UDP_L4 packets have no TCP header:
    tcp_hdrlen() then reads one byte of the UDP payload, and header_len
    can be anything in [0, 60] instead of the transport offset plus the
    eight bytes of the UDP header that gve_prep_tso() programs into the
    TSO context descriptor.

    A wrong header length shifts all the segment boundaries computed in
    the loop, so the number of buffers per segment can be over or under
    estimated. In the first case, GSO is needlessly disabled for this
    packet by gve_features_check_dqo() and the stack has to segment it.
    In the second case, the driver hands the device a packet whose
    segments span more than GVE_TX_MAX_DATA_DESCS buffers.

    Use the UDP header length for SKB_GSO_UDP_L4 packets, matching what
    gve_prep_tso() does.

    Fixes: 014c607f86ab ("gve: add support for UDP GSO for DQO format")
    Closes: https://lore.kernel.org/netdev/CANn89i+MS4L60sFQ49=-f-mibeveUfcrpVkD5X+Qy6SOnEpd6w@mail.gmail.com/
    Signed-off-by: Eric Dumazet <edumazet@google.com>
    Cc: Ankit Garg <nktgrg@google.com>
    Cc: Harshitha Ramamurthy <hramamurthy@google.com>
    Cc: Joshua Washington <joshwash@google.com>
    Cc: Willem de Bruijn <willemb@google.com>
    Reviewed-by: Ankit Garg <nktgrg@google.com>
    Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
    Link: https://patch.msgid.link/20260923145942.731365-1-edumazet@google.com
    Signed-off-by: Jakub Kicinski <kuba@kernel.org>

diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index 80ab0a449ff5..0f6f7c5dbb2e 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -918,13 +918,19 @@ static bool gve_can_send_tso(const struct sk_buff *skb)
 {
 	const int max_bufs_per_seg = GVE_TX_MAX_DATA_DESCS - 1;
 	const struct skb_shared_info *shinfo = skb_shinfo(skb);
-	const int header_len = skb_tcp_all_headers(skb);
 	const int gso_size = shinfo->gso_size;
 	int cur_seg_num_bufs;
 	int prev_frag_size;
 	int cur_seg_size;
+	int header_len;
 	int i;

+	/* Must match the header length programmed by gve_prep_tso(). */
+	if (skb_is_gso_tcp(skb))
+		header_len = skb_tcp_all_headers(skb);
+	else
+		header_len = skb_transport_offset(skb) + sizeof(struct udphdr);
+
 	cur_seg_size = skb_headlen(skb) - header_len;
 	prev_frag_size = skb_headlen(skb);
 	cur_seg_num_bufs = cur_seg_size > 0;