diff --git a/Measurements_Glab.ods b/Measurements_Glab.ods deleted file mode 100644 index eb98e12..0000000 Binary files a/Measurements_Glab.ods and /dev/null differ diff --git a/README.md b/README.md index 0c3d32e..f7e6ff7 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ vpncloud -c REMOTE_HOST:PORT --ifup 'ifconfig $IFNAME 10.0.0.1/24 mtu 1400 up' ``` More details can be found in [the manpage](vpncloud.md). +Some performance measurements can be found [here](performance.md). ### Current Status @@ -31,6 +32,7 @@ However there are some open issues: * The protocol can still change. * The software is not very well tested. * The coverage score includes all unused methods from *libsodium* +* The software has not been optimized for speed. Please feel free to help and contribute code. diff --git a/performance.md b/performance.md new file mode 100644 index 0000000..f13e4b7 --- /dev/null +++ b/performance.md @@ -0,0 +1,91 @@ +Performance Tests +----------------- + +### Test setup + +Two nodes with: + * 2x Intel(R) Xeon(R) CPU L5420 + * 16 GiB Ram + * Intel Corporation 80003ES2LAN Gigabit Ethernet Controller (Kernel driver e1000e) + * Debian Linux 7.0 (Kernel 2.6.32-26-pve) + * Connected by Cisco Catalyst 4506 switch + +VpnCloud version: `VpnCloud v0.1.0 (without crypto support, protocol version 1)` + + +### Test 1: Unencrypted throughput + +Node 1: +``` +$> ./vpncloud -t tap -l NODE1:3210 -c NODE2:3210 \ + --ifup 'ifconfig $IFNAME 10.2.1.1/24 mtu MTU up' & +``` + +Node 2: +``` +$> ./vpncloud -t tap -l NODE2:3210 -c NODE1:3210 \ + --ifup 'ifconfig $IFNAME 10.2.1.2/24 mtu MTU up' & +$> iperf -s & +$> top +``` + +First, the test is run **without VpnCloud**: +``` +$> iperf -c NODE2 -t 60 +``` + +and then **via VpnCloud**: +``` +$> iperf -c 10.2.1.2 -t 60 +``` + +**Results:** + * Throughput without VpnCloud: 938 Mbits/sec + * Throughput via VpnCloud (MTU=1400): 363 Mbits/sec + * CPU usage for VpnCloud (MTU=1400): maxed out at ~105% of one core + * Throughput via VpnCloud (MTU=16384): 946 Mbits/sec (no idea why this is higher) + * CPU usage for VpnCloud (MTU=16384): ~73% of one core + + +### Test 2: Unencrypted ping + +Node 1: +``` +$> ./vpncloud -t tap -l NODE1:3210 -c NODE2:3210 \ + --ifup 'ifconfig $IFNAME 10.2.1.1/24 mtu 1400 up' & +``` + +Node 2: +``` +$> ./vpncloud -t tap -l NODE2:3210 -c NODE1:3210 \ + --ifup 'ifconfig $IFNAME 10.2.1.2/24 mtu 1400 up' & +``` + +Each test is first run without VpnCloud: +``` +$> ping NODE2 -c 1000 -i 0.01 -s SIZE -U -q +``` + +and then with VpnCloud: +``` +$> ping 10.2.1.2 -c 1000 -i 0.01 -s SIZE -U -q +``` + +SIZE: 50 bytes + * Without VpnCloud: Ø= 200 µs, stddev= 28 µs + * With VpnCloud: Ø= 318 µs, stddev= 26 µs + +SIZE: 500 bytes + * Without VpnCloud: Ø= 235 µs, stddev= 29 µs + * With VpnCloud: Ø= 351 µs, stddev= 26 µs + +SIZE: 1400 bytes + * Without VpnCloud: Ø= 303 µs, stddev= 32 µs + * With VpnCloud: Ø= 421 µs, stddev= 31 µs + + +### Conclusion + +* VpnCloud achieves about 360 MBit/s with default MTU settings. +* At increased MTU, VpnCloud is able to saturate a Gigabit link. +* VpnCloud adds about 120µs to the round trip times, i.e. 60µs latency increase. diff --git a/src/ethernet.rs b/src/ethernet.rs index 22b5472..73aeb65 100644 --- a/src/ethernet.rs +++ b/src/ethernet.rs @@ -58,12 +58,13 @@ struct SwitchTableValue { pub struct SwitchTable { table: HashMap, + cache: Option<(Address, SocketAddr)>, timeout: Duration } impl SwitchTable { pub fn new(timeout: Duration) -> Self { - SwitchTable{table: HashMap::new(), timeout: timeout} + SwitchTable{table: HashMap::new(), cache: None, timeout: timeout} } } @@ -80,20 +81,21 @@ impl Table for SwitchTable { info!("Forgot address {:?}", key); self.table.remove(&key); } + self.cache = None; } fn learn(&mut self, key: Address, _prefix_len: Option, addr: SocketAddr) { - let value = SwitchTableValue{address: addr, timeout: SteadyTime::now()+self.timeout}; - if self.table.insert(key.clone(), value).is_none() { - info!("Learned address {:?} => {}", key, addr); - } + let value = SwitchTableValue{address: addr, timeout: SteadyTime::now()+self.timeout}; + if self.table.insert(key.clone(), value).is_none() { + info!("Learned address {:?} => {}", key, addr); + } } - fn lookup(&self, key: &Address) -> Option { - match self.table.get(key) { - Some(value) => Some(value.address), - None => None - } + fn lookup(&mut self, key: &Address) -> Option { + match self.table.get(key) { + Some(value) => Some(value.address), + None => None + } } fn remove_all(&mut self, _addr: SocketAddr) { diff --git a/src/ip.rs b/src/ip.rs index 8891532..af0a66c 100644 --- a/src/ip.rs +++ b/src/ip.rs @@ -63,7 +63,7 @@ impl Table for RoutingTable { } } - fn lookup(&self, addr: &Address) -> Option { + fn lookup(&mut self, addr: &Address) -> Option { let len = addr.0.len()/2 * 2; for i in 0..(len/2)+1 { if let Some(group) = self.0.get(&addr.0[0..len-2*i]) { diff --git a/src/types.rs b/src/types.rs index 92014cb..f70fd33 100644 --- a/src/types.rs +++ b/src/types.rs @@ -122,7 +122,7 @@ impl fmt::Display for Mode { pub trait Table { fn learn(&mut self, Address, Option, SocketAddr); - fn lookup(&self, &Address) -> Option; + fn lookup(&mut self, &Address) -> Option; fn housekeep(&mut self); fn remove_all(&mut self, SocketAddr); }