diff --git a/src/rust/uisp_integration/src/blackboard.rs b/src/rust/uisp_integration/src/blackboard.rs index 59841146..958f7c05 100644 --- a/src/rust/uisp_integration/src/blackboard.rs +++ b/src/rust/uisp_integration/src/blackboard.rs @@ -1,8 +1,8 @@ //! Collects the blackboard functionality together +use lqos_bus::BlackboardSystem; use serde::Serialize; use tracing::info; -use lqos_bus::BlackboardSystem; pub async fn blackboard(subsystem: BlackboardSystem, key: &str, value: &str) { let Ok(config) = lqos_config::load_config() else { @@ -40,4 +40,4 @@ pub async fn blackboard_blob(key: &str, value: T) -> anyhow::Resul let _ = lqos_bus::bus_request(req).await; } Ok(()) -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/main.rs b/src/rust/uisp_integration/src/main.rs index a832f50b..419f706e 100644 --- a/src/rust/uisp_integration/src/main.rs +++ b/src/rust/uisp_integration/src/main.rs @@ -2,19 +2,19 @@ //! be ported back to Python, with Rust support structures - but I'll iterate //! faster in Rust. +mod blackboard; #[warn(missing_docs)] mod errors; pub mod ip_ranges; mod strategies; pub mod uisp_types; -mod blackboard; use crate::errors::UispIntegrationError; use crate::ip_ranges::IpRanges; +pub use blackboard::*; use lqos_config::Config; use tokio::time::Instant; use tracing::{error, info}; -pub use blackboard::*; /// Start the tracing/logging system fn init_tracing() { @@ -35,7 +35,6 @@ fn check_enabled_status(config: &Config) -> Result<(), UispIntegrationError> { } } - #[tokio::main] async fn main() -> Result<(), UispIntegrationError> { let now = Instant::now(); diff --git a/src/rust/uisp_integration/src/strategies/ap_only.rs b/src/rust/uisp_integration/src/strategies/ap_only.rs index 731a8735..4ca1761f 100644 --- a/src/rust/uisp_integration/src/strategies/ap_only.rs +++ b/src/rust/uisp_integration/src/strategies/ap_only.rs @@ -1,12 +1,12 @@ -use std::fs::write; -use std::path::Path; -use std::sync::Arc; -use tracing::{error, info, warn}; -use lqos_config::Config; use crate::errors::UispIntegrationError; use crate::ip_ranges::IpRanges; use crate::strategies::common::UispData; use crate::strategies::full::shaped_devices_writer::ShapedDevice; +use lqos_config::Config; +use std::fs::write; +use std::path::Path; +use std::sync::Arc; +use tracing::{error, info, warn}; /// Creates a network with only APs detected /// from clients. @@ -35,8 +35,14 @@ pub async fn build_ap_only_network( ap_object.insert("children".to_string(), serde_json::Map::new().into()); // Limits - ap_object.insert("downloadBandwidthMbps".to_string(), serde_json::Value::Number(ap_device.download.into())); - ap_object.insert("uploadBandwidthMbps".to_string(), serde_json::Value::Number(ap_device.upload.into())); + ap_object.insert( + "downloadBandwidthMbps".to_string(), + serde_json::Value::Number(ap_device.download.into()), + ); + ap_object.insert( + "uploadBandwidthMbps".to_string(), + serde_json::Value::Number(ap_device.upload.into()), + ); // Metadata ap_object.insert("type".to_string(), "AP".to_string().into()); @@ -60,7 +66,11 @@ pub async fn build_ap_only_network( for (parent, client_ids) in mappings.iter() { for client_id in client_ids { let site = uisp_data.sites.iter().find(|s| *client_id == s.id).unwrap(); - let devices = uisp_data.devices.iter().filter(|d| d.site_id == *client_id).collect::>(); + let devices = uisp_data + .devices + .iter() + .filter(|d| d.site_id == *client_id) + .collect::>(); for device in devices.iter().filter(|d| d.has_address()) { let sd = ShapedDevice { circuit_id: site.id.clone(), @@ -105,4 +115,4 @@ pub async fn build_ap_only_network( info!("Wrote {} lines to ShapedDevices.csv", shaped_devices.len()); Ok(()) -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/strategies/ap_site.rs b/src/rust/uisp_integration/src/strategies/ap_site.rs index c0de4937..ac278985 100644 --- a/src/rust/uisp_integration/src/strategies/ap_site.rs +++ b/src/rust/uisp_integration/src/strategies/ap_site.rs @@ -1,14 +1,14 @@ -use std::collections::{HashMap, HashSet}; -use std::fs::write; -use std::path::Path; -use std::sync::Arc; -use tracing::{error, info, warn}; -use lqos_config::Config; use crate::blackboard_blob; use crate::errors::UispIntegrationError; use crate::ip_ranges::IpRanges; use crate::strategies::common::UispData; use crate::strategies::full::shaped_devices_writer::ShapedDevice; +use lqos_config::Config; +use std::collections::{HashMap, HashSet}; +use std::fs::write; +use std::path::Path; +use std::sync::Arc; +use tracing::{error, info, warn}; #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone)] pub enum GraphMapping { @@ -29,12 +29,11 @@ pub async fn build_ap_site_network( let uisp_data = UispData::fetch_uisp_data(config.clone(), ip_ranges).await?; // Find trouble-spots! - let _trouble = find_troublesome_sites(&uisp_data).await - .map_err(|e|{ - error!("Error finding troublesome sites"); - error!("{e:?}"); - UispIntegrationError::UnknownSiteType - })?; + let _trouble = find_troublesome_sites(&uisp_data).await.map_err(|e| { + error!("Error finding troublesome sites"); + error!("{e:?}"); + UispIntegrationError::UnknownSiteType + })?; // Find the clients let ap_mappings = uisp_data.map_clients_to_aps(); @@ -76,7 +75,10 @@ pub async fn build_ap_site_network( Ok(()) } -pub(crate) fn write_shaped_devices(config: &Arc, shaped_devices: &mut Vec) -> Result<(), UispIntegrationError> { +pub(crate) fn write_shaped_devices( + config: &Arc, + shaped_devices: &mut Vec, +) -> Result<(), UispIntegrationError> { let file_path = Path::new(&config.lqos_directory).join("ShapedDevices.csv"); let mut writer = csv::WriterBuilder::new() .has_headers(true) @@ -95,18 +97,23 @@ pub(crate) fn write_shaped_devices(config: &Arc, shaped_devices: &mut Ve Ok(()) } -pub(crate) fn map_sites_above_aps(uisp_data: &UispData, ap_mappings: HashMap>, access_points: HashMap) -> HashMap { +pub(crate) fn map_sites_above_aps( + uisp_data: &UispData, + ap_mappings: HashMap>, + access_points: HashMap, +) -> HashMap { let mut sites = HashMap::new(); for (ap_name, client_ids) in ap_mappings.iter() { if let Some(device) = uisp_data.find_device_by_name(ap_name) { if let Some(device_site_id) = device.get_site_id() { if let Some(device_site) = uisp_data.sites.iter().find(|s| s.id == device_site_id) { - let site_entry = sites.entry(device_site.name.clone()).or_insert_with(|| { - Layer { - id: GraphMapping::SiteByName(device_site.name.clone()), - children: Vec::new(), - } - }); + let site_entry = + sites + .entry(device_site.name.clone()) + .or_insert_with(|| Layer { + id: GraphMapping::SiteByName(device_site.name.clone()), + children: Vec::new(), + }); let ap_map = access_points.get(ap_name).unwrap().clone(); site_entry.children.push(ap_map); } @@ -165,15 +172,21 @@ impl Layer { GraphMapping::SiteByName(name) | GraphMapping::AccessPointByName(name) => { name.to_owned() } - _ => "".to_owned() + _ => "".to_owned(), }; for child in self.children.iter() { match &child.id { GraphMapping::SiteByName(name) | GraphMapping::AccessPointByName(name) => { - children.insert(name.clone(), child.walk_children(Some(&parent_name), uisp_data, shaped_devices, config).into()); + children.insert( + name.clone(), + child + .walk_children(Some(&parent_name), uisp_data, shaped_devices, config) + .into(), + ); } GraphMapping::ClientById(_client_id) => { - let _ = child.walk_children(Some(&parent_name), uisp_data, shaped_devices, config); + let _ = + child.walk_children(Some(&parent_name), uisp_data, shaped_devices, config); } _ => {} } @@ -185,7 +198,10 @@ impl Layer { root.insert("type".to_string(), "Site".into()); root.insert("name".to_string(), name.clone().into()); if let Some(site) = uisp_data.sites.iter().find(|s| s.name == *name) { - root.insert("downloadBandwidthMbps".to_owned(), site.max_down_mbps.into()); + root.insert( + "downloadBandwidthMbps".to_owned(), + site.max_down_mbps.into(), + ); root.insert("uploadBandwidthMbps".to_owned(), site.max_up_mbps.into()); root.insert("uisp_site".to_string(), site.id.clone().into()); root.insert("parent_site".to_string(), name.to_string().into()); @@ -203,7 +219,11 @@ impl Layer { } GraphMapping::ClientById(client_id) => { if let Some(site) = uisp_data.sites.iter().find(|c| c.id == *client_id) { - let devices = uisp_data.devices.iter().filter(|d| d.site_id == *client_id).collect::>(); + let devices = uisp_data + .devices + .iter() + .filter(|d| d.site_id == *client_id) + .collect::>(); for device in devices.iter().filter(|d| d.has_address()) { let sd = ShapedDevice { circuit_id: site.id.clone(), @@ -238,7 +258,10 @@ impl Layer { } } if parent.is_some() { - root.insert("children".to_string(), serde_json::to_value(children).unwrap()); + root.insert( + "children".to_string(), + serde_json::to_value(children).unwrap(), + ); } else { for child in children { root.insert(child.0, child.1); @@ -253,9 +276,7 @@ pub struct TroublesomeClients { pub client_of_clients: HashSet, } -pub(crate) async fn find_troublesome_sites( - data: &UispData, -) -> anyhow::Result { +pub(crate) async fn find_troublesome_sites(data: &UispData) -> anyhow::Result { let multi_entry_points = find_clients_with_multiple_entry_points(data)?; let client_of_clients = find_clients_linked_from_other_clients(data)?; @@ -268,17 +289,19 @@ pub(crate) async fn find_troublesome_sites( }) } -fn find_clients_with_multiple_entry_points( - data: &UispData, -) -> anyhow::Result> { +fn find_clients_with_multiple_entry_points(data: &UispData) -> anyhow::Result> { let mut result = HashSet::new(); for client in data.find_client_sites() { let mut links_to_client = HashSet::new(); for link in data.data_links_raw.iter() { if let (Some(from_site), Some(to_site)) = (&link.from.site, &link.to.site) { - if from_site.identification.id == client.id && to_site.identification.id != client.id { + if from_site.identification.id == client.id + && to_site.identification.id != client.id + { links_to_client.insert(to_site.identification.id.clone()); - } else if from_site.identification.id != client.id && to_site.identification.id == client.id { + } else if from_site.identification.id != client.id + && to_site.identification.id == client.id + { links_to_client.insert(from_site.identification.id.clone()); } } @@ -295,24 +318,30 @@ fn find_clients_with_multiple_entry_points( Ok(result) } -fn find_clients_linked_from_other_clients( - data: &UispData -) -> anyhow::Result> { +fn find_clients_linked_from_other_clients(data: &UispData) -> anyhow::Result> { let all_clients = data.find_client_sites(); let mut result = HashSet::new(); for client in &all_clients { for link in data.data_links_raw.iter() { if let (Some(from_site), Some(to_site)) = (&link.from.site, &link.to.site) { - if from_site.identification.id == client.id && to_site.identification.id != client.id - && all_clients.iter().any(|c| c.id == to_site.identification.id) { + if from_site.identification.id == client.id + && to_site.identification.id != client.id + && all_clients + .iter() + .any(|c| c.id == to_site.identification.id) + { warn!( "Client {} is linked from another client: {}", client.name, to_site.identification.id ); result.insert(client.id.clone()); } - if from_site.identification.id != client.id && to_site.identification.id == client.id - && all_clients.iter().any(|c| c.id == from_site.identification.id) { + if from_site.identification.id != client.id + && to_site.identification.id == client.id + && all_clients + .iter() + .any(|c| c.id == from_site.identification.id) + { warn!( "Client {} is linked to another client: {}", client.name, from_site.identification.id @@ -323,4 +352,4 @@ fn find_clients_linked_from_other_clients( } } Ok(result) -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/strategies/common.rs b/src/rust/uisp_integration/src/strategies/common.rs index dd736867..8c5e699e 100644 --- a/src/rust/uisp_integration/src/strategies/common.rs +++ b/src/rust/uisp_integration/src/strategies/common.rs @@ -1,14 +1,14 @@ +use crate::blackboard_blob; +use crate::errors::UispIntegrationError; +use crate::ip_ranges::IpRanges; +use crate::strategies::full::parse::parse_uisp_datasets; +use crate::strategies::full::uisp_fetch::load_uisp_data; +use crate::uisp_types::{UispDataLink, UispDevice, UispSite, UispSiteType}; +use lqos_config::Config; use std::collections::HashMap; use std::sync::Arc; use tracing::warn; -use lqos_config::Config; use uisp::{DataLink, Device, Site}; -use crate::blackboard_blob; -use crate::ip_ranges::IpRanges; -use crate::strategies::full::uisp_fetch::load_uisp_data; -use crate::errors::UispIntegrationError; -use crate::strategies::full::parse::parse_uisp_datasets; -use crate::uisp_types::{UispDataLink, UispDevice, UispSite, UispSiteType}; pub(crate) struct UispData { pub sites_raw: Vec, @@ -63,19 +63,29 @@ impl UispData { } pub fn find_client_sites(&self) -> Vec<&UispSite> { - self.sites.iter().filter(|s| s.site_type == UispSiteType::Client).collect() + self.sites + .iter() + .filter(|s| s.site_type == UispSiteType::Client) + .collect() } pub fn find_devices_in_site(&self, site_id: &str) -> Vec<&Device> { - self.devices_raw.iter().filter(|d| d.get_site_id().unwrap_or_default() == site_id).collect() + self.devices_raw + .iter() + .filter(|d| d.get_site_id().unwrap_or_default() == site_id) + .collect() } pub fn find_device_by_id(&self, device_id: &str) -> Option<&Device> { - self.devices_raw.iter().find(|d| d.identification.id == device_id) + self.devices_raw + .iter() + .find(|d| d.identification.id == device_id) } pub fn find_device_by_name(&self, device_name: &str) -> Option<&Device> { - self.devices_raw.iter().find(|d| d.get_name().unwrap_or_default() == device_name) + self.devices_raw + .iter() + .find(|d| d.get_name().unwrap_or_default() == device_name) } pub fn map_clients_to_aps(&self) -> HashMap> { @@ -120,9 +130,12 @@ impl UispData { if let Some(from_device) = &link.from.device { if from_device.identification.id == device.identification.id { if let Some(to_device) = &link.to.device { - if let Some(apdev) = self.find_device_by_id(&to_device.identification.id) { + if let Some(apdev) = + self.find_device_by_id(&to_device.identification.id) + { if apdev.get_site_id().unwrap_or_default() != client.id { - parent = Some(("AP", apdev.get_name().unwrap_or_default())); + parent = + Some(("AP", apdev.get_name().unwrap_or_default())); found = true; } } @@ -133,9 +146,12 @@ impl UispData { if let Some(to_device) = &link.to.device { if to_device.identification.id == device.identification.id { if let Some(from_device) = &link.from.device { - if let Some(apdev) = self.find_device_by_id(&from_device.identification.id) { + if let Some(apdev) = + self.find_device_by_id(&from_device.identification.id) + { if apdev.get_site_id().unwrap_or_default() != client.id { - parent = Some(("AP", apdev.get_name().unwrap_or_default())); + parent = + Some(("AP", apdev.get_name().unwrap_or_default())); found = true; } } @@ -152,7 +168,9 @@ impl UispData { if let Some(from_site) = &link.from.site { if from_site.identification.id == client.id { if let Some(to_device) = &link.to.device { - if let Some(apdev) = self.find_device_by_id(&to_device.identification.id) { + if let Some(apdev) = + self.find_device_by_id(&to_device.identification.id) + { if apdev.get_site_id().unwrap_or_default() != client.id { parent = Some(("AP", apdev.get_name().unwrap_or_default())); found = true; @@ -164,7 +182,9 @@ impl UispData { if let Some(to_site) = &link.to.site { if to_site.identification.id == client.id { if let Some(from_device) = &link.from.device { - if let Some(apdev) = self.find_device_by_id(&from_device.identification.id) { + if let Some(apdev) = + self.find_device_by_id(&from_device.identification.id) + { if apdev.get_site_id().unwrap_or_default() != client.id { parent = Some(("AP", apdev.get_name().unwrap_or_default())); found = true; @@ -178,7 +198,9 @@ impl UispData { if !found { //println!("Client {} has no obvious parent AP", client.name); - let entry = mappings.entry("Orphans".to_string()).or_insert_with(Vec::new); + let entry = mappings + .entry("Orphans".to_string()) + .or_insert_with(Vec::new); entry.push(client.id.clone()); } else { //info!("Client {} is connected to {:?}", client.name, parent); @@ -191,4 +213,3 @@ impl UispData { mappings } } - diff --git a/src/rust/uisp_integration/src/strategies/full2.rs b/src/rust/uisp_integration/src/strategies/full2.rs index c52c9e12..6b7836ca 100644 --- a/src/rust/uisp_integration/src/strategies/full2.rs +++ b/src/rust/uisp_integration/src/strategies/full2.rs @@ -1,28 +1,28 @@ +mod dot; mod graph_mapping; mod link_mapping; -mod dot; mod net_json_parent; -use std::collections::{HashMap, HashSet}; -use std::fs::write; -use std::path::Path; +use crate::blackboard_blob; use crate::errors::UispIntegrationError; use crate::ip_ranges::IpRanges; use crate::strategies::common::UispData; -use crate::uisp_types::UispDevice; -use lqos_config::Config; -use std::sync::Arc; -use petgraph::{Graph, Undirected}; -use petgraph::graph::NodeIndex; -use tracing::{error, info, warn}; -use petgraph::visit::{EdgeRef, NodeRef}; -use crate::blackboard_blob; +use crate::strategies::full::routes_override::RouteOverride; +use crate::strategies::full::shaped_devices_writer::ShapedDevice; use crate::strategies::full2::dot::save_dot_file; use crate::strategies::full2::graph_mapping::GraphMapping; use crate::strategies::full2::link_mapping::LinkMapping; -use crate::strategies::full2::net_json_parent::{walk_parents, NetJsonParent}; -use crate::strategies::full::routes_override::RouteOverride; -use crate::strategies::full::shaped_devices_writer::ShapedDevice; +use crate::strategies::full2::net_json_parent::{NetJsonParent, walk_parents}; +use crate::uisp_types::UispDevice; +use lqos_config::Config; +use petgraph::graph::NodeIndex; +use petgraph::visit::{EdgeRef, NodeRef}; +use petgraph::{Graph, Undirected}; +use std::collections::{HashMap, HashSet}; +use std::fs::write; +use std::path::Path; +use std::sync::Arc; +use tracing::{error, info, warn}; type GraphType = petgraph::Graph; @@ -34,15 +34,17 @@ pub async fn build_full_network_v2( let uisp_data = UispData::fetch_uisp_data(config.clone(), ip_ranges).await?; // Report on obvious UISP errors that should be fixed - let _trouble = crate::strategies::ap_site::find_troublesome_sites(&uisp_data).await + let _trouble = crate::strategies::ap_site::find_troublesome_sites(&uisp_data) + .await .map_err(|e| { - error!("Error finding troublesome sites"); - error!("{e:?}"); - UispIntegrationError::UnknownSiteType - })?; + error!("Error finding troublesome sites"); + error!("{e:?}"); + UispIntegrationError::UnknownSiteType + })?; // Load overrides - let bandwidth_overrides = crate::strategies::full::bandwidth_overrides::get_site_bandwidth_overrides(&config)?; + let bandwidth_overrides = + crate::strategies::full::bandwidth_overrides::get_site_bandwidth_overrides(&config)?; let routing_overrides = crate::strategies::full::routes_override::get_route_overrides(&config)?; // Create a new graph @@ -54,7 +56,13 @@ pub async fn build_full_network_v2( // Add all sites to the graph let mut site_map = HashMap::new(); let mut root_idx = None; - add_all_sites_to_graph(&uisp_data, &mut graph, &root_site_name, &mut site_map, &mut root_idx); + add_all_sites_to_graph( + &uisp_data, + &mut graph, + &root_site_name, + &mut site_map, + &mut root_idx, + ); let root_idx = root_idx.expect("Root site not found"); // Iterate all UISP devices and if their parent site is in the graph, add them @@ -65,21 +73,16 @@ pub async fn build_full_network_v2( add_device_links_to_graph(&uisp_data, &mut graph, &mut device_map); // Now we iterate only sites, looking for connectivity to the root - let orphans = graph.add_node(GraphMapping::GeneratedSite{ name: "Orphans".to_string()}); + let orphans = graph.add_node(GraphMapping::GeneratedSite { + name: "Orphans".to_string(), + }); graph.add_edge(root_idx, orphans, LinkMapping::Ethernet); for (_, site_ref) in site_map.iter() { if *site_ref == root_idx { continue; } - let a_star_run = petgraph::algo::astar( - &graph, - *site_ref, - |n| { - n.id() == root_idx.id() - }, - |_| 0, - |_| 0, - ); + let a_star_run = + petgraph::algo::astar(&graph, *site_ref, |n| n.id() == root_idx.id(), |_| 0, |_| 0); if a_star_run.is_none() { warn!( @@ -96,7 +99,11 @@ pub async fn build_full_network_v2( // Find the APs that have clients let mut aps_with_clients = HashSet::new(); for (ap_name, _client_ids) in client_mappings.iter() { - let Some(ap_device) = uisp_data.devices_raw.iter().find(|d| d.get_name().unwrap_or_default() == *ap_name) else { + let Some(ap_device) = uisp_data + .devices_raw + .iter() + .find(|d| d.get_name().unwrap_or_default() == *ap_name) + else { // Orphaning is already handled continue; }; @@ -106,11 +113,11 @@ pub async fn build_full_network_v2( // Count linkages to APs let mut ap_link_count = HashMap::::new(); for edge_ref in graph.edge_references() { - if let GraphMapping::AccessPoint{ref id, ..} = graph[edge_ref.source()] { + if let GraphMapping::AccessPoint { ref id, .. } = graph[edge_ref.source()] { let entry = ap_link_count.entry(id.clone()).or_insert(0); *entry += 1; }; - if let GraphMapping::AccessPoint{ref id, ..} = graph[edge_ref.target()] { + if let GraphMapping::AccessPoint { ref id, .. } = graph[edge_ref.target()] { let entry = ap_link_count.entry(id.clone()).or_insert(0); *entry += 1; }; @@ -129,7 +136,10 @@ pub async fn build_full_network_v2( } to_remove.push(*ap_ref); } - info!("Removing {} APs with no clients or only one link", to_remove.len()); + info!( + "Removing {} APs with no clients or only one link", + to_remove.len() + ); for ap_ref in to_remove.iter() { graph.remove_node(*ap_ref); } @@ -145,36 +155,52 @@ pub async fn build_full_network_v2( continue; } match &graph[node] { - GraphMapping::GeneratedSite{name} | GraphMapping::Site{name, ..} | - GraphMapping::AccessPoint{name, ..} => { + GraphMapping::GeneratedSite { name } + | GraphMapping::Site { name, .. } + | GraphMapping::AccessPoint { name, .. } => { let route = petgraph::algo::astar( &graph, root_idx, |n| n == node, - |e| (10_000u64).saturating_sub(link_capacity_mbps(&e.weight(), &uisp_data.devices, &routing_overrides)), + |e| { + (10_000u64).saturating_sub(link_capacity_mbps( + &e.weight(), + &uisp_data.devices, + &routing_overrides, + )) + }, |_| 0, - ).unwrap_or((0, vec![])); + ) + .unwrap_or((0, vec![])); if route.1.is_empty() { //println!("No path detected from {:?} to {}", graph[node], root_site_name); - parents.insert(name.to_owned(), NetJsonParent { - parent_name: "Orphans".to_string(), - mapping: &graph[node], - download: config.queues.generated_pn_download_mbps, - upload: config.queues.generated_pn_upload_mbps, - }); + parents.insert( + name.to_owned(), + NetJsonParent { + parent_name: "Orphans".to_string(), + mapping: &graph[node], + download: config.queues.generated_pn_download_mbps, + upload: config.queues.generated_pn_upload_mbps, + }, + ); } else { - let mut capacity = (config.queues.generated_pn_download_mbps,config.queues.generated_pn_upload_mbps); - if !config.uisp_integration.ignore_calculated_capacity { - match &graph[node] { - GraphMapping::AccessPoint { id, .. } => { - if let Some(device) = uisp_data.devices.iter().find(|d| d.id == *id) { - capacity = (device.download, device.upload); - if let Some(bw_override) = bandwidth_overrides.get(&device.name) { - capacity = (bw_override.0 as u64, bw_override.1 as u64); - } + let mut capacity = ( + config.queues.generated_pn_download_mbps, + config.queues.generated_pn_upload_mbps, + ); + if !config.uisp_integration.ignore_calculated_capacity { + match &graph[node] { + GraphMapping::AccessPoint { id, .. } => { + if let Some(device) = uisp_data.devices.iter().find(|d| d.id == *id) + { + capacity = (device.download, device.upload); + if let Some(bw_override) = bandwidth_overrides.get(&device.name) + { + capacity = (bw_override.0 as u64, bw_override.1 as u64); } } + } _ => {} } } @@ -183,12 +209,15 @@ pub async fn build_full_network_v2( // We need the weight from node to parent_node in the graph edges if let Some(_edge) = graph.find_edge(parent_node, node) { let parent = graph[route.1[route.1.len() - 2]].name(); - parents.insert(name.to_owned(), NetJsonParent { - parent_name: parent, - mapping: &graph[node], - download: capacity.0, - upload: capacity.1, - }); + parents.insert( + name.to_owned(), + NetJsonParent { + parent_name: parent, + mapping: &graph[node], + download: capacity.0, + upload: capacity.1, + }, + ); } else { panic!("DID NOT FIND THE EDGE"); } @@ -200,14 +229,14 @@ pub async fn build_full_network_v2( // Write the network.json file let mut network_json = serde_json::Map::new(); - for (name, node_info) in parents.iter().filter(|(_name, parent)| parent.parent_name == root_site_name) { - network_json.insert(name.into(), walk_parents( - &parents, - name, - &node_info, - &config, - &graph, - ).into()); + for (name, node_info) in parents + .iter() + .filter(|(_name, parent)| parent.parent_name == root_site_name) + { + network_json.insert( + name.into(), + walk_parents(&parents, name, &node_info, &config, &graph).into(), + ); } let network_path = Path::new(&config.lqos_directory).join("network.json"); if network_path.exists() && !config.integration_common.always_overwrite_network_json { @@ -240,10 +269,14 @@ pub async fn build_full_network_v2( continue; } - let download = (site.max_down_mbps as f32) * config.uisp_integration.bandwidth_overhead_factor; - let upload = (site.max_up_mbps as f32) * config.uisp_integration.bandwidth_overhead_factor; - let download_min = (download * config.uisp_integration.commit_bandwidth_multiplier) as u64; - let upload_min = (upload * config.uisp_integration.commit_bandwidth_multiplier) as u64; + let download = + (site.max_down_mbps as f32) * config.uisp_integration.bandwidth_overhead_factor; + let upload = + (site.max_up_mbps as f32) * config.uisp_integration.bandwidth_overhead_factor; + let download_min = + (download * config.uisp_integration.commit_bandwidth_multiplier) as u64; + let upload_min = + (upload * config.uisp_integration.commit_bandwidth_multiplier) as u64; let download_max = download as u64; let upload_max = upload as u64; @@ -285,7 +318,11 @@ pub async fn build_full_network_v2( Ok(()) } -fn add_device_links_to_graph(uisp_data: &UispData, graph: &mut Graph, device_map: &mut HashMap) { +fn add_device_links_to_graph( + uisp_data: &UispData, + graph: &mut Graph, + device_map: &mut HashMap, +) { for link in uisp_data.data_links_raw.iter() { let Some(from_device) = &link.from.device else { continue; @@ -303,9 +340,19 @@ fn add_device_links_to_graph(uisp_data: &UispData, graph: &mut Graph, site_map: &mut HashMap, device_map: &mut HashMap) { +fn add_devices_to_graph( + uisp_data: &UispData, + graph: &mut Graph, + site_map: &mut HashMap, + device_map: &mut HashMap, +) { for device in uisp_data.devices_raw.iter() { let Some(site_id) = &device.identification.site else { continue; @@ -339,7 +398,13 @@ fn add_devices_to_graph(uisp_data: &UispData, graph: &mut Graph, root_site_name: &String, site_map: &mut HashMap, root_idx: &mut Option) { +pub fn add_all_sites_to_graph( + uisp_data: &UispData, + graph: &mut Graph, + root_site_name: &String, + site_map: &mut HashMap, + root_idx: &mut Option, +) { for site in uisp_data.sites_raw.iter().filter(|s| !s.is_client_site()) { let site_name = site.name_or_blank(); let id = site.id.clone(); @@ -363,20 +428,30 @@ pub fn add_all_sites_to_graph(uisp_data: &UispData, graph: &mut Graph u64 { +fn link_capacity_mbps( + link_mapping: &LinkMapping, + devices: &[UispDevice], + route_overrides: &[RouteOverride], +) -> u64 { match link_mapping { LinkMapping::Ethernet => 10_000, LinkMapping::DevicePair(device_a, device_b) => { - let capacity ; + let capacity; if let Some(device_a) = devices.iter().find(|d| d.id == *device_a) { - if let Some(override_a) = route_overrides.iter().find(|o| o.from_site == device_a.name || o.to_site == device_a.name) { + if let Some(override_a) = route_overrides + .iter() + .find(|o| o.from_site == device_a.name || o.to_site == device_a.name) + { capacity = override_a.cost as u64; } else { capacity = device_a.download; } } else if let Some(device_b) = devices.iter().find(|d| d.id == *device_b) { - if let Some(override_b) = route_overrides.iter().find(|o| o.from_site == device_b.name || o.to_site == device_b.name) { + if let Some(override_b) = route_overrides + .iter() + .find(|o| o.from_site == device_b.name || o.to_site == device_b.name) + { capacity = override_b.cost as u64; } else { capacity = device_b.download; diff --git a/src/rust/uisp_integration/src/strategies/full2/dot.rs b/src/rust/uisp_integration/src/strategies/full2/dot.rs index aeb2823e..f0521548 100644 --- a/src/rust/uisp_integration/src/strategies/full2/dot.rs +++ b/src/rust/uisp_integration/src/strategies/full2/dot.rs @@ -1,10 +1,13 @@ -use std::fs::write; use crate::errors::UispIntegrationError; use crate::strategies::full2::GraphType; +use std::fs::write; pub fn save_dot_file(graph: &GraphType) -> Result<(), UispIntegrationError> { // Save the dot file - let dot_data = format!("{:?}", petgraph::dot::Dot::with_config(graph, &[petgraph::dot::Config::EdgeNoLabel])); + let dot_data = format!( + "{:?}", + petgraph::dot::Dot::with_config(graph, &[petgraph::dot::Config::EdgeNoLabel]) + ); let _ = write("graph.dot", dot_data.as_bytes()); let _ = std::process::Command::new("dot") .arg("-Tpng") @@ -13,4 +16,4 @@ pub fn save_dot_file(graph: &GraphType) -> Result<(), UispIntegrationError> { .arg("graph.png") .output(); Ok(()) -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/strategies/full2/graph_mapping.rs b/src/rust/uisp_integration/src/strategies/full2/graph_mapping.rs index 853a1666..1de9deb6 100644 --- a/src/rust/uisp_integration/src/strategies/full2/graph_mapping.rs +++ b/src/rust/uisp_integration/src/strategies/full2/graph_mapping.rs @@ -2,10 +2,22 @@ use serde::Serialize; #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Serialize)] pub enum GraphMapping { - Root { name: String, id: String }, - Site { name: String, id: String }, - GeneratedSite { name: String }, - AccessPoint { name: String, id: String, site_name: String }, + Root { + name: String, + id: String, + }, + Site { + name: String, + id: String, + }, + GeneratedSite { + name: String, + }, + AccessPoint { + name: String, + id: String, + site_name: String, + }, } impl GraphMapping { @@ -17,4 +29,4 @@ impl GraphMapping { GraphMapping::AccessPoint { name, .. } => name.clone(), } } -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/strategies/full2/link_mapping.rs b/src/rust/uisp_integration/src/strategies/full2/link_mapping.rs index b07356f7..161815aa 100644 --- a/src/rust/uisp_integration/src/strategies/full2/link_mapping.rs +++ b/src/rust/uisp_integration/src/strategies/full2/link_mapping.rs @@ -4,4 +4,4 @@ use serde::Serialize; pub enum LinkMapping { Ethernet, DevicePair(String, String), -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/strategies/full2/net_json_parent.rs b/src/rust/uisp_integration/src/strategies/full2/net_json_parent.rs index ceeb13e4..517acf78 100644 --- a/src/rust/uisp_integration/src/strategies/full2/net_json_parent.rs +++ b/src/rust/uisp_integration/src/strategies/full2/net_json_parent.rs @@ -1,8 +1,8 @@ +use crate::strategies::full2::GraphType; +use crate::strategies::full2::graph_mapping::GraphMapping; +use lqos_config::Config; use std::collections::HashMap; use std::sync::Arc; -use lqos_config::Config; -use crate::strategies::full2::graph_mapping::GraphMapping; -use crate::strategies::full2::GraphType; #[derive(Debug)] pub struct NetJsonParent<'a> { @@ -33,7 +33,11 @@ pub fn walk_parents( GraphMapping::GeneratedSite { .. } => { map.insert("type".into(), "Site".into()); } - GraphMapping::AccessPoint { name: _, id, site_name } => { + GraphMapping::AccessPoint { + name: _, + id, + site_name, + } => { map.insert("type".into(), "AP".into()); map.insert("parent_site".into(), site_name.clone().into()); map.insert("uisp_device".into(), id.clone().into()); @@ -41,8 +45,10 @@ pub fn walk_parents( } let mut children = serde_json::Map::new(); - for (name, node_info) in parents.iter().filter(|(_, node_info)| - node_info.parent_name == *name) { + for (name, node_info) in parents + .iter() + .filter(|(_, node_info)| node_info.parent_name == *name) + { let child = walk_parents(parents, name, &node_info, config, graph); children.insert(name.into(), child.into()); } @@ -50,4 +56,4 @@ pub fn walk_parents( map.insert("children".into(), children.into()); map -} \ No newline at end of file +} diff --git a/src/rust/uisp_integration/src/strategies/mod.rs b/src/rust/uisp_integration/src/strategies/mod.rs index 8d0e777f..38c0d240 100644 --- a/src/rust/uisp_integration/src/strategies/mod.rs +++ b/src/rust/uisp_integration/src/strategies/mod.rs @@ -1,8 +1,8 @@ -mod flat; -mod full; mod ap_only; mod ap_site; mod common; +mod flat; +mod full; mod full2; use crate::blackboard;