Restructuring and dependency version bump.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#![feature(test)]
|
||||
#![feature(weak_into_raw)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "profiler")]
|
||||
extern crate cpuprofiler;
|
||||
|
||||
|
||||
@@ -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,
|
||||
12
src/platform/dummy/tun/mod.rs
Normal file
12
src/platform/dummy/tun/mod.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use super::super::tun::*;
|
||||
|
||||
mod dummy;
|
||||
mod void;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TunError {
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
pub use dummy::*;
|
||||
pub use void::*;
|
||||
43
src/platform/dummy/tun/void.rs
Normal file
43
src/platform/dummy/tun/void.rs
Normal file
@@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -26,9 +26,6 @@ pub use peer::Peer;
|
||||
// represents a WireGuard interface
|
||||
pub use wireguard::WireGuard;
|
||||
|
||||
#[cfg(test)]
|
||||
pub use types::dummy_keypair;
|
||||
|
||||
#[cfg(test)]
|
||||
use super::platform::dummy;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::mem;
|
||||
use core::mem;
|
||||
|
||||
// Implementation of RFC 6479.
|
||||
// https://tools.ietf.org/html/rfc6479
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::mem;
|
||||
use core::mem;
|
||||
|
||||
use byteorder::BigEndian;
|
||||
use zerocopy::byteorder::U16;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::ip::*;
|
||||
|
||||
// TODO: no_std alternatives
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
|
||||
use spin::RwLock;
|
||||
|
||||
@@ -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;
|
||||
|
||||
424
src/wireguard/router/tests/bench.rs
Normal file
424
src/wireguard/router/tests/bench.rs
Normal file
@@ -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();
|
||||
}
|
||||
*/
|
||||
48
src/wireguard/router/tests/mod.rs
Normal file
48
src/wireguard/router/tests/mod.rs
Normal file
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user