public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
@ 2026-04-02 12:09 Yingnan Zhang
  2026-04-02 12:59 ` Julian Anastasov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Yingnan Zhang @ 2026-04-02 12:09 UTC (permalink / raw)
  To: horms, ja
  Cc: pablo, fw, phil, davem, edumazet, kuba, pabeni, netdev, lvs-devel,
	netfilter-devel, coreteam, linux-kernel, Yingnan Zhang

Currently, IPVS skips MTU checks for GSO packets by excluding them with
the !skb_is_gso(skb) condition in both IPv4 and IPv6 code paths. This
creates problems when IPVS tunnel mode encapsulates GSO packets with
IPIP or IPv6 tunnel headers.

The issue manifests in two ways:

1. MTU violation after encapsulation:
   When a GSO packet passes through IPVS tunnel mode, the original MTU
   check is bypassed. After adding the tunnel header, the packet size
   may exceed the outgoing interface MTU, leading to unexpected
   fragmentation at the IP layer.

2. Fragmentation with problematic IP IDs:
   When net.ipv4.vs.pmtu_disc=1 and a GSO packet with multiple segments
   is fragmented after encapsulation, each segment gets a sequentially
   incremented IP ID (0, 1, 2, ...). This happens because:

   a) The GSO packet bypasses MTU check and gets encapsulated
   b) At __ip_finish_output, the oversized GSO packet is split into
      separate SKBs (one per segment), with IP IDs incrementing
   c) Each SKB is then fragmented again based on the actual MTU

   This sequential IP ID allocation differs from the expected behavior
   and can cause issues with fragment reassembly and packet tracking.

Fix this by removing the GSO packet exception from the MTU check in both
IPv4 and IPv6 paths, and properly validating GSO packets using
skb_gso_validate_network_len(). The condition is refactored to avoid
code duplication.

Fixes: 4cdd34084d53 ("netfilter: nf_conntrack_ipv6: improve fragmentation handling")
Signed-off-by: Yingnan Zhang <342144303@qq.com>
---
Changes in v2:
- Added IPv6 fix in __mtu_check_toobig_v6() per Julian's review
- Refactored to avoid code duplication per Julian's suggestion
- Applied same validation pattern to both IPv4 and IPv6 paths

v1: https://lore.kernel.org/netdev/20260401152228.31190-1-342144303@qq.com/

 net/netfilter/ipvs/ip_vs_xmit.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 3601eb86d..ac2ad7518 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -112,7 +112,8 @@ __mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
 		if (IP6CB(skb)->frag_max_size > mtu)
 			return true; /* largest fragment violate MTU */
 	}
-	else if (skb->len > mtu && !skb_is_gso(skb)) {
+	} else if (skb->len > mtu &&
+		   !(skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))) {
 		return true; /* Packet size violate MTU size */
 	}
 	return false;
@@ -232,8 +233,9 @@ static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af,
 			return true;
 
 		if (unlikely(ip_hdr(skb)->frag_off & htons(IP_DF) &&
-			     skb->len > mtu && !skb_is_gso(skb) &&
-			     !ip_vs_iph_icmp(ipvsh))) {
+		     skb->len > mtu && !ip_vs_iph_icmp(ipvsh) &&
+		     !(skb_is_gso(skb) &&
+		       skb_gso_validate_network_len(skb, mtu)))) {
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
 				  htonl(mtu));
 			IP_VS_DBG(1, "frag needed for %pI4\n",
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
  2026-04-02 12:09 [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode Yingnan Zhang
@ 2026-04-02 12:59 ` Julian Anastasov
  2026-04-07 10:38 ` kernel test robot
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Julian Anastasov @ 2026-04-02 12:59 UTC (permalink / raw)
  To: Yingnan Zhang
  Cc: horms, pablo, fw, phil, davem, edumazet, kuba, pabeni, netdev,
	lvs-devel, netfilter-devel, coreteam, linux-kernel


	Hello,

On Thu, 2 Apr 2026, Yingnan Zhang wrote:

> Currently, IPVS skips MTU checks for GSO packets by excluding them with
> the !skb_is_gso(skb) condition in both IPv4 and IPv6 code paths. This
> creates problems when IPVS tunnel mode encapsulates GSO packets with
> IPIP or IPv6 tunnel headers.
> 
> The issue manifests in two ways:
> 
> 1. MTU violation after encapsulation:
>    When a GSO packet passes through IPVS tunnel mode, the original MTU
>    check is bypassed. After adding the tunnel header, the packet size
>    may exceed the outgoing interface MTU, leading to unexpected
>    fragmentation at the IP layer.
> 
> 2. Fragmentation with problematic IP IDs:
>    When net.ipv4.vs.pmtu_disc=1 and a GSO packet with multiple segments
>    is fragmented after encapsulation, each segment gets a sequentially
>    incremented IP ID (0, 1, 2, ...). This happens because:
> 
>    a) The GSO packet bypasses MTU check and gets encapsulated
>    b) At __ip_finish_output, the oversized GSO packet is split into
>       separate SKBs (one per segment), with IP IDs incrementing
>    c) Each SKB is then fragmented again based on the actual MTU
> 
>    This sequential IP ID allocation differs from the expected behavior
>    and can cause issues with fragment reassembly and packet tracking.
> 
> Fix this by removing the GSO packet exception from the MTU check in both
> IPv4 and IPv6 paths, and properly validating GSO packets using
> skb_gso_validate_network_len(). The condition is refactored to avoid
> code duplication.
> 
> Fixes: 4cdd34084d53 ("netfilter: nf_conntrack_ipv6: improve fragmentation handling")
> Signed-off-by: Yingnan Zhang <342144303@qq.com>
> ---
> Changes in v2:
> - Added IPv6 fix in __mtu_check_toobig_v6() per Julian's review
> - Refactored to avoid code duplication per Julian's suggestion
> - Applied same validation pattern to both IPv4 and IPv6 paths
> 
> v1: https://lore.kernel.org/netdev/20260401152228.31190-1-342144303@qq.com/
> 
>  net/netfilter/ipvs/ip_vs_xmit.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
> index 3601eb86d..ac2ad7518 100644
> --- a/net/netfilter/ipvs/ip_vs_xmit.c
> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
> @@ -112,7 +112,8 @@ __mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
>  		if (IP6CB(skb)->frag_max_size > mtu)
>  			return true; /* largest fragment violate MTU */
>  	}

	You should remove the above line because compilation fails...

> -	else if (skb->len > mtu && !skb_is_gso(skb)) {
> +	} else if (skb->len > mtu &&
> +		   !(skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))) {
>  		return true; /* Packet size violate MTU size */
>  	}
>  	return false;
> @@ -232,8 +233,9 @@ static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af,
>  			return true;
>  
>  		if (unlikely(ip_hdr(skb)->frag_off & htons(IP_DF) &&
> -			     skb->len > mtu && !skb_is_gso(skb) &&
> -			     !ip_vs_iph_icmp(ipvsh))) {
> +		     skb->len > mtu && !ip_vs_iph_icmp(ipvsh) &&
> +		     !(skb_is_gso(skb) &&
> +		       skb_gso_validate_network_len(skb, mtu)))) {

	Please keep the indentation, just like in my example

>  			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
>  				  htonl(mtu));
>  			IP_VS_DBG(1, "frag needed for %pI4\n",
> -- 
> 2.51.0

Regards

--
Julian Anastasov <ja@ssi.bg>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
  2026-04-02 12:09 [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode Yingnan Zhang
  2026-04-02 12:59 ` Julian Anastasov
