From 34ae0fd2491ab23c85d9eb1822b278f550b3de68 Mon Sep 17 00:00:00 2001 From: Matas Misiunas Date: Wed, 10 Jul 2024 13:28:17 +0300 Subject: [PATCH] Enable performance cores on Apple --- Cargo.lock | 7 ++++++ boringtun/Cargo.toml | 3 +++ boringtun/src/device/mod.rs | 47 ++++++++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6113f68b..fcaaca9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,7 @@ dependencies = [ "blake2", "chacha20poly1305", "criterion", + "dispatch", "etherparse", "hex", "hmac", @@ -443,6 +444,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + [[package]] name = "either" version = "1.7.0" diff --git a/boringtun/Cargo.toml b/boringtun/Cargo.toml index 3f42ae7f..25a635a7 100644 --- a/boringtun/Cargo.toml +++ b/boringtun/Cargo.toml @@ -41,6 +41,9 @@ mock_instant = { version = "0.2", optional = true } socket2 = { version = "0.5", features = ["all"], optional = true } thiserror = { version = "1", optional = true } +[target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))'.dependencies] +dispatch = "0.2.0" + [target.'cfg(unix)'.dependencies] nix = { version = "0.28", default-features = false, features = [ "time", diff --git a/boringtun/src/device/mod.rs b/boringtun/src/device/mod.rs index c02b52d9..275bcf65 100644 --- a/boringtun/src/device/mod.rs +++ b/boringtun/src/device/mod.rs @@ -35,7 +35,6 @@ use std::os::unix::io::AsRawFd; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::thread; -use std::thread::JoinHandle; use crate::noise::errors::WireGuardError; use crate::noise::handshake::parse_handshake_anon; @@ -118,7 +117,10 @@ impl MakeExternalBoringtun for MakeExternalBoringtunNoop { pub struct DeviceHandle { pub device: Arc>, // The interface this handle owns - threads: Vec>, + #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))] + threads: Vec>, + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))] + threads: (dispatch::Group, dispatch::Queue), } #[derive(Clone)] @@ -186,19 +188,36 @@ impl DeviceHandle { pub fn new_with_tun(tun: TunSocket, config: DeviceConfig) -> Result { let n_threads = config.n_threads; + let mut wg_interface = Device::new_with_tun(tun, config)?; wg_interface.open_listen_socket(0)?; // Start listening on a random port let interface_lock = Arc::new(Lock::new(wg_interface)); - let mut threads = vec![]; - - for i in 0..n_threads { - threads.push({ - let dev = Arc::clone(&interface_lock); - thread::spawn(move || DeviceHandle::event_loop(i, &dev)) + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))] + let threads = { + let group = dispatch::Group::create(); + let queue = dispatch::Queue::global(dispatch::QueuePriority::High); + let dev = Arc::clone(&interface_lock); + let group_clone = group.clone(); + queue.exec_async(move || { + group_clone.enter(); + DeviceHandle::event_loop(0, &dev); }); - } + (group, queue) + }; + + #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))] + let threads = { + let mut threads = vec![]; + for i in 0..n_threads { + threads.push({ + let dev = Arc::clone(&interface_lock); + thread::spawn(move || DeviceHandle::event_loop(i, &dev)) + }); + } + threads + }; Ok(DeviceHandle { device: interface_lock, @@ -221,12 +240,18 @@ impl DeviceHandle { self.device.read().drop_connected_sockets(); } + #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))] pub fn wait(&mut self) { while let Some(thread) = self.threads.pop() { thread.join().unwrap(); } } + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))] + pub fn wait(&mut self) { + self.threads.0.wait(); + } + pub fn clean(&mut self) { for path in &self.device.read().cleanup_paths { // attempt to remove any file we created in the work dir @@ -303,12 +328,12 @@ impl DeviceHandle { } } - fn new_thread_local(thread_id: usize, device_lock: &LockReadGuard) -> ThreadData { + fn new_thread_local(_thread_id: usize, device_lock: &LockReadGuard) -> ThreadData { #[cfg(target_os = "linux")] let t_local = ThreadData { src_buf: [0u8; MAX_UDP_SIZE], dst_buf: [0u8; MAX_UDP_SIZE], - iface: if thread_id == 0 || !device_lock.config.use_multi_queue { + iface: if _thread_id == 0 || !device_lock.config.use_multi_queue { // For the first thread use the original iface Arc::clone(&device_lock.iface) } else {