mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2024-11-22 08:16:25 -06:00
Add documentation and cleanup
This commit is contained in:
parent
3696c14fc9
commit
1952498ce2
@ -1,5 +1,6 @@
|
||||
use thiserror::Error;
|
||||
|
||||
/// Error types for UISP Integration
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
pub enum UispIntegrationError {
|
||||
#[error("Unable to load configuration")]
|
||||
|
@ -5,12 +5,16 @@ use lqos_config::Config;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use tracing::info;
|
||||
|
||||
/// Represents a set of IP ranges that are allowed or ignored.
|
||||
pub struct IpRanges {
|
||||
/// The allowed IP ranges
|
||||
allowed: IpNetworkTable<bool>,
|
||||
/// The ignored IP ranges
|
||||
ignored: IpNetworkTable<bool>,
|
||||
}
|
||||
|
||||
impl IpRanges {
|
||||
/// Creates a new IpRanges from a configuration.
|
||||
pub fn new(config: &Config) -> Result<Self, UispIntegrationError> {
|
||||
info!("Building allowed/excluded IP range lookups from configuration file");
|
||||
|
||||
@ -54,6 +58,7 @@ impl IpRanges {
|
||||
Ok(Self { allowed, ignored })
|
||||
}
|
||||
|
||||
/// Checks if an IP address is permitted.
|
||||
pub fn is_permitted(&self, ip: IpAddr) -> bool {
|
||||
if let Some(_allow) = self.allowed.longest_match(ip) {
|
||||
if let Some(_deny) = self.ignored.longest_match(ip) {
|
||||
|
@ -2,6 +2,8 @@
|
||||
//! be ported back to Python, with Rust support structures - but I'll iterate
|
||||
//! faster in Rust.
|
||||
|
||||
#[warn(missing_docs)]
|
||||
|
||||
mod errors;
|
||||
pub mod ip_ranges;
|
||||
mod strategies;
|
||||
|
@ -7,6 +7,7 @@ use std::fs;
|
||||
use std::path::Path;
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Represents a shaped device in the ShapedDevices.csv file.
|
||||
#[derive(Serialize, Debug)]
|
||||
struct ShapedDevice {
|
||||
pub circuit_id: String,
|
||||
@ -24,6 +25,11 @@ struct ShapedDevice {
|
||||
pub comment: String,
|
||||
}
|
||||
|
||||
/// Builds a flat network for UISP
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config` - The configuration
|
||||
/// * `ip_ranges` - The IP ranges to use for the network
|
||||
pub async fn build_flat_network(
|
||||
config: Config,
|
||||
ip_ranges: IpRanges,
|
||||
|
@ -4,6 +4,16 @@ use std::collections::HashSet;
|
||||
use tracing::info;
|
||||
use uisp::{DataLink, Device, Site};
|
||||
|
||||
/// Finds access points that are connected to other sites and promotes them to their own site.
|
||||
/// This is useful for sites that have multiple APs, but are currently represented as a single site.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites to modify
|
||||
/// * `devices_raw` - The list of devices
|
||||
/// * `data_links_raw` - The list of data links
|
||||
/// * `sites_raw` - The list of sites
|
||||
/// * `devices` - The list of devices with their speeds
|
||||
/// * `config` - The configuration
|
||||
pub fn promote_access_points(
|
||||
sites: &mut Vec<UispSite>,
|
||||
devices_raw: &[Device],
|
||||
|
@ -10,6 +10,26 @@ pub type BandwidthOverrides = HashMap<String, (f32, f32)>;
|
||||
|
||||
/// Attempts to load integrationUISPbandwidths.csv to use for
|
||||
/// bandwidth overrides. Returns an empty set if not found.
|
||||
/// Returns an error if the file is found but cannot be read.
|
||||
///
|
||||
/// The file should be a CSV with the following columns:
|
||||
///
|
||||
/// | Parent Node | Down | Up |
|
||||
/// |-------------|------|----|
|
||||
/// | Site1 | 100 | 10 |
|
||||
/// | Site2 | 200 | 20 |
|
||||
///
|
||||
/// The Parent Node should match the name of the site in UISP.
|
||||
/// The Down and Up columns should be the desired bandwidth in Mbps.
|
||||
///
|
||||
/// If the file is found, the overrides will be applied to the sites
|
||||
/// in the `UispSite` array by the `apply_bandwidth_overrides` function.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config` - The configuration
|
||||
///
|
||||
/// # Returns
|
||||
/// * A `BandwidthOverrides` map of site names to bandwidth overrides
|
||||
pub fn get_site_bandwidth_overrides(
|
||||
config: &Config,
|
||||
) -> Result<BandwidthOverrides, UispIntegrationError> {
|
||||
@ -69,6 +89,11 @@ fn numeric_string_to_f32(text: &str) -> Option<f32> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the bandwidth overrides to the sites in the array.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites to modify
|
||||
/// * `bandwidth_overrides` - The bandwidth overrides to apply
|
||||
pub fn apply_bandwidth_overrides(sites: &mut [UispSite], bandwidth_overrides: &BandwidthOverrides) {
|
||||
for site in sites.iter_mut() {
|
||||
if let Some((up, down)) = bandwidth_overrides.get(&site.name) {
|
||||
@ -82,3 +107,26 @@ pub fn apply_bandwidth_overrides(sites: &mut [UispSite], bandwidth_overrides: &B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_numeric_string_to_f32_valid_float() {
|
||||
let result = numeric_string_to_f32("3.14");
|
||||
assert_eq!(result, Some(3.14));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_numeric_string_to_f32_valid_integer() {
|
||||
let result = numeric_string_to_f32("42");
|
||||
assert_eq!(result, Some(42.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_numeric_string_to_f32_invalid_string() {
|
||||
let result = numeric_string_to_f32("abc");
|
||||
assert_eq!(result, None);
|
||||
}
|
||||
}
|
@ -3,6 +3,15 @@ use crate::uisp_types::{UispSite, UispSiteType};
|
||||
use std::collections::HashSet;
|
||||
use tracing::info;
|
||||
|
||||
/// Promotes client sites with multiple child sites to a new site type.
|
||||
/// This is useful for sites that have multiple child sites, but are currently represented as a single site.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites to modify
|
||||
///
|
||||
/// # Returns
|
||||
/// * An `Ok` if the operation was successful
|
||||
/// * An `Err` if the operation failed
|
||||
pub fn promote_clients_with_children(
|
||||
sites: &mut Vec<UispSite>,
|
||||
) -> Result<(), UispIntegrationError> {
|
||||
|
@ -33,6 +33,16 @@ use crate::uisp_types::{UispSite, UispSiteType};
|
||||
use lqos_config::Config;
|
||||
|
||||
/// Attempt to construct a full hierarchy topology for the UISP network.
|
||||
/// This function will load the UISP data, parse it into a more usable format,
|
||||
/// and then attempt to build a full network topology.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config` - The configuration
|
||||
/// * `ip_ranges` - The IP ranges to use for the network
|
||||
///
|
||||
/// # Returns
|
||||
/// * An `Ok` if the operation was successful
|
||||
/// * An `Err` if the operation failed
|
||||
pub async fn build_full_network(
|
||||
config: Config,
|
||||
ip_ranges: IpRanges,
|
||||
|
@ -5,6 +5,16 @@ use std::fs::write;
|
||||
use std::path::Path;
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Writes the network.json file for UISP
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config` - The configuration
|
||||
/// * `sites` - The list of sites
|
||||
/// * `root_idx` - The index of the root site
|
||||
///
|
||||
/// # Returns
|
||||
/// * An `Ok` if the operation was successful
|
||||
/// * An `Err` if the operation failed
|
||||
pub fn write_network_file(
|
||||
config: &Config,
|
||||
sites: &[UispSite],
|
||||
|
@ -4,6 +4,17 @@ use lqos_config::Config;
|
||||
use tracing::info;
|
||||
use uisp::{DataLink, Device, Site};
|
||||
|
||||
/// Parses the UISP datasets into a more usable format.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites_raw` - The raw site data
|
||||
/// * `data_links_raw` - The raw data link data
|
||||
/// * `devices_raw` - The raw device data
|
||||
/// * `config` - The configuration
|
||||
/// * `ip_ranges` - The IP ranges to use for the network
|
||||
///
|
||||
/// # Returns
|
||||
/// * A tuple containing the parsed sites, data links, and devices
|
||||
pub fn parse_uisp_datasets(
|
||||
sites_raw: &[Site],
|
||||
data_links_raw: &[DataLink],
|
||||
|
@ -65,6 +65,12 @@ fn handle_multiple_internet_connected_sites(
|
||||
Ok(root_site_name)
|
||||
}
|
||||
|
||||
/// Sets the root site in the site list.
|
||||
/// If there are multiple root sites, it will return an error.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites
|
||||
/// * `root_site` - The name of the root site
|
||||
pub fn set_root_site(sites: &mut [UispSite], root_site: &str) -> Result<(), UispIntegrationError> {
|
||||
if let Some(root) = sites.iter_mut().find(|s| s.name == root_site) {
|
||||
root.site_type = UispSiteType::Root;
|
||||
|
@ -5,13 +5,39 @@ use serde::Deserialize;
|
||||
use std::path::Path;
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Represents a route override in the integrationUISProutes.csv file.
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct RouteOverride {
|
||||
/// The site to override the route from.
|
||||
pub from_site: String,
|
||||
/// The site to override the route to.
|
||||
pub to_site: String,
|
||||
/// The cost of the route.
|
||||
pub cost: u32,
|
||||
}
|
||||
|
||||
/// Attempts to load integrationUISProutes.csv to use for
|
||||
/// route overrides. Returns an empty set if not found.
|
||||
/// Returns an error if the file is found but cannot be read.
|
||||
///
|
||||
/// The file should be a CSV with the following columns:
|
||||
///
|
||||
/// | From Site | To Site | Cost |
|
||||
/// |-----------|---------|------|
|
||||
/// | Site1 | Site2 | 100 |
|
||||
/// | Site2 | Site3 | 200 |
|
||||
///
|
||||
/// The From Site and To Site should match the name of the site in UISP.
|
||||
///
|
||||
/// If the file is found, the overrides will be applied to the routes
|
||||
/// in the `UispSite` array by the `apply_route_overrides` function.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config` - The configuration
|
||||
///
|
||||
/// # Returns
|
||||
/// * An `Ok(Vec)` of `RouteOverride` objects
|
||||
/// * An `Err` if the file is found but cannot be read
|
||||
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() {
|
||||
|
@ -5,6 +5,7 @@ use serde::Serialize;
|
||||
use std::path::Path;
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Represents a shaped device in the ShapedDevices.csv file.
|
||||
#[derive(Serialize, Debug)]
|
||||
struct ShapedDevice {
|
||||
pub circuit_id: String,
|
||||
@ -22,6 +23,13 @@ struct ShapedDevice {
|
||||
pub comment: String,
|
||||
}
|
||||
|
||||
/// Writes the ShapedDevices.csv file for UISP
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config` - The configuration
|
||||
/// * `sites` - The list of sites
|
||||
/// * `root_idx` - The index of the root site
|
||||
/// * `devices` - The list of devices
|
||||
pub fn write_shaped_devices(
|
||||
config: &Config,
|
||||
sites: &[UispSite],
|
||||
|
@ -1,6 +1,15 @@
|
||||
use crate::errors::UispIntegrationError;
|
||||
use crate::uisp_types::{UispSite, UispSiteType};
|
||||
|
||||
/// Squashes single entry access points
|
||||
///
|
||||
/// This function will squash access points that have only one child site.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites to modify
|
||||
///
|
||||
/// # Returns
|
||||
/// * An `Ok` if the operation was successful
|
||||
pub fn squash_single_aps(sites: &mut [UispSite]) -> Result<(), UispIntegrationError> {
|
||||
let mut squashable = Vec::new();
|
||||
for (idx, site) in sites.iter().enumerate() {
|
||||
|
@ -2,6 +2,14 @@ use crate::errors::UispIntegrationError;
|
||||
use crate::strategies::full::routes_override::RouteOverride;
|
||||
use crate::uisp_types::{UispSite, UispSiteType};
|
||||
|
||||
/// Walks the tree to determine the best route for each site
|
||||
///
|
||||
/// This function will walk the tree to determine the best route for each site.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites
|
||||
/// * `root_site` - The name of the root site
|
||||
/// * `overrides` - The list of route overrides
|
||||
pub fn walk_tree_for_routing(
|
||||
sites: &mut Vec<UispSite>,
|
||||
root_site: &str,
|
||||
|
@ -46,6 +46,14 @@ fn iterate_child_sites(sites: &[UispSite], parent: usize, indent: usize) {
|
||||
});
|
||||
}
|
||||
|
||||
/// Warns if there are any sites with no parents, and promotes them to be parented off of the root
|
||||
/// site.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites
|
||||
/// * `devices_raw` - The raw device data
|
||||
/// * `root_idx` - The index of the root site
|
||||
/// * `config` - The configuration
|
||||
pub fn warn_of_no_parents_and_promote(
|
||||
sites: &mut Vec<UispSite>,
|
||||
devices_raw: &[Device],
|
||||
|
@ -1,6 +1,12 @@
|
||||
use crate::uisp_types::UispSite;
|
||||
use lqos_config::Config;
|
||||
|
||||
/// Corrects zero capacity sites by setting their capacity to the parent's capacity.
|
||||
/// If the site has no parent, the capacity is set to the default generated capacity.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `sites` - The list of sites to correct
|
||||
/// * `config` - The configuration
|
||||
pub fn correct_zero_capacity_sites(sites: &mut [UispSite], config: &Config) {
|
||||
for i in 0..sites.len() {
|
||||
if sites[i].max_down_mbps == 0 {
|
||||
|
@ -6,6 +6,7 @@ use crate::ip_ranges::IpRanges;
|
||||
use lqos_config::Config;
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Builds the network using the selected strategy.
|
||||
pub async fn build_with_strategy(
|
||||
config: Config,
|
||||
ip_ranges: IpRanges,
|
||||
|
@ -1,3 +1,4 @@
|
||||
/// Detected Access Point
|
||||
#[derive(Debug)]
|
||||
pub struct DetectedAccessPoint {
|
||||
pub site_id: String,
|
||||
|
@ -11,6 +11,10 @@ pub struct UispDataLink {
|
||||
}
|
||||
|
||||
impl UispDataLink {
|
||||
/// Converts a UISP DataLink into a UispDataLink.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `value` - The UISP DataLink to convert
|
||||
pub fn from_uisp(value: &DataLink) -> Option<Self> {
|
||||
let mut from_site_id = String::new();
|
||||
let mut to_site_id = String::new();
|
||||
|
@ -17,6 +17,12 @@ pub struct UispDevice {
|
||||
}
|
||||
|
||||
impl UispDevice {
|
||||
/// Creates a new UispDevice from a UISP device
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `device` - The device to convert
|
||||
/// * `config` - The configuration
|
||||
/// * `ip_ranges` - The IP ranges to use for the network
|
||||
pub fn from_uisp(device: &Device, config: &Config, ip_ranges: &IpRanges) -> Self {
|
||||
let mut ipv4 = HashSet::new();
|
||||
let mut ipv6 = HashSet::new();
|
||||
|
@ -40,6 +40,7 @@ impl Default for UispSite {
|
||||
}
|
||||
|
||||
impl UispSite {
|
||||
/// Converts a UISP Site into a UispSite.
|
||||
pub fn from_uisp(value: &Site, config: &Config) -> Self {
|
||||
let mut uisp_parent_id = None;
|
||||
|
||||
|
@ -28,6 +28,7 @@ impl Display for UispSiteType {
|
||||
}
|
||||
|
||||
impl UispSiteType {
|
||||
/// Converts a UISP site record into a UispSiteType
|
||||
pub fn from_uisp_record(site: &Site) -> Result<Self, UispIntegrationError> {
|
||||
if let Some(id) = &site.identification {
|
||||
if let Some(t) = &id.site_type {
|
||||
|
Loading…
Reference in New Issue
Block a user