Add shared virtual NIC core with per-member routing

Share a named TUN across instances while keeping unnamed devices
dedicated. Track member addresses, routes, and MTU, and reject
overlapping destinations except the common Magic DNS host route.

Dispatch packets between the physical TUN and member tunnels. Keep
IPv4 and ordinary IPv6 source translation for mobile wrong-source
traffic. Update platform configuration and runtime host integration,
with unit and network namespace coverage for routing and lifecycle.

Use smoltcp for packet parsing and checksum updates. Keep core CI
matrix jobs independent.

Reserve native inbound flows before source translations allocate their
wire tuples. Keep active reservations under table pressure and leave
forwarded subnet traffic outside the local flow table.

Complete interface claim updates on the shared runtime and retain member
registrations until the transaction commits. Keep address, route, and
MTU cleanup ordered after cancelled callers, including device
initialization.

Project mobile VPN addresses, routes, and DNS from admitted native
members. Prefer unchanged attached claims and report conflicting members
individually. Apply each member's complete initial claims before opening
the shared fd, so conflicts leave healthy members usable.

Cover inbound IPv4/IPv6 collisions, cancellation during native changes
and dispatcher acknowledgments, admission priority, and atomic mobile
claim rejection with regression tests.

Use scoped TestNetwork fixtures for shared TUN bridge setup and cleanup.
Resolve public IPv6 namespace aliases through the lab's actual names so
the new tests remain isolated under parallel upstream test runs.
This commit is contained in:
KKRainbow committed 2026-10-13 00:44:35 +08:00
1 parent 9bc1a0941f
commit ca4f867e43
26 files changed
+8502 -339

No files matched your search

+58
View File
@@ -413,6 +413,64 @@ Process-global capability objects may contain stateless or shared platform
mechanisms. They must not contain instance-specific peer, route,
configuration, or connectivity state.
### Native shared TUN ownership
The native composition owns `SharedVirtualNicRegistry`. Named desktop TUNs
are shared within a network namespace; mobile instances attach to one supplied
TUN descriptor. Members own address, route, and MTU claims, not the physical
device. Bootstrap route cleanup runs only when that device is created. Mobile
IPv6 claims are initialized before forwarding and follow public IPv6 updates.
Mobile VPN configuration is projected from admitted members' native claims.
Admission keeps unchanged attached members ahead of conflicting newcomers or
reconfigured members. Rejected members are reported individually, while the
remaining members stay attached. Each member's initial claims are applied as
one batch before it can open or replace the shared descriptor.
Mobile claims update dispatcher tables without configuring the OS interface;
the platform VPN owns its addresses, routes, and MTU.
If applying native claims fails, the shared NIC is invalidated and its
dispatcher is stopped so every member can recreate the device. Restoring only
the recorded claims would leave partially applied OS configuration in use.
Desktop and mobile shared TUNs use the same lazily initialized native Tokio
runtime, independent of every member's executor. It creates the device's async
I/O registration, drives dispatchers, and completes member claim cleanup even
after the member executor stops or the registration is dropped outside Tokio.
The runtime has two workers on desktop to allow independent TUN dispatchers
to run concurrently, and retains one worker on mobile. It owns no registry or
member claims; those remain with each shared NIC. Cleanup remains asynchronous,
and the last member's cleanup stops the dispatcher and releases the desktop
device. A process-lifetime runtime does not extend the device's lifetime.
Unnamed desktop TUNs and instance-local work retain their existing executors.
Only the member running the Magic DNS resolver claims its shared fake-IP
route. The claim is removed before resolver shutdown and acquired by the next
serving member after takeover. Client-only runners do not claim that route.
The dispatcher preserves desktop kernel-forwarded subnet sources. It corrects
wrong-member local sources and, on mobile, synthetic sources. Native local
flows and translated flows reserve member-scoped transport tuples so address
translation cannot merge sockets using the same port and remote endpoint.
Collisions remap the source port or ICMP Echo identifier; replies restore the
original tuple. Unrelated route updates and member removals retain mappings.
All Echo sequence numbers for one identifier share a reservation; translation
preserves the sequence field in each request and reply.
Removing an involved address or member releases its mappings. A full member
queue drops that packet without blocking other members or control messages.
Reservations are bounded at 4096 flows. Activity in either direction refreshes
them; table pressure reclaims reservations idle for at least 180 seconds. If
all slots remain active, new tracked flows are dropped rather than evicting a
live mapping. Desktop external-source forwarding bypasses this table. As with
other idle-expiring NAT state, very late replies after tuple reuse cannot be
distinguished from replies to the new flow.
Translation supports unfragmented IPv4 and ordinary IPv6 TCP, UDP, and ICMP
Echo traffic. IPv4 fragment and IPv6 extension-header translation remain
unsupported. ICMP errors quoting a translated flow are not reverse-translated;
in particular, a smaller downstream MTU can prevent PMTU discovery for such
flows. This limitation does not affect unmodified flows and is intentionally
retained rather than extending the dispatcher into a full ICMP/fragment NAT.
## Runtime configuration authority
`TomlConfig` is the authoritative desired configuration used for management