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.
This commit is contained in:
sijie.sun
2026-06-13 15:54:55 +08:00
parent 5efbf4853a
commit 62e43855cb
4 changed files with 49 additions and 5 deletions
+12 -3
View File
@@ -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(())
}
@@ -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<Box<dyn Tunnel>, 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
+1 -1
View File
@@ -863,7 +863,7 @@ impl NicBackend {
) -> Result<Box<dyn Tunnel>, 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,
}
}
+1 -1
View File
@@ -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(),