mirror of
https://github.com/threefoldtech/mycelium.git
synced 2026-06-06 07:41:41 +00:00
propagting routes
This commit is contained in:
-44
@@ -52,50 +52,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
// Creating a new PeerManager instance
|
||||
let _peer_manager: peer_manager::PeerManager = peer_manager::PeerManager::new(router.clone(), static_peers);
|
||||
|
||||
|
||||
// create routing entry for this node
|
||||
// for the moment we say that each node has a /24 subnet that it can route
|
||||
// only IPv4 is supported for now
|
||||
// {
|
||||
// // omit the last octet of the node_tun address to get the prefix
|
||||
// let tun_octects = node_tun.address().unwrap().octets();
|
||||
// let node_prefix = Ipv4Addr::new(tun_octects[0], tun_octects[1], tun_octects[2], 0);
|
||||
|
||||
// // create a source key for the node
|
||||
// let source_key = SourceKey {
|
||||
// prefix: IpAddr::V4(node_prefix),
|
||||
// plen: 24,
|
||||
// router_id: router.router_id,
|
||||
// };
|
||||
// // default metric value for own source is 0
|
||||
// let feas_dist = FeasibilityDistance(0, 0);
|
||||
// // insert source into source table of router
|
||||
// router.source_table.lock().unwrap().insert(source_key, feas_dist);
|
||||
|
||||
// // create a routing entry for the node
|
||||
// let route_key = RouteKey {
|
||||
// prefix: IpAddr::V4(node_prefix),
|
||||
// plen: 24,
|
||||
// neighbor: IpAddr::V4(node_tun.address().unwrap()),
|
||||
// };
|
||||
|
||||
// // bit skuft: we create a dummy peer for this node itself as this is required for the route entry
|
||||
// let dummy_peer = Peer::new_dummy(node_tun.address().unwrap());
|
||||
|
||||
// // creates a route entry for the node and also creates an update timer for the route
|
||||
// let route_entry = RouteEntry::new(
|
||||
// source_key.clone(),
|
||||
// dummy_peer,
|
||||
// 0, // metric value for own route is 0
|
||||
// router.router_seqno,
|
||||
// IpAddr::V4(node_tun.address().unwrap()),
|
||||
// true,
|
||||
// );
|
||||
|
||||
// router.routing_table.lock().unwrap().insert(route_key, route_entry);
|
||||
|
||||
// }
|
||||
|
||||
// Read packets from the TUN interface (originating from the kernel) and send them to the router
|
||||
// Note: we will never receive control packets from the kernel, only data packets
|
||||
{
|
||||
|
||||
+62
-8
@@ -4,8 +4,8 @@ use crate::{
|
||||
DataPacket,
|
||||
},
|
||||
peer::Peer,
|
||||
routing_table::{RouteEntry, RouteKey, RoutingTable},
|
||||
source_table::{SourceKey, SourceTable, FeasibilityDistance}, timers::{Timer, self},
|
||||
routing_table::{RouteEntry, RouteKey, RoutingTable, self},
|
||||
source_table::{SourceKey, SourceTable, FeasibilityDistance, self}, timers::{Timer, self},
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@@ -59,6 +59,10 @@ impl Router {
|
||||
// loops over all peers and adds routing table entries for each peer
|
||||
tokio::spawn(Router::initialize_peer_route_entries(router.clone()));
|
||||
|
||||
|
||||
// propagate routes
|
||||
tokio::spawn(Router::propagate_routes(router.clone()));
|
||||
|
||||
router
|
||||
}
|
||||
|
||||
@@ -70,8 +74,12 @@ impl Router {
|
||||
BabelTLVType::Ack => todo!(),
|
||||
BabelTLVType::Hello => Self::handle_incoming_hello(control_struct),
|
||||
BabelTLVType::IHU => Self::handle_incoming_ihu(&self, control_struct),
|
||||
BabelTLVType::NextHop => todo!(),
|
||||
BabelTLVType::Update => todo!(),
|
||||
BabelTLVType::NextHop => todo!(),
|
||||
BabelTLVType::Update => {
|
||||
let mut source_table = self.source_table.lock().unwrap();
|
||||
let mut routing_table = self.routing_table.lock().unwrap();
|
||||
Self::handle_incoming_update(self.clone(), &mut source_table, &mut routing_table, control_struct);
|
||||
},
|
||||
BabelTLVType::RouteReq => todo!(),
|
||||
BabelTLVType::SeqnoReq => todo!(),
|
||||
}
|
||||
@@ -145,6 +153,32 @@ impl Router {
|
||||
println!("IHU timer for peer {:?} reset", source_peer.overlay_ip);
|
||||
}
|
||||
|
||||
fn handle_incoming_update(router: Router, source_table: &mut SourceTable, routing_table: &mut RoutingTable, update: ControlStruct) {
|
||||
if source_table.is_feasible(&update) {
|
||||
source_table.update(&update);
|
||||
|
||||
// get routing table entry for the source of the update
|
||||
match update.control_packet.body.tlv {
|
||||
BabelTLV::Update { plen, interval, seqno, metric, prefix, router_id } => {
|
||||
|
||||
|
||||
let source_ip = update.src_overlay_ip;
|
||||
let source_peer = router.get_peer_by_ip(source_ip).unwrap();
|
||||
|
||||
// get RouteEntry for the source of the update
|
||||
if let Some(route_entry) = routing_table.table.get_mut(&RouteKey { prefix, plen, neighbor: source_ip }) {
|
||||
route_entry.update(update);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
} else {
|
||||
// received update is not feasible
|
||||
// unselect to route if it was selected
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_directly_connected_peer(&self, peer: Peer) {
|
||||
self.peer_interfaces.lock().unwrap().push(peer);
|
||||
}
|
||||
@@ -185,6 +219,8 @@ impl Router {
|
||||
// this is done by looking at the currently set link cost. as the cost gets initialized to 65535, we can use this to check if
|
||||
// the link cost has been set to a lower value, indicating that the peer is reachable and a routing table entry exits already
|
||||
pub async fn initialize_peer_route_entries(self) {
|
||||
// we wait for 10 seconds before we start initializing the routing table entries
|
||||
// possible optimization: only run this when necassary (e.g. when a new peer is added)
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
|
||||
for peer in self.peer_interfaces.lock().unwrap().iter_mut() {
|
||||
@@ -218,7 +254,6 @@ impl Router {
|
||||
seqno: 0, // we set the seqno to 0 for now
|
||||
next_hop: IpAddr::V4(peer.overlay_ip),
|
||||
selected: true, // set selected always to true for now as we have manually decided the topology to only have p2p links
|
||||
route_expiry_timer: Timer::new_route_expiry_timer(UPDATE_INTERVAL as u64),
|
||||
};
|
||||
// create the routing table entry
|
||||
self.routing_table.lock().unwrap().insert(route_key, route_entry);
|
||||
@@ -231,11 +266,30 @@ impl Router {
|
||||
// routing table updates are send periodically to all directly connected peers
|
||||
// updates are used to advertise new routes or the retract existing routes (retracting when the metric is set to 0xFFFF)
|
||||
// this function is run when the route_update timer expires
|
||||
pub fn propagate_update(self) {
|
||||
let router_table = self.routing_table.lock().unwrap();
|
||||
pub async fn propagate_routes(self) {
|
||||
|
||||
loop {
|
||||
// routes are propagated every 10 secs
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
|
||||
|
||||
// loop over all directly connected peers
|
||||
let router_table = self.routing_table.lock().unwrap();
|
||||
let peers = self.peer_interfaces.lock().unwrap();
|
||||
|
||||
for (key, entry) in router_table.table.iter() {
|
||||
for peer in peers.iter() {
|
||||
let update = ControlPacket::new_update (
|
||||
key.plen,
|
||||
UPDATE_INTERVAL as u16,
|
||||
entry.seqno,
|
||||
entry.metric,
|
||||
key.prefix,
|
||||
entry.source.router_id,
|
||||
);
|
||||
|
||||
peer.to_peer_control.send(update).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
-9
@@ -1,6 +1,6 @@
|
||||
use std::{net::IpAddr, collections::HashMap};
|
||||
|
||||
use crate::{source_table::SourceKey, peer::Peer, timers::Timer};
|
||||
use crate::{source_table::SourceKey, peer::Peer, timers::Timer, router::Router, packet::{ControlStruct, BabelTLV}};
|
||||
|
||||
const HELLO_INTERVAL: u16 = 4;
|
||||
const IHU_INTERVAL: u16 = HELLO_INTERVAL * 3;
|
||||
@@ -21,11 +21,11 @@ pub struct RouteEntry {
|
||||
pub seqno: u16,
|
||||
pub next_hop: IpAddr, // This is the Peer's address
|
||||
pub selected: bool,
|
||||
pub route_expiry_timer: Timer,
|
||||
//pub route_expiry_timer: Timer,
|
||||
}
|
||||
|
||||
impl RouteEntry {
|
||||
pub fn new(source: SourceKey, neighbor: Peer, metric: u16, seqno: u16, next_hop: IpAddr, selected: bool) -> Self {
|
||||
pub fn new(source: SourceKey, neighbor: Peer, metric: u16, seqno: u16, next_hop: IpAddr, selected: bool, router: Router) -> Self {
|
||||
Self {
|
||||
source,
|
||||
neighbor,
|
||||
@@ -33,14 +33,26 @@ impl RouteEntry {
|
||||
seqno,
|
||||
next_hop,
|
||||
selected,
|
||||
route_expiry_timer: Timer::new_route_expiry_timer(UPDATE_INTERVAL as u64),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, metric: u16, seqno: u16, next_hop: IpAddr) {
|
||||
self.metric = metric;
|
||||
self.seqno = seqno;
|
||||
self.next_hop = next_hop;
|
||||
// pub fn update(&mut self, metric: u16, seqno: u16, next_hop: IpAddr) {
|
||||
// self.metric = metric;
|
||||
// self.seqno = seqno;
|
||||
// self.next_hop = next_hop;
|
||||
// }
|
||||
|
||||
pub fn update(&mut self, update: ControlStruct) {
|
||||
// the update is assumed to be feasible here
|
||||
match update.control_packet.body.tlv {
|
||||
BabelTLV::Update { plen, interval, seqno, metric, prefix, router_id } => {
|
||||
self.metric = metric;
|
||||
self.seqno = seqno;
|
||||
},
|
||||
_ => {
|
||||
println!("Received update with invalid TLV");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retracted(&mut self) {
|
||||
@@ -67,7 +79,7 @@ impl RoutingTable {
|
||||
|
||||
pub fn insert(&mut self, key: RouteKey, entry: RouteEntry) {
|
||||
self.table.insert(key, entry);
|
||||
println!("Added route to routing table: {:?}", self.table);
|
||||
//println!("Added route to routing table: {:?}", self.table);
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: &RouteKey) {
|
||||
|
||||
+70
-2
@@ -1,5 +1,7 @@
|
||||
use std::{net::IpAddr, collections::HashMap};
|
||||
|
||||
use crate::packet::{ControlStruct, BabelTLV};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
|
||||
pub struct SourceKey {
|
||||
pub prefix: IpAddr,
|
||||
@@ -7,8 +9,7 @@ pub struct SourceKey {
|
||||
pub router_id: u64, // We temporarily use 100 for all router IDs
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FeasibilityDistance(pub u16, pub u16); // (metric, seqno)
|
||||
|
||||
// Store (prefix, plen, router_id) -> feasibility distance mapping
|
||||
@@ -34,4 +35,71 @@ impl SourceTable {
|
||||
pub fn get(&self, key: &SourceKey) -> Option<&FeasibilityDistance> {
|
||||
self.table.get(key)
|
||||
}
|
||||
|
||||
pub fn update(&mut self, update: &ControlStruct) {
|
||||
|
||||
match update.control_packet.body.tlv {
|
||||
BabelTLV::Update { plen, interval, seqno, metric, prefix, router_id } => {
|
||||
|
||||
// first check if the update is feasible
|
||||
if !self.is_feasible(update) {
|
||||
return;
|
||||
}
|
||||
|
||||
let key = SourceKey {
|
||||
prefix: prefix,
|
||||
plen: plen,
|
||||
router_id: router_id
|
||||
};
|
||||
|
||||
let new_distance = FeasibilityDistance(metric, seqno);
|
||||
let old_distance = self.table.get(&key).cloned();
|
||||
match old_distance {
|
||||
Some(old_distance) => {
|
||||
if new_distance.0 < old_distance.0 {
|
||||
self.table.insert(key, FeasibilityDistance(new_distance.0, new_distance.1));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.table.insert(key, FeasibilityDistance(new_distance.0, new_distance.1));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("not an update");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn is_feasible(&self, update: &ControlStruct) -> bool {
|
||||
|
||||
match update.control_packet.body.tlv {
|
||||
BabelTLV::Update { plen, interval, seqno, metric, prefix, router_id } => {
|
||||
let key = SourceKey {
|
||||
prefix: prefix,
|
||||
plen: plen,
|
||||
router_id: router_id
|
||||
};
|
||||
|
||||
match self.table.get(&key) {
|
||||
Some(&source_entry) => {
|
||||
|
||||
let metric_2= source_entry.0;
|
||||
let seqno_2 = source_entry.1;
|
||||
|
||||
if seqno > seqno_2 || (seqno == seqno_2 && metric < metric_2) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
None => return true,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("not an update");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,23 +67,4 @@ impl Timer {
|
||||
timer
|
||||
}
|
||||
|
||||
// add update timer
|
||||
pub fn new_route_expiry_timer(update_interval: u64) -> Timer {
|
||||
let timer = Timer::new(Duration::from_secs(update_interval));
|
||||
|
||||
{
|
||||
let timer = timer.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
timer.run(|| {
|
||||
println!("Route timer expired! Sending routes...");
|
||||
// send update packet of that route to all peers
|
||||
|
||||
}).await;
|
||||
});
|
||||
}
|
||||
|
||||
timer
|
||||
}
|
||||
// add ack timer
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user