From 62e43855cb2e77fde826157cad22d0a7e61d2367 Mon Sep 17 00:00:00 2001 From: "sijie.sun" Date: Sat, 13 Jun 2026 15:54:55 +0800 Subject: [PATCH] feat: support shared nic mobile fd Create the shared virtual nic dispatcher from the mobile tun fd. Later shared members attach through their ring tunnel and do not consume another fd. Dedicated mobile nic creation stays unchanged. Fix mobile no-magic-dns cfg so the mobile tun path checks without enabling magic-dns. --- easytier/src/instance/instance.rs | 15 +++++++-- easytier/src/instance/shared_virtual_nic.rs | 35 +++++++++++++++++++++ easytier/src/instance/virtual_nic.rs | 2 +- easytier/src/launcher.rs | 2 +- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/easytier/src/instance/instance.rs b/easytier/src/instance/instance.rs index d6c2f156..6d927256 100644 --- a/easytier/src/instance/instance.rs +++ b/easytier/src/instance/instance.rs @@ -4,15 +4,17 @@ use std::collections::HashSet; use std::net::{IpAddr, Ipv4Addr}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Weak}; -#[cfg(feature = "tun")] +#[cfg(all(feature = "tun", not(mobile)))] use std::time::Duration; use anyhow::Context; use cidr::{IpCidr, Ipv4Inet}; use futures::FutureExt; +#[cfg(all(feature = "tun", not(mobile)))] +use tokio::sync::oneshot; use tokio::sync::{Mutex, Notify}; #[cfg(feature = "tun")] -use tokio::{sync::oneshot, task::JoinSet}; +use tokio::task::JoinSet; #[cfg(feature = "magic-dns")] use tokio_util::sync::CancellationToken; use tokio_util::task::AbortOnDropHandle; @@ -1588,12 +1590,19 @@ impl Instance { .await .with_context(|| "add ip failed")?; + #[cfg(feature = "magic-dns")] let magic_dns_runner = if let Some(ipv4) = global_ctx.get_ipv4() { Self::create_magic_dns_runner(peer_manager.clone(), None, ipv4) } else { None }; - Self::use_new_nic_ctx(nic_ctx.clone(), new_nic_ctx, magic_dns_runner).await; + Self::use_new_nic_ctx( + nic_ctx.clone(), + new_nic_ctx, + #[cfg(feature = "magic-dns")] + magic_dns_runner, + ) + .await; Ok(()) } diff --git a/easytier/src/instance/shared_virtual_nic.rs b/easytier/src/instance/shared_virtual_nic.rs index aaa0009c..6f5a4213 100644 --- a/easytier/src/instance/shared_virtual_nic.rs +++ b/easytier/src/instance/shared_virtual_nic.rs @@ -404,6 +404,26 @@ impl SharedVirtualNic { )); Ok(()) } + + #[cfg(mobile)] + async fn ensure_dispatcher_for_mobile( + &mut self, + tun_fd: std::os::fd::RawFd, + ) -> Result<(), Error> { + self.ensure_valid()?; + + if self.dispatcher.is_some() { + return Ok(()); + } + + let tunnel = self.nic.lock().await.create_dev_for_mobile(tun_fd).await?; + self.dispatcher = Some(SharedVirtualNicDispatcher::start( + tunnel, + self.member_tunnel_table.clone(), + self.valid.clone(), + )); + Ok(()) + } } struct SharedVirtualNicMemberRegistration { @@ -500,6 +520,21 @@ impl SharedVirtualNicMember { Ok(member_tunnel) } + #[cfg(mobile)] + pub async fn create_dev_for_mobile( + &self, + tun_fd: std::os::fd::RawFd, + ) -> Result, Error> { + let (member_tunnel, shared_tunnel) = create_ring_tunnel_pair(); + { + let mut shared_nic = self.shared_nic.lock().await; + shared_nic.ensure_dispatcher_for_mobile(tun_fd).await?; + } + self.registration + .register_tunnel(shared_tunnel, self.close_notifier.clone())?; + Ok(member_tunnel) + } + #[cfg(not(target_os = "linux"))] pub async fn ifcfg_and_ifname(&self) -> Result<(IfConfiger, String), Error> { self.shared_nic.lock().await.ifcfg_and_ifname().await diff --git a/easytier/src/instance/virtual_nic.rs b/easytier/src/instance/virtual_nic.rs index b0cc00ca..c7c7a2de 100644 --- a/easytier/src/instance/virtual_nic.rs +++ b/easytier/src/instance/virtual_nic.rs @@ -863,7 +863,7 @@ impl NicBackend { ) -> Result, Error> { match self { Self::Dedicated(nic) => nic.lock().await.create_dev_for_mobile(tun_fd).await, - Self::Shared(member) => member.create_dev().await, + Self::Shared(member) => member.create_dev_for_mobile(tun_fd).await, } } diff --git a/easytier/src/launcher.rs b/easytier/src/launcher.rs index 9b7d4f4a..a4056cf1 100644 --- a/easytier/src/launcher.rs +++ b/easytier/src/launcher.rs @@ -128,7 +128,7 @@ impl EasyTierLauncher { let Some(tun_fd) = tun_fd_receiver.recv().await.flatten() else { return; }; - let res = Instance::setup_nic_ctx_for_mobile( + let _ = Instance::setup_nic_ctx_for_mobile( nic_ctx.clone(), global_ctx.clone(), peer_mgr.clone(),