WIP - Basic interface and Bifrost config displayable.

This commit is contained in:
Herbert Wolverson 2023-01-05 15:03:48 +00:00
parent bff88a6386
commit 41eb47c063
7 changed files with 282 additions and 61 deletions

95
src/rust/Cargo.lock generated
View File

@ -383,6 +383,16 @@ dependencies = [
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
@ -543,6 +553,18 @@ dependencies = [
"cipher",
]
[[package]]
name = "default-net"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14e349ed1e06fb344a7dd8b5a676375cf671b31e8900075dd2be816efc063a63"
dependencies = [
"libc",
"memalloc",
"system-configuration",
"windows 0.30.0",
]
[[package]]
name = "devise"
version = "0.3.1"
@ -786,7 +808,7 @@ dependencies = [
"libc",
"log",
"rustversion",
"windows",
"windows 0.39.0",
]
[[package]]
@ -1202,6 +1224,7 @@ name = "lqos_node_manager"
version = "0.1.0"
dependencies = [
"anyhow",
"default-net",
"lazy_static",
"lqos_bus",
"lqos_config",
@ -1278,6 +1301,12 @@ dependencies = [
"regex-automata",
]
[[package]]
name = "memalloc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1"
[[package]]
name = "memchr"
version = "2.5.0"
@ -2209,6 +2238,27 @@ dependencies = [
"winapi",
]
[[package]]
name = "system-configuration"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd"
dependencies = [
"bitflags",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "target-lexicon"
version = "0.12.5"
@ -2594,6 +2644,19 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
dependencies = [
"windows_aarch64_msvc 0.30.0",
"windows_i686_gnu 0.30.0",
"windows_i686_msvc 0.30.0",
"windows_x86_64_gnu 0.30.0",
"windows_x86_64_msvc 0.30.0",
]
[[package]]
name = "windows"
version = "0.39.0"
@ -2628,6 +2691,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
[[package]]
name = "windows_aarch64_msvc"
version = "0.39.0"
@ -2640,6 +2709,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
[[package]]
name = "windows_i686_gnu"
version = "0.39.0"
@ -2652,6 +2727,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
[[package]]
name = "windows_i686_msvc"
version = "0.39.0"
@ -2664,6 +2745,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.39.0"
@ -2682,6 +2769,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.39.0"

View File

@ -1,15 +1,15 @@
use std::path::Path;
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use anyhow::{Result, Error};
#[derive(Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct EtcLqos {
pub lqos_directory: String,
pub bridge: Option<BridgeConfig>,
pub tuning: Option<Tunables>,
}
#[derive(Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Tunables {
pub stop_irq_balance: bool,
pub netdev_budget_usecs: u32,
@ -21,21 +21,21 @@ pub struct Tunables {
pub disable_offload: Vec<String>,
}
#[derive(Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BridgeConfig {
pub use_kernel_bridge: bool,
pub interface_mapping: Vec<BridgeInterface>,
pub vlan_mapping: Vec<BridgeVlan>,
}
#[derive(Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BridgeInterface {
pub name: String,
pub scan_vlans: bool,
pub redirect_to: String,
}
#[derive(Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BridgeVlan {
pub parent: String,
pub tag: u32,

View File

@ -1,7 +1,9 @@
use anyhow::{Error, Result};
use serde::{Serialize, Deserialize};
use std::{fs, path::{Path, PathBuf}};
use crate::etc;
#[derive(Serialize, Deserialize, Debug)]
pub struct LibreQoSConfig {
pub internet_interface: String,
pub isp_interface: String,

View File

@ -17,3 +17,4 @@ lqos_config = { path = "../lqos_config" }
anyhow = "1"
sysinfo = "0"
notify = { version = "5.0.0", default-features = false, feature=["macos_kqueue"] } # Not using crossbeam because of Tokio
default-net = "0"

View File

@ -1,9 +1,43 @@
use rocket::fs::NamedFile;
use crate::cache_control::{LongCache, NoCache};
use default_net::get_interfaces;
use lqos_config::{LibreQoSConfig, EtcLqos};
use rocket::{fs::NamedFile, serde::json::Json};
use crate::cache_control::NoCache;
// Note that NoCache can be replaced with a cache option
// once the design work is complete.
#[get("/config")]
pub async fn config_page<'a>() -> NoCache<Option<NamedFile>> {
NoCache::new(NamedFile::open("static/config.html").await.ok())
}
#[get("/api/list_nics")]
pub async fn get_nic_list<'a>() -> NoCache<Json<Vec<(String, String, String)>>> {
let mut result = Vec::new();
for eth in get_interfaces().iter() {
let mac = if let Some(mac) = &eth.mac_addr {
mac.to_string()
} else {
String::new()
};
result.push((
eth.name.clone(),
format!("{:?}", eth.if_type),
mac,
));
}
NoCache::new(Json(result))
}
#[get("/api/python_config")]
pub async fn get_current_python_config() -> NoCache<Json<LibreQoSConfig>> {
let config = lqos_config::LibreQoSConfig::load().unwrap();
println!("{:#?}", config);
NoCache::new(Json(config))
}
#[get("/api/lqosd_config")]
pub async fn get_current_lqosd_config() -> NoCache<Json<EtcLqos>> {
let config = lqos_config::EtcLqos::load().unwrap();
println!("{:#?}", config);
NoCache::new(Json(config))
}

