While testing UDP GSO fraglists forwarding through driver that uses
Fast GRO (via napi_gro_frags()), I was observing lots of out-of-order
iperf packets:
[ ID] Interval Transfer Bitrate Jitter
[SUM] 0.0-40.0 sec 12106 datagrams received out-of-order
Simple switch to napi_gro_receive() or any other method without frag0
shortcut completely resolved them.
I've found two incorrect header accesses in GRO receive callback(s):
- udp_hdr() (instead of udp_gro_udphdr()) that always points to junk
in "fast" mode and could probably do this in "regular".
This was the actual bug that caused all out-of-order delivers;
- udp{4,6}_lib_lookup_skb() -> ip{,v6}_hdr() (instead of
skb_gro_network_header()) that potentionally might return odd
pointers in both modes.
Each patch addresses one of these two issues.
This doesn't cover a support for nested tunnels as it's out of the
subject and requires more invasive changes. It will be handled
separately in net-next series.
Credits:
Cc: Eric Dumazet <[email protected]>
Cc: Jakub Kicinski <[email protected]>
Cc: Willem de Bruijn <[email protected]>
Since v4 [0]:
- split the fix into two logical ones (Willem);
- replace ternaries with plain ifs to beautify the code (Jakub);
- drop p->data part to reintroduce it later in abovementioned set.
Since v3 [1]:
- restore the original {,__}udp{4,6}_lib_lookup_skb() and use
private versions of them inside GRO code (Willem).
Since v2 [2]:
- dropped redundant check introduced in v2 as it's performed right
before (thanks to Eric);
- udp_hdr() switched to data + off for skbs from list (also Eric);
- fixed possible malfunction of {,__}udp{4,6}_lib_lookup_skb() with
Fast/frag0 due to ip{,v6}_hdr() usage (Willem).
Since v1 [3]:
- added a NULL pointer check for "uh" as suggested by Willem.
[0] https://lore.kernel.org/netdev/[email protected]
[1] https://lore.kernel.org/netdev/[email protected]
[2] https://lore.kernel.org/netdev/[email protected]
[3] https://lore.kernel.org/netdev/[email protected]
Alexander Lobakin (2):
net: udp: fix UDP header access on Fast/frag0 UDP GRO
net: udp: fix IP header access and skb lookup on Fast/frag0 UDP GRO
net/ipv4/udp_offload.c | 19 ++++++++++++++++---
net/ipv6/udp_offload.c | 17 +++++++++++++++--
2 files changed, 31 insertions(+), 5 deletions(-)
--
2.29.2
On Wed, 11 Nov 2020 20:44:08 +0000 Alexander Lobakin wrote:
> While testing UDP GSO fraglists forwarding through driver that uses
> Fast GRO (via napi_gro_frags()), I was observing lots of out-of-order
> iperf packets:
>
> [ ID] Interval Transfer Bitrate Jitter
> [SUM] 0.0-40.0 sec 12106 datagrams received out-of-order
>
> Simple switch to napi_gro_receive() or any other method without frag0
> shortcut completely resolved them.
>
> I've found two incorrect header accesses in GRO receive callback(s):
> - udp_hdr() (instead of udp_gro_udphdr()) that always points to junk
> in "fast" mode and could probably do this in "regular".
> This was the actual bug that caused all out-of-order delivers;
> - udp{4,6}_lib_lookup_skb() -> ip{,v6}_hdr() (instead of
> skb_gro_network_header()) that potentionally might return odd
> pointers in both modes.
>
> Each patch addresses one of these two issues.
>
> This doesn't cover a support for nested tunnels as it's out of the
> subject and requires more invasive changes. It will be handled
> separately in net-next series.
Applied, thanks!