Browse Source

Experiment with locking performance.

locking
Mathias Hall-Andersen 6 years ago
parent
commit
e7c3bf6047
  1. 5
      src/wireguard/router/device.rs
  2. 2
      src/wireguard/router/mod.rs
  3. 91
      src/wireguard/router/mutex.rs
  4. 14
      src/wireguard/router/peer.rs
  5. 3
      src/wireguard/router/queue.rs
  6. 2
      src/wireguard/router/receive.rs
  7. 3
      src/wireguard/router/route.rs
  8. 5
      src/wireguard/router/send.rs
  9. 22
      src/wireguard/router/tests/bench.rs

5
src/wireguard/router/device.rs

@ -6,7 +6,10 @@ use std::thread;
use std::time::Instant;
use log;
use spin::{Mutex, RwLock};
// TESTING
use super::mutex::*;
use zerocopy::LayoutVerified;
use super::anti_replay::AntiReplay;

2
src/wireguard/router/mod.rs

@ -12,6 +12,8 @@ mod receive;
mod send;
mod worker;
mod mutex;
#[cfg(test)]
mod tests;

91
src/wireguard/router/mutex.rs

@ -0,0 +1,91 @@
/*
use std::sync::Mutex as StdMutex;
use std::sync::MutexGuard;
use std::sync::RwLock as StdRwLock;
use std::sync::RwLockReadGuard;
use std::sync::RwLockWriteGuard;
pub struct Mutex<T> {
mutex: StdMutex<T>,
}
pub struct RwLock<T> {
rwlock: StdRwLock<T>,
}
impl<T> Mutex<T> {
pub fn new(v: T) -> Mutex<T> {
Mutex {
mutex: StdMutex::new(v),
}
}
pub fn lock(&self) -> MutexGuard<T> {
self.mutex.lock().unwrap()
}
}
impl<T> RwLock<T> {
pub fn new(v: T) -> RwLock<T> {
RwLock {
rwlock: StdRwLock::new(v),
}
}
pub fn read(&self) -> RwLockReadGuard<T> {
self.rwlock.read().unwrap()
}
pub fn write(&self) -> RwLockWriteGuard<T> {
self.rwlock.write().unwrap()
}
}
*/
use spin::Mutex as StdMutex;
use spin::MutexGuard;
use spin::RwLock as StdRwLock;
use spin::RwLockReadGuard;
use spin::RwLockWriteGuard;
pub struct Mutex<T> {
mutex: StdMutex<T>,
}
pub struct RwLock<T> {
rwlock: StdRwLock<T>,
}
impl<T> Mutex<T> {
pub fn new(v: T) -> Mutex<T> {
Mutex {
mutex: StdMutex::new(v),
}
}
pub fn lock(&self) -> MutexGuard<T> {
self.mutex.lock()
}
pub fn try_lock(&self) -> Option<MutexGuard<T>> {
self.mutex.try_lock()
}
}
impl<T> RwLock<T> {
pub fn new(v: T) -> RwLock<T> {
RwLock {
rwlock: StdRwLock::new(v),
}
}
pub fn read(&self) -> RwLockReadGuard<T> {
self.rwlock.read()
}
pub fn write(&self) -> RwLockWriteGuard<T> {
self.rwlock.write()
}
}

14
src/wireguard/router/peer.rs

@ -21,12 +21,14 @@ use core::sync::atomic::AtomicBool;
use alloc::sync::Arc;
// TESTING
use super::mutex::Mutex;
// TODO: consider no_std alternatives
use std::net::{IpAddr, SocketAddr};
use arraydeque::{ArrayDeque, Wrapping};
use log;
use spin::Mutex;
pub struct KeyWheel {
next: Option<Arc<KeyPair>>, // next key state (unconfirmed)
@ -111,7 +113,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> DecryptionSta
DecryptionState {
confirmed: AtomicBool::new(keypair.initiator),
keypair: keypair.clone(),
protector: spin::Mutex::new(AntiReplay::new()),
protector: Mutex::new(AntiReplay::new()),
death: keypair.birth + REJECT_AFTER_TIME,
peer,
}
@ -168,15 +170,15 @@ pub fn new_peer<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
device,
inbound: Queue::new(),
outbound: Queue::new(),
enc_key: spin::Mutex::new(None),
endpoint: spin::Mutex::new(None),
keys: spin::Mutex::new(KeyWheel {
enc_key: Mutex::new(None),
endpoint: Mutex::new(None),
keys: Mutex::new(KeyWheel {
next: None,
current: None,
previous: None,
retired: vec![],
}),
staged_packets: spin::Mutex::new(ArrayDeque::new()),
staged_packets: Mutex::new(ArrayDeque::new()),
}),
}
};

3
src/wireguard/router/queue.rs

@ -1,5 +1,6 @@
use super::mutex::Mutex;
use arraydeque::ArrayDeque;
use spin::Mutex;
use core::mem;
use core::sync::atomic::{AtomicUsize, Ordering};

2
src/wireguard/router/receive.rs

@ -6,11 +6,11 @@ use super::types::Callbacks;
use super::{REJECT_AFTER_MESSAGES, SIZE_TAG};
use super::super::{tun, udp, Endpoint};
use super::mutex::Mutex;
use alloc::sync::Arc;
use core::sync::atomic::{AtomicBool, Ordering};
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
use spin::Mutex;
use zerocopy::{AsBytes, LayoutVerified};
struct Inner<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {

3
src/wireguard/router/route.rs

@ -3,7 +3,8 @@ use super::ip::*;
// TODO: no_std alternatives
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use spin::RwLock;
use super::mutex::RwLock;
use treebitmap::address::Address;
use treebitmap::IpLookupTable;
use zerocopy::LayoutVerified;

5
src/wireguard/router/send.rs

@ -11,9 +11,10 @@ use alloc::sync::Arc;
use core::sync::atomic::{AtomicBool, Ordering};
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
use spin::Mutex;
use zerocopy::{AsBytes, LayoutVerified};
use super::mutex::Mutex;
struct Inner<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {
ready: AtomicBool,
buffer: Mutex<Vec<u8>>,
@ -127,7 +128,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> SequentialJob
// send to peer
let job = &self.0;
let msg = job.buffer.lock();
let msg = job.buffer.try_lock().unwrap(); // never contested
let xmit = job.peer.send_raw(&msg[..]).is_ok();
// trigger callback (for timers)

22
src/wireguard/router/tests/bench.rs

@ -80,7 +80,7 @@ fn profiler_start(name: &str) {
#[bench]
fn bench_router_outbound(b: &mut Bencher) {
// 10 GB transmission per iteration
// 1 GB transmission per iteration
const BYTES_PER_ITER: usize = 100 * 1024 * 1024 * 1024;
// inner payload of IPv4 packet is 1440 bytes
@ -118,16 +118,20 @@ fn bench_router_outbound(b: &mut Bencher) {
#[cfg(feature = "profiler")]
profiler_start("outbound");
// repeatedly transmit 10 GB
b.iter(|| {
opaque.reset();
while opaque.sent() < BYTES_PER_ITER / packet.len() {
router
.send(msg.to_vec())
.expect("failed to crypto-route packet");
}
// repeatedly transmit 1 GB
let summary = b.bench(|bench| {
bench.iter(|| {
opaque.reset();
while opaque.sent() < BYTES_PER_ITER / packet.len() {
router
.send(msg.to_vec())
.expect("failed to crypto-route packet");
}
})
});
println!("{:?}", summary);
// stop profiler
#[cfg(feature = "profiler")]
profiler_stop();

Loading…
Cancel
Save