aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/main.rs2
-rw-r--r--src/platform/dummy/tun/dummy.rs (renamed from src/platform/dummy/tun.rs)27
-rw-r--r--src/platform/dummy/tun/mod.rs12
-rw-r--r--src/platform/dummy/tun/void.rs43
-rw-r--r--src/wireguard/mod.rs3
-rw-r--r--src/wireguard/router/anti_replay.rs2
-rw-r--r--src/wireguard/router/ip.rs2
-rw-r--r--src/wireguard/router/mod.rs3
-rw-r--r--src/wireguard/router/peer.rs11
-rw-r--r--src/wireguard/router/queue.rs4
-rw-r--r--src/wireguard/router/receive.rs5
-rw-r--r--src/wireguard/router/route.rs1
-rw-r--r--src/wireguard/router/send.rs4
-rw-r--r--src/wireguard/router/tests/bench.rs424
-rw-r--r--src/wireguard/router/tests/mod.rs48
-rw-r--r--src/wireguard/router/tests/tests.rs (renamed from src/wireguard/router/tests.rs)78
-rw-r--r--src/wireguard/router/types.rs10
-rw-r--r--src/wireguard/router/worker.rs6
-rw-r--r--src/wireguard/tests.rs12
-rw-r--r--src/wireguard/types.rs27
20 files changed, 584 insertions, 140 deletions
diff --git a/src/main.rs b/src/main.rs
index d8e4667..8877422 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,8 @@
#![feature(test)]
#![feature(weak_into_raw)]
+extern crate alloc;
+
#[cfg(feature = "profiler")]
extern crate cpuprofiler;
diff --git a/src/platform/dummy/tun.rs b/src/platform/dummy/tun/dummy.rs
index 1955884..0f3479a 100644
--- a/src/platform/dummy/tun.rs
+++ b/src/platform/dummy/tun/dummy.rs
@@ -1,7 +1,13 @@
-use hex;
-use log::debug;
-use rand::rngs::OsRng;
-use rand::Rng;
+// This provides a mock tunnel interface.
+// Which enables unit tests where WireGuard interfaces
+// are configured to match each other and a full test of:
+//
+// - Handshake
+// - Transport encryption/decryption
+//
+// Can be executed.
+
+use super::*;
use std::cmp::min;
use std::error::Error;
@@ -11,15 +17,16 @@ use std::sync::Mutex;
use std::thread;
use std::time::Duration;
-use super::super::tun::*;
-
-#[derive(Debug)]
-pub enum TunError {
- Disconnected,
-}
+use hex;
+use log::debug;
+use rand::rngs::OsRng;
+use rand::Rng;
pub struct TunTest {}
+// Represents the "other end" (kernel/OS end) of the TUN connection:
+//
+// Used to send/receive packets to the mock WireGuard interface.
pub struct TunFakeIO {
id: u32,
store: bool,
diff --git a/src/platform/dummy/tun/mod.rs b/src/platform/dummy/tun/mod.rs
new file mode 100644
index 0000000..da03c7a
--- /dev/null
+++ b/src/platform/dummy/tun/mod.rs
@@ -0,0 +1,12 @@
+use super::super::tun::*;
+
+mod dummy;
+mod void;
+
+#[derive(Debug)]
+pub enum TunError {
+ Disconnected,
+}
+
+pub use dummy::*;
+pub use void::*;
diff --git a/src/platform/dummy/tun/void.rs b/src/platform/dummy/tun/void.rs
new file mode 100644
index 0000000..0777541
--- /dev/null
+++ b/src/platform/dummy/tun/void.rs
@@ -0,0 +1,43 @@
+/*
+// This code provides a "void" implementation of the tunnel interface:
+// The implementation never reads and immediately discards any write without error
+//
+// This is used during benchmarking and profiling of the inbound path.
+
+use super::*;
+
+pub struct VoidTun {}
+
+pub struct VoidReader {}
+
+pub struct VoidWriter {}
+
+impl Tun for VoidTun {
+ type Writer = VoidWriter;
+ type Reader = VoidReader;
+ type Error = TunError;
+}
+
+
+impl Reader for VodReader {
+ type Error = TunError;
+
+ fn write(&self, src: &[u8]) -> Result<(), Self::Error> {
+ debug!(
+ "dummy::TUN({}) : write ({}, {})",
+ self.id,
+ src.len(),
+ hex::encode(src)
+ );
+ if self.store {
+ let m = src.to_owned();
+ match self.tx.lock().unwrap().send(m) {
+ Ok(_) => Ok(()),
+ Err(_) => Err(TunError::Disconnected),
+ }
+ } else {
+ Ok(())
+ }
+ }
+}
+*/
diff --git a/src/wireguard/mod.rs b/src/wireguard/mod.rs
index c08fe1e..ee1fd78 100644
--- a/src/wireguard/mod.rs
+++ b/src/wireguard/mod.rs
@@ -27,9 +27,6 @@ pub use peer::Peer;
pub use wireguard::WireGuard;
#[cfg(test)]
-pub use types::dummy_keypair;
-
-#[cfg(test)]
use super::platform::dummy;
use super::platform::{tun, udp, Endpoint};
diff --git a/src/wireguard/router/anti_replay.rs b/src/wireguard/router/anti_replay.rs
index b47dea9..bb899a9 100644
--- a/src/wireguard/router/anti_replay.rs
+++ b/src/wireguard/router/anti_replay.rs
@@ -1,4 +1,4 @@
-use std::mem;
+use core::mem;
// Implementation of RFC 6479.
// https://tools.ietf.org/html/rfc6479
diff --git a/src/wireguard/router/ip.rs b/src/wireguard/router/ip.rs
index 532c512..1c72e38 100644
--- a/src/wireguard/router/ip.rs
+++ b/src/wireguard/router/ip.rs
@@ -1,4 +1,4 @@
-use std::mem;
+use core::mem;
use byteorder::BigEndian;
use zerocopy::byteorder::U16;
diff --git a/src/wireguard/router/mod.rs b/src/wireguard/router/mod.rs
index 699c621..7ab291b 100644
--- a/src/wireguard/router/mod.rs
+++ b/src/wireguard/router/mod.rs
@@ -16,12 +16,13 @@ mod worker;
mod tests;
use messages::TransportHeader;
-use std::mem;
use super::constants::REJECT_AFTER_MESSAGES;
use super::queue::ParallelQueue;
use super::types::*;
+use core::mem;
+
pub const SIZE_TAG: usize = 16;
pub const SIZE_MESSAGE_PREFIX: usize = mem::size_of::<TransportHeader>();
pub const CAPACITY_MESSAGE_POSTFIX: usize = SIZE_TAG;
diff --git a/src/wireguard/router/peer.rs b/src/wireguard/router/peer.rs
index 689674d..67d90d8 100644
--- a/src/wireguard/router/peer.rs
+++ b/src/wireguard/router/peer.rs
@@ -15,11 +15,14 @@ use super::receive::ReceiveJob;
use super::send::SendJob;
use super::worker::JobUnion;
-use std::mem;
+use core::mem;
+use core::ops::Deref;
+use core::sync::atomic::AtomicBool;
+
+use alloc::sync::Arc;
+
+// TODO: consider no_std alternatives
use std::net::{IpAddr, SocketAddr};
-use std::ops::Deref;
-use std::sync::atomic::AtomicBool;
-use std::sync::Arc;
use arraydeque::{ArrayDeque, Wrapping};
use log;
diff --git a/src/wireguard/router/queue.rs b/src/wireguard/router/queue.rs
index 6517ba4..d5d657a 100644
--- a/src/wireguard/router/queue.rs
+++ b/src/wireguard/router/queue.rs
@@ -1,8 +1,8 @@
use arraydeque::ArrayDeque;
use spin::Mutex;
-use std::mem;
-use std::sync::atomic::{AtomicUsize, Ordering};
+use core::mem;
+use core::sync::atomic::{AtomicUsize, Ordering};
use super::constants::INORDER_QUEUE_SIZE;
diff --git a/src/wireguard/router/receive.rs b/src/wireguard/router/receive.rs
index 45ef423..15eb8fb 100644
--- a/src/wireguard/router/receive.rs
+++ b/src/wireguard/router/receive.rs
@@ -7,9 +7,8 @@ use super::{REJECT_AFTER_MESSAGES, SIZE_TAG};
use super::super::{tun, udp, Endpoint};
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::Arc;
-
+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};
diff --git a/src/wireguard/router/route.rs b/src/wireguard/router/route.rs
index 3680157..a556010 100644
--- a/src/wireguard/router/route.rs
+++ b/src/wireguard/router/route.rs
@@ -1,5 +1,6 @@
use super::ip::*;
+// TODO: no_std alternatives
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use spin::RwLock;
diff --git a/src/wireguard/router/send.rs b/src/wireguard/router/send.rs
index 0472e11..7e14209 100644
--- a/src/wireguard/router/send.rs
+++ b/src/wireguard/router/send.rs
@@ -7,8 +7,8 @@ use super::{REJECT_AFTER_MESSAGES, SIZE_TAG};
use super::super::{tun, udp, Endpoint};
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::Arc;
+use alloc::sync::Arc;
+use core::sync::atomic::{AtomicBool, Ordering};
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
use spin::Mutex;
diff --git a/src/wireguard/router/tests/bench.rs b/src/wireguard/router/tests/bench.rs
new file mode 100644
index 0000000..f025dc9
--- /dev/null
+++ b/src/wireguard/router/tests/bench.rs
@@ -0,0 +1,424 @@
+extern crate test;
+
+use super::*;
+
+use std::net::IpAddr;
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+use std::sync::Arc;
+
+use num_cpus;
+use test::Bencher;
+
+//
+struct TransmissionCounter {
+ sent: AtomicUsize,
+ recv: AtomicUsize,
+}
+
+impl TransmissionCounter {
+ fn new() -> TransmissionCounter {
+ TransmissionCounter {
+ sent: AtomicUsize::new(0),
+ recv: AtomicUsize::new(0),
+ }
+ }
+
+ fn reset(&self) {
+ self.sent.store(0, Ordering::SeqCst);
+ self.recv.store(0, Ordering::SeqCst);
+ }
+
+ fn sent(&self) -> usize {
+ self.sent.load(Ordering::Acquire)
+ }
+
+ fn recv(&self) -> usize {
+ self.recv.load(Ordering::Acquire)
+ }
+}
+
+struct BencherCallbacks {}
+
+impl Callbacks for BencherCallbacks {
+ type Opaque = Arc<TransmissionCounter>;
+ fn send(t: &Self::Opaque, size: usize, _sent: bool, _keypair: &Arc<KeyPair>, _counter: u64) {
+ t.sent.fetch_add(size, Ordering::SeqCst);
+ }
+ fn recv(t: &Self::Opaque, size: usize, _sent: bool, _keypair: &Arc<KeyPair>) {
+ t.recv.fetch_add(size, Ordering::SeqCst);
+ }
+ fn need_key(_t: &Self::Opaque) {}
+ fn key_confirmed(_t: &Self::Opaque) {}
+}
+
+#[cfg(feature = "profiler")]
+use cpuprofiler::PROFILER;
+
+#[cfg(feature = "profiler")]
+fn profiler_stop() {
+ println!("Stopping profiler");
+ PROFILER.lock().unwrap().stop().unwrap();
+}
+
+#[cfg(feature = "profiler")]
+fn profiler_start(name: &str) {
+ use std::path::Path;
+
+ // find first available path to save profiler output
+ let mut n = 0;
+ loop {
+ let path = format!("./{}-{}.profile", name, n);
+ if !Path::new(path.as_str()).exists() {
+ println!("Starting profiler: {}", path);
+ PROFILER.lock().unwrap().start(path).unwrap();
+ break;
+ };
+ n += 1;
+ }
+}
+
+#[bench]
+fn bench_router_outbound(b: &mut Bencher) {
+ // 10 GB transmission per iteration
+ const BYTES_PER_ITER: usize = 100 * 1024 * 1024 * 1024;
+
+ // inner payload of IPv4 packet is 1440 bytes
+ const BYTES_PER_PACKET: usize = 1440;
+
+ // create device
+ let (_fake, _reader, tun_writer, _mtu) = dummy::TunTest::create(false);
+ let router: Device<_, BencherCallbacks, dummy::TunWriter, dummy::VoidBind> =
+ Device::new(num_cpus::get_physical(), tun_writer);
+
+ // add peer to router
+ let opaque = Arc::new(TransmissionCounter::new());
+ let peer = router.new_peer(opaque.clone());
+ peer.add_keypair(dummy_keypair(true));
+
+ // add subnet to peer
+ let (mask, len, dst) = ("192.168.1.0", 24, "192.168.1.20");
+ let mask: IpAddr = mask.parse().unwrap();
+ peer.add_allowed_ip(mask, len);
+
+ // create "IP packet"
+ let dst = dst.parse().unwrap();
+ let src = match dst {
+ IpAddr::V4(_) => "127.0.0.1".parse().unwrap(),
+ IpAddr::V6(_) => "::1".parse().unwrap(),
+ };
+ let packet = make_packet(BYTES_PER_PACKET, src, dst, 0);
+
+ // suffix with zero and reserve capacity for tag
+ // (normally done to enable in-place transport message construction)
+ let mut msg = pad(&packet);
+ msg.reserve(16);
+
+ // setup profiler
+ #[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");
+ }
+ });
+
+ // stop profiler
+ #[cfg(feature = "profiler")]
+ profiler_stop();
+}
+
+/*
+#[test]
+fn bench_router_bidirectional(b: &mut Bencher) {
+ const MAX_SIZE_BODY: usize = 1500;
+
+ let tests = [
+ (
+ ("192.168.1.0", 24, "192.168.1.20", true),
+ ("172.133.133.133", 32, "172.133.133.133", true),
+ ),
+ (
+ ("192.168.1.0", 24, "192.168.1.20", true),
+ ("172.133.133.133", 32, "172.133.133.133", true),
+ ),
+ (
+ (
+ "2001:db8::ff00:42:8000",
+ 113,
+ "2001:db8::ff00:42:ffff",
+ true,
+ ),
+ (
+ "2001:db8::ff40:42:8000",
+ 113,
+ "2001:db8::ff40:42:ffff",
+ true,
+ ),
+ ),
+ (
+ (
+ "2001:db8::ff00:42:8000",
+ 113,
+ "2001:db8::ff00:42:ffff",
+ true,
+ ),
+ (
+ "2001:db8::ff40:42:8000",
+ 113,
+ "2001:db8::ff40:42:ffff",
+ true,
+ ),
+ ),
+ ];
+
+ let p1 = ("192.168.1.0", 24, "192.168.1.20");
+ let p2 = ("172.133.133.133", 32, "172.133.133.133");
+
+ let ((bind_reader1, bind_writer1), (bind_reader2, bind_writer2)) = dummy::PairBind::pair();
+
+ let mut confirm_packet_size = SIZE_KEEPALIVE;
+
+ // create matching device
+ let (_fake, _, tun_writer1, _) = dummy::TunTest::create(false);
+ let (_fake, _, tun_writer2, _) = dummy::TunTest::create(false);
+
+ let router1: Device<_, TestCallbacks, _, _> = Device::new(1, tun_writer1);
+ router1.set_outbound_writer(bind_writer1);
+
+ let router2: Device<_, TestCallbacks, _, _> = Device::new(1, tun_writer2);
+ router2.set_outbound_writer(bind_writer2);
+
+ // prepare opaque values for tracing callbacks
+
+ let opaque1 = Opaque::new();
+ let opaque2 = Opaque::new();
+
+ // create peers with matching keypairs and assign subnets
+
+ let peer1 = router1.new_peer(opaque1.clone());
+ let peer2 = router2.new_peer(opaque2.clone());
+
+ {
+ let (mask, len, _ip, _okay) = p1;
+ let mask: IpAddr = mask.parse().unwrap();
+ peer1.add_allowed_ip(mask, *len);
+ peer1.add_keypair(dummy_keypair(false));
+ }
+
+ {
+ let (mask, len, _ip, _okay) = p2;
+ let mask: IpAddr = mask.parse().unwrap();
+ peer2.add_allowed_ip(mask, *len);
+ peer2.set_endpoint(dummy::UnitEndpoint::new());
+ }
+
+ if confirm_with_staged_packet {
+ // create IP packet
+ let (_mask, _len, ip1, _okay) = p1;
+ let (_mask, _len, ip2, _okay) = p2;
+
+ let msg = make_packet(
+ SIZE_MSG,
+ ip1.parse().unwrap(), // src
+ ip2.parse().unwrap(), // dst
+ 0,
+ );
+
+ // calculate size of encapsulated IP packet
+ confirm_packet_size = msg.len() + SIZE_KEEPALIVE;
+
+ // stage packet for sending
+ router2
+ .send(pad(&msg))
+ .expect("failed to sent staged packet");
+
+ // a new key should have been requested from the handshake machine
+ assert_eq!(
+ opaque2.need_key.wait(TIMEOUT),
+ Some(()),
+ "a new key should be requested since a packet was attempted transmitted"
+ );
+
+ // no other events should fire
+ no_events!(opaque1);
+ no_events!(opaque2);
+ }
+
+ // add a keypair
+ assert_eq!(peer1.get_endpoint(), None, "no endpoint has yet been set");
+ peer2.add_keypair(dummy_keypair(true));
+
+ // this should cause a key-confirmation packet (keepalive or staged packet)
+ assert_eq!(
+ opaque2.send.wait(TIMEOUT),
+ Some((confirm_packet_size, true)),
+ "expected successful transmission of a confirmation packet"
+ );
+
+ // no other events should fire
+ no_events!(opaque1);
+ no_events!(opaque2);
+
+ // read confirming message received by the other end ("across the internet")
+ let mut buf = vec![0u8; SIZE_MSG * 2];
+ let (len, from) = bind_reader1.read(&mut buf).unwrap();
+ buf.truncate(len);
+
+ assert_eq!(
+ len, confirm_packet_size,
+ "unexpected size of confirmation message"
+ );
+
+ // pass to the router for processing
+ router1
+ .recv(from, buf)
+ .expect("failed to receive confirmation message");
+
+ // check that a receive event is fired
+ assert_eq!(
+ opaque1.recv.wait(TIMEOUT),
+ Some((confirm_packet_size, true)),
+ "we expect processing to be successful"
+ );
+
+ // the key is confirmed
+ assert_eq!(
+ opaque1.key_confirmed.wait(TIMEOUT),
+ Some(()),
+ "confirmation message should confirm the key"
+ );
+
+ // peer1 learns the endpoint
+ assert!(
+ peer1.get_endpoint().is_some(),
+ "peer1 should learn the endpoint of peer2 from the confirmation message (roaming)"
+ );
+
+ // no other events should fire
+ no_events!(opaque1);
+ no_events!(opaque2);
+
+ // now that peer1 has an endpoint
+ // route packets in the other direction: peer1 -> peer2
+ let mut sizes = vec![0, 1, 1500, MAX_SIZE_BODY];
+ for _ in 0..100 {
+ let body_size: usize = rng.gen();
+ let body_size = body_size % MAX_SIZE_BODY;
+ sizes.push(body_size);
+ }
+ for (id, body_size) in sizes.iter().enumerate() {
+ println!("packet: id = {}, body_size = {}", id, body_size);
+
+ // pass IP packet to router
+ let (_mask, _len, ip1, _okay) = p1;
+ let (_mask, _len, ip2, _okay) = p2;
+ let msg = make_packet(
+ *body_size,
+ ip2.parse().unwrap(), // src
+ ip1.parse().unwrap(), // dst
+ id as u64,
+ );
+
+ // calculate encrypted size
+ let encrypted_size = msg.len() + SIZE_KEEPALIVE;
+
+ router1
+ .send(pad(&msg))
+ .expect("we expect routing to be successful");
+
+ // encryption succeeds and the correct size is logged
+ assert_eq!(
+ opaque1.send.wait(TIMEOUT),
+ Some((encrypted_size, true)),
+ "expected send event for peer1 -> peer2 payload"
+ );
+
+ // otherwise no events
+ no_events!(opaque1);
+ no_events!(opaque2);
+
+ // receive ("across the internet") on the other end
+ let mut buf = vec![0u8; MAX_SIZE_BODY + 512];
+ let (len, from) = bind_reader2.read(&mut buf).unwrap();
+ buf.truncate(len);
+ router2.recv(from, buf).unwrap();
+
+ // check that decryption succeeds
+ assert_eq!(
+ opaque2.recv.wait(TIMEOUT),
+ Some((msg.len() + SIZE_KEEPALIVE, true)),
+ "decryption and routing should succeed"
+ );
+
+ // otherwise no events
+ no_events!(opaque1);
+ no_events!(opaque2);
+ }
+}
+
+#[bench]
+fn bench_router_inbound(b: &mut Bencher) {
+ struct BencherCallbacks {}
+ impl Callbacks for BencherCallbacks {
+ type Opaque = Arc<AtomicUsize>;
+ fn send(
+ _t: &Self::Opaque,
+ _size: usize,
+ _sent: bool,
+ _keypair: &Arc<KeyPair>,
+ _counter: u64,
+ ) {
+ }
+ fn recv(t: &Self::Opaque, size: usize, _sent: bool, _keypair: &Arc<KeyPair>) {
+ t.fetch_add(size, Ordering::SeqCst);
+ }
+ fn need_key(_t: &Self::Opaque) {}
+ fn key_confirmed(_t: &Self::Opaque) {}
+ }
+
+ // create device
+ let (_fake, _reader, tun_writer, _mtu) = dummy::TunTest::create(false);
+ let router: Device<_, BencherCallbacks, dummy::TunWriter, dummy::VoidBind> =
+ Device::new(num_cpus::get_physical(), tun_writer);
+
+ // add new peer
+ let opaque = Arc::new(AtomicUsize::new(0));
+ let peer = router.new_peer(opaque.clone());
+ peer.add_keypair(dummy_keypair(true));
+
+ // add subnet to peer
+ let (mask, len, dst) = ("192.168.1.0", 24, "192.168.1.20");
+ let mask: IpAddr = mask.parse().unwrap();
+ peer.add_allowed_ip(mask, len);
+
+ // create "IP packet"
+ let dst = dst.parse().unwrap();
+ let src = match dst {
+ IpAddr::V4(_) => "127.0.0.1".parse().unwrap(),
+ IpAddr::V6(_) => "::1".parse().unwrap(),
+ };
+ let mut msg = pad(&make_packet(1024, src, dst, 0));
+
+ msg.reserve(16);
+
+ #[cfg(feature = "profiler")]
+ profiler_start("outbound");
+
+ // every iteration sends 10 GB
+ b.iter(|| {
+ opaque.store(0, Ordering::SeqCst);
+ while opaque.load(Ordering::Acquire) < 10 * 1024 * 1024 {
+ router.send(msg.to_vec()).unwrap();
+ }
+ });
+
+ #[cfg(feature = "profiler")]
+ profiler_stop();
+}
+*/
diff --git a/src/wireguard/router/tests/mod.rs b/src/wireguard/router/tests/mod.rs
new file mode 100644
index 0000000..50bcc37
--- /dev/null
+++ b/src/wireguard/router/tests/mod.rs
@@ -0,0 +1,48 @@
+mod bench;
+mod tests;
+
+use super::message_data_len;
+use super::SIZE_MESSAGE_PREFIX;
+use super::{Callbacks, Device};
+use super::{Key, KeyPair};
+
+use super::super::dummy;
+use super::super::tests::make_packet;
+
+use std::time::Instant;
+
+fn init() {
+ let _ = env_logger::builder().is_test(true).try_init();
+}
+
+fn pad(msg: &[u8]) -> Vec<u8> {
+ let mut o = vec![0; msg.len() + SIZE_MESSAGE_PREFIX];
+ o[SIZE_MESSAGE_PREFIX..SIZE_MESSAGE_PREFIX + msg.len()].copy_from_slice(msg);
+ o
+}
+
+pub fn dummy_keypair(initiator: bool) -> KeyPair {
+ let k1 = Key {
+ key: [0x53u8; 32],
+ id: 0x646e6573,
+ };
+ let k2 = Key {
+ key: [0x52u8; 32],
+ id: 0x76636572,
+ };
+ if initiator {
+ KeyPair {
+ birth: Instant::now(),
+ initiator: true,
+ send: k1,
+ recv: k2,
+ }
+ } else {
+ KeyPair {
+ birth: Instant::now(),
+ initiator: false,
+ send: k2,
+ recv: k1,
+ }
+ }
+}
diff --git a/src/wireguard/router/tests.rs b/src/wireguard/router/tests/tests.rs
index 842dd52..6819644 100644
--- a/src/wireguard/router/tests.rs
+++ b/src/wireguard/router/tests/tests.rs
@@ -1,28 +1,15 @@
-use super::KeyPair;
-use super::SIZE_MESSAGE_PREFIX;
-use super::{Callbacks, Device};
-
-use super::message_data_len;
-
-use super::super::dummy;
-use super::super::dummy_keypair;
-use super::super::tests::make_packet;
-
use crate::platform::udp::Reader;
use std::net::IpAddr;
use std::ops::Deref;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
use std::sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender};
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
-use env_logger;
-use num_cpus;
use rand::Rng;
-use test::Bencher;
+
+use super::*;
extern crate test;
@@ -130,67 +117,6 @@ impl Callbacks for TestCallbacks {
}
}
-fn init() {
- let _ = env_logger::builder().is_test(true).try_init();
-}
-
-fn pad(msg: &[u8]) -> Vec<u8> {
- let mut o = vec![0; msg.len() + SIZE_MESSAGE_PREFIX];
- o[SIZE_MESSAGE_PREFIX..SIZE_MESSAGE_PREFIX + msg.len()].copy_from_slice(msg);
- o
-}
-
-#[bench]
-fn bench_outbound(b: &mut Bencher) {
- struct BencherCallbacks {}
- impl Callbacks for BencherCallbacks {
- type Opaque = Arc<AtomicUsize>;
- fn send(
- t: &Self::Opaque,
- size: usize,
- _sent: bool,
- _keypair: &Arc<KeyPair>,
- _counter: u64,
- ) {
- t.fetch_add(size, Ordering::SeqCst);
- }
- fn recv(_: &Self::Opaque, _size: usize, _sent: bool, _keypair: &Arc<KeyPair>) {}
- fn need_key(_: &Self::Opaque) {}
- fn key_confirmed(_: &Self::Opaque) {}
- }
-
- // create device
- let (_fake, _reader, tun_writer, _mtu) = dummy::TunTest::create(false);
- let router: Device<_, BencherCallbacks, dummy::TunWriter, dummy::VoidBind> =
- Device::new(num_cpus::get(), tun_writer);
-
- // add new peer
- let opaque = Arc::new(AtomicUsize::new(0));
- let peer = router.new_peer(opaque.clone());
- peer.add_keypair(dummy_keypair(true));
-
- // add subnet to peer
- let (mask, len, dst) = ("192.168.1.0", 24, "192.168.1.20");
- let mask: IpAddr = mask.parse().unwrap();
- peer.add_allowed_ip(mask, len);
-
- // create "IP packet"
- let dst = dst.parse().unwrap();
- let src = match dst {
- IpAddr::V4(_) => "127.0.0.1".parse().unwrap(),
- IpAddr::V6(_) => "::1".parse().unwrap(),
- };
- let msg = pad(&make_packet(1024, src, dst, 0));
-
- // every iteration sends 10 GB
- b.iter(|| {
- opaque.store(0, Ordering::SeqCst);
- while opaque.load(Ordering::Acquire) < 10 * 1024 * 1024 {
- router.send(msg.to_vec()).unwrap();
- }
- });
-}
-
#[test]
fn test_outbound() {
init();
diff --git a/src/wireguard/router/types.rs b/src/wireguard/router/types.rs
index ae37a6b..e0cd459 100644
--- a/src/wireguard/router/types.rs
+++ b/src/wireguard/router/types.rs
@@ -1,9 +1,11 @@
-use std::error::Error;
-use std::fmt;
-use std::sync::Arc;
-
use super::KeyPair;
+use alloc::sync::Arc;
+use core::fmt;
+
+// TODO: no_std alternatives
+use std::error::Error;
+
pub trait Opaque: Send + Sync + 'static {}
impl<T> Opaque for T where T: Send + Sync + 'static {}
diff --git a/src/wireguard/router/worker.rs b/src/wireguard/router/worker.rs
index 459a198..4913a21 100644
--- a/src/wireguard/router/worker.rs
+++ b/src/wireguard/router/worker.rs
@@ -1,10 +1,10 @@
-use super::super::{tun, udp, Endpoint};
-use super::types::Callbacks;
-
use super::queue::ParallelJob;
use super::receive::ReceiveJob;
use super::send::SendJob;
+use super::super::{tun, udp, Endpoint};
+use super::types::Callbacks;
+
use crossbeam_channel::Receiver;
use log;
diff --git a/src/wireguard/tests.rs b/src/wireguard/tests.rs
index 4cc441e..bb1f87a 100644
--- a/src/wireguard/tests.rs
+++ b/src/wireguard/tests.rs
@@ -59,7 +59,14 @@ fn init() {
let _ = env_logger::builder().is_test(true).try_init();
}
-/* Create and configure two matching pure instances of WireGuard
+/* Create and configure
+ * two matching pure (no side-effects) instances of WireGuard.
+ *
+ * Test:
+ *
+ * - Handshaking completes successfully
+ * - All packets up to MTU are delivered
+ * - All packets are delivered in-order
*/
#[test]
fn test_pure_wireguard() {
@@ -137,7 +144,7 @@ fn test_pure_wireguard() {
for id in 0..num_packets {
packets.push(make_packet(
- 50 + 50 * id as usize, // size
+ 50 * id as usize, // size
"192.168.1.20".parse().unwrap(), // src
"192.168.2.10".parse().unwrap(), // dst
id as u64, // prng seed
@@ -153,7 +160,6 @@ fn test_pure_wireguard() {
while let Some(p) = backup.pop() {
println!("read");
-
assert_eq!(
hex::encode(fake2.read()),
hex::encode(p),
diff --git a/src/wireguard/types.rs b/src/wireguard/types.rs
index d4355a9..b899ed9 100644
--- a/src/wireguard/types.rs
+++ b/src/wireguard/types.rs
@@ -2,33 +2,6 @@ use clear_on_drop::clear::Clear;
use std::fmt;
use std::time::Instant;
-#[cfg(test)]
-pub fn dummy_keypair(initiator: bool) -> KeyPair {
- let k1 = Key {
- key: [0x53u8; 32],
- id: 0x646e6573,
- };
- let k2 = Key {
- key: [0x52u8; 32],
- id: 0x76636572,
- };
- if initiator {
- KeyPair {
- birth: Instant::now(),
- initiator: true,
- send: k1,
- recv: k2,
- }
- } else {
- KeyPair {
- birth: Instant::now(),
- initiator: false,
- send: k2,
- recv: k1,
- }
- }
-}
-
#[derive(Clone)]
pub struct Key {
pub key: [u8; 32],