diff --git a/src/units/bmp_tcp_in/http/router_info/response.rs b/src/units/bmp_tcp_in/http/router_info/response.rs index 58d5de2..2a6dd90 100644 --- a/src/units/bmp_tcp_in/http/router_info/response.rs +++ b/src/units/bmp_tcp_in/http/router_info/response.rs @@ -169,7 +169,7 @@ impl RouterInfoApi { Timestamp IP Address ASN - # Prefixes + Prefixes Flags "# @@ -179,17 +179,17 @@ impl RouterInfoApi { for pph in peer_states.get_peers() { let peer_key = format!("{}", pph); - let num_prefixes = peer_states - .get_announced_prefixes(pph) - .map_or(0, |iter| iter.count()); - let prefixes_link = if num_prefixes > 0 { - format!( - "{}", - &base_http_path, pph, num_prefixes - ) - } else { - "0".to_string() - }; + let prefixes_link = peer_states.get_peer_ingress_id(pph) + .map(|ingress_id| + format!( + "prefixes", + ingress_id + ) + ).unwrap_or("".to_string()); + + // As soon as the per-mui iterators in the store work, remove + // this line and actually show the hyperlinks. + let prefixes_link = "".to_string(); writeln!(peer_report, "{}{}{}{}{:08b} [more]", pph.timestamp(), pph.address(), diff --git a/src/units/rib_unit/http/request.rs b/src/units/rib_unit/http/request.rs index 45b195d..83bab24 100644 --- a/src/units/rib_unit/http/request.rs +++ b/src/units/rib_unit/http/request.rs @@ -84,7 +84,11 @@ impl ProcessRequest for PrefixesApi { if request.method() == Method::GET && req_path.starts_with(self.http_api_path.deref()) { - match self.handle_prefix_query(req_path, request).await { + let res = match request.uri().path().split("/").count() { + 3 => self.handle_ingress_id_query(req_path, request).await, + _ => self.handle_prefix_query(req_path, request).await, + }; + match res { Ok(res) => Some(res), Err(err) => Some( Response::builder() @@ -283,6 +287,45 @@ impl PrefixesApi { Ok(res) } + async fn handle_ingress_id_query( + &self, + req_path: &str, + _request: &Request, + ) -> Result, String> { + debug!("in handle_ingress_id_query"); + + let ingress_id = req_path + .strip_prefix(self.http_api_path.as_str()).unwrap() + .parse::() + .map_err(|e| e.to_string())?; + + if self.rib_type != RibType::Physical { + return Err("unsupported on virtual rib".to_string()); + } + + let store = self.rib.load(); + let mut res = String::new(); + let records = store.match_ingress_id(ingress_id).map_err(|e| e.to_string())?; + + for pubrec in records { + res += &pubrec.prefix.to_string(); + res.push('\n'); + for m in pubrec.meta { + res.push('\t'); + res += &serde_json::to_string(&m.meta).unwrap(); + res.push('\n'); + } + } + + Ok( + Response::builder() + .header("Content-Type", "text/plain") + .body(res.into()) + .unwrap() + ) + + } + fn parse_include_param( params: &QueryParams, query_limits: Arc>, diff --git a/src/units/rib_unit/rib.rs b/src/units/rib_unit/rib.rs index a8f5c06..983dd11 100644 --- a/src/units/rib_unit/rib.rs +++ b/src/units/rib_unit/rib.rs @@ -12,8 +12,7 @@ use log::{debug, error}; // typevalue::TypeValue, //}, vm::FieldIndex}; use rotonda_store::{ - custom_alloc::UpsertReport, prelude::multi::{PrefixStoreError, RouteStatus}, MatchOptions, MultiThreadedStore, QueryResult, - epoch + custom_alloc::UpsertReport, epoch, prelude::{multi::{PrefixStoreError, RouteStatus}, PrefixRecord}, MatchOptions, MultiThreadedStore, QueryResult }; use inetnum::{addr::Prefix, asn::Asn}; use routecore::bgp::{nlri::afisafi::{IsPrefix, Nlri}, path_attributes::PaMap, path_selection::{OrdRoute, Rfc4271, TiebreakerInfo}, types::AfiSafiType}; @@ -298,6 +297,33 @@ impl Rib { } Ok(unicast_res) } + + pub fn match_ingress_id( + &self, + ingress_id: IngressId, + //match_options: &MatchOptions, + ) -> Result>, String> { + let guard = &epoch::pin(); + let store = (*self.unicast).as_ref() + .ok_or(PrefixStoreError::StoreNotReadyError.to_string())?; + let include_withdrawals = false; + let mut res = store + .iter_records_for_mui_v4(ingress_id, include_withdrawals, guard) + .collect::>(); + res.append(&mut store + .iter_records_for_mui_v6(ingress_id, include_withdrawals, guard) + .collect::>() + ); + + //tmp: while the per mui methods do not work yet, we can use + //.prefixes_iter() to test the output. + //let res = store.prefixes_iter().collect::>(); + debug!( + "rib::match_ingress_id for {ingress_id}: {} results", + res.len() + ); + Ok(res) + } } impl Default for Rib {