net: gro: fix outer network offset
Subsystems (3)
Paolo Abeni
maintainerPATCH v2 1/2 net: gro: fix outer network offset
In reply to Paolo AbeniThe udp GRO complete stage assumes that all the packets inserted the RX have the encapsulation flag zeroed. Such assumption is not true, as a few H/W NICs can set such flag when H/W offloading the checksum for an UDP encapsulated traffic, the tun driver can inject GSO packets with UDP encapsulation and the problematic layout can also be created via a veth based setup.
Due to the above, in the problematic scenarios, udp4_gro_complete() uses the wrong network offset (inner instead of outer) to compute the outer UDP header pseudo checksum, leading to csum validation errors later on in packet processing.
Address the issue always clearing the encapsulation flag at GRO completion time. Such flag will be set again as needed for encapsulated packets by udp_gro_complete().
--- net/core/gro.c | 2 ++ 1 file changed, 2 insertions(+)
net/core/gro.c +2 -0
@@ -265,6 +265,8 @@ static void gro_complete(struct gro_node *gro, struct sk_buff *skb) goto out; } +/* NICs can feed encapsulated packets into GRO */ + skb->encapsulation =0 ;rcu_read_lock ();list_for_each_entry_rcu (ptype, head, list) {if (ptype->type != type || !ptype->callbacks.gro_complete)
Signature · 1 line
2.52.0
Paolo Abeni
maintainerPATCH v2 2/2 selftest: net: add a test-case for encap segmentation after GRO
In reply to Paolo AbeniWe had a few patches in this area and no explicit coverage so far. The test case covers the scenario addressed by the previous fix; reusing the existing udpgro_fwd.sh script to leverage part of the of the virtual network setup, even if such script is possibly not a perfect fit.
Note that the mentioned script already contains several shellcheck violation; this patch does not fix the existing code, just avoids adding more issues in the new one.
---
v1 -> v2:
- fixed comment typos
- dropped unneeded 'nodad' from del command
--- tools/testing/selftests/net/udpgro_fwd.sh | 64 +++++++++++++++++++++++ 1 file changed, 64 insertions(+)
tools/testing/selftests/net/udpgro_fwd.sh +64 -0
@@ -162,6 +162,39 @@ run_test() { echo " ok" } +run_test_csum() { + local -r msg="$1" + local -r dst="$2" + local csum_error_filter=UdpInCsumErrors + local csum_errors + + printf "%-40s" "$msg" + + is_ipv6 "$dst" && csum_error_filter=Udp6InCsumErrors + + ip netns exec "$NS_DST" iperf3 -s -1 >/dev/null & + wait_local_port_listen "$NS_DST" 5201 tcp + local spid="$!" + ip netns exec "$NS_SRC" iperf3 -c "$dst" -t 2 >/dev/null + local retc="$?" + wait "$spid" + local rets="$?" + if [ "$rets" -ne 0 ] || [ "$retc" -ne 0 ]; then + echo " fail client exit code $retc, server $rets" + ret=1 + return + fi + + csum_errors=$(ip netns exec "$NS_DST" nstat -as "$csum_error_filter" | + grep "$csum_error_filter" | awk '{print $2}') + if [ -n "$csum_errors" ] && [ "$csum_errors" -gt 0 ]; then + echo " fail - csum error on receive $csum_errors, expected 0" + ret=1 + return + fi + echo " ok" +} + run_bench() { local -r msg=$1 local -r dst=$2
@@ -260,6 +293,37 @@ for family in 4 6; do ip netns exec $NS_SRC $PING -q -c 1 $OL_NET$DST_NAT >/dev/null run_test "GRO fwd over UDP tunnel" $OL_NET$DST_NAT 10 10 $OL_NET$DST cleanup + + # force segmentation and re-aggregation + create_vxlan_pair + ip netns exec "$NS_DST" ethtool -K veth"$DST" generic-receive-offload on + ip netns exec "$NS_SRC" ethtool -K veth"$SRC" tso off + ip -n "$NS_SRC" link set dev veth"$SRC" mtu 1430 + + # forward to a 2nd veth pair + ip -n "$NS_DST" link add br0 type bridge + ip -n "$NS_DST" link set dev veth"$DST" master br0 + + # segment the aggregated TSO packet, without csum offload + ip -n "$NS_DST" link add veth_segment type veth peer veth_rx + for FEATURE in tso tx-udp-segmentation tx-checksumming; do + ip netns exec "$NS_DST" ethtool -K veth_segment "$FEATURE" off + done + ip -n "$NS_DST" link set dev veth_segment master br0 up + ip -n "$NS_DST" link set dev br0 up + ip -n "$NS_DST" link set dev veth_rx up + + # move the lower layer IP in the last added veth + for ADDR in "$BM_NET_V4$DST/24" "$BM_NET_V6$DST/64"; do + # the dad argument will let iproute emit a unharmful warning + # with ipv4 addresses + ip -n "$NS_DST" addr del dev veth"$DST" "$ADDR" + ip -n "$NS_DST" addr add dev veth_rx "$ADDR" \ + nodad 2>/dev/null + done + + run_test_csum "GSO after GRO" "$OL_NET$DST" + cleanup done exit $ret
Signature · 1 line
2.52.0
Paolo Abeni
maintainerv2 cover net: gro: fix outer network offset
The GRO stage has still problems in some edge scenarios when dealing with encapsulated traffic: the first patch address an issue there leading to bad checksums.
The second patch introduces a test case covering the relevant scenario:
S/W segmentation after GRO for encapsulated traffic.
v1 -> v2:
- fixed typos in patch 2/2
Paolo Abeni (2):
net: gro: fix outer network offset
selftest: net: add a test-case for encap segmentation after GRO
net/core/gro.c | 2 + tools/testing/selftests/net/udpgro_fwd.sh | 64 +++++++++++++++++++++++ 2 files changed, 66 insertions(+)
Signature · 1 line
2.52.0
Quoted 13 lines · Paolo Abeni
The udp GRO complete stage assumes that all the packets inserted the RX have the
encapsulationflag zeroed. Such assumption is not true, as a few H/W NICs can set such flag when H/W offloading the checksum for an UDP encapsulated traffic, the tun driver can inject GSO packets with UDP encapsulation and the problematic layout can also be created via a veth based setup.Due to the above, in the problematic scenarios,
udp4_gro_complete()uses the wrong network offset (inner instead of outer) to compute the outer UDP header pseudo checksum, leading to csum validation errors later on in packet processing.
Quoted 8 lines
Address the issue always clearing the encapsulation flag at GRO completion time. Such flag will be set again as needed for encapsulated packets by
udp_gro_complete().Fixes 5ef31ea5d053 ("net: gro: fix udp bad offset in socket lookup by adding {inner_}network_offset to napi_gro_cb")Reviewed-by Willem de Bruijn <[email protected]>Signed-off-by Paolo Abeni <[email protected]>---
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:
Quoted 8 lines · On Mon, 2 Feb 2026 12:43:13 +0100 you wrote:
The GRO stage has still problems in some edge scenarios when dealing with encapsulated traffic: the first patch address an issue there leading to bad checksums.
The second patch introduces a test case covering the relevant scenario:
S/W segmentation after GRO for encapsulated traffic.[...]
Here is the summary with links:
- [v2,net,1/2] net: gro: fix outer network offset
https://git.kernel.org/netdev/net/c/5c2c3c38be39 - [v2,net,2/2] selftest: net: add a test-case for encap segmentation after GRO https://git.kernel.org/netdev/net/c/bee60ce21b75
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html