TC Queue Check Frequency and Display

* The frequency with which TC queues are polled for statistics is
  now controled by `queue_check_period_ms` in `/etc/lqos`.
* Example file updated.
* Configuration display updated.

This is designed to act as a compromise: for detailed analysis, it
can be updated to a low number. For regular running, it can be updated
to 1000 or more.

Signed-off-by: Herbert Wolverson <herberticus@gmail.com>
This commit is contained in:
Herbert Wolverson 2023-01-06 14:38:40 +00:00
parent c5e8da8159
commit 56f421daed
6 changed files with 41 additions and 26 deletions

View File

@ -3,6 +3,7 @@
# Where is LibreQoS installed?
lqos_directory = '/opt/libreqos/src'
queue_check_period_ms = 1000
[tuning]
stop_irq_balance = true
@ -30,4 +31,4 @@ interface_mapping = [
vlan_mapping = [
{ parent = "enp1s0f1", tag = 3, redirect_to = 4 },
{ parent = "enp1s0f1", tag = 4, redirect_to = 3 }
]
]

View File

@ -5,6 +5,7 @@ use anyhow::{Result, Error};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct EtcLqos {
pub lqos_directory: String,
pub queue_check_period_ms: u64,
pub bridge: Option<BridgeConfig>,
pub tuning: Option<Tunables>,
}

View File

@ -197,17 +197,17 @@
}
let graph = document.getElementById("tinTp_" + tin);
let graph_data = [
{x: entries.x[0], y:entries.y[0], name: 'Download', type: 'scatter', fill: 'tozeroy'},
{x: entries.x[1], y:entries.y[1], name: 'Upload', type: 'scatter', fill: 'tozeroy'},
{x: entries.x[0], y:entries.y[0], name: 'Download', type: 'scatter'},
{x: entries.x[1], y:entries.y[1], name: 'Upload', type: 'scatter'},
];
Plotly.newPlot(graph, graph_data, { margin: { l:0,r:0,b:0,t:0,pad:4 }, yaxis: { automargin: true }, xaxis: {automargin: true} });
graph = document.getElementById("tinMd_" + tin);
graph_data = [
{x: entries.x[2], y:entries.y[2], name: 'Down Drops', type: 'scatter', fill: 'tozeroy'},
{x: entries.x[3], y:entries.y[3], name: 'Down Marks', type: 'scatter', fill: 'tozeroy'},
{x: entries.x[4], y:entries.y[4], name: 'Up Drops', type: 'scatter', fill: 'tozeroy'},
{x: entries.x[5], y:entries.y[5], name: 'Up Marks', type: 'scatter', fill: 'tozeroy'},
{x: entries.x[2], y:entries.y[2], name: 'Down Drops', type: 'scatter'},
{x: entries.x[3], y:entries.y[3], name: 'Down Marks', type: 'scatter'},
{x: entries.x[4], y:entries.y[4], name: 'Up Drops', type: 'scatter'},
{x: entries.x[5], y:entries.y[5], name: 'Up Marks', type: 'scatter'},
];
Plotly.newPlot(graph, graph_data, { margin: { l:0,r:0,b:0,t:0,pad:4 }, yaxis: { automargin: true }, xaxis: {automargin: true} });
}

View File

@ -229,6 +229,20 @@
<div class="tab-pane fade" id="v-pills-server" role="tabpanel" aria-labelledby="v-pills-server-tab">
<h2><i class="fa fa-server"></i> Server Settings</h2>
<table class="table">
<tr>
<td colspan="2" class="alert-info" role="alert">
How frequently should the TC queues be polled? 30-50 is good for detailed analysis,
1000 is good for normal running.
</td>
</tr>
<tr>
<td>
Queue Check Frequency (ms)
</td>
<td>
<input type="number" min="10" max="1000" id="queuecheckms" />
</td>
</tr>
<tr>
<td colspan="2" class="alert-danger">
<i class="fa fa-warning"></i> Disabling actual shell commands stops LibreQoS from actually doing anything. Simulated
@ -417,6 +431,7 @@
$("#generatedDownload").val(python_config.generated_download_mbps);
$("#generatedUpload").val(python_config.generated_upload_mbps);
$("#binpacking").prop('checked', python_config.use_binpacking);
$("#queuecheckms").val(lqosd_config.queue_check_period_ms);
$("#actualShellCommands").prop('checked', python_config.enable_shell_commands);
$("#useSudo").prop('checked', python_config.run_as_sudo);
$("#overrideQueues").val(python_config.override_queue_count);