@ 2026-04-07 10:38 ` kernel test robot
  2026-04-07 11:43 ` kernel test robot
  2026-04-07 12:22 ` kernel test robot
  3 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2026-04-07 10:38 UTC (permalink / raw)
  To: Yingnan Zhang, horms, ja
  Cc: llvm, oe-kbuild-all, pablo, fw, phil, davem, edumazet, kuba,
	pabeni, netdev, lvs-devel, netfilter-devel, coreteam,
	linux-kernel, Yingnan Zhang

Hi Yingnan,

kernel test robot noticed the following build errors:

[auto build test ERROR on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Yingnan-Zhang/ipvs-fix-MTU-check-for-GSO-packets-in-tunnel-mode/20260407-141549
base:   net/main
patch link:    https://lore.kernel.org/r/tencent_CA2C1C219C99D315086BE55E8654AF7E6009%40qq.com
patch subject: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260407/202604071825.Sh4Y1fMi-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260407/202604071825.Sh4Y1fMi-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604071825.Sh4Y1fMi-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

>> net/netfilter/ipvs/ip_vs_xmit.c:115:2: warning: non-void function does not return a value in all control paths [-Wreturn-type]
     115 |         } else if (skb->len > mtu &&
         |         ^
>> net/netfilter/ipvs/ip_vs_xmit.c:115:4: error: expected identifier or '('
     115 |         } else if (skb->len > mtu &&
         |           ^
   net/netfilter/ipvs/ip_vs_xmit.c:119:2: error: expected identifier or '('
     119 |         return false;
         |         ^
>> net/netfilter/ipvs/ip_vs_xmit.c:120:1: error: extraneous closing brace ('}')
     120 | }
         | ^
   1 warning and 3 errors generated.


vim +115 net/netfilter/ipvs/ip_vs_xmit.c

   104	
   105	static inline bool
   106	__mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
   107	{
   108		if (IP6CB(skb)->frag_max_size) {
   109			/* frag_max_size tell us that, this packet have been
   110			 * defragmented by netfilter IPv6 conntrack module.
   111			 */
   112			if (IP6CB(skb)->frag_max_size > mtu)
   113				return true; /* largest fragment violate MTU */
   114		}
 > 115		} else if (skb->len > mtu &&
   116			   !(skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))) {
   117			return true; /* Packet size violate MTU size */
   118		}
   119		return false;
 > 120	}
   121	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
  2026-04-02 12:09 [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode Yingnan Zhang
  2026-04-02 12:59 ` Julian Anastasov
  2026-04-07 10:38 ` kernel test robot
@ 2026-04-07 11:43 ` kernel test robot
  2026-04-07 12:22 ` kernel test robot
  3 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2026-04-07 11:43 UTC (permalink / raw)
  To: Yingnan Zhang, horms, ja
  Cc: oe-kbuild-all, pablo, fw, phil, davem, edumazet, kuba, pabeni,
	netdev, lvs-devel, netfilter-devel, coreteam, linux-kernel,
	Yingnan Zhang

Hi Yingnan,

kernel test robot noticed the following build errors:

[auto build test ERROR on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Yingnan-Zhang/ipvs-fix-MTU-check-for-GSO-packets-in-tunnel-mode/20260407-141549
base:   net/main
patch link:    https://lore.kernel.org/r/tencent_CA2C1C219C99D315086BE55E8654AF7E6009%40qq.com
patch subject: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
config: x86_64-rhel-9.4-ltp (https://download.01.org/0day-ci/archive/20260407/202604071309.RskiawHA-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260407/202604071309.RskiawHA-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604071309.RskiawHA-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

>> net/netfilter/ipvs/ip_vs_xmit.c:115:11: error: expected identifier or '(' before 'else'
     115 |         } else if (skb->len > mtu &&
         |           ^~~~
>> net/netfilter/ipvs/ip_vs_xmit.c:119:9: error: expected identifier or '(' before 'return'
     119 |         return false;
         |         ^~~~~~
>> net/netfilter/ipvs/ip_vs_xmit.c:120:1: error: expected identifier or '(' before '}' token
     120 | }
         | ^
   net/netfilter/ipvs/ip_vs_xmit.c: In function '__mtu_check_toobig_v6':
>> net/netfilter/ipvs/ip_vs_xmit.c:115:9: warning: control reaches end of non-void function [-Wreturn-type]
     115 |         } else if (skb->len > mtu &&
         |         ^


vim +115 net/netfilter/ipvs/ip_vs_xmit.c

   104	
   105	static inline bool
   106	__mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
   107	{
   108		if (IP6CB(skb)->frag_max_size) {
   109			/* frag_max_size tell us that, this packet have been
   110			 * defragmented by netfilter IPv6 conntrack module.
   111			 */
   112			if (IP6CB(skb)->frag_max_size > mtu)
   113				return true; /* largest fragment violate MTU */
   114		}
 > 115		} else if (skb->len > mtu &&
   116			   !(skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))) {
   117			return true; /* Packet size violate MTU size */
   118		}
 > 119		return false;
 > 120	}
   121	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
  2026-04-02 12:09 [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode Yingnan Zhang
                   ` (2 preceding siblings ...)
  2026-04-07 11:43 ` kernel test robot
@ 2026-04-07 12:22 ` kernel test robot
  3 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2026-04-07 12:22 UTC (permalink / raw)
  To: Yingnan Zhang, horms, ja
  Cc: oe-kbuild-all, pablo, fw, phil, davem, edumazet, kuba, pabeni,
	netdev, lvs-devel, netfilter-devel, coreteam, linux-kernel,
	Yingnan Zhang

