mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Support routing overrides
This commit is contained in:
parent
6cd3993a34
commit
d7181a663d
@ -3,15 +3,16 @@ use std::path::Path;
|
||||
use csv::ReaderBuilder;
|
||||
use tracing::{error, info};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use lqos_config::Config;
|
||||
use crate::errors::UispIntegrationError;
|
||||
|
||||
pub type BandwidthOverrides = HashMap<String, (f32, f32)>;
|
||||
|
||||
/// Attempts to load integrationUISPbandwidths.csv to use for
|
||||
/// bandwidth overrides. Returns an empty set if not found.
|
||||
pub fn get_site_bandwidth_overrides() -> Result<BandwidthOverrides, UispIntegrationError> {
|
||||
pub fn get_site_bandwidth_overrides(config: &Config) -> Result<BandwidthOverrides, UispIntegrationError> {
|
||||
info!("Looking for integrationUISPbandwidths.csv");
|
||||
let file_path = Path::new("integrationUISPbandwidths.csv");
|
||||
let file_path = Path::new(&config.lqos_directory).join("integrationUISPbandwidths.csv");
|
||||
if file_path.exists() {
|
||||
let reader = ReaderBuilder::new()
|
||||
.comment(Some(b'#'))
|
||||
|
@ -7,6 +7,7 @@ mod tree_walk;
|
||||
mod uisp_fetch;
|
||||
mod utils;
|
||||
mod bandwidth_overrides;
|
||||
mod routes_override;
|
||||
|
||||
use crate::errors::UispIntegrationError;
|
||||
use crate::strategies::full::ap_promotion::promote_access_points;
|
||||
@ -21,11 +22,15 @@ use crate::uisp_types::UispSite;
|
||||
use lqos_config::Config;
|
||||
use crate::strategies::full::bandwidth_overrides::get_site_bandwidth_overrides;
|
||||
pub use bandwidth_overrides::BandwidthOverrides;
|
||||
use crate::strategies::full::routes_override::get_route_overrides;
|
||||
|
||||
/// Attempt to construct a full hierarchy topology for the UISP network.
|
||||
pub async fn build_full_network(config: Config) -> Result<(), UispIntegrationError> {
|
||||
// Load any bandwidth overrides
|
||||
let bandwidth_overrides = get_site_bandwidth_overrides()?;
|
||||
let bandwidth_overrides = get_site_bandwidth_overrides(&config)?;
|
||||
|
||||
// Load any routing overrrides
|
||||
let routing_overrides = get_route_overrides(&config)?;
|
||||
|
||||
// Obtain the UISP data and transform it into easier to work with types
|
||||
let (sites_raw, devices_raw, data_links_raw) = load_uisp_data(config.clone()).await?;
|
||||
@ -55,7 +60,7 @@ pub async fn build_full_network(config: Config) -> Result<(), UispIntegrationErr
|
||||
squash_single_aps(&mut sites)?;
|
||||
|
||||
// Build Path Weights
|
||||
walk_tree_for_routing(&mut sites, &root_site)?;
|
||||
walk_tree_for_routing(&mut sites, &root_site, &routing_overrides)?;
|
||||
|
||||
// Issue No Parent Warnings
|
||||
warn_of_no_parents(&sites, &devices_raw);
|
||||
@ -67,21 +72,3 @@ pub async fn build_full_network(config: Config) -> Result<(), UispIntegrationErr
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn walk_node(
|
||||
idx: usize,
|
||||
weight: u32,
|
||||
sites: &mut Vec<UispSite>,
|
||||
visited: &mut std::collections::HashSet<usize>,
|
||||
) {
|
||||
if visited.contains(&idx) {
|
||||
return;
|
||||
}
|
||||
visited.insert(idx);
|
||||
for i in 0..sites.len() {
|
||||
if sites[i].parent_indices.contains(&idx) {
|
||||
sites[i].route_weights.push((idx, weight));
|
||||
walk_node(i, weight + 10, sites, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
use std::path::Path;
|
||||
use csv::ReaderBuilder;
|
||||
use serde::Deserialize;
|
||||
use tracing::{error, info};
|
||||
use lqos_config::Config;
|
||||
use crate::errors::UispIntegrationError;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct RouteOverride {
|
||||
pub from_site: String,
|
||||
pub to_site: String,
|
||||
pub cost: u32,
|
||||
}
|
||||
|
||||
pub fn get_route_overrides(config: &Config) -> Result<Vec<RouteOverride>, UispIntegrationError> {
|
||||
let file_path = Path::new(&config.lqos_directory).join("integrationUISProutes.csv");
|
||||
if file_path.exists() {
|
||||
let reader = ReaderBuilder::new()
|
||||
.comment(Some(b'#'))
|
||||
.trim(csv::Trim::All)
|
||||
.from_path(file_path);
|
||||
if reader.is_err() {
|
||||
error!("Unable to read integrationUISProutes.csv");
|
||||
error!("{:?}", reader);
|
||||
return Err(UispIntegrationError::CsvError);
|
||||
}
|
||||
let mut reader = reader.unwrap();
|
||||
let mut overrides = Vec::new();
|
||||
for result in reader.deserialize::<RouteOverride>() {
|
||||
if let Ok(result) = result {
|
||||
overrides.push(result);
|
||||
}
|
||||
}
|
||||
info!("Loaded {} route overrides", overrides.len());
|
||||
Ok(overrides)
|
||||
} else {
|
||||
info!("No integrationUISProutes.csv found - no route overrides loaded.");
|
||||
Ok(Vec::new())
|
||||
}
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
use crate::errors::UispIntegrationError;
|
||||
use crate::strategies::full::walk_node;
|
||||
use crate::strategies::full::routes_override::RouteOverride;
|
||||
use crate::uisp_types::{UispSite, UispSiteType};
|
||||
|
||||
pub fn walk_tree_for_routing(
|
||||
sites: &mut Vec<UispSite>,
|
||||
root_site: &str,
|
||||
overrides: &Vec<RouteOverride>,
|
||||
) -> Result<(), UispIntegrationError> {
|
||||
if let Some(root_idx) = sites.iter().position(|s| s.name == root_site) {
|
||||
let mut visited = std::collections::HashSet::new();
|
||||
let mut current_node = root_idx;
|
||||
walk_node(current_node, 10, sites, &mut visited);
|
||||
walk_node(current_node, 10, sites, &mut visited, overrides);
|
||||
} else {
|
||||
tracing::error!("Unable to build a path-weights graph because I can't find the root node");
|
||||
return Err(UispIntegrationError::NoRootSite);
|
||||
@ -26,3 +27,28 @@ pub fn walk_tree_for_routing(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn walk_node(
|
||||
idx: usize,
|
||||
weight: u32,
|
||||
sites: &mut Vec<UispSite>,
|
||||
visited: &mut std::collections::HashSet<usize>,
|
||||
overrides: &Vec<RouteOverride>,
|
||||
) {
|
||||
if visited.contains(&idx) {
|
||||
return;
|
||||
}
|
||||
visited.insert(idx);
|
||||
for i in 0..sites.len() {
|
||||
if sites[i].parent_indices.contains(&idx) {
|
||||
let from = sites[i].name.clone();
|
||||
let to = sites[idx].name.clone();
|
||||
if let Some(route_override) = overrides.iter().find(|o| o.from_site == from && o.to_site == to) {
|
||||
sites[i].route_weights.push((idx, route_override.cost));
|
||||
} else {
|
||||
sites[i].route_weights.push((idx, weight));
|
||||
}
|
||||
walk_node(i, weight + 10, sites, visited, overrides);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user