View File

@ -49,6 +49,9 @@ fn rocket() -> _ {
unknown_devices::unknown_devices_range,
queue_info::raw_queue_by_circuit,
queue_info::run_btest,
config_control::get_nic_list,
config_control::get_current_python_config,
config_control::get_current_lqosd_config,
// Supporting files
static_pages::bootsrap_css,

View File

@ -55,6 +55,14 @@
<div class="card bg-light">
<div class="card-body">
<h5 class="card-title"><i class="fa fa-users"></i> Configuration</h5>
<div class="col-sm-8 mx-auto" style="padding: 4px; margin-bottom: 4px;">
<a href="#" class="btn btn-primary"><i class="fa fa-save"></i> Save ispConfig.py</a>&nbsp;
<a href="#" class="btn btn-danger"><i class="fa fa-save"></i> Save /etc/lqos</a>&nbsp;
<a href="#" class="btn btn-primary"><i class="fa fa-refresh"></i> Reload LibreQoS</a>&nbsp;
<a href="#" class="btn btn-danger"><i class="fa fa-refresh"></i> (Re)Start lqosd</a>
</div>
<div class="d-flex align-items-start">
<div class="nav flex-column nav-pills me-3" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<button class="nav-link active" id="v-pills-home-tab" data-bs-toggle="pill" data-bs-target="#v-pills-home" type="button" role="tab" aria-controls="v-pills-home" aria-selected="true"><i class="fa fa-wifi"></i> Network</button>
@ -68,72 +76,78 @@
<div class="tab-pane fade show active" id="v-pills-home" role="tabpanel" aria-labelledby="v-pills-home-tab">
<h2><i class="fa fa-wifi"></i> Network Settings</h2>
<p>
Setup the basic network interface configuration.
</p>
<h3>Network Interface (NIC) Designation</h3>
<div class="alert alert-info" role="alert">
<p>
For normal operation, you need one NIC port facing the Internet, and a second facing your core router.
If you are operating in "on a stick" mode (with a single NIC, and VLANs for inbound and outbound),
select the same NIC for both directions.
</p>
</div>
<table class="table">
<tr>
<td colspan="2">Setup the basic network interface configuration.</td>
</tr>
<tr>
<td colspan="2" class="alert alert-info" role="alert">
<i class="fa fa-info"></i> For normal operation, you need one NIC port facing the Internet, and a second facing your core router.
If you are operating in "on a stick" mode (with a single NIC, and VLANs for inbound and outbound),
select the same NIC for both directions.
</td>
</tr>
<tr>
<td>Interface facing your core router</td>
<td>...</td>
<td><select id="nicCore"></option></td>
</tr>
<tr>
<td>Interface facing the Internet</td>
<td>...</td>
<td><select id="nicInternet"></option></td>
</tr>
</table>
<h3>Shaper "On A Stick" Configuration</h3>
<div class="alert alert-info" role="alert">
<p>
"On a stick" mode allows you to operate with a single NIC, with one VLAN
containing inbound traffic and the other outbound. Please refer to the
documentation.
</p>
</div>
<table class="table">
<tr>
<td>Enable "on a stick" mode?</td>
<td>...</td>
<td colspan="2"><h3>Single-Interface ("On A Stick") Configuration</td>
</tr>
<tr>
<td colspan="2" class="alert alert-info" role="alert">
<i class="fa fa-info"></i> "On a stick" mode allows you to operate with a single NIC, with one VLAN
containing inbound traffic and the other outbound. Please refer to the
documentation.
</td>
</tr>
<tr colspan="2">
<td>
<input class="form-check-input" type="checkbox" value="" id="onAStick">
<label class="form-check-label" for="onAStick">
Enable Single-Interface ("on a stick") mode?
</label>
</td>
</tr>
<tr>
<td>VLAN facing your core router</td>
<td>...</td>
<td>
<input class="form-input" type="number" min="0" max="4094" id="StickVLANCore" />
</td>
</tr>
<tr>
<td>VLAN facing the Internet</td>
<td>...</td>
</tr>
</table>
<h3>BiFrost XDP-Accelerated Bridge</h3>
<div class="alert alert-warning" role="alert">
<p>
Bifrost is an experimental feature at this time. Bifrost XDP allows you to bypass the entire
Linux bridge system, and use XDP to bridge directly between interfaces or VLANs. This can result
in significant performance improvements on NICs that support XDP in "driver" mode.
</p>
</div>
<table class="table">
<tr>
<td>Enable Bifrost?</td>
<td>...</td>
<td>
<input class="form-input" type="number" min="0" max="4094" id="StickVLANInternet" />
</td>
</tr>
<tr>
<td>Interface Mappings</td>
<td>...</td>
<td colspan="2"><h3>Bifrost XDP-Accelerated Bridge</h3></td>
</tr>
<tr>
<td>VLAN Mappings</td>
<td>...</td>
<td colspan="2" class="alert alert-warning" role="alert">
<i class="fa fa-warning"></i> Bifrost is an experimental feature at this time. Bifrost XDP allows you to bypass the entire
Linux bridge system, and use XDP to bridge directly between interfaces or VLANs. This can result
in significant performance improvements on NICs that support XDP in "driver" mode.
</td>
</tr>
<tr>
<td colspan="2">
<input class="form-check-input" type="checkbox" value="" id="useKernelBridge">
<label class="form-check-label" for="useKernelBridge">
Enable Bifrost Acceleration
</label>
</td>
</tr>
<tr>
<td id="bifrostInterfaces" colspan="2">Interface Mapping</td>
</tr>
<tr>
<td id="bifrostVlans" colspan="2">VLAN Mapping</td>
</tr>
</table>
</div>
@ -199,7 +213,7 @@
<h2><i class="fa fa-server"></i> Server Settings</h2>
<table class="table">
<tr>
<td colspan="2" class="alert-warning">
<td colspan="2" class="alert-danger">
Disabling actual shell commands stops LibreQoS from actually doing anything. Simulated
output is logged to the console and text files, allowing for debugging.
</td>
@ -209,7 +223,7 @@
<td>...</td>
</tr>
<tr>
<td colspan="2" class="alert-warning">
<td colspan="2" class="alert-danger">
Running shell commands with "sudo" isn't necessary on a default configuration.
</td>
</tr>
@ -230,7 +244,7 @@
</table>
</div>
<div class="tab-pane fade" id="v-pills-tuning" role="tabpanel" aria-labelledby="v-pills-tuning-tab">
<h2>Tuning Settings</h2>
<h2><i class="fa fa-warning"></i> Tuning Settings</h2>
<div class="alert alert-danger" role="alert">
<i class="fa fa-warning"></i> <strong>DANGER</strong>
<p>These settings can drastically affect performance of your server, including rendering it non-functional.</p>
@ -259,10 +273,84 @@
<footer>Copyright (c) 2022, LibreQoE LLC</footer>
<script>
let python_config = null;
let nics = null;
let lqosd_config = null;
function start() {
colorReloadButton();
updateHostCounts();
$.get("/api/python_config", (data) => {
python_config = data;
$.get("/api/lqosd_config", (data) => {
lqosd_config = data;
$.get("/api/list_nics", (data) => {
nics = data;
console.log(nics);
fillNicList("nicCore", python_config.isp_interface);
fillNicList("nicInternet", python_config.internet_interface);
$("#onAStick").prop('checked', python_config.on_a_stick_mode);
$("#StickVLANCore").val(python_config.stick_vlans[0]);
$("#StickVLANInternet").val(python_config.stick_vlans[1]);
if (lqosd_config.bridge != null) {
$("#useKernelBridge").prop('checked', lqosd_config.bridge.use_kernel_bridge);
// Map Bifrost Interfaces
let html = "<h4>Interface Mapping</h4>";
html += "<table class='table'>";
html += "<thead><th>Input Interface</th><th>Output Interface</th><th>Scan VLANs?</th></thead>";
html += "<tbody>";
for (let i=0; i<lqosd_config.bridge.interface_mapping.length; i++) {
html += "<tr>";
html += "<td>" + buildNICList('bfIn_' + i, lqosd_config.bridge.interface_mapping[i].name) + "</td>";
html += "<td>" + buildNICList('bfOut_' + i, lqosd_config.bridge.interface_mapping[i].redirect_to) + "</td>";
html += "<td><input type='checkbox' class='form-check-input' id='bfScanVLAN_" + i + "'";
if (lqosd_config.bridge.interface_mapping[i].scan_vlans) {
html += ' checked';
}
html += "/></td>";
html += "</tr>";
}
html += "</tbody></table>";
$("#bifrostInterfaces").html(html);
// Map Bifrost VLAN mappings
html = "<h4>VLAN Mapping</h4>";
// TODO
$("#bifrostVlans").html(html);
}
});
});
});
}
function fillNicList(id, selected) {
let select = $("#" + id);
let html = "";
for (i=0; i<nics.length; i++) {
html += "<option value=\"";
html += nics[i][0] + "\"";
if (nics[i][0] == selected) {
html += " selected";
}
html += ">" + nics[i][0] + " - " + nics[i][1] + " - " + nics[i][2] + "</option>";
}
select.html(html);
}
function buildNICList(id, selected) {
let html = "<select id='" + id + "'>";
for (i=0; i<nics.length; i++) {
html += "<option value=\"";
html += nics[i][0] + "\"";
if (nics[i][0] == selected) {
html += " selected";
}
html += ">" + nics[i][0] + " - " + nics[i][1] + " - " + nics[i][2] + "</option>";
}
html += "</select>";
return html;
}
$(document).ready(start);