* [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
@ 2026-09-23 14:10 Hannu Varjoranta
2026-09-23 14:23 ` Eric Dumazet
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Hannu Varjoranta @ 2026-09-23 14:10 UTC (permalink / raw)
To: Joshua Washington, Harshitha Ramamurthy
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Ankit Garg, Willem de Bruijn,
Praveen Kaligineedi
Since commit 014c607f86ab ("gve: add support for UDP GSO for DQO
format"), gve_prep_tso() matches shinfo->gso_type exactly. gso_type is
a bitmask, though: SKB_GSO_DODGY is set on every GSO packet that comes
from tun/tap, packet sockets or other untrusted sources, and
SKB_GSO_TCP_ECN and SKB_GSO_TCP_FIXEDID can be set as well. Such packets
hit the default case, gve_tx_add_skb_dqo() fails and gve_try_tx_skb()
drops them, counting them in tx_dropped.
These packets do reach the driver: tcp_gso_segment() passes DODGY skbs
through unsegmented to devices that support TSO, after recomputing
gso_segs, so drivers must tolerate the bit.
This breaks virtual machines behind a tap on GCE instances using the DQO
queue formats. Every TSO packet forwarded from a guest (gso_type
SKB_GSO_TCPV4 | SKB_GSO_DODGY) is dropped, and guest uploads slow to a
crawl of retransmissions or stall entirely, while the host's own TSO
traffic (gso_type SKB_GSO_TCPV4) is unaffected. On an n4 instance
(DQO-QPL) with a Cloud Hypervisor guest, a 64 MB upload from the guest
went from a 60 s timeout at ~0.9 MB/s to 0.19 s with this change, with
tx_dropped no longer increasing.
Restore the bitmask test that commit 1b9f75634441 ("gve: ignore
nonrelevant GSO type bits when processing TSO headers") introduced for
the same problem, keeping the UDP GSO support.
Fixes: 014c607f86ab ("gve: add support for UDP GSO for DQO format")
Signed-off-by: Hannu Varjoranta <hannu@varjosoft.com>
---
drivers/net/ethernet/google/gve/gve_tx_dqo.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index 80ab0a449ff5..675c7644817a 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -596,21 +596,20 @@ static int gve_prep_tso(struct sk_buff *skb)
l4_start = skb_transport_offset(skb);
paylen = skb->len - l4_start;
- switch (shinfo->gso_type) {
- case SKB_GSO_TCPV4:
- case SKB_GSO_TCPV6:
+ /* gso_type is a bitmask: SKB_GSO_DODGY, SKB_GSO_TCP_ECN and
+ * SKB_GSO_TCP_FIXEDID may be set alongside the protocol bit.
+ */
+ if (shinfo->gso_type & (SKB_GSO_TCPV4 | 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:
+ } else if (shinfo->gso_type & 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:
+ } else {
return -EINVAL;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-23 14:10 [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits Hannu Varjoranta
@ 2026-09-23 14:23 ` Eric Dumazet
2026-09-23 14:38 ` Eric Dumazet
2026-09-23 17:05 ` Ankit Garg
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2026-09-23 14:23 UTC (permalink / raw)
To: Hannu Varjoranta
Cc: Joshua Washington, Harshitha Ramamurthy, netdev, Andrew Lunn,
David S . Miller, Jakub Kicinski, Paolo Abeni, Ankit Garg,
Willem de Bruijn, Praveen Kaligineedi
On Wed, Sep 23, 2026 at 4:11 PM Hannu Varjoranta <hannu@varjosoft.com> wrote:
>
> Since commit 014c607f86ab ("gve: add support for UDP GSO for DQO
> format"), gve_prep_tso() matches shinfo->gso_type exactly. gso_type is
> a bitmask, though: SKB_GSO_DODGY is set on every GSO packet that comes
> from tun/tap, packet sockets or other untrusted sources, and
> SKB_GSO_TCP_ECN and SKB_GSO_TCP_FIXEDID can be set as well. Such packets
> hit the default case, gve_tx_add_skb_dqo() fails and gve_try_tx_skb()
> drops them, counting them in tx_dropped.
>
> These packets do reach the driver: tcp_gso_segment() passes DODGY skbs
> through unsegmented to devices that support TSO, after recomputing
> gso_segs, so drivers must tolerate the bit.
>
> This breaks virtual machines behind a tap on GCE instances using the DQO
> queue formats. Every TSO packet forwarded from a guest (gso_type
> SKB_GSO_TCPV4 | SKB_GSO_DODGY) is dropped, and guest uploads slow to a
> crawl of retransmissions or stall entirely, while the host's own TSO
> traffic (gso_type SKB_GSO_TCPV4) is unaffected. On an n4 instance
> (DQO-QPL) with a Cloud Hypervisor guest, a 64 MB upload from the guest
> went from a 60 s timeout at ~0.9 MB/s to 0.19 s with this change, with
> tx_dropped no longer increasing.
>
> Restore the bitmask test that commit 1b9f75634441 ("gve: ignore
> nonrelevant GSO type bits when processing TSO headers") introduced for
> the same problem, keeping the UDP GSO support.
>
> Fixes: 014c607f86ab ("gve: add support for UDP GSO for DQO format")
> Signed-off-by: Hannu Varjoranta <hannu@varjosoft.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Thanks for the fix!
Note the breakage is not limited to tap/VM traffic: gve sets
NETIF_F_TSO_ECN, and tcp_ecn_send() sets SKB_GSO_TCP_ECN on TSO skbs
carrying CWR, so plain host TCP with ECN has been losing those packets
as well since v7.1.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-23 14:23 ` Eric Dumazet
@ 2026-09-23 14:38 ` Eric Dumazet
0 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2026-09-23 14:38 UTC (permalink / raw)
To: Hannu Varjoranta
Cc: Joshua Washington, Harshitha Ramamurthy, netdev, Andrew Lunn,
David S . Miller, Jakub Kicinski, Paolo Abeni, Ankit Garg,
Willem de Bruijn, Praveen Kaligineedi
On Wed, Sep 23, 2026 at 4:23 PM Eric Dumazet <edumazet@google.com> wrote:
>
> On Wed, Sep 23, 2026 at 4:11 PM Hannu Varjoranta <hannu@varjosoft.com> wrote:
> >
> > Since commit 014c607f86ab ("gve: add support for UDP GSO for DQO
> > format"), gve_prep_tso() matches shinfo->gso_type exactly. gso_type is
> > a bitmask, though: SKB_GSO_DODGY is set on every GSO packet that comes
> > from tun/tap, packet sockets or other untrusted sources, and
> > SKB_GSO_TCP_ECN and SKB_GSO_TCP_FIXEDID can be set as well. Such packets
> > hit the default case, gve_tx_add_skb_dqo() fails and gve_try_tx_skb()
> > drops them, counting them in tx_dropped.
> >
> > These packets do reach the driver: tcp_gso_segment() passes DODGY skbs
> > through unsegmented to devices that support TSO, after recomputing
> > gso_segs, so drivers must tolerate the bit.
> >
> > This breaks virtual machines behind a tap on GCE instances using the DQO
> > queue formats. Every TSO packet forwarded from a guest (gso_type
> > SKB_GSO_TCPV4 | SKB_GSO_DODGY) is dropped, and guest uploads slow to a
> > crawl of retransmissions or stall entirely, while the host's own TSO
> > traffic (gso_type SKB_GSO_TCPV4) is unaffected. On an n4 instance
> > (DQO-QPL) with a Cloud Hypervisor guest, a 64 MB upload from the guest
> > went from a 60 s timeout at ~0.9 MB/s to 0.19 s with this change, with
> > tx_dropped no longer increasing.
> >
> > Restore the bitmask test that commit 1b9f75634441 ("gve: ignore
> > nonrelevant GSO type bits when processing TSO headers") introduced for
> > the same problem, keeping the UDP GSO support.
> >
> > Fixes: 014c607f86ab ("gve: add support for UDP GSO for DQO format")
> > Signed-off-by: Hannu Varjoranta <hannu@varjosoft.com>
>
> Reviewed-by: Eric Dumazet <edumazet@google.com>
>
> Thanks for the fix!
>
> Note the breakage is not limited to tap/VM traffic: gve sets
> NETIF_F_TSO_ECN, and tcp_ecn_send() sets SKB_GSO_TCP_ECN on TSO skbs
> carrying CWR, so plain host TCP with ECN has been losing those packets
> as well since v7.1.
BTW, there is another related bug in gve_can_send_tso()
Using skb_tcp_all_headers() for UDP does not look right.
I will send a fix like the following, unless gve folks (and/or Willem) disagree.
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index 80ab0a449ff54e3d19e9c69226949465d48dfe3f..0f6f7c5dbb2e027bb0a45eeaf76cfabff558ec79
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;
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-23 14:10 [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits Hannu Varjoranta
2026-09-23 14:23 ` Eric Dumazet
@ 2026-09-23 17:05 ` Ankit Garg
2026-09-23 19:23 ` Harshitha Ramamurthy
2026-09-25 2:13 ` netdev-bot+sashiko
3 siblings, 0 replies; 9+ messages in thread
From: Ankit Garg @ 2026-09-23 17:05 UTC (permalink / raw)
To: Hannu Varjoranta
Cc: Joshua Washington, Harshitha Ramamurthy, netdev, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Willem de Bruijn, Praveen Kaligineedi
On Wed, Sep 23, 2026 at 7:11 AM Hannu Varjoranta <hannu@varjosoft.com> wrote:
>
> Since commit 014c607f86ab ("gve: add support for UDP GSO for DQO
> format"), gve_prep_tso() matches shinfo->gso_type exactly. gso_type is
> a bitmask, though: SKB_GSO_DODGY is set on every GSO packet that comes
> from tun/tap, packet sockets or other untrusted sources, and
> SKB_GSO_TCP_ECN and SKB_GSO_TCP_FIXEDID can be set as well. Such packets
> hit the default case, gve_tx_add_skb_dqo() fails and gve_try_tx_skb()
> drops them, counting them in tx_dropped.
>
> These packets do reach the driver: tcp_gso_segment() passes DODGY skbs
> through unsegmented to devices that support TSO, after recomputing
> gso_segs, so drivers must tolerate the bit.
>
> This breaks virtual machines behind a tap on GCE instances using the DQO
> queue formats. Every TSO packet forwarded from a guest (gso_type
> SKB_GSO_TCPV4 | SKB_GSO_DODGY) is dropped, and guest uploads slow to a
> crawl of retransmissions or stall entirely, while the host's own TSO
> traffic (gso_type SKB_GSO_TCPV4) is unaffected. On an n4 instance
> (DQO-QPL) with a Cloud Hypervisor guest, a 64 MB upload from the guest
> went from a 60 s timeout at ~0.9 MB/s to 0.19 s with this change, with
> tx_dropped no longer increasing.
>
> Restore the bitmask test that commit 1b9f75634441 ("gve: ignore
> nonrelevant GSO type bits when processing TSO headers") introduced for
> the same problem, keeping the UDP GSO support.
>
> Fixes: 014c607f86ab ("gve: add support for UDP GSO for DQO format")
> Signed-off-by: Hannu Varjoranta <hannu@varjosoft.com>
Reviewed-by: Ankit Garg <nktgrg@google.com>
> ---
> drivers/net/ethernet/google/gve/gve_tx_dqo.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> index 80ab0a449ff5..675c7644817a 100644
> --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> @@ -596,21 +596,20 @@ static int gve_prep_tso(struct sk_buff *skb)
> l4_start = skb_transport_offset(skb);
> paylen = skb->len - l4_start;
>
> - switch (shinfo->gso_type) {
> - case SKB_GSO_TCPV4:
> - case SKB_GSO_TCPV6:
> + /* gso_type is a bitmask: SKB_GSO_DODGY, SKB_GSO_TCP_ECN and
> + * SKB_GSO_TCP_FIXEDID may be set alongside the protocol bit.
> + */
> + if (shinfo->gso_type & (SKB_GSO_TCPV4 | 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:
> + } else if (shinfo->gso_type & 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:
> + } else {
> return -EINVAL;
> }
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-23 14:10 [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits Hannu Varjoranta
2026-09-23 14:23 ` Eric Dumazet
2026-09-23 17:05 ` Ankit Garg
@ 2026-09-23 19:23 ` Harshitha Ramamurthy
2026-09-25 2:13 ` netdev-bot+sashiko
3 siblings, 0 replies; 9+ messages in thread
From: Harshitha Ramamurthy @ 2026-09-23 19:23 UTC (permalink / raw)
To: Hannu Varjoranta
Cc: Joshua Washington, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Ankit Garg,
Willem de Bruijn, Praveen Kaligineedi
On Wed, Sep 23, 2026 at 7:11 AM Hannu Varjoranta <hannu@varjosoft.com> wrote:
>
> Since commit 014c607f86ab ("gve: add support for UDP GSO for DQO
> format"), gve_prep_tso() matches shinfo->gso_type exactly. gso_type is
> a bitmask, though: SKB_GSO_DODGY is set on every GSO packet that comes
> from tun/tap, packet sockets or other untrusted sources, and
> SKB_GSO_TCP_ECN and SKB_GSO_TCP_FIXEDID can be set as well. Such packets
> hit the default case, gve_tx_add_skb_dqo() fails and gve_try_tx_skb()
> drops them, counting them in tx_dropped.
>
> These packets do reach the driver: tcp_gso_segment() passes DODGY skbs
> through unsegmented to devices that support TSO, after recomputing
> gso_segs, so drivers must tolerate the bit.
>
> This breaks virtual machines behind a tap on GCE instances using the DQO
> queue formats. Every TSO packet forwarded from a guest (gso_type
> SKB_GSO_TCPV4 | SKB_GSO_DODGY) is dropped, and guest uploads slow to a
> crawl of retransmissions or stall entirely, while the host's own TSO
> traffic (gso_type SKB_GSO_TCPV4) is unaffected. On an n4 instance
> (DQO-QPL) with a Cloud Hypervisor guest, a 64 MB upload from the guest
> went from a 60 s timeout at ~0.9 MB/s to 0.19 s with this change, with
> tx_dropped no longer increasing.
>
> Restore the bitmask test that commit 1b9f75634441 ("gve: ignore
> nonrelevant GSO type bits when processing TSO headers") introduced for
> the same problem, keeping the UDP GSO support.
>
> Fixes: 014c607f86ab ("gve: add support for UDP GSO for DQO format")
> Signed-off-by: Hannu Varjoranta <hannu@varjosoft.com>
Thanks for the fix,
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
> ---
> drivers/net/ethernet/google/gve/gve_tx_dqo.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> index 80ab0a449ff5..675c7644817a 100644
> --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> @@ -596,21 +596,20 @@ static int gve_prep_tso(struct sk_buff *skb)
> l4_start = skb_transport_offset(skb);
> paylen = skb->len - l4_start;
>
> - switch (shinfo->gso_type) {
> - case SKB_GSO_TCPV4:
> - case SKB_GSO_TCPV6:
> + /* gso_type is a bitmask: SKB_GSO_DODGY, SKB_GSO_TCP_ECN and
> + * SKB_GSO_TCP_FIXEDID may be set alongside the protocol bit.
> + */
> + if (shinfo->gso_type & (SKB_GSO_TCPV4 | 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:
> + } else if (shinfo->gso_type & 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:
> + } else {
> return -EINVAL;
> }
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-23 14:10 [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits Hannu Varjoranta
` (2 preceding siblings ...)
2026-09-23 19:23 ` Harshitha Ramamurthy
@ 2026-09-25 2:13 ` netdev-bot+sashiko
2026-09-25 2:28 ` Eric Dumazet
3 siblings, 1 reply; 9+ messages in thread
From: netdev-bot+sashiko @ 2026-09-25 2:13 UTC (permalink / raw)
To: hannu
Cc: joshwash, hramamurthy, netdev, andrew+netdev, davem, edumazet,
kuba, pabeni, nktgrg, willemb, pkaligineedi
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.
Critical: 0 · High: 0 · Medium: 1 (2) · Low: 0
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [Medium] With the new bitmask test in gve_prep_tso()
(gve_tx_dqo.c:602/607), SKB_GSO_DODGY TSO/USO skbs are now accepted,…
Pre-existing issues:
- [Medium] gve_can_send_tso()
(drivers/net/ethernet/google/gve/gve_tx_dqo.c:916) always computes…
- [Medium] gve_prep_tso() caches `shinfo = skb_shinfo(skb)` at line 573
and then calls `skb_cow_head(skb, 0)` at line 592.
--
gve: DQO: accept TSO packets with non-protocol gso_type bits
This commit replaces the exact gso_type switch in gve_prep_tso() with
bitmask tests. TSO/USO packets that carry SKB_GSO_DODGY, SKB_GSO_TCP_ECN
or SKB_GSO_TCP_FIXEDID are therefore no longer dropped. The change fixes
TSO traffic forwarded from tap-backed guests on DQO queue formats, which
was being dropped and counted in tx_dropped.
> diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> index 80ab0a449ff54..675c7644817a6 100644
> --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> @@ -596,21 +596,20 @@ static int gve_prep_tso(struct sk_buff *skb)
> l4_start = skb_transport_offset(skb);
> paylen = skb->len - l4_start;
>
> - switch (shinfo->gso_type) {
> - case SKB_GSO_TCPV4:
> - case SKB_GSO_TCPV6:
> + /* gso_type is a bitmask: SKB_GSO_DODGY, SKB_GSO_TCP_ECN and
> + * SKB_GSO_TCP_FIXEDID may be set alongside the protocol bit.
> + */
> + if (shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
[Severity: Medium]
Now that SKB_GSO_DODGY skbs get through here, is their gso_size ever
checked against the hardware maximum?
The comment at the top of gve_prep_tso() explains why the upper bound is
not checked, and only the lower bound is enforced:
/* Note: HW requires MSS (gso_size) to be <= 9728 and the total length
* of the TSO to be <= 262143.
*
* However, we don't validate these because:
* - Hypervisor enforces a limit of 9K MTU
* - Kernel will not produce a TSO larger than 64k
*/
if (unlikely(shinfo->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
return -1;
For DODGY skbs, gso_size comes from an untrusted virtio_net_hdr through
__virtio_net_hdr_to_skb() (tun/tap or PACKET_VNET_HDR). That function only
rejects 0 and GSO_BY_FRAGS, and it never compares gso_size to an MTU.
tcp_gso_segment() and __udp_gso_segment() then pass the skb through
unsegmented. On bridged, macvtap or direct AF_PACKET paths, the value ends
up in a 14-bit descriptor field:
gve_tx_fill_tso_ctx_desc() {
...
desc->mss = skb_shinfo(skb)->gso_size;
}
gve_desc_dqo.h:
u16 mss: 14;
A gso_size from 9729 to 16383 exceeds the documented hardware limit. A
gso_size of 16384 or more is truncated, so 16384 becomes mss 0 and 16472
becomes mss 88.
gve_can_send_tso() also relies on the same 9728 assumption:
* Since max gso size (9728) is less than
* GVE_TX_MAX_BUF_SIZE_DQO, it is impossible
* for the segment to span more than two
* descriptors.
With gso_size above 16383, one segment can span more than two descriptors
of a single frag, so the per-segment buffer count can come out too low.
Before this patch, the exact switch dropped every DODGY skb, so these
values never reached the descriptor. Should gve_prep_tso() reject
gso_size above 9728, or should gve_features_check_dqo() fall back to
software GSO in that case? If so, the comment above the check would need
updating too.
> 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:
> + } else if (shinfo->gso_type & SKB_GSO_UDP_L4) {
[Severity: Medium]
This isn't a bug introduced by this patch, but both gso_type tests still
use the shinfo pointer that was cached before skb_cow_head():
gve_prep_tso() {
struct skb_shared_info *shinfo = skb_shinfo(skb);
...
err = skb_cow_head(skb, 0);
...
if (shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
...
} else if (shinfo->gso_type & SKB_GSO_UDP_L4) {
...
}
When the header is cloned, skb_cow_head() calls pskb_expand_head(). This
happens, for example, when dev_queue_xmit_nit() clones for a packet tap,
or when a bridge floods. pskb_expand_head() copies skb_shared_info into a
new head and calls skb_release_data() on the old one.
After that, only the other clones hold the old head, and they can free it
on another CPU at any time. Can these shinfo->gso_type reads then touch
freed memory?
A garbage gso_type could send a TCP skb down the UDP branch and rewrite
bytes at the UDP check offset, or it could drop the packet. On KASAN
kernels, it would show up as a use-after-free.
Would it make sense to reload shinfo = skb_shinfo(skb) after a successful
skb_cow_head(), or to copy gso_type into a local before the COW?
> udp = udp_hdr(skb);
> csum_replace_by_diff(&udp->check,
> (__force __wsum)htonl(paylen));
> header_len = sizeof(struct udphdr) + l4_start;
[Severity: Medium]
This is a pre-existing issue, but gve_can_send_tso() never got the UDP
handling that commit 014c607f86ab added here. It still uses the TCP header
length for every GSO type:
gve_can_send_tso() {
...
const int header_len = skb_tcp_all_headers(skb);
...
cur_seg_size = skb_headlen(skb) - header_len;
...
}
For SKB_GSO_UDP_L4, tcp_hdrlen() reads the doff nibble at offset 12 of the
transport header. That is byte 4 of the UDP payload, which the sender
controls. header_len can then be anywhere from l4_start to l4_start + 60,
while the value gve_prep_tso() programs is l4_start + 8.
gve_features_check_dqo() is the only place that enforces the
GVE_TX_MAX_DATA_DESCS per-segment limit. With every modelled segment
boundary shifted by -8..+52 bytes, can a real segment span more than 9
buffers and still pass the check? Small frags from MSG_SPLICE_PAGES,
sendfile or vhost-net zerocopy could trigger this. On RDA queues, the
device would then get a layout that exceeds its per-segment limit.
This patch now lets SKB_GSO_UDP_L4 | SKB_GSO_DODGY frames from tap guests
and packet sockets through, which adds guest-controlled senders for this
path. Should gve_can_send_tso() compute header_len the same way
gve_prep_tso() does?
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260923141047.14047-1-hannu%40varjosoft.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-25 2:13 ` netdev-bot+sashiko
@ 2026-09-25 2:28 ` Eric Dumazet
2026-09-25 2:29 ` Eric Dumazet
0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2026-09-25 2:28 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: hannu, joshwash, hramamurthy, netdev, andrew+netdev, davem, kuba,
pabeni, nktgrg, willemb, pkaligineedi
On Fri, Sep 25, 2026 at 4:13 AM <netdev-bot+sashiko@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 0 · Medium: 1 (2) · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [Medium] With the new bitmask test in gve_prep_tso()
> (gve_tx_dqo.c:602/607), SKB_GSO_DODGY TSO/USO skbs are now accepted,…
>
> Pre-existing issues:
> - [Medium] gve_can_send_tso()
> (drivers/net/ethernet/google/gve/gve_tx_dqo.c:916) always computes…
> - [Medium] gve_prep_tso() caches `shinfo = skb_shinfo(skb)` at line 573
> and then calls `skb_cow_head(skb, 0)` at line 592.
Indeed.
Please Hannu send a V2 of your patch squashing the following reload of shinfo:
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index 616c1921aebeacb4eb711ed3cf87821559eb421f..f7511aa835082e4f9b2514a212c497d5319844af
100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -595,6 +595,7 @@ static int gve_prep_tso(struct sk_buff *skb)
err = skb_cow_head(skb, 0);
if (err < 0)
return err;
+ shinfo = shinfo = skb_shinfo(skb);
l4_start = skb_transport_offset(skb);
paylen = skb->len - l4_start;
Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-25 2:28 ` Eric Dumazet
@ 2026-09-25 2:29 ` Eric Dumazet
2026-09-25 11:51 ` Hannu Varjoranta
0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2026-09-25 2:29 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: hannu, joshwash, hramamurthy, netdev, andrew+netdev, davem, kuba,
pabeni, nktgrg, willemb, pkaligineedi
On Fri, Sep 25, 2026 at 4:28 AM Eric Dumazet <edumazet@google.com> wrote:
> Indeed.
>
> Please Hannu send a V2 of your patch squashing the following reload of shinfo:
>
> diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> index 616c1921aebeacb4eb711ed3cf87821559eb421f..f7511aa835082e4f9b2514a212c497d5319844af
> 100644
> --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
> @@ -595,6 +595,7 @@ static int gve_prep_tso(struct sk_buff *skb)
> err = skb_cow_head(skb, 0);
> if (err < 0)
> return err;
> + shinfo = shinfo = skb_shinfo(skb);
Typo, this should have been:
shinfo = skb_shinfo(skb);
>
> l4_start = skb_transport_offset(skb);
> paylen = skb->len - l4_start;
>
> Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits
2026-09-25 2:29 ` Eric Dumazet
@ 2026-09-25 11:51 ` Hannu Varjoranta
0 siblings, 0 replies; 9+ messages in thread
From: Hannu Varjoranta @ 2026-09-25 11:51 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev-bot+sashiko, netdev, joshwash, hramamurthy, andrew+netdev,
davem, kuba, pabeni, nktgrg, willemb, pkaligineedi
On Fri, Sep 25, 2026 at 4:30 AM Eric Dumazet <edumazet@google.com> wrote:
> Typo, this should have been:
>
> shinfo = skb_shinfo(skb);
Thanks Eric, v2 with the reload squashed follows.
The other two Sashiko items are already handled in net, and v2 is
rebased on top of them:
- gso_size above the hardware limit: 296c83b5ccc8 ("gve: DQO: reject TSO
packets with an out of range MSS").
- gve_can_send_tso() using the TCP header length for UDP GSO:
83769c23fb18 ("gve: DQO: fix header length used by gve_can_send_tso()
for UDP GSO").
pw-bot: cr
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-25 11:52 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-23 14:10 [PATCH net] gve: DQO: accept TSO packets with non-protocol gso_type bits Hannu Varjoranta
2026-09-23 14:23 ` Eric Dumazet
2026-09-23 14:38 ` Eric Dumazet
2026-09-23 17:05 ` Ankit Garg
2026-09-23 19:23 ` Harshitha Ramamurthy
2026-09-25 2:13 ` netdev-bot+sashiko
2026-09-25 2:28 ` Eric Dumazet
2026-09-25 2:29 ` Eric Dumazet
2026-09-25 11:51 ` Hannu Varjoranta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox