mirror of https://github.com/dswd/vpncloud.git
More improvements
This commit is contained in:
parent
946e384660
commit
ecb57b24de
|
@ -12,6 +12,7 @@ log = "0.3"
|
|||
epoll = "0.2"
|
||||
signal = "0.1"
|
||||
nix = "*"
|
||||
libc = "*"
|
||||
libsodium-sys = {version = "0.0.9", optional = true}
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -41,10 +41,10 @@ $> iperf -c 10.2.1.2 -t 60
|
|||
|
||||
**Results:**
|
||||
* Throughput without VpnCloud: 938 Mbits/sec
|
||||
* Throughput via VpnCloud (MTU=1400): 363 Mbits/sec
|
||||
* Throughput via VpnCloud (MTU=1400): 461 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
|
||||
* Throughput via VpnCloud (MTU=16384): 949 Mbits/sec (no idea why this is higher)
|
||||
* CPU usage for VpnCloud (MTU=16384): ~68% of one core
|
||||
|
||||
|
||||
### Test 2: Unencrypted ping
|
||||
|
@ -86,6 +86,6 @@ SIZE: 1400 bytes
|
|||
|
||||
### Conclusion
|
||||
|
||||
* VpnCloud achieves about 360 MBit/s with default MTU settings.
|
||||
* VpnCloud achieves about 460 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.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use test::Bencher;
|
||||
|
||||
use time::{SteadyTime, Duration};
|
||||
use time::Duration;
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
@ -61,7 +61,8 @@ fn switch_lookup(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn ethernet_parse(b: &mut Bencher) {
|
||||
let data = [0; 1500];
|
||||
let mut data = [0; 1500];
|
||||
data[5] = 45;
|
||||
b.iter(|| {
|
||||
Frame::parse(&data).unwrap()
|
||||
})
|
||||
|
|
38
src/cloud.rs
38
src/cloud.rs
|
@ -7,19 +7,20 @@ use std::fmt;
|
|||
use std::os::unix::io::AsRawFd;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use time::{Duration, SteadyTime, precise_time_ns};
|
||||
use epoll;
|
||||
use nix::sys::signal::{SIGTERM, SIGQUIT, SIGINT};
|
||||
use signal::trap::Trap;
|
||||
use time::SteadyTime;
|
||||
|
||||
use super::types::{Table, Protocol, Range, Error, NetworkId};
|
||||
use super::device::Device;
|
||||
use super::udpmessage::{encode, decode, Options, Message};
|
||||
use super::crypto::Crypto;
|
||||
use super::util::{now, Time, Duration, time_rand};
|
||||
|
||||
struct PeerList {
|
||||
timeout: Duration,
|
||||
peers: HashMap<SocketAddr, SteadyTime>
|
||||
peers: HashMap<SocketAddr, Time>
|
||||
}
|
||||
|
||||
impl PeerList {
|
||||
|
@ -28,7 +29,7 @@ impl PeerList {
|
|||
}
|
||||
|
||||
fn timeout(&mut self) -> Vec<SocketAddr> {
|
||||
let now = SteadyTime::now();
|
||||
let now = now();
|
||||
let mut del: Vec<SocketAddr> = Vec::new();
|
||||
for (&addr, &timeout) in &self.peers {
|
||||
if timeout < now {
|
||||
|
@ -49,7 +50,7 @@ impl PeerList {
|
|||
|
||||
#[inline]
|
||||
fn add(&mut self, addr: &SocketAddr) {
|
||||
if self.peers.insert(*addr, SteadyTime::now()+self.timeout).is_none() {
|
||||
if self.peers.insert(*addr, now()+self.timeout as Time).is_none() {
|
||||
info!("New peer: {:?}", addr);
|
||||
}
|
||||
}
|
||||
|
@ -96,10 +97,10 @@ pub struct GenericCloud<P: Protocol> {
|
|||
device: Device,
|
||||
options: Options,
|
||||
crypto: Crypto,
|
||||
next_peerlist: SteadyTime,
|
||||
next_peerlist: Time,
|
||||
update_freq: Duration,
|
||||
buffer_out: [u8; 64*1024],
|
||||
next_housekeep: SteadyTime,
|
||||
next_housekeep: Time,
|
||||
_dummy_p: PhantomData<P>,
|
||||
}
|
||||
|
||||
|
@ -124,10 +125,10 @@ impl<P: Protocol> GenericCloud<P> {
|
|||
device: device,
|
||||
options: options,
|
||||
crypto: crypto,
|
||||
next_peerlist: SteadyTime::now(),
|
||||
next_peerlist: now(),
|
||||
update_freq: peer_timeout/2,
|
||||
buffer_out: [0; 64*1024],
|
||||
next_housekeep: SteadyTime::now(),
|
||||
next_housekeep: now(),
|
||||
_dummy_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +170,7 @@ impl<P: Protocol> GenericCloud<P> {
|
|||
fn housekeep(&mut self) -> Result<(), Error> {
|
||||
self.peers.timeout();
|
||||
self.table.housekeep();
|
||||
if self.next_peerlist <= SteadyTime::now() {
|
||||
if self.next_peerlist <= now() {
|
||||
debug!("Send peer list to all peers");
|
||||
let mut peer_num = self.peers.len();
|
||||
if peer_num > 10 {
|
||||
|
@ -178,12 +179,12 @@ impl<P: Protocol> GenericCloud<P> {
|
|||
peer_num = 10;
|
||||
}
|
||||
}
|
||||
let peers = self.peers.subset(peer_num, precise_time_ns() as u32);
|
||||
let peers = self.peers.subset(peer_num, time_rand() as u32);
|
||||
let msg = Message::Peers(peers);
|
||||
for addr in &self.peers.as_vec() {
|
||||
try!(self.send_msg(addr, &msg));
|
||||
}
|
||||
self.next_peerlist = SteadyTime::now() + self.update_freq;
|
||||
self.next_peerlist = now() + self.update_freq as Time;
|
||||
}
|
||||
for addr in self.reconnect_peers.clone() {
|
||||
try!(self.connect(addr, false));
|
||||
|
@ -272,6 +273,7 @@ impl<P: Protocol> GenericCloud<P> {
|
|||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
let dummy_time = SteadyTime::now();
|
||||
let trap = Trap::trap(&[SIGINT, SIGTERM, SIGQUIT]);
|
||||
let epoll_handle = try_fail!(epoll::create1(0), "Failed to create epoll handle: {}");
|
||||
let socket_fd = self.socket.as_raw_fd();
|
||||
|
@ -284,10 +286,6 @@ impl<P: Protocol> GenericCloud<P> {
|
|||
let mut buffer = [0; 64*1024];
|
||||
loop {
|
||||
let count = try_fail!(epoll::wait(epoll_handle, &mut events, 1000), "Epoll wait failed: {}");
|
||||
// Check for signals
|
||||
if trap.wait(SteadyTime::now()).is_some() {
|
||||
break;
|
||||
}
|
||||
// Process events
|
||||
for i in 0..count {
|
||||
match &events[i as usize].data {
|
||||
|
@ -308,13 +306,17 @@ impl<P: Protocol> GenericCloud<P> {
|
|||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
// Do the housekeeping
|
||||
if self.next_housekeep < SteadyTime::now() {
|
||||
if self.next_housekeep < now() {
|
||||
// Check for signals
|
||||
if trap.wait(dummy_time).is_some() {
|
||||
break;
|
||||
}
|
||||
// Do the housekeeping
|
||||
match self.housekeep() {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!("Error: {:?}", e)
|
||||
}
|
||||
self.next_housekeep = SteadyTime::now() + Duration::seconds(1)
|
||||
self.next_housekeep = now() + 1
|
||||
}
|
||||
}
|
||||
info!("Shutting down...");
|
||||
|
|
|
@ -3,9 +3,7 @@ use std::net::SocketAddr;
|
|||
use std::collections::HashMap;
|
||||
|
||||
use super::types::{Error, Table, Protocol, Address};
|
||||
|
||||
use time::{Duration, SteadyTime};
|
||||
|
||||
use super::util::{now, Time, Duration};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct Frame;
|
||||
|
@ -49,7 +47,7 @@ impl Protocol for Frame {
|
|||
|
||||
struct SwitchTableValue {
|
||||
address: SocketAddr,
|
||||
timeout: SteadyTime
|
||||
timeout: Time
|
||||
}
|
||||
|
||||
pub struct SwitchTable {
|
||||
|
@ -66,7 +64,7 @@ impl SwitchTable {
|
|||
|
||||
impl Table for SwitchTable {
|
||||
fn housekeep(&mut self) {
|
||||
let now = SteadyTime::now();
|
||||
let now = now();
|
||||
let mut del: Vec<Address> = Vec::new();
|
||||
for (key, val) in &self.table {
|
||||
if val.timeout < now {
|
||||
|
@ -82,7 +80,7 @@ impl Table for SwitchTable {
|
|||
|
||||
#[inline]
|
||||
fn learn(&mut self, key: Address, _prefix_len: Option<u8>, addr: SocketAddr) {
|
||||
let value = SwitchTableValue{address: addr, timeout: SteadyTime::now()+self.timeout};
|
||||
let value = SwitchTableValue{address: addr, timeout: now()+self.timeout as Time};
|
||||
if self.table.insert(key.clone(), value).is_none() {
|
||||
info!("Learned address {:?} => {}", key, addr);
|
||||
}
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -6,6 +6,7 @@ extern crate rustc_serialize;
|
|||
extern crate epoll;
|
||||
extern crate signal;
|
||||
extern crate nix;
|
||||
extern crate libc;
|
||||
#[cfg(feature = "crypto")] extern crate libsodium_sys;
|
||||
#[cfg(feature = "bench")] extern crate test;
|
||||
|
||||
|
@ -19,7 +20,6 @@ mod cloud;
|
|||
mod device;
|
||||
#[cfg(feature = "bench")] mod benches;
|
||||
|
||||
use time::Duration;
|
||||
use docopt::Docopt;
|
||||
|
||||
use std::hash::{Hash, SipHasher, Hasher};
|
||||
|
@ -33,6 +33,7 @@ use types::{Error, Mode, Type, Range, Table, Protocol};
|
|||
use cloud::GenericCloud;
|
||||
use udpmessage::VERSION;
|
||||
use crypto::Crypto;
|
||||
use util::Duration;
|
||||
|
||||
|
||||
struct SimpleLogger;
|
||||
|
@ -63,8 +64,8 @@ struct Args {
|
|||
flag_listen: String,
|
||||
flag_network_id: Option<String>,
|
||||
flag_connect: Vec<String>,
|
||||
flag_peer_timeout: usize,
|
||||
flag_dst_timeout: usize,
|
||||
flag_peer_timeout: Duration,
|
||||
flag_dst_timeout: Duration,
|
||||
flag_verbose: bool,
|
||||
flag_quiet: bool,
|
||||
flag_ifup: Option<String>,
|
||||
|
@ -93,8 +94,8 @@ fn run<T: Protocol> (args: Args) {
|
|||
for s in args.flag_subnet {
|
||||
ranges.push(try_fail!(Range::from_str(&s), "Invalid subnet format: {} ({})", s));
|
||||
}
|
||||
let dst_timeout = Duration::seconds(args.flag_dst_timeout as i64);
|
||||
let peer_timeout = Duration::seconds(args.flag_peer_timeout as i64);
|
||||
let dst_timeout = args.flag_dst_timeout;
|
||||
let peer_timeout = args.flag_peer_timeout;
|
||||
let (learning, broadcasting, table): (bool, bool, Box<Table>) = match args.flag_mode {
|
||||
Mode::Normal => match args.flag_type {
|
||||
Type::Tap => (true, true, Box::new(SwitchTable::new(dst_timeout))),
|
||||
|
|
19
src/util.rs
19
src/util.rs
|
@ -1,4 +1,23 @@
|
|||
use std::{mem, slice};
|
||||
use libc;
|
||||
|
||||
pub type Duration = u32;
|
||||
pub type Time = i64;
|
||||
|
||||
#[inline]
|
||||
pub fn now() -> Time {
|
||||
let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
|
||||
unsafe { libc::clock_gettime(6, &mut tv); }
|
||||
tv.tv_sec
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn time_rand() -> i64 {
|
||||
let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
|
||||
unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut tv); }
|
||||
tv.tv_sec ^ tv.tv_nsec
|
||||
}
|
||||
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn as_bytes<T>(obj: &T) -> &[u8] {
|
||||
|
|
Loading…
Reference in New Issue