mirror of https://github.com/dswd/vpncloud.git
Some routing code
This commit is contained in:
parent
93fc3f85d8
commit
8c414f9c23
|
@ -11,7 +11,7 @@ use epoll;
|
||||||
|
|
||||||
use super::{ethernet, udpmessage};
|
use super::{ethernet, udpmessage};
|
||||||
use super::udpmessage::{Options, Message};
|
use super::udpmessage::{Options, Message};
|
||||||
use super::ethernet::VlanId;
|
use super::ethernet::MacTable;
|
||||||
use super::tapdev::TapDevice;
|
use super::tapdev::TapDevice;
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,60 +104,6 @@ impl PeerList {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
struct MacTableKey {
|
|
||||||
mac: Mac,
|
|
||||||
vlan: VlanId
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MacTableValue {
|
|
||||||
address: SocketAddr,
|
|
||||||
timeout: SteadyTime
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MacTable {
|
|
||||||
table: HashMap<MacTableKey, MacTableValue>,
|
|
||||||
timeout: Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MacTable {
|
|
||||||
fn new(timeout: Duration) -> MacTable {
|
|
||||||
MacTable{table: HashMap::new(), timeout: timeout}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn timeout(&mut self) {
|
|
||||||
let now = SteadyTime::now();
|
|
||||||
let mut del: Vec<MacTableKey> = Vec::new();
|
|
||||||
for (&key, val) in &self.table {
|
|
||||||
if val.timeout < now {
|
|
||||||
del.push(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for key in del {
|
|
||||||
info!("Forgot mac: {:?} (vlan {})", key.mac, key.vlan);
|
|
||||||
self.table.remove(&key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn learn(&mut self, mac: &Mac, vlan: VlanId, addr: &SocketAddr) {
|
|
||||||
let key = MacTableKey{mac: *mac, vlan: vlan};
|
|
||||||
let value = MacTableValue{address: *addr, timeout: SteadyTime::now()+self.timeout};
|
|
||||||
if self.table.insert(key, value).is_none() {
|
|
||||||
info!("Learned mac: {:?} (vlan {}) => {}", mac, vlan, addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn lookup(&self, mac: &Mac, vlan: VlanId) -> Option<SocketAddr> {
|
|
||||||
let key = MacTableKey{mac: *mac, vlan: vlan};
|
|
||||||
match self.table.get(&key) {
|
|
||||||
Some(value) => Some(value.address),
|
|
||||||
None => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EthCloud {
|
pub struct EthCloud {
|
||||||
peers: PeerList,
|
peers: PeerList,
|
||||||
reconnect_peers: Vec<SocketAddr>,
|
reconnect_peers: Vec<SocketAddr>,
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
use std::{mem, ptr, fmt};
|
use std::{mem, ptr, fmt};
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::ethcloud::{Mac, Error};
|
use super::ethcloud::{Mac, Error};
|
||||||
use super::util::{as_bytes, as_obj};
|
use super::util::{as_bytes, as_obj};
|
||||||
|
|
||||||
|
use time::{Duration, SteadyTime};
|
||||||
|
|
||||||
|
|
||||||
pub type VlanId = u16;
|
pub type VlanId = u16;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -67,6 +72,61 @@ pub fn encode(frame: &Frame, buf: &mut [u8]) -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
struct MacTableKey {
|
||||||
|
mac: Mac,
|
||||||
|
vlan: VlanId
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MacTableValue {
|
||||||
|
address: SocketAddr,
|
||||||
|
timeout: SteadyTime
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MacTable {
|
||||||
|
table: HashMap<MacTableKey, MacTableValue>,
|
||||||
|
timeout: Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MacTable {
|
||||||
|
pub fn new(timeout: Duration) -> MacTable {
|
||||||
|
MacTable{table: HashMap::new(), timeout: timeout}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn timeout(&mut self) {
|
||||||
|
let now = SteadyTime::now();
|
||||||
|
let mut del: Vec<MacTableKey> = Vec::new();
|
||||||
|
for (&key, val) in &self.table {
|
||||||
|
if val.timeout < now {
|
||||||
|
del.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for key in del {
|
||||||
|
info!("Forgot mac: {:?} (vlan {})", key.mac, key.vlan);
|
||||||
|
self.table.remove(&key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn learn(&mut self, mac: &Mac, vlan: VlanId, addr: &SocketAddr) {
|
||||||
|
let key = MacTableKey{mac: *mac, vlan: vlan};
|
||||||
|
let value = MacTableValue{address: *addr, timeout: SteadyTime::now()+self.timeout};
|
||||||
|
if self.table.insert(key, value).is_none() {
|
||||||
|
info!("Learned mac: {:?} (vlan {}) => {}", mac, vlan, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn lookup(&self, mac: &Mac, vlan: VlanId) -> Option<SocketAddr> {
|
||||||
|
let key = MacTableKey{mac: *mac, vlan: vlan};
|
||||||
|
match self.table.get(&key) {
|
||||||
|
Some(value) => Some(value.address),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn without_vlan() {
|
fn without_vlan() {
|
||||||
let src = Mac([1,2,3,4,5,6]);
|
let src = Mac([1,2,3,4,5,6]);
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::collections::{hash_map, HashMap};
|
||||||
|
|
||||||
|
struct RoutingEntry {
|
||||||
|
address: SocketAddr,
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
prefix_len: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RoutingTable(HashMap<Vec<u8>, Vec<RoutingEntry>>);
|
||||||
|
|
||||||
|
impl RoutingTable {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
RoutingTable(HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, bytes: Vec<u8>, prefix_len: u8, address: SocketAddr) {
|
||||||
|
let group_len = (prefix_len as usize / 16) * 2;
|
||||||
|
let group_bytes: Vec<u8> = bytes[..group_len].iter().map(|b| *b).collect();
|
||||||
|
let routing_entry = RoutingEntry{address: address, bytes: bytes, prefix_len: prefix_len};
|
||||||
|
match self.0.entry(group_bytes) {
|
||||||
|
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry),
|
||||||
|
hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup(&self, bytes: Vec<u8>) -> Option<SocketAddr> {
|
||||||
|
let mut len = bytes.len()/2 * 2;
|
||||||
|
for i in 0..len/2 {
|
||||||
|
if let Some(group) = self.0.get(&bytes[0..len-2*i]) {
|
||||||
|
for entry in group {
|
||||||
|
if entry.bytes.len() != bytes.len() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut match_len = 0;
|
||||||
|
for i in 0..bytes.len() {
|
||||||
|
let b = bytes[i] ^ entry.bytes[i];
|
||||||
|
if b == 0 {
|
||||||
|
match_len += 8;
|
||||||
|
} else {
|
||||||
|
match_len += b.leading_zeros();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if match_len as u8 >= entry.prefix_len {
|
||||||
|
return Some(entry.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ mod util;
|
||||||
mod udpmessage;
|
mod udpmessage;
|
||||||
mod tapdev;
|
mod tapdev;
|
||||||
mod ethernet;
|
mod ethernet;
|
||||||
|
mod ip;
|
||||||
mod ethcloud;
|
mod ethcloud;
|
||||||
|
|
||||||
use time::Duration;
|
use time::Duration;
|
||||||
|
|
Loading…
Reference in New Issue