This patch enhances GSO segment checks by verifying the presence of frag_list and protocol consistency, addressing low throughput issues on IPv4 servers when used as hotspots Specifically, it fixes a bug in GSO segmentation when forwarding GRO packets with frag_list. The function skb_segment_list cannot correctly process GRO skbs converted by XLAT, because XLAT only converts the header of the head skb. As a result, skbs in the frag_list may remain unconverted, leading to protocol inconsistencies and reduced throughput. To resolve this, the patch uses skb_segment to handle forwarded packets converted by XLAT, ensuring that all fragments are properly converted and segmented. Signed-off-by: Jibin Zhang --- net/ipv4/tcp_offload.c | 3 ++- net/ipv4/udp_offload.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index fdda18b1abda..162a384a15bb 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -104,7 +104,8 @@ static struct sk_buff *tcp4_gso_segment(struct sk_buff *skb, if (!pskb_may_pull(skb, sizeof(struct tcphdr))) return ERR_PTR(-EINVAL); - if (skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST) { + if ((skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST) && skb_has_frag_list(skb) && + (skb->protocol == skb_shinfo(skb)->frag_list->protocol)) { struct tcphdr *th = tcp_hdr(skb); if (skb_pagelen(skb) - th->doff * 4 == skb_shinfo(skb)->gso_size) diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 19d0b5b09ffa..704fb32d10d7 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -512,7 +512,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, return NULL; } - if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) { + if ((skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) && skb_has_frag_list(gso_skb) && + (gso_skb->protocol == skb_shinfo(gso_skb)->frag_list->protocol)) { /* Detect modified geometry and pass those to skb_segment. */ if (skb_pagelen(gso_skb) - sizeof(*uh) == skb_shinfo(gso_skb)->gso_size) return __udp_gso_segment_list(gso_skb, features, is_ipv6); -- 2.45.2