Cleanup: cargo fmt run

This commit is contained in:
Herbert Wolverson committed 2025-04-08 08:51:45 -05:00
1 parent 60d8a3dfe6
commit bebba9def0
11 files changed
+332 -177

No files matched your search

+2 -2
View File
@@ -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<T: Serialize>(key: &str, value: T) -> anyhow::Resul
let _ = lqos_bus::bus_request(req).await;
}
Ok(())
}
}
+2 -3
View File
@@ -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();
@@ -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::<Vec<_>>();
let devices = uisp_data
.devices
.iter()
.filter(|d| d.site_id == *client_id)
.collect::<Vec<_>>();
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(())
}
}
@@ -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<Config>, shaped_devices: &mut Vec<ShapedDevice>) -> Result<(), UispIntegrationError> {
pub(crate) fn write_shaped_devices(
config: &Arc<Config>,
shaped_devices: &mut Vec<ShapedDevice>,
) -> 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<Config>, shaped_devices: &mut Ve
Ok(())
}
pub(crate) fn map_sites_above_aps(uisp_data: &UispData, ap_mappings: HashMap<String, Vec<String>>, access_points: HashMap<String, Layer>) -> HashMap<String, Layer> {
pub(crate) fn map_sites_above_aps(
uisp_data: &UispData,
ap_mappings: HashMap<String, Vec<String>>,
access_points: HashMap<String, Layer>,
) -> HashMap<String, Layer> {
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::<Vec<_>>();
let devices = uisp_data
.devices
.iter()
.filter(|d| d.site_id == *client_id)
.collect::<Vec<_>>();
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<String>,
}
pub(crate) async fn find_troublesome_sites(
data: &UispData,
) -> anyhow::Result<TroublesomeClients> {
pub(crate) async fn find_troublesome_sites(data: &UispData) -> anyhow::Result<TroublesomeClients> {
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<HashSet<String>> {
fn find_clients_with_multiple_entry_points(data: &UispData) -> anyhow::Result<HashSet<String>> {
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<HashSet<String>> {
fn find_clients_linked_from_other_clients(data: &UispData) -> anyhow::Result<HashSet<String>> {
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)
}
}
@@ -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<Site>,
@@ -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<String, Vec<String>> {
@@ -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
}
}
+159 -84
View File
@@ -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<GraphMapping, LinkMapping, Undirected>;
@@ -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::<String, usize>::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<GraphMapping, LinkMapping, Undirected>, device_map: &mut HashMap<String, NodeIndex>) {
fn add_device_links_to_graph(
uisp_data: &UispData,
graph: &mut Graph<GraphMapping, LinkMapping, Undirected>,
device_map: &mut HashMap<String, NodeIndex>,
) {
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<GraphMappin
// If the devices are the same, we don't need to add an edge
continue;
}
if let Some(dev_a) = uisp_data.devices_raw.iter().find(|d| d.get_id() == from_device.identification.id) {
if let Some(dev_b) = uisp_data.devices_raw.iter().find(|d| d.get_id() == to_device.identification.id) {
if dev_a.get_site_id().unwrap_or_default() == dev_b.get_site_id().unwrap_or_default() {
if let Some(dev_a) = uisp_data
.devices_raw
.iter()
.find(|d| d.get_id() == from_device.identification.id)
{
if let Some(dev_b) = uisp_data
.devices_raw
.iter()
.find(|d| d.get_id() == to_device.identification.id)
{
if dev_a.get_site_id().unwrap_or_default()
== dev_b.get_site_id().unwrap_or_default()
{
// If the devices are in the same site, we don't need to add an edge
continue;
}
@@ -315,11 +362,23 @@ fn add_device_links_to_graph(uisp_data: &UispData, graph: &mut Graph<GraphMappin
// If the edge already exists, we don't need to add it
continue;
}
graph.add_edge(*a_ref, *b_ref, LinkMapping::DevicePair(from_device.identification.id.clone(), to_device.identification.id.clone()));
graph.add_edge(
*a_ref,
*b_ref,
LinkMapping::DevicePair(
from_device.identification.id.clone(),
to_device.identification.id.clone(),
),
);
}
}
fn add_devices_to_graph(uisp_data: &UispData, graph: &mut Graph<GraphMapping, LinkMapping, Undirected>, site_map: &mut HashMap<String, NodeIndex>, device_map: &mut HashMap<String, NodeIndex>) {
fn add_devices_to_graph(
uisp_data: &UispData,
graph: &mut Graph<GraphMapping, LinkMapping, Undirected>,
site_map: &mut HashMap<String, NodeIndex>,
device_map: &mut HashMap<String, NodeIndex>,
) {
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<GraphMapping, Li
}
}
pub fn add_all_sites_to_graph(uisp_data: &UispData, graph: &mut Graph<GraphMapping, LinkMapping, Undirected>, root_site_name: &String, site_map: &mut HashMap<String, NodeIndex>, root_idx: &mut Option<NodeIndex>) {
pub fn add_all_sites_to_graph(
uisp_data: &UispData,
graph: &mut Graph<GraphMapping, LinkMapping, Undirected>,
root_site_name: &String,
site_map: &mut HashMap<String, NodeIndex>,
root_idx: &mut Option<NodeIndex>,
) {
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<GraphMappi
}
}
fn link_capacity_mbps(link_mapping: &LinkMapping, devices: &[UispDevice], route_overrides: &[RouteOverride]) -> 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;
@@ -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(())
}
}
@@ -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(),
}
}
}
}
@@ -4,4 +4,4 @@ use serde::Serialize;
pub enum LinkMapping {
Ethernet,
DevicePair(String, String),
}
}
@@ -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
}
}
@@ -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;