X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fbgp_client.rs;h=78c2f8829b96181b5f65038d954ff4a549ff420d;hb=HEAD;hp=8dfb3eba579d94cbc0c3297f1cea9a6e7fccca1a;hpb=226b696cb2f4daf899be0197d619cb5e2fe9defc;p=dnsseed-rust diff --git a/src/bgp_client.rs b/src/bgp_client.rs index 8dfb3eb..78c2f88 100644 --- a/src/bgp_client.rs +++ b/src/bgp_client.rs @@ -79,6 +79,8 @@ struct RoutingTable { // and Vecs are way more memory-effecient in that case. v4_table: HashMap>, v6_table: HashMap>, + max_paths: usize, + routes_with_max: usize, } impl RoutingTable { @@ -86,6 +88,8 @@ impl RoutingTable { Self { v4_table: HashMap::with_capacity(900_000), v6_table: HashMap::with_capacity(100_000), + max_paths: 0, + routes_with_max: 0, } } @@ -117,6 +121,12 @@ impl RoutingTable { ($rt: expr, $v: expr, $id: expr) => { { match $rt.entry($v.into()) { hash_map::Entry::Occupied(mut entry) => { + if entry.get().len() == self.max_paths { + self.routes_with_max -= 1; + if self.routes_with_max == 0 { + self.max_paths = 0; + } + } entry.get_mut().retain(|e| e.0 != $id); if entry.get_mut().is_empty() { entry.remove(); @@ -151,9 +161,22 @@ impl RoutingTable { fn announce(&mut self, prefix: NLRIEncoding, route: Route) { macro_rules! insert { ($rt: expr, $v: expr, $id: expr) => { { - let entry = $rt.entry($v.into()).or_insert(Vec::new()); + let old_max_paths = self.max_paths; + let entry = $rt.entry($v.into()).or_insert_with(|| Vec::with_capacity(old_max_paths)); + let entry_had_max = entry.len() == self.max_paths; entry.retain(|e| e.0 != $id); + if entry_had_max { + entry.reserve_exact(1); + } else { + entry.reserve_exact(cmp::max(self.max_paths, entry.len() + 1) - entry.len()); + } entry.push(($id, route)); + if entry.len() > self.max_paths { + self.max_paths = entry.len(); + self.routes_with_max = 1; + } else if entry.len() == self.max_paths { + if !entry_had_max { self.routes_with_max += 1; } + } } } } match prefix { @@ -357,7 +380,7 @@ impl BGPClient { } else { None } } - fn connect_given_client(addr: SocketAddr, timeout: Duration, printer: &'static Printer, client: Arc) { + fn connect_given_client(remote_asn: u32, addr: SocketAddr, timeout: Duration, printer: &'static Printer, client: Arc) { tokio::spawn(Delay::new(Instant::now() + timeout / 4).then(move |_| { let connect_timeout = Delay::new(Instant::now() + timeout.clone()).then(|_| { future::err(std::io::Error::new(std::io::ErrorKind::TimedOut, "timeout reached")) @@ -375,15 +398,16 @@ impl BGPClient { .then(|_| { future::err(()) })); + let peer_asn = if remote_asn > u16::max_value() as u32 { 23456 } else { remote_asn as u16 }; let _ = sender.try_send(Message::Open(Open { version: 4, - peer_asn: 23456, + peer_asn, hold_timer: timeout.as_secs() as u16, - identifier: 0x453b1215, // 69.59.18.21 + identifier: 0x453b1215, // 69.59.18.21. Note that you never actually need to change this. parameters: vec![OpenParameter::Capabilities(vec![ OpenCapability::MultiProtocol((AFI::IPV4, SAFI::Unicast)), OpenCapability::MultiProtocol((AFI::IPV6, SAFI::Unicast)), - OpenCapability::FourByteASN(397444), + OpenCapability::FourByteASN(remote_asn), OpenCapability::RouteRefresh, OpenCapability::AddPath(vec![ (AFI::IPV4, SAFI::Unicast, AddPathDirection::ReceivePaths), @@ -416,6 +440,7 @@ impl BGPClient { } printer.set_stat(Stat::V4RoutingTableSize(route_table.v4_table.len())); printer.set_stat(Stat::V6RoutingTableSize(route_table.v6_table.len())); + printer.set_stat(Stat::RoutingTablePaths(route_table.max_paths)); }, _ => {} } @@ -426,7 +451,7 @@ impl BGPClient { }) }).then(move |_| { if !client_reconn.shutdown.load(Ordering::Relaxed) { - BGPClient::connect_given_client(addr, timeout, printer, client_reconn); + BGPClient::connect_given_client(remote_asn, addr, timeout, printer, client_reconn); } future::ok(()) }) @@ -434,12 +459,12 @@ impl BGPClient { ); } - pub fn new(addr: SocketAddr, timeout: Duration, printer: &'static Printer) -> Arc { + pub fn new(remote_asn: u32, addr: SocketAddr, timeout: Duration, printer: &'static Printer) -> Arc { let client = Arc::new(BGPClient { routes: Mutex::new(RoutingTable::new()), shutdown: AtomicBool::new(false), }); - BGPClient::connect_given_client(addr, timeout, printer, Arc::clone(&client)); + BGPClient::connect_given_client(remote_asn, addr, timeout, printer, Arc::clone(&client)); client } }