use futures::sync::mpsc;
-use crate::printer::Printer;
+use crate::printer::{Printer, Stat};
struct Route {
path: Vec<u32>,
($addrty: ty, $addr: expr, $table: expr, $addr_bits: expr) => { {
let mut res = Vec::new();
//TODO: Optimize this!
- for i in (0..($addr_bits + 1)).rev() {
+ for i in (0..$addr_bits).rev() {
let mut lookup = $addr.octets();
for b in 0..(i / 8) {
- lookup[lookup.len() - b] = 0;
+ lookup[lookup.len() - b - 1] = 0;
}
- lookup[lookup.len() - (i/8)] &= !(((1u16 << (i % 8)) - 1) as u8);
+ lookup[lookup.len() - (i/8) - 1] &= !(((1u16 << (i % 8)) - 1) as u8);
let lookup_addr = <$addrty>::from(lookup);
- for attrs in $table.range((Included((lookup_addr, $addr_bits, 0)), Included((lookup_addr, $addr_bits, std::u32::MAX)))) {
+ for attrs in $table.range((Included((lookup_addr, $addr_bits - i as u8, 0)), Included((lookup_addr, $addr_bits - i as u8, std::u32::MAX)))) {
res.push(Arc::clone(&attrs.1));
}
if !res.is_empty() { break; }
impl BGPClient {
pub fn get_asn(&self, addr: IpAddr) -> u32 {
let mut path_vecs = self.routes.lock().unwrap().get_route_attrs(addr).clone();
+ if path_vecs.is_empty() { return 0; }
+
path_vecs.sort_unstable_by(|path_a, path_b| {
path_a.pref.cmp(&path_b.pref)
.then(path_b.path.len().cmp(&path_a.path.len()))
.then(path_b.med.cmp(&path_a.med))
});
- // TODO: Find last common ASN among all paths
- *path_vecs[0].path.last().unwrap_or(&0)
+
+ let primary_route = path_vecs.pop().unwrap();
+ 'asn_candidates: for asn in primary_route.path.iter().rev() {
+ for secondary_route in path_vecs.iter() {
+ if !secondary_route.path.contains(asn) {
+ continue 'asn_candidates;
+ }
+ }
+ return *asn;
+ }
+ *primary_route.path.last().unwrap_or(&0)
}
pub fn disconnect(&self) {
}
match bgp_msg {
Message::Open(_) => {
- printer.add_line("Connected to BGP route provider".to_string(), true);
+ client.routes.lock().unwrap().v4_table.clear();
+ client.routes.lock().unwrap().v6_table.clear();
+ printer.add_line("Connected to BGP route provider".to_string(), false);
},
Message::KeepAlive => {
let _ = sender.try_send(Message::KeepAlive);
route_table.announce(r, Arc::clone(&path_arc));
}
}
+ printer.set_stat(Stat::V4RoutingTableSize(route_table.v4_table.len()));
+ printer.set_stat(Stat::V6RoutingTableSize(route_table.v6_table.len()));
},
_ => {}
}