From nobody Mon Jan 26 22:50:08 2026 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25BBE33DEE0; Mon, 26 Jan 2026 15:21:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769440897; cv=none; b=SkhLVjg6G3BPbuNCKgh1ML2nYoffr69qCJQPBlGgwtJq/QRgxs65XyDx69RECz8y5GMuMuVYAFRKcOuvlOEeIBYUiHbVdjGXqc5LTbL5wtGWIVmJ8mjveOjFGNCqFwZV/42ElCUyzS774B6ea91eQ0h/O1jHH30sIGa+b/5zEmY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769440897; c=relaxed/simple; bh=l9alNzLtbKf/N5wbrT78rj1ZCgxuxNdCfWh18n8WqEA=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=UnVWTEJMbyhXKbT8F/29AkbLRIZzTPkk/ubkYnXFDf93xqDayk1jiw/c52lzFTDSZIP7p9EQUQJdNNXtf7ZDwdWStqyshh1+vCZ5sY02gyBdIGF/9IZ0pZ6sWIEEKHgV66lGFxDM7SR5AsaxTNhR42w7TdWFHzl7GydXIo/OJF8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=iN87vqpQ; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="iN87vqpQ" X-UUID: ac239e02faca11f0b7fc4fdb8733b2bc-20260126 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:CC:To:From; bh=/KO48sLcc1Pw1/EXPTPJ/6Em+9GtVtY6da5KGjQjsQs=; b=iN87vqpQPRNVbGVSX8BHLXFSkWeRvW4JqTOMTjLLL+ZwQ84kYdzOERhSROifFOI8ryRRfOFULk8XJHBhCZ8WajkevyjC2BGWCoweXvj812lgilj4QSrzuSTvnimQrBcHRGYM9hj1fahjgMsClmc1t5x1eIafhtVfy2Z0WuNmY+w=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.3.11,REQID:8c5965e4-d5d2-4bef-babf-7080bd9be116,IP:0,U RL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION: release,TS:0 X-CID-META: VersionHash:89c9d04,CLOUDID:27903c7a-8c8a-4fc4-88c0-3556e7711556,B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102|836|888|898,TC:-5,Content:0|15|5 0,EDM:-3,IP:nil,URL:1,File:130,RT:0,Bulk:nil,QS:nil,BEC:-1,COL:0,OSI:0,OSA :0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 2,SSN|SDN X-CID-BAS: 2,SSN|SDN,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULS X-CID-RHF: D41D8CD98F00B204E9800998ECF8427E X-UUID: ac239e02faca11f0b7fc4fdb8733b2bc-20260126 Received: from mtkmbs13n1.mediatek.inc [(172.21.101.193)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 354293242; Mon, 26 Jan 2026 23:21:22 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs13n1.mediatek.inc (172.21.101.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.29; Mon, 26 Jan 2026 23:21:17 +0800 Received: from mbjsdccf07.gcn.mediatek.inc (10.15.20.246) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.2562.29 via Frontend Transport; Mon, 26 Jan 2026 23:21:16 +0800 From: Jibin Zhang To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Neal Cardwell , Kuniyuki Iwashima , David Ahern , Matthias Brugger , AngeloGioacchino Del Regno , , , , , CC: , Jibin Zhang Subject: [PATCH v4] net: fix segmentation of forwarding fraglist GRO Date: Mon, 26 Jan 2026 23:21:11 +0800 Message-ID: <20260126152114.1211-1-jibin.zhang@mediatek.com> X-Mailer: git-send-email 2.45.2 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch enhances GSO segment handling by properly checking the SKB_GSO_DODGY flag for frag_list GSO packets, addressing low throughput issues observed when a station accesses IPv4 servers via hotspots with an IPv6-only upstream interface. Specifically, it fixes a bug in GSO segmentation when forwarding GRO packets containing a frag_list. The function skb_segment_list cannot correctly process GRO skbs that have been converted by XLAT, since XLAT only translates the header of the head skb. Consequently, skbs in the frag_list may remain untranslated, resulting in protocol inconsistencies and reduced throughput. To address this, the patch explicitly sets the SKB_GSO_DODGY flag for GSO packets in XLAT's IPv4/IPv6 protocol translation helpers (bpf_skb_proto_4_to_6 and bpf_skb_proto_6_to_4). This marks GSO packets as potentially modified after protocol translation. As a result, GSO segmentation will avoid using skb_segment_list and instead falls back to skb_segment for packets with the SKB_GSO_DODGY flag. This ensures that only safe and fully translated frag_list packets are processed by skb_segment_list, resolving protocol inconsistencies and improving throughput when forwarding GRO packets converted by XLAT. Signed-off-by: Jibin Zhang --- v4: Change according to Willem de Bruijn's suggestions 1. Set SKB_GSO_DODGY when XLAT modifies headers for GSO packets. 2. GSO segmentation is downgraded to use skb_segment instead of skb_segment_list to ensure robust handling of potentially modified packets when the SKB_GSO_DODGY flag is set on a GSO packet. v3: Apply the same fix to tcp6_gso_segment(), as suggested. v2: To apply the added condition to a narrower scop In this version, the condition (skb_has_frag_list(gso_skb) && (gso_skb->protocol =3D=3D skb_shinfo(gso_skb)->frag_list->protocol)) is moved into inner 'if' statement to a narrower scope. Send out the patch again for further discussion because: 1. This issue has a significant impact and has occurred in many countries and regions. 2. Currently, modifying BPF is not a good option, because BPF code cannot access the header of skb on the fraglist, and the required changes would affect a wide range of code. 3. Directly disabling GRO aggregation for XLAT flows is also not a good solution, as this change would disable GRO even when forwarding is not needed, and it would also require cooperation from all device drivers. [3]: https://patchwork.kernel.org/patch/14397344 [2]: https://patchwork.kernel.org/patch/14375646 [1]: https://patchwork.kernel.org/patch/14350844 --- net/core/filter.c | 2 ++ net/ipv4/tcp_offload.c | 3 ++- net/ipv4/udp_offload.c | 3 ++- net/ipv6/tcpv6_offload.c | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 616e0520a0bb..bcd73d9bd764 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3353,6 +3353,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb) shinfo->gso_type &=3D ~SKB_GSO_TCPV4; shinfo->gso_type |=3D SKB_GSO_TCPV6; } + shinfo->gso_type |=3D SKB_GSO_DODGY; } =20 bpf_skb_change_protocol(skb, ETH_P_IPV6); @@ -3383,6 +3384,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb) shinfo->gso_type &=3D ~SKB_GSO_TCPV6; shinfo->gso_type |=3D SKB_GSO_TCPV4; } + shinfo->gso_type |=3D SKB_GSO_DODGY; } =20 bpf_skb_change_protocol(skb, ETH_P_IP); diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index fdda18b1abda..942a948f1a31 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -107,7 +107,8 @@ static struct sk_buff *tcp4_gso_segment(struct sk_buff = *skb, if (skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST) { struct tcphdr *th =3D tcp_hdr(skb); =20 - if (skb_pagelen(skb) - th->doff * 4 =3D=3D skb_shinfo(skb)->gso_size) + if ((skb_pagelen(skb) - th->doff * 4 =3D=3D skb_shinfo(skb)->gso_size) && + !(skb_shinfo(skb)->gso_type & SKB_GSO_DODGY)) return __tcp4_gso_segment_list(skb, features); =20 skb->ip_summed =3D CHECKSUM_NONE; diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 19d0b5b09ffa..589456bd8b5f 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -514,7 +514,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_s= kb, =20 if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) { /* Detect modified geometry and pass those to skb_segment. */ - if (skb_pagelen(gso_skb) - sizeof(*uh) =3D=3D skb_shinfo(gso_skb)->gso_s= ize) + if ((skb_pagelen(gso_skb) - sizeof(*uh) =3D=3D skb_shinfo(gso_skb)->gso_= size) && + !(skb_shinfo(gso_skb)->gso_type & SKB_GSO_DODGY)) return __udp_gso_segment_list(gso_skb, features, is_ipv6); =20 ret =3D __skb_linearize(gso_skb); diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index effeba58630b..5670d32c27f8 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c @@ -170,7 +170,8 @@ static struct sk_buff *tcp6_gso_segment(struct sk_buff = *skb, if (skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST) { struct tcphdr *th =3D tcp_hdr(skb); =20 - if (skb_pagelen(skb) - th->doff * 4 =3D=3D skb_shinfo(skb)->gso_size) + if ((skb_pagelen(skb) - th->doff * 4 =3D=3D skb_shinfo(skb)->gso_size) && + !(skb_shinfo(skb)->gso_type & SKB_GSO_DODGY)) return __tcp6_gso_segment_list(skb, features); =20 skb->ip_summed =3D CHECKSUM_NONE; --=20 2.45.2