From 9f92dc505b81a6a3005e6c9dcd755baab9a0b176 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 14 Jun 2026 08:45:19 +0000 Subject: [PATCH] fix(client/pkg): ship 32MB UDP recv-buffer sysctl with the Linux client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The client asks the kernel for a 32 MB SO_RCVBUF, but the kernel silently clamps it to net.core.rmem_max — whose default is far too small. A too-small recv buffer is the dominant client-side wall above ~1 Gbps. Measured live (Fedora host -> two clients, real 2.5G LAN, GSO off): a client capped at 4 MB rmem_max dropped 31.6% of a 2 Gbps stream at the receiver, while a 32 MB client delivered the same 2 Gbps at 0.0% loss. The host already shipped this tuning; the client packages didn't (the RPM's %post even referenced the host-only file), so a client-only install streamed lossy at high bitrate. Add scripts/99-punktfunk-client-net.conf (rmem/wmem = 32 MB, distinct filename so host+client can coexist) and ship+apply it from both the .deb (build-client-deb.sh) and the RPM client subpackage (install, %files client, %post client). For reference the full ladder (punktfunk speed-test): 0% loss to 1.5 Gbps on a 4 MB client; 31.6% at 2 Gbps on 4 MB vs 0% at 2 Gbps on 32 MB. iperf3 put the raw link at ~2.35 Gbps TCP / ~2.4 Gbps UDP, so the stack now tracks the wire given a big enough recv buffer. Co-Authored-By: Claude Opus 4.8 (1M context) --- packaging/debian/build-client-deb.sh | 7 +++++++ packaging/rpm/punktfunk.spec | 10 ++++++++++ scripts/99-punktfunk-client-net.conf | 8 ++++++++ 3 files changed, 25 insertions(+) create mode 100644 scripts/99-punktfunk-client-net.conf diff --git a/packaging/debian/build-client-deb.sh b/packaging/debian/build-client-deb.sh index ee61538..a919d8b 100644 --- a/packaging/debian/build-client-deb.sh +++ b/packaging/debian/build-client-deb.sh @@ -35,6 +35,11 @@ install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \ # DualSense hidraw access (full pad fidelity through SDL's HIDAPI driver). install -Dm0644 scripts/70-punktfunk-client.rules \ "$STAGE/usr/lib/udev/rules.d/70-punktfunk-client.rules" +# UDP receive-buffer tuning (32 MB) — without it the kernel clamps the client's SO_RCVBUF and +# high-bitrate streams overflow it at the receiver (measured: 4 MB cap = 31.6% loss at 2 Gbps, +# 32 MB = 0%). systemd-sysctl applies it at boot; the postinst applies it on install. +install -Dm0644 scripts/99-punktfunk-client-net.conf \ + "$STAGE/usr/lib/sysctl.d/99-punktfunk-client-net.conf" install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT" install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE" install -Dm0644 README.md "$DOCDIR/README.md" @@ -107,6 +112,8 @@ if [ "$1" = "configure" ]; then udevadm control --reload-rules 2>/dev/null || true udevadm trigger --subsystem-match=hidraw 2>/dev/null || true update-desktop-database /usr/share/applications 2>/dev/null || true + # Apply the UDP recv-buffer tuning now (also auto-applied at boot by systemd-sysctl). + sysctl -p /usr/lib/sysctl.d/99-punktfunk-client-net.conf >/dev/null 2>&1 || true fi exit 0 EOF diff --git a/packaging/rpm/punktfunk.spec b/packaging/rpm/punktfunk.spec index 742a857..9bd65b6 100644 --- a/packaging/rpm/punktfunk.spec +++ b/packaging/rpm/punktfunk.spec @@ -154,6 +154,12 @@ install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \ # DualSense hidraw access (full pad fidelity through SDL's HIDAPI driver). install -Dm0644 scripts/70-punktfunk-client.rules \ %{buildroot}%{_udevrulesdir}/70-punktfunk-client.rules +# UDP receive-buffer tuning (32 MB) — the client asks for a 32 MB SO_RCVBUF; without raising +# net.core.rmem_max the kernel clamps it and high-bitrate streams overflow at the receiver +# (measured: 4 MB cap = 31.6% loss at 2 Gbps, 32 MB = 0%). Distinct filename from the host's so +# both can be installed on one box. +install -Dm0644 scripts/99-punktfunk-client-net.conf \ + %{buildroot}%{_prefix}/lib/sysctl.d/99-punktfunk-client-net.conf # Headless session helpers + example config + OpenAPI doc (reference material). install -d %{buildroot}%{_datadir}/%{name}/headless @@ -184,12 +190,16 @@ install -Dm0644 docs/api/openapi.json %{buildroot}%{_datadir}/% %{_bindir}/punktfunk-client %{_datadir}/applications/io.unom.Punktfunk.desktop %{_udevrulesdir}/70-punktfunk-client.rules +%{_prefix}/lib/sysctl.d/99-punktfunk-client-net.conf %post client # Pick up the DualSense hidraw rule without a reboot (best-effort; on rpm-ostree it # applies on the next boot into the layered deployment). udevadm control --reload-rules 2>/dev/null || : udevadm trigger --subsystem-match=hidraw 2>/dev/null || : +# Apply the UDP recv-buffer tuning now (also auto-applied at boot by systemd-sysctl; on +# rpm-ostree it takes effect on the next boot into the layered deployment). +sysctl -p %{_prefix}/lib/sysctl.d/99-punktfunk-client-net.conf >/dev/null 2>&1 || : %post # Reload udev so /dev/uinput picks up the new rule without a reboot (best-effort). diff --git a/scripts/99-punktfunk-client-net.conf b/scripts/99-punktfunk-client-net.conf new file mode 100644 index 0000000..087eb52 --- /dev/null +++ b/scripts/99-punktfunk-client-net.conf @@ -0,0 +1,8 @@ +# punktfunk client UDP socket-buffer tuning. The client asks the kernel for a 32 MB UDP receive +# buffer (SO_RCVBUF) so high-bitrate video bursts don't overflow it, but the kernel silently CLAMPS +# the request to net.core.rmem_max — whose default (~208 KB-4 MB) is far too small. A too-small recv +# buffer is the dominant client-side wall above ~1 Gbps: measured live, a 4 MB cap dropped 31.6% of a +# 2 Gbps stream at the receiver while a 32 MB cap delivered the same 2 Gbps at 0.0% loss. wmem covers +# the mic-uplink / input send side. systemd-sysctl applies this at boot; the postinst applies it now. +net.core.rmem_max = 33554432 +net.core.wmem_max = 33554432