From 7022a9dbf4d5a5cd20ffaaa31a9ee3764c952ea3 Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Tue, 14 Jan 2025 10:39:00 -0600 Subject: [PATCH 1/4] Try this: perform route building AFTER single AP squashing. This ensures that the route weights that are used match the "logical" weights. --- src/rust/uisp_integration/src/strategies/full/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/uisp_integration/src/strategies/full/mod.rs b/src/rust/uisp_integration/src/strategies/full/mod.rs index 54072ea5..6828086d 100644 --- a/src/rust/uisp_integration/src/strategies/full/mod.rs +++ b/src/rust/uisp_integration/src/strategies/full/mod.rs @@ -128,9 +128,6 @@ pub async fn build_full_network( // Do Link Squashing squash_single_aps(&mut sites)?; - // Build Path Weights - walk_tree_for_routing(&mut sites, &root_site, &routing_overrides)?; - // Apply bandwidth overrides apply_bandwidth_overrides(&mut sites, &bandwidth_overrides); @@ -140,6 +137,9 @@ pub async fn build_full_network( // Squash any sites that are in the squash list squash_squashed_sites(&mut sites, config.clone(), &root_site)?; + // Build Path Weights + walk_tree_for_routing(&mut sites, &root_site, &routing_overrides)?; + // Print Sites if let Some(root_idx) = sites.iter().position(|s| s.name == root_site) { // Issue No Parent Warnings From 0dbf0efee0f9a398b769739a8dc47688e8299b12 Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Tue, 14 Jan 2025 10:49:50 -0600 Subject: [PATCH 2/4] Output integrationUISProutes.template.csv while building the tree. --- .../src/strategies/full/mod.rs | 2 +- .../src/strategies/full/routes_override.rs | 12 ++++++++++ .../src/strategies/full/tree_walk.rs | 23 +++++++++++++++---- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/rust/uisp_integration/src/strategies/full/mod.rs b/src/rust/uisp_integration/src/strategies/full/mod.rs index 6828086d..1dc9b661 100644 --- a/src/rust/uisp_integration/src/strategies/full/mod.rs +++ b/src/rust/uisp_integration/src/strategies/full/mod.rs @@ -138,7 +138,7 @@ pub async fn build_full_network( squash_squashed_sites(&mut sites, config.clone(), &root_site)?; // Build Path Weights - walk_tree_for_routing(&mut sites, &root_site, &routing_overrides)?; + walk_tree_for_routing(config.clone(), &mut sites, &root_site, &routing_overrides)?; // Print Sites if let Some(root_idx) = sites.iter().position(|s| s.name == root_site) { diff --git a/src/rust/uisp_integration/src/strategies/full/routes_override.rs b/src/rust/uisp_integration/src/strategies/full/routes_override.rs index 2cc7bb05..8f6a85d4 100644 --- a/src/rust/uisp_integration/src/strategies/full/routes_override.rs +++ b/src/rust/uisp_integration/src/strategies/full/routes_override.rs @@ -3,6 +3,7 @@ use csv::ReaderBuilder; use lqos_config::Config; use serde::{Deserialize, Serialize}; use std::path::Path; +use std::sync::Arc; use tracing::{error, info}; /// Represents a route override in the integrationUISProutes.csv file. @@ -82,3 +83,14 @@ pub fn get_route_overrides(config: &Config) -> Result, UispIn Ok(Vec::new()) } } + +pub fn write_routing_overrides_template(config: Arc, natural_routes: &[RouteOverride]) -> anyhow::Result<()> { + let file_path = Path::new(&config.lqos_directory).join("integrationUISProutes.template.csv"); + let mut writer = csv::Writer::from_path(file_path)?; + writer.write_record(&["From Site", "To Site", "Cost"])?; + for route in natural_routes { + writer.write_record(&[&route.from_site, &route.to_site, &route.cost.to_string()])?; + } + writer.flush()?; + Ok(()) +} diff --git a/src/rust/uisp_integration/src/strategies/full/tree_walk.rs b/src/rust/uisp_integration/src/strategies/full/tree_walk.rs index 931b5bac..c11309bd 100644 --- a/src/rust/uisp_integration/src/strategies/full/tree_walk.rs +++ b/src/rust/uisp_integration/src/strategies/full/tree_walk.rs @@ -1,6 +1,8 @@ use std::io::Write; +use std::sync::Arc; +use lqos_config::Config; use crate::errors::UispIntegrationError; -use crate::strategies::full::routes_override::RouteOverride; +use crate::strategies::full::routes_override::{write_routing_overrides_template, RouteOverride}; use crate::uisp_types::{UispSite, UispSiteType}; /// Walks the tree to determine the best route for each site @@ -12,6 +14,7 @@ use crate::uisp_types::{UispSite, UispSiteType}; /// * `root_site` - The name of the root site /// * `overrides` - The list of route overrides pub fn walk_tree_for_routing( + config: Arc, sites: &mut Vec, root_site: &str, overrides: &Vec, @@ -19,8 +22,9 @@ pub fn walk_tree_for_routing( if let Some(root_idx) = sites.iter().position(|s| s.name == root_site) { let mut visited = std::collections::HashSet::new(); let current_node = root_idx; + let mut natural_weights: Vec = Vec::new(); let mut dot_graph = "digraph G {\n graph [ ranksep=2.0 overlap=false ]".to_string(); - walk_node(current_node, 10, sites, &mut visited, overrides, &mut dot_graph); + walk_node(current_node, 10, sites, &mut visited, overrides, &mut dot_graph, &mut natural_weights); dot_graph.push_str("}\n"); { let graph_file = std::fs::File::create("graph.dot"); @@ -28,6 +32,11 @@ pub fn walk_tree_for_routing( let _ = file.write_all(dot_graph.as_bytes()); } } + if let Err(e) = write_routing_overrides_template(config, &natural_weights) { + tracing::error!("Unable to write routing overrides template: {:?}", e); + } else { + tracing::info!("Wrote routing overrides template"); + } } else { tracing::error!("Unable to build a path-weights graph because I can't find the root node"); return Err(UispIntegrationError::NoRootSite); @@ -52,6 +61,7 @@ fn walk_node( visited: &mut std::collections::HashSet, overrides: &Vec, dot_graph: &mut String, + natural_weights: &mut Vec, ) { if visited.contains(&idx) { return; @@ -61,9 +71,14 @@ fn walk_node( if sites[i].parent_indices.contains(&idx) { let from = sites[i].name.clone(); let to = sites[idx].name.clone(); - if sites[idx].site_type != UispSiteType::Client + if sites[idx].site_type != UispSiteType::Client && sites[i].site_type != UispSiteType::Client { dot_graph.push_str(&format!("\"{}\" [label=\"{}\"];\n", to, to)); + natural_weights.push(RouteOverride { + from_site: from.clone(), + to_site: to.clone(), + cost: weight, + }); } if let Some(route_override) = overrides .iter() @@ -74,7 +89,7 @@ fn walk_node( } else { sites[i].route_weights.push((idx, weight)); } - walk_node(i, weight + 10, sites, visited, overrides, dot_graph); + walk_node(i, weight + 10, sites, visited, overrides, dot_graph, natural_weights); } } } From f5a26932612debcc4a5150650274e15161fc99e1 Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Wed, 15 Jan 2025 09:28:41 -0600 Subject: [PATCH 3/4] Correct routing detection error. --- src/rust/uisp_integration/src/uisp_types/uisp_data_link.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/uisp_integration/src/uisp_types/uisp_data_link.rs b/src/rust/uisp_integration/src/uisp_types/uisp_data_link.rs index 9feb6295..53234a65 100644 --- a/src/rust/uisp_integration/src/uisp_types/uisp_data_link.rs +++ b/src/rust/uisp_integration/src/uisp_types/uisp_data_link.rs @@ -19,12 +19,12 @@ impl UispDataLink { let mut from_site_id = String::new(); let mut to_site_id = String::new(); let mut to_site_name = String::new(); - let from_site_name = String::new(); + let mut from_site_name = String::new(); // Obvious Site Links if let Some(from_site) = &value.from.site { from_site_id = from_site.identification.id.clone(); - to_site_id = from_site.identification.name.clone(); + from_site_name = from_site.identification.name.clone(); } if let Some(to_site) = &value.to.site { to_site_id = to_site.identification.id.clone(); From 327ae0c46e6a436485442371a309df015c36557d Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Wed, 15 Jan 2025 09:48:18 -0600 Subject: [PATCH 4/4] DOT graph creation fixed and shows weights. --- src/rust/uisp_integration/src/strategies/full/tree_walk.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/uisp_integration/src/strategies/full/tree_walk.rs b/src/rust/uisp_integration/src/strategies/full/tree_walk.rs index c11309bd..6f18431f 100644 --- a/src/rust/uisp_integration/src/strategies/full/tree_walk.rs +++ b/src/rust/uisp_integration/src/strategies/full/tree_walk.rs @@ -23,7 +23,7 @@ pub fn walk_tree_for_routing( let mut visited = std::collections::HashSet::new(); let current_node = root_idx; let mut natural_weights: Vec = Vec::new(); - let mut dot_graph = "digraph G {\n graph [ ranksep=2.0 overlap=false ]".to_string(); + let mut dot_graph = "digraph G {\n graph [ ranksep=2.0 overlap=false ]\n".to_string(); walk_node(current_node, 10, sites, &mut visited, overrides, &mut dot_graph, &mut natural_weights); dot_graph.push_str("}\n"); { @@ -73,7 +73,7 @@ fn walk_node( let to = sites[idx].name.clone(); if sites[idx].site_type != UispSiteType::Client && sites[i].site_type != UispSiteType::Client { - dot_graph.push_str(&format!("\"{}\" [label=\"{}\"];\n", to, to)); + dot_graph.push_str(&format!("\"{}\" -> \"{}\" [label=\"{}\"] \n", from, to, weight)); natural_weights.push(RouteOverride { from_site: from.clone(), to_site: to.clone(),