]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
gve: add support for UDP GSO for DQO format
authorAnkit Garg <nktgrg@google.com>
Fri, 6 Mar 2026 22:48:16 +0000 (22:48 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 10 Mar 2026 02:17:52 +0000 (19:17 -0700)
Enable support for UDP GSO when using DQO format. Advertise the feature
flag during device initialization and enable offload by default.

Signed-off-by: Ankit Garg <nktgrg@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
Link: https://patch.msgid.link/20260306224816.3391551-1-hramamurthy@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/google/gve/gve_adminq.c
drivers/net/ethernet/google/gve/gve_tx_dqo.c

index 129f3e11a442a55974ae815d4e91ee75c6878ed6..08587bf40ed4a556c3d5bd0121bd2997bfecc13d 100644 (file)
@@ -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 =
index f33035018b89ce3e5f84b1c22c246c2f68177ef3..80ab0a449ff54e3d19e9c69226949465d48dfe3f 100644 (file)
@@ -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;
 
-       tcp = tcp_hdr(skb);
-       paylen = skb->len - skb_transport_offset(skb);
-       csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen));
-       header_len = skb_tcp_all_headers(skb);
+       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);
+               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;