Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 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>

authored by

Ankit Garg and committed by
Jakub Kicinski
014c607f dc9c9193

+29 -12
+5 -3
drivers/net/ethernet/google/gve/gve_adminq.c
··· 1117 1117 1118 1118 gve_set_default_rss_sizes(priv); 1119 1119 1120 - /* DQO supports HW-GRO. */ 1120 + /* DQO supports HW-GRO and UDP_GSO */ 1121 1121 if (gve_is_dqo(priv)) { 1122 - priv->dev->hw_features |= NETIF_F_GRO_HW; 1123 - priv->dev->features |= NETIF_F_GRO_HW; 1122 + u64 additional_features = NETIF_F_GRO_HW | NETIF_F_GSO_UDP_L4; 1123 + 1124 + priv->dev->hw_features |= additional_features; 1125 + priv->dev->features |= additional_features; 1124 1126 } 1125 1127 1126 1128 priv->max_registered_pages =
+24 -9
drivers/net/ethernet/google/gve/gve_tx_dqo.c
··· 570 570 */ 571 571 static int gve_prep_tso(struct sk_buff *skb) 572 572 { 573 + struct skb_shared_info *shinfo = skb_shinfo(skb); 574 + u32 paylen, l4_start; 573 575 struct tcphdr *tcp; 576 + struct udphdr *udp; 574 577 int header_len; 575 - u32 paylen; 576 578 int err; 577 579 578 580 /* Note: HW requires MSS (gso_size) to be <= 9728 and the total length ··· 585 583 * - Kernel will not produce a TSO larger than 64k 586 584 */ 587 585 588 - if (unlikely(skb_shinfo(skb)->gso_size < GVE_TX_MIN_TSO_MSS_DQO)) 586 + if (unlikely(shinfo->gso_size < GVE_TX_MIN_TSO_MSS_DQO)) 589 587 return -1; 590 - 591 - if (!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) 592 - return -EINVAL; 593 588 594 589 /* Needed because we will modify header. */ 595 590 err = skb_cow_head(skb, 0); 596 591 if (err < 0) 597 592 return err; 598 593 599 - tcp = tcp_hdr(skb); 600 - paylen = skb->len - skb_transport_offset(skb); 601 - csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen)); 602 - header_len = skb_tcp_all_headers(skb); 594 + l4_start = skb_transport_offset(skb); 595 + paylen = skb->len - l4_start; 596 + 597 + switch (shinfo->gso_type) { 598 + case SKB_GSO_TCPV4: 599 + case SKB_GSO_TCPV6: 600 + tcp = tcp_hdr(skb); 601 + csum_replace_by_diff(&tcp->check, 602 + (__force __wsum)htonl(paylen)); 603 + header_len = skb_tcp_all_headers(skb); 604 + break; 605 + case SKB_GSO_UDP_L4: 606 + udp = udp_hdr(skb); 607 + csum_replace_by_diff(&udp->check, 608 + (__force __wsum)htonl(paylen)); 609 + header_len = sizeof(struct udphdr) + l4_start; 610 + break; 611 + default: 612 + return -EINVAL; 613 + } 603 614 604 615 if (unlikely(header_len > GVE_TX_MAX_HDR_SIZE_DQO)) 605 616 return -EINVAL;