mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2026-10-31 16:37:42 -05:00
fix: reject conflicting duplicate circuit rows
This commit is contained in:
1 parent
67d8e9c3b5
commit
95edbe8a11
1 file changed
+89
@@ -541,6 +541,32 @@ fn resolve_effective_parent_from_anchor(
|
||||
None
|
||||
}
|
||||
|
||||
fn duplicate_circuit_shape_conflicts(
|
||||
circuit: &TopologyShapingCircuitInput,
|
||||
device: &lqos_config::ShapedDevice,
|
||||
) -> Vec<&'static str> {
|
||||
let mut conflicts = Vec::new();
|
||||
if circuit.download_min_mbps != device.download_min_mbps {
|
||||
conflicts.push("Download Min Mbps");
|
||||
}
|
||||
if circuit.upload_min_mbps != device.upload_min_mbps {
|
||||
conflicts.push("Upload Min Mbps");
|
||||
}
|
||||
if circuit.download_max_mbps != device.download_max_mbps {
|
||||
conflicts.push("Download Max Mbps");
|
||||
}
|
||||
if circuit.upload_max_mbps != device.upload_max_mbps {
|
||||
conflicts.push("Upload Max Mbps");
|
||||
}
|
||||
if circuit.comment != device.comment {
|
||||
conflicts.push("Comment");
|
||||
}
|
||||
if circuit.sqm_override != device.sqm_override {
|
||||
conflicts.push("sqm");
|
||||
}
|
||||
conflicts
|
||||
}
|
||||
|
||||
fn ipv4_with_prefix_to_string(entry: &(std::net::Ipv4Addr, u32)) -> String {
|
||||
if entry.1 >= 32 {
|
||||
entry.0.to_string()
|
||||
@@ -879,6 +905,14 @@ fn build_shaping_inputs(
|
||||
device.circuit_id
|
||||
));
|
||||
}
|
||||
let conflicts = duplicate_circuit_shape_conflicts(circuit, device);
|
||||
if !conflicts.is_empty() {
|
||||
errors.push(format!(
|
||||
"Circuit '{}' had conflicting circuit-level fields across ShapedDevices.csv rows while building shaping_inputs.json: {}.",
|
||||
device.circuit_id,
|
||||
conflicts.join(", ")
|
||||
));
|
||||
}
|
||||
index
|
||||
} else {
|
||||
let index = circuits.len();
|
||||
@@ -5818,6 +5852,61 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shaping_inputs_reject_duplicate_circuit_shape_conflicts() {
|
||||
let lqos_directory = unique_temp_dir("lqos-topology-duplicate-circuit-shape");
|
||||
let config = Config {
|
||||
lqos_directory: lqos_directory.to_string_lossy().to_string(),
|
||||
state_directory: None,
|
||||
..Config::default()
|
||||
};
|
||||
fs::write(
|
||||
lqos_directory.join("ShapedDevices.csv"),
|
||||
concat!(
|
||||
"Circuit ID,Circuit Name,Device ID,Device Name,Parent Node,Parent Node ID,Anchor Node ID,MAC,IPv4,IPv6,Download Min Mbps,Upload Min Mbps,Download Max Mbps,Upload Max Mbps,Comment,sqm\n",
|
||||
"\"circuit-1\",\"Circuit 1\",\"device-1\",\"Device 1\",\"Tower 1\",\"tower-1\",\"\",\"aa:bb:cc:dd:ee:01\",\"192.0.2.10/32\",\"\",\"10\",\"10\",\"100\",\"100\",\"first\",\"cake\"\n",
|
||||
"\"circuit-1\",\"Circuit 1\",\"device-2\",\"Device 2\",\"Tower 1\",\"tower-1\",\"\",\"aa:bb:cc:dd:ee:02\",\"192.0.2.11/32\",\"\",\"20\",\"30\",\"200\",\"300\",\"second\",\"fq_codel\"\n",
|
||||
),
|
||||
)
|
||||
.expect("ShapedDevices.csv should write");
|
||||
|
||||
let artifacts = EffectiveTopologyArtifacts {
|
||||
effective: TopologyEffectiveStateFile {
|
||||
schema_version: 1,
|
||||
generated_unix: Some(1),
|
||||
canonical_generated_unix: Some(1),
|
||||
health_generated_unix: Some(1),
|
||||
nodes: Vec::new(),
|
||||
},
|
||||
ui_state: TopologyEditorStateFile {
|
||||
schema_version: 1,
|
||||
source: "test".to_string(),
|
||||
generated_unix: Some(1),
|
||||
ingress_identity: None,
|
||||
nodes: Vec::new(),
|
||||
},
|
||||
effective_network: Some(json!({
|
||||
"Tower 1": {
|
||||
"id": "tower-1",
|
||||
"name": "Tower 1",
|
||||
"children": {}
|
||||
}
|
||||
})),
|
||||
};
|
||||
|
||||
let err = build_shaping_inputs(&config, &artifacts)
|
||||
.expect_err("duplicate circuit conflicts should fail shaping inputs");
|
||||
let message = err.to_string();
|
||||
|
||||
assert!(message.contains("conflicting circuit-level fields"));
|
||||
assert!(message.contains("Download Min Mbps"));
|
||||
assert!(message.contains("Upload Min Mbps"));
|
||||
assert!(message.contains("Download Max Mbps"));
|
||||
assert!(message.contains("Upload Max Mbps"));
|
||||
assert!(message.contains("Comment"));
|
||||
assert!(message.contains("sqm"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shaping_inputs_resolve_legacy_parent_against_exported_effective_tree() {
|
||||
let lqos_directory = unique_temp_dir("lqos-topology-legacy-parent-resolution");
|
||||
|
||||
Reference in new issue
Block a user