Commit fc1179b2 authored by Milan Pässler's avatar Milan Pässler 🐈

first working version of ethernet switch

parent 009fe9ee
This diff is collapsed.
......@@ -10,3 +10,4 @@ libqaul = { git = "https://git.open-communication.net/qaul/qaul.net" }
ratman = { git = "https://git.open-communication.net/qaul/qaul.net" }
netmod-mem = { git = "https://git.open-communication.net/qaul/qaul.net" }
libc = "0.2"
crossbeam-channel = "*"
......@@ -12,6 +12,7 @@ then
sudo pkill qaul-switch
sudo ip netns del 23
sudo ip netns del 42
sudo ip netns del 43
else
target/debug/qaul-switch 2> /dev/null &
sleep 1
......@@ -24,4 +25,9 @@ else
ip l set dev foo2 netns 42
ip -n 42 l set dev foo2 up
ip -n 42 a add 10.0.0.1/24 dev foo2
ip netns add 43
ip l set dev foo3 netns 43
ip -n 43 l set dev foo3 up
ip -n 43 a add 10.0.0.3/24 dev foo3
fi
......@@ -2,13 +2,18 @@
mod tap_linux;
use libqaul::{messages::Recipient, users::UserAuth, Qaul};
use std::convert::TryInto;
use libqaul::messages::Recipient;
use libqaul::users::UserAuth;
use libqaul::{Identity, Qaul};
use ratman::Router;
use netmod_mem::MemMod;
use std::sync::Arc;
use std::convert::TryFrom;
use tap_linux::TapSocket;
use std::time::Duration;
use std::collections::HashMap;
use crossbeam_channel::{unbounded, Sender, Receiver};
const MAX_UDP_SIZE: usize = (1 << 16) - 1;
const ASC_NAME: &'static str = "qaul-switch";
......@@ -29,10 +34,31 @@ pub enum Error {
ApiSocket(std::io::Error),
}
#[derive(Hash, PartialEq, Eq, Debug)]
struct MacAddress ([u8; 6]);
#[repr(u16)]
enum EtherType {
ARP = 0x0806,
IPv6 = 0x86dd,
IPv4 = 0x0800,
}
struct EthernetHeader {
dst: MacAddress,
src: MacAddress,
ether_type: EtherType,
}
struct TestNetwork {
q1: Arc<Qaul>,
q2: Arc<Qaul>,
q3: Arc<Qaul>,
q_a: Arc<Qaul>,
q_b: Arc<Qaul>,
q_c: Arc<Qaul>,
q_d: Arc<Qaul>,
u_a: UserAuth,
u_b: UserAuth,
u_c: UserAuth,
u_d: UserAuth,
}
/// This function creates a little test network with three nodes.
......@@ -42,34 +68,80 @@ struct TestNetwork {
/// C, a message must traverse node B.
///
/// ```
/// A - B - C
/// A
/// \
/// B——C
/// /
/// D
/// ```
fn init_network() -> TestNetwork {
let mut mm1 = MemMod::new();
let mut mm2 = MemMod::new();
let mut mm3 = MemMod::new();
let mut mm4 = MemMod::new();
let mut mm5 = MemMod::new();
let mut mm6 = MemMod::new();
mm1.link(&mut mm2);
mm3.link(&mut mm4);
mm5.link(&mut mm6);
let r_a = Router::new();
let r_b = Router::new();
let r_c = Router::new();
let r_d = Router::new();
r_a.modify().add_ep(mm1);
r_b.modify().add_ep(mm2);
r_b.modify().add_ep(mm3);
r_c.modify().add_ep(mm4);
r_b.modify().add_ep(mm5);
r_d.modify().add_ep(mm6);
let q_a = Qaul::new(r_a);
let q_b = Qaul::new(r_b);
let q_c = Qaul::new(r_c);
let q_d = Qaul::new(r_d);
let u_a = q_a.users().create("a").unwrap();
let u_b = q_b.users().create("b").unwrap();
let u_c = q_c.users().create("c").unwrap();
let u_d = q_d.users().create("d").unwrap();
let r1 = Router::new();
let r2 = Router::new();
let r3 = Router::new();
r1.modify().add_ep(mm1);
r2.modify().add_ep(mm2);
r2.modify().add_ep(mm3);
r3.modify().add_ep(mm4);
// Manually make Routers discover each other
#[allow(deprecated)]
{
q_a.router().discover(u_b.0, 0);
q_a.router().discover(u_c.0, 0);
q_a.router().discover(u_d.0, 0);
q_b.router().discover(u_a.0, 0);
q_b.router().discover(u_c.0, 1);
q_b.router().discover(u_d.0, 2);
q_c.router().discover(u_a.0, 0);
q_c.router().discover(u_b.0, 0);
q_c.router().discover(u_d.0, 0);
q_d.router().discover(u_a.0, 0);
q_d.router().discover(u_b.0, 0);
q_d.router().discover(u_c.0, 0);
}
TestNetwork {
q1: Qaul::new(r1),
q2: Qaul::new(r2),
q3: Qaul::new(r3),
q_a: q_a,
q_b: q_b,
q_c: q_c,
q_d: q_d,
u_a: u_a,
u_b: u_b,
u_c: u_c,
u_d: u_d,
}
}
fn init_node(iface_name: &str, q: Arc<Qaul>, u1: UserAuth, u2: UserAuth) {
fn init_node(iface_name: &str, q: Arc<Qaul>, u: UserAuth, all_users: Vec<Identity>) {
let all_users = all_users.clone().into_iter().filter(|i| i != &u.0).collect::<Vec<Identity>>();
let flood = Recipient::Group(all_users.clone());
let (new_mac_send, new_mac_recv) = unbounded();
let iface = TapSocket::new(iface_name).unwrap().set_non_blocking().unwrap();
let mut src_buf = [0u8; MAX_UDP_SIZE];
......@@ -77,24 +149,42 @@ fn init_node(iface_name: &str, q: Arc<Qaul>, u1: UserAuth, u2: UserAuth) {
{
let iface = iface.clone();
// Then we setup a messaging endponti on note u1
let new_mac_send2 = new_mac_send.clone();
q.services().register(ASC_NAME).unwrap();
q.messages().listen(u1.clone(), ASC_NAME, move |msg| {
q.messages().listen(u.clone(), ASC_NAME, move |msg| {
println!("{:?}", msg);
let src_mac: &[u8; 6] = &msg.payload[6..12].try_into().unwrap();
new_mac_send2.send((MacAddress(*src_mac), msg.sender)).unwrap();
iface.write(&msg.payload);
Ok(())
}).unwrap();
}
std::thread::spawn(move || {
let mut mac_to_identity: HashMap<MacAddress, Identity> = HashMap::new();
loop {
while let Ok(src) = iface.read(&mut src_buf[..mtu]) {
// and send a message to u2
let target: Recipient;
let dst_mac: &[u8; 6] = &src[0..6].try_into().unwrap();
if *dst_mac == [255u8; 6] || dst_mac[0] % 2 == 1 {
target = flood.clone();
} else {
target = match mac_to_identity.get(&MacAddress(*dst_mac)) {
Some(i) => Recipient::User(*i),
None => flood.clone(),
};
}
//println!("{:?}", target);
q
.messages()
.send(u1.clone(), Recipient::User(u2.0), ASC_NAME, src.to_vec())
.send(u.clone(), target, ASC_NAME, src.to_vec())
.unwrap();
}
while let Ok((mac, id)) = new_mac_recv.try_recv() {
mac_to_identity.insert(mac, id);
}
}
});
}
......@@ -102,21 +192,12 @@ fn init_node(iface_name: &str, q: Arc<Qaul>, u1: UserAuth, u2: UserAuth) {
fn main() {
let _network = init_network();
// Generate two user profiles on node 1 and 3
let u1 = _network.q1.users().create("abc").unwrap();
let u2 = _network.q3.users().create("abc").unwrap();
// Manually make Routers discover each other
#[allow(deprecated)]
{
_network.q1.router().discover(u2.0, 0);
_network.q2.router().discover(u1.0, 0);
_network.q2.router().discover(u2.0, 1);
_network.q3.router().discover(u1.0, 0);
}
init_node("foo1", _network.q1, u1.clone(), u2.clone());
init_node("foo2", _network.q3, u2.clone(), u1.clone());
let all_users = vec![ _network.u_a.0, _network.u_b.0, _network.u_c.0, _network.u_d.0 ];
println!("{:?}", all_users);
init_node("foo1", _network.q_a, _network.u_a, all_users.clone());
init_node("foo2", _network.q_b, _network.u_b, all_users.clone());
init_node("foo3", _network.q_c, _network.u_c, all_users.clone());
init_node("foo4", _network.q_d, _network.u_d, all_users.clone());
loop {
std::thread::sleep(Duration::from_millis(1000));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment