Skip to content

LLT-7562, LLT-7644: Rebuild Apple listen sockets on network change and release the old port on listen_port change - #76

Merged
sfraczek merged 3 commits into
mainfrom
sfraczek/LLT-7562-rebuild-sockets-on-network-change
Aug 25, 2026
Merged

LLT-7562, LLT-7644: Rebuild Apple listen sockets on network change and release the old port on listen_port change#76
sfraczek merged 3 commits into
mainfrom
sfraczek/LLT-7562-rebuild-sockets-on-network-change

Conversation

@sfraczek

@sfraczek sfraczek commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

On macOS/iOS/tvOS the WireGuard UDP socket is pinned to a physical interface via IP_BOUND_IF, since these platforms have no fwmark equivalent for routing the socket's traffic around the tunnel. When that interface disappears and comes back, the socket's flow control can wedge against the dead incarnation: every send fails with EAGAIN and the queue never drains, because the kernel's resume signal can only come from that same incarnation.

drop_connected_sockets() is the only thing run on a network change, and it doesn't help - it closes per-peer connected sockets, which are compiled out on Apple.

This rebuilds the shared socket instead: close the old one, then rebind the same port so an existing NAT mapping stays valid when the same interface returns with the same address, falling back to an ephemeral port if that port is taken. Closing has to go through the event loop, since it holds a duplicate of the descriptor that keeps the port allocated.

@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch from ff2ae3e to 889b27e Compare August 11, 2026 18:46
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.45324% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.81%. Comparing base (a45a31d) to head (3f9784b).

Files with missing lines Patch % Lines
neptun/src/device/mod.rs 82.57% 23 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #76      +/-   ##
==========================================
+ Coverage   73.02%   73.81%   +0.78%     
==========================================
  Files          20       20              
  Lines        4601     4724     +123     
==========================================
+ Hits         3360     3487     +127     
+ Misses       1241     1237       -4     
Flag Coverage Δ
linux 76.74% <84.28%> (+0.13%) ⬆️
macos 59.98% <86.00%> (+2.62%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch 2 times, most recently from f2bffa6 to 7779dc7 Compare August 11, 2026 19:55
@sfraczek
sfraczek requested review from djkarwowski, lcruz99, mathiaspeters and tomasz-grz and removed request for djkarwowski and lcruz99 August 12, 2026 06:46
@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch from 7779dc7 to 0f7c885 Compare August 12, 2026 14:40
@sfraczek

Copy link
Copy Markdown
Contributor Author

Follow-up filed: LLT-7623

@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch from 0f7c885 to 87d2e04 Compare August 14, 2026 12:48
Comment thread neptun/tests/device.rs Outdated
Comment thread neptun/tests/device.rs Outdated
Comment thread neptun/src/device/mod.rs
Comment thread neptun/src/device/mod.rs Outdated
Comment thread neptun/src/device/mod.rs Outdated
@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch 3 times, most recently from 5be0a6b to 377084d Compare August 21, 2026 10:01
@sfraczek sfraczek changed the title LLT-7562: Rebuild listen sockets on network change on Apple platforms LLT-7562, LLT-7644: Rebuild Apple listen sockets on network change and release the old port on listen_port change Aug 21, 2026
@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch from 377084d to 1c54b7c Compare August 21, 2026 11:42
@sfraczek
sfraczek requested a review from matislovas August 21, 2026 12:08

@mathiaspeters mathiaspeters left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch 2 times, most recently from 88c7e56 to a4d8f8f Compare August 24, 2026 09:40
tomasz-grz
tomasz-grz previously approved these changes Aug 24, 2026

@tomasz-grz tomasz-grz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 ship it 🚢

Comment thread neptun/src/device/mod.rs Outdated
Comment thread neptun/src/device/mod.rs Outdated
register_udp_handler took a try_clone() duplicate, so the event was
registered under the duplicate's descriptor while cleanup cleared the
original's: the event survived, kept its dup of the socket open, and
the old port stayed bound after a rebind. With a shared Arc there is
one descriptor throughout, and cleanup clears it straight off the
socket it is about to drop.
Reading the port back only fails if the bound socket reports an address
family other than AF_INET, which should not happen. The old branch let
it fall through: the IPv6 socket then bound another random port and
listen_port stayed 0, which api.rs reports as no port at all.
@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch from 0397bf3 to 6ad87dd Compare August 24, 2026 14:50
On Apple the UDP socket is pinned to a physical interface, and its flow
control can wedge against a dead interface incarnation - every send
fails with EAGAIN and the queue never drains. drop_connected_sockets()
does not help there, it only closes per-peer sockets.

Rebuild the socket instead: close it, then rebind the same port to keep
NAT mappings, falling back to an ephemeral one.
@sfraczek
sfraczek force-pushed the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch from 6ad87dd to 3f9784b Compare August 24, 2026 14:57
@matislovas

Copy link
Copy Markdown
Contributor

+0.5

@sfraczek
sfraczek enabled auto-merge August 24, 2026 15:50
@sfraczek
sfraczek merged commit 3a40095 into main Aug 25, 2026
30 checks passed
@sfraczek
sfraczek deleted the sfraczek/LLT-7562-rebuild-sockets-on-network-change branch August 25, 2026 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants