perf: add a zero-copy pbuf output path for WireGuard - #33
Open
kedimuzafer wants to merge 1 commit into
Open
Conversation
wireguard_udp_output_fn takes a flat byte buffer, so both magicsock output paths mem_malloc() a buffer and pbuf_copy_partial() the encrypted pbuf into it. The integrator then has to build a pbuf again to hand it to udp_sendto, which is a second allocation and a second copy of the same ~1.3 KB. All four happen on the TCPIP thread, once per outgoing packet. The encrypted pbuf is allocated PBUF_TRANSPORT in wireguardif_output_to_peer, so it already has room for the UDP and IP headers and udp_sendto can take it as-is. Adds wireguard_udp_output_pbuf_fn plus wireguardif_set_udp_output_pbuf(), and prefers it in both output paths when set. The byte-buffer callback is untouched and still used when no pbuf callback is registered, so this is additive for existing integrators. ml_wg_mgr registers one, since it already sends through a raw udp_pcb. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bqLmUG7wJ7p9ya2Vp4A9J
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
wireguard_udp_output_fntakes a flat byte buffer, so both magicsock output paths inwireguardif.cdo this per packet:and
ml_wg_mgr's callback then has to turn it back into a pbuf forudp_sendto:Two allocations and two ~1.3 KB copies of the same bytes, once per outgoing packet, all on the TCPIP thread.
That thread is the constraint.
vTaskGetRunTimeStatson an ESP32-S3 carrying a single 1.4 MB/s TCP stream through the tunnel:The encrypted pbuf is allocated
PBUF_TRANSPORTinwireguardif_output_to_peer(), so it already has headroom for the UDP and IP headers —udp_sendtocan take it directly.Change
Adds
wireguard_udp_output_pbuf_fnandwireguardif_set_udp_output_pbuf(), and prefers it in both output paths when registered. The existing byte-buffer callback is untouched and still used when no pbuf callback is set, so this is additive — existing integrators are unaffected.ml_wg_mgrregisters one, since it already sends through a rawudp_pcband never needed the flat buffer.Ownership is unchanged:
udp_sendtodoes not consume the pbuf, and the callback is synchronous, sowireguardif's existingpbuf_freestill applies.Measured
Single-stream throughput through the tunnel, ESP32-S3 SOCKS5 proxy: 1.44 MB/s → 1.49 MB/s. Modest on its own, but it is 25% of the per-packet work on the thread that is nearest to saturation, so it should matter more on boards or workloads where that thread is the limit.
Independent of #30, #31 and #32.