Hi Yingnan,

kernel test robot noticed the following build errors:

[auto build test ERROR on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Yingnan-Zhang/ipvs-fix-MTU-check-for-GSO-packets-in-tunnel-mode/20260407-141549
base:   net/main
patch link:    https://lore.kernel.org/r/tencent_CA2C1C219C99D315086BE55E8654AF7E6009%40qq.com
patch subject: [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode
config: nios2-allmodconfig (https://download.01.org/0day-ci/archive/20260407/202604072049.zQPE6QFA-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260407/202604072049.zQPE6QFA-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604072049.zQPE6QFA-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

>> net/netfilter/ipvs/ip_vs_xmit.c:115:11: error: expected identifier or '(' before 'else'
     115 |         } else if (skb->len > mtu &&
         |           ^~~~
>> net/netfilter/ipvs/ip_vs_xmit.c:119:9: error: expected identifier or '(' before 'return'
     119 |         return false;
         |         ^~~~~~
>> net/netfilter/ipvs/ip_vs_xmit.c:120:1: error: expected identifier or '(' before '}' token
     120 | }
         | ^
   net/netfilter/ipvs/ip_vs_xmit.c: In function '__mtu_check_toobig_v6':
>> net/netfilter/ipvs/ip_vs_xmit.c:115:9: warning: control reaches end of non-void function [-Wreturn-type]
     115 |         } else if (skb->len > mtu &&
         |         ^


vim +115 net/netfilter/ipvs/ip_vs_xmit.c

   104	
   105	static inline bool
   106	__mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
   107	{
   108		if (IP6CB(skb)->frag_max_size) {
   109			/* frag_max_size tell us that, this packet have been
   110			 * defragmented by netfilter IPv6 conntrack module.
   111			 */
   112			if (IP6CB(skb)->frag_max_size > mtu)
   113				return true; /* largest fragment violate MTU */
   114		}
 > 115		} else if (skb->len > mtu &&
   116			   !(skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))) {
   117			return true; /* Packet size violate MTU size */
   118		}
 > 119		return false;
 > 120	}
   121	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-04-07 12:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-02 12:09 [PATCH net v2] ipvs: fix MTU check for GSO packets in tunnel mode Yingnan Zhang
2026-04-02 12:59 ` Julian Anastasov
2026-04-07 10:38 ` kernel test robot
2026-04-07 11:43 ` kernel test robot
2026-04-07 12:22 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox