Hi,
These patches were initially included in a joint GSO-GRO series [1]
implementing both TX and RX batching mechanisms in the ovpn data path.
Sashiko's review of v2 of that series identified fundamental flaws in
the GRO part which required a broad redesign of the new RX path. So I
decided to proceed with the GSO series separately [2] and keep this
series GRO-specific since the two mechanisms are not functionally
dependent. The series applies both on its own and on top of [2].
The redesign uses the standard SKB_GSO_UDP_L4 | SKB_GSO_FRAGLIST
representation instead of giving an ovpn aggregate tunnel-specific
completion semantics. This requires UDP to let an encapsulation callback
opt into consuming that representation, while retaining a
segment-and-redeliver fallback when the callback is absent or declines
it. It also requires detachable GRO callbacks: unlike a conventional
kernel-owned tunnel socket, ovpn attaches to a userspace socket which
can outlive its association with the driver. The first three patches
provide those core contracts and make UDP_ENCAP changes retire
detachable callbacks before replacing the encapsulation state. Clearly,
those patches are more suited to netdev than openvpn-devel, but in order
to keep this series applicable and reviewable, they are included in this
openvpn-devel-targeted series. Patch 1 explains why this opt-in does not
reopen commit 3d010c8031e3 and shows that consuming the aggregate
directly is 22.7% to 25.2% faster than letting UDP segment it first.
On receive, the ovpn GRO callback collects compatible DATA_V2 records
from one outer transport flow, matching their opcode, key and peer
header while retaining every complete encrypted record as a separate
frag-list entry. The aggregate continues through the ordinary outer
receive stack. At the encapsulation callback, ovpn validates its layout,
ownership, headers and outer tuple before detaching the records,
propagating post-GRO metadata and authenticating each one independently.
Any aggregate which ovpn cannot accept whole, such as a foreign or
modified one, is declined, causing UDP to segment it and retry delivery
one datagram at a time. The final patch uses the resulting lookahead to
prefetch ciphertext two records before it is decrypted.
Performance was measured with the GSO series [2] applied solely to keep
transmit from limiting the receive comparison. Five interleaved
60-second iperf3 -Z single-flow AES-128-GCM runs in each direction,
after a 10-second warm-up, over two directly connected 100-Gbit/s mlx5
ports produced:
Forward Reverse
Without GRO 18.721 Gbit/s 18.777 Gbit/s
With GRO 21.542 Gbit/s 21.366 Gbit/s
With GRO + RX prefetch 25.741 Gbit/s 25.150 Gbit/s
The complete series improved throughput by 37.5% forward and 33.9%
reverse. Across the monitored data-path CPUs, mean cycles per byte fell
from 4.535 to 3.896 (-14.1%) and instructions per byte from 10.913 to
9.492 (-13.0%). Individual patch messages contain the incremental
measurements and further test details.
Thanks,
Ralf Lici
Mandelbit Srl
[1]
https://lore.kernel.org/openvpn-devel/[email protected]/
[2]
https://lore.kernel.org/openvpn-devel/[email protected]/
---
Ralf Lici (5):
udp: let encapsulation callbacks consume UDP frag-list GSO
udp_tunnel: support detachable GRO receive callbacks
udp: detach tunnel GRO before changing UDP encapsulation
ovpn: coalesce UDP data records with GRO
ovpn: prefetch encrypted records before GRO batch decryption
drivers/net/ovpn/udp.c | 332 ++++++++++++++++++++++++++++++++++++-
include/linux/udp.h | 13 ++
include/net/udp_tunnel.h | 3 +
net/core/gro.c | 1 +
net/ipv4/udp.c | 43 ++++-
net/ipv4/udp_offload.c | 59 ++++++-
net/ipv4/udp_tunnel_core.c | 31 +++-
net/ipv6/udp.c | 37 ++++-
8 files changed, 487 insertions(+), 32 deletions(-)
base-commit: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
--
2.56.0
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel