[Openvpn-devel,v2] tun: set IFF_BACKPRESSURE on Linux

Message ID 20261030111806.92252-1-simon.schippers@tu-dortmund.de
State New
Headers
Series [Openvpn-devel,v2] tun: set IFF_BACKPRESSURE on Linux |

Commit Message

Simon Schippers Oct. 30, 2026, 11:18 a.m. UTC
  When the internal ring of a TUN/TAP device is full, the kernel silently
drops packets, bypassing any qdisc. TCP then sees loss, retransmits and
shrinks its congestion window.

My series "tun/tap & vhost-net: apply qdisc backpressure on full
ptr_ring to reduce TX drops" [1] adds IFF_BACKPRESSURE in Linux 7.3
(commit d00c7369ef24 "tun/tap & vhost-net: stop tail-drop when
IFF_BACKPRESSURE is set"). It stops the TX queue instead, so the qdisc
holds the packets and applies its AQM and fairness.

Our paper [2] evaluated this with OpenVPN: over a 120 ms RTT link
between Germany and the USA, TCP throughput without the patch was up to
36% worse, and with it no retransmissions occurred. With higher
latencies, throughput without the patch can be even worse.

Stopping and waking the queue costs CPU time, which reduced throughput
in a synthetic test with eight iperf3 senders into a QEMU VM on a
Ryzen 9 9950X [3]. With OpenVPN, the encryption is the bottleneck
instead. A benchmark on the same CPU with eight iperf3 streams through
OpenVPN between two network namespaces [4] gives these means over 40
runs of 30 s, with the flag off and on (drops: TX drops of the client
TUN device, retr: TCP retransmits):

  txqueuelen   off Mbit/s    on Mbit/s   change  off drops   on drops   off retr    on retr
         500         3971         3952    -0.5%      40226          0      36624        531
        5000         4005         3923    -2.1%       1358          0        658          0

The throughput difference is within the run-to-run standard deviation of
340 to 380 Mbit/s (about 9%), while the TUN drops are gone and the
retransmits nearly so. The flag is therefore always set.

The flag is only set when the headers define IFF_BACKPRESSURE, and older
kernels ignore it. The DCO path uses no TUN device and is unaffected.

[1] https://lore.kernel.org/netdev/20260803183641.96882-1-simon.schippers@tu-dortmund.de/T/#u
[2] https://cni.etit.tu-dortmund.de/storages/cni-etit/r/Research/Publications/2025/Gebauer_2025_VTCFall/Gebauer_VTCFall2025_AuthorsVersion.pdf
[3] https://lore.kernel.org/netdev/akVnoOYQOrt8k-Gu@karahi.librecast.net/
[4] https://github.com/simoschip2000/openvpn-bench

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Simon Schippers <simon.schippers@tu-dortmund.de>
---
v2:
- Always set the flag instead of adding a --tun-backpressure option, as
  discussed with Antonio.
- Add OpenVPN benchmark results.

 src/openvpn/tun.c | 4 ++++
 1 file changed, 4 insertions(+)
  

Patch

diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index fdd13ae7e..85daefd10 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -2100,6 +2100,10 @@  open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
         ifr.ifr_flags |= IFF_ONE_QUEUE;
 #endif
 
+#ifdef IFF_BACKPRESSURE
+        ifr.ifr_flags |= IFF_BACKPRESSURE;
+#endif
+
         /*
          * Figure out if tun or tap device
          */