View File

@ -2,7 +2,7 @@ use std::{time::{Duration, Instant}, collections::HashMap};
use lqos_bus::BusResponse;
use lqos_config::LibreQoSConfig;
use serde::Serialize;
use tokio::{task, time};
use tokio::{task, time, join};
use crate::libreqos_tracker::QUEUE_STRUCTURE;
use self::queue_reader::{QueueType, QueueDiff, make_queue_diff};
mod queue_reader;
@ -54,16 +54,17 @@ lazy_static! {
pub(crate) static ref CIRCUIT_TO_QUEUE : RwLock<HashMap<String, QueueStore>> = RwLock::new(HashMap::new());
}
fn track_queues() {
async fn track_queues() {
let config = LibreQoSConfig::load().unwrap();
let queues = if config.on_a_stick_mode {
let queues = queue_reader::read_tc_queues(&config.internet_interface).unwrap();
let queues = queue_reader::read_tc_queues(&config.internet_interface).await.unwrap();
vec![queues]
} else {
vec![
queue_reader::read_tc_queues(&config.isp_interface).unwrap(),
queue_reader::read_tc_queues(&config.internet_interface).unwrap(),
]
let (isp, internet) = join!{
queue_reader::read_tc_queues(&config.isp_interface),
queue_reader::read_tc_queues(&config.internet_interface),
};
vec![isp.unwrap(), internet.unwrap()]
};
// Time to associate queues with circuits
@ -164,18 +165,15 @@ fn track_queues() {
pub async fn spawn_queue_monitor() {
let _ = task::spawn(async {
let mut interval = time::interval(Duration::from_secs(1));
let queue_check_period_ms = lqos_config::EtcLqos::load().unwrap().queue_check_period_ms;
let mut interval = time::interval(Duration::from_millis(queue_check_period_ms));
loop {
let now = Instant::now();
let _ = task::spawn_blocking(move || {
track_queues()
})
.await;
let _ = track_queues().await;
let elapsed = now.elapsed();
println!("TC Reader tick with mapping consumed {:.4} seconds.", elapsed.as_secs_f32());
if elapsed.as_secs_f32() < 10.0 {
let duration = Duration::from_secs(1) - elapsed;
//println!("TC Reader tick with mapping consumed {} ms.", elapsed.as_millis());
if elapsed.as_millis() < queue_check_period_ms as u128 {
let duration = Duration::from_millis(queue_check_period_ms) - elapsed;
//println!("Sleeping for {:.2} seconds", duration.as_secs_f32());
tokio::time::sleep(duration).await;
} else {

View File

@ -5,10 +5,10 @@ mod tc_cake;
use anyhow::{Result, Error};
use serde::Serialize;
use serde_json::Value;
use std::process::Command;
mod queue_diff;
pub use queue_diff::QueueDiff;
pub(crate) use queue_diff::make_queue_diff;
use tokio::process::Command;
#[derive(Debug, Clone, Serialize)]
pub(crate) enum QueueType {
@ -32,11 +32,11 @@ impl QueueType {
}
}
pub(crate) fn read_tc_queues(interface: &str) -> Result<Vec<QueueType>> {
pub(crate) async fn read_tc_queues(interface: &str) -> Result<Vec<QueueType>> {
let mut result = Vec::new();
let command_output = Command::new("/sbin/tc")
.args(["-s", "-j", "qdisc", "show", "dev", interface])
.output()?;
.output().await?;
let json = String::from_utf8(command_output.stdout)?;
let json: Value = serde_json::from_str(&json)?;
if let Value::Array(array) = &json {