mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Implement correct signal handling for SIGINT, SIGTERM and SIGHUP
Extend the signals handler to reload configuration on SIGHUP, and terminate on SIGINT and SIGTERM. FIXES #202
This commit is contained in:
@@ -2,23 +2,23 @@ mod ip_mapping;
|
||||
mod libreqos_tracker;
|
||||
#[cfg(feature = "equinix_tests")]
|
||||
mod lqos_daht_test;
|
||||
mod offloads;
|
||||
mod tuning;
|
||||
mod program_control;
|
||||
mod queue_tracker;
|
||||
mod throughput_tracker;
|
||||
use crate::{ip_mapping::{clear_ip_flows, del_ip_flow, list_mapped_ips, map_ip_to_flow}, queue_tracker::QUEUE_MONITOR_INTERVAL};
|
||||
use crate::{ip_mapping::{clear_ip_flows, del_ip_flow, list_mapped_ips, map_ip_to_flow}};
|
||||
use anyhow::Result;
|
||||
use log::{info, warn};
|
||||
use lqos_bus::{
|
||||
cookie_value, decode_request, encode_response, BusReply, BusRequest, BUS_BIND_ADDRESS,
|
||||
};
|
||||
use lqos_config::{EtcLqos, LibreQoSConfig};
|
||||
use lqos_config::LibreQoSConfig;
|
||||
use lqos_sys::LibreQoSKernels;
|
||||
use signal_hook::{consts::SIGINT, iterator::Signals};
|
||||
use signal_hook::{consts::{SIGINT, SIGHUP, SIGTERM }, iterator::Signals};
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
join,
|
||||
net::{TcpListener, TcpStream},
|
||||
net::{TcpListener, TcpStream}
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
@@ -26,18 +26,7 @@ async fn main() -> Result<()> {
|
||||
env_logger::init(); // Configure log level with RUST_LOG environment variable
|
||||
info!("LibreQoS Daemon Starting");
|
||||
let config = LibreQoSConfig::load()?;
|
||||
let etc_lqos = EtcLqos::load()?;
|
||||
|
||||
// Disable offloading
|
||||
if let Some(tuning) = &etc_lqos.tuning {
|
||||
offloads::bpf_sysctls().await;
|
||||
if tuning.stop_irq_balance {
|
||||
offloads::stop_irq_balance().await;
|
||||
}
|
||||
offloads::netdev_budget(tuning.netdev_budget_usecs, tuning.netdev_budget_packets).await;
|
||||
offloads::ethtool_tweaks(&config.internet_interface, tuning).await;
|
||||
offloads::ethtool_tweaks(&config.isp_interface, tuning).await;
|
||||
}
|
||||
tuning::tune_lqosd_from_config_file(&config)?;
|
||||
|
||||
// Start the XDP/TC kernels
|
||||
let kernels = if config.on_a_stick_mode {
|
||||
@@ -58,13 +47,34 @@ async fn main() -> Result<()> {
|
||||
libreqos_tracker::spawn_queue_structure_monitor(),
|
||||
);
|
||||
|
||||
let mut signals = Signals::new(&[SIGINT])?;
|
||||
|
||||
// Handle signals
|
||||
let mut signals = Signals::new(&[SIGINT, SIGHUP, SIGTERM ])?;
|
||||
std::thread::spawn(move || {
|
||||
for sig in signals.forever() {
|
||||
warn!("Received signal {:?}", sig);
|
||||
std::mem::drop(kernels);
|
||||
std::process::exit(0);
|
||||
match sig {
|
||||
SIGINT | SIGTERM => {
|
||||
match sig {
|
||||
SIGINT => warn!("Terminating on SIGINT"),
|
||||
SIGTERM => warn!("Terminating on SIGTERM"),
|
||||
_ => warn!("This should never happen - terminating on unknown signal"),
|
||||
}
|
||||
std::mem::drop(kernels);
|
||||
std::process::exit(0);
|
||||
}
|
||||
SIGHUP => {
|
||||
warn!("Reloading configuration because of SIGHUP");
|
||||
if let Ok(config) = LibreQoSConfig::load() {
|
||||
let result = tuning::tune_lqosd_from_config_file(&config);
|
||||
match result {
|
||||
Err(err) => { warn!("Unable to HUP tunables: {:?}", err) },
|
||||
Ok(..) => {}
|
||||
}
|
||||
} else {
|
||||
warn!("Unable to reload configuration");
|
||||
}
|
||||
}
|
||||
_ => warn!("No handler for signal: {sig}"),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -116,18 +126,8 @@ async fn main() -> Result<()> {
|
||||
BusRequest::GetRawQueueData(circuit_id) => {
|
||||
queue_tracker::get_raw_circuit_data(&circuit_id)
|
||||
}
|
||||
BusRequest::UpdateLqosDTuning(interval, tuning) => {
|
||||
// Real-time tuning changes. Probably dangerous.
|
||||
if let Ok(config) = LibreQoSConfig::load() {
|
||||
if tuning.stop_irq_balance {
|
||||
offloads::stop_irq_balance().await;
|
||||
}
|
||||
offloads::netdev_budget(tuning.netdev_budget_usecs, tuning.netdev_budget_packets).await;
|
||||
offloads::ethtool_tweaks(&config.internet_interface, tuning).await;
|
||||
offloads::ethtool_tweaks(&config.isp_interface, tuning).await;
|
||||
}
|
||||
QUEUE_MONITOR_INTERVAL.store(*interval, std::sync::atomic::Ordering::Relaxed);
|
||||
lqos_bus::BusResponse::Ack
|
||||
BusRequest::UpdateLqosDTuning(..) => {
|
||||
tuning::tune_lqosd_from_bus(&req).await
|
||||
}
|
||||
#[cfg(feature = "equinix_tests")]
|
||||
BusRequest::RequestLqosEquinixTest => {
|
||||
|
||||
42
src/rust/lqosd/src/tuning/mod.rs
Normal file
42
src/rust/lqosd/src/tuning/mod.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
mod offloads;
|
||||
use anyhow::Result;
|
||||
use lqos_bus::{BusRequest, BusResponse};
|
||||
use lqos_config::{EtcLqos, LibreQoSConfig};
|
||||
use crate::queue_tracker::QUEUE_MONITOR_INTERVAL;
|
||||
|
||||
pub fn tune_lqosd_from_config_file(config: &LibreQoSConfig) -> Result<()> {
|
||||
let etc_lqos = EtcLqos::load()?;
|
||||
|
||||
// Disable offloading
|
||||
if let Some(tuning) = &etc_lqos.tuning {
|
||||
offloads::bpf_sysctls();
|
||||
if tuning.stop_irq_balance {
|
||||
offloads::stop_irq_balance();
|
||||
}
|
||||
offloads::netdev_budget(tuning.netdev_budget_usecs, tuning.netdev_budget_packets);
|
||||
offloads::ethtool_tweaks(&config.internet_interface, tuning);
|
||||
offloads::ethtool_tweaks(&config.isp_interface, tuning);
|
||||
}
|
||||
let interval = etc_lqos.queue_check_period_ms;
|
||||
QUEUE_MONITOR_INTERVAL.store(interval, std::sync::atomic::Ordering::Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn tune_lqosd_from_bus(request: &BusRequest) -> BusResponse {
|
||||
match request {
|
||||
BusRequest::UpdateLqosDTuning(interval, tuning) => {
|
||||
// Real-time tuning changes. Probably dangerous.
|
||||
if let Ok(config) = LibreQoSConfig::load() {
|
||||
if tuning.stop_irq_balance {
|
||||
offloads::stop_irq_balance();
|
||||
}
|
||||
offloads::netdev_budget(tuning.netdev_budget_usecs, tuning.netdev_budget_packets);
|
||||
offloads::ethtool_tweaks(&config.internet_interface, tuning);
|
||||
offloads::ethtool_tweaks(&config.isp_interface, tuning);
|
||||
}
|
||||
QUEUE_MONITOR_INTERVAL.store(*interval, std::sync::atomic::Ordering::Relaxed);
|
||||
lqos_bus::BusResponse::Ack
|
||||
}
|
||||
_ => BusResponse::Fail("That wasn't a tuning request".to_string())
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,38 @@
|
||||
use lqos_config::Tunables;
|
||||
use tokio::process::Command;
|
||||
use std::process::Command;
|
||||
|
||||
pub async fn bpf_sysctls() {
|
||||
pub fn bpf_sysctls() {
|
||||
let _ = Command::new("/sbin/sysctl")
|
||||
.arg(format!("net.core.bpf_jit_enable=1"))
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
}
|
||||
|
||||
pub async fn stop_irq_balance() {
|
||||
pub fn stop_irq_balance() {
|
||||
let _ = Command::new("/bin/systemctl")
|
||||
.args(["stop", "irqbalance"])
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
}
|
||||
|
||||
pub async fn netdev_budget(usecs: u32, packets: u32) {
|
||||
pub fn netdev_budget(usecs: u32, packets: u32) {
|
||||
let _ = Command::new("/sbin/sysctl")
|
||||
.arg(format!("net.core.netdev_budget_usecs={usecs}"))
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
|
||||
let _ = Command::new("/sbin/sysctl")
|
||||
.arg(format!("net.core.netdev_budget={packets}"))
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
}
|
||||
|
||||
async fn disable_individual_offload(interface: &str, feature: &str) {
|
||||
fn disable_individual_offload(interface: &str, feature: &str) {
|
||||
let _ = Command::new("/sbin/ethtool")
|
||||
.args(["--offload", interface, feature, "off"])
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
}
|
||||
|
||||
pub async fn ethtool_tweaks(interface: &str, tuning: &Tunables) {
|
||||
pub fn ethtool_tweaks(interface: &str, tuning: &Tunables) {
|
||||
// Disabling individually to avoid complaints that a card doesn't support a feature anyway
|
||||
for feature in tuning.disable_offload.iter() {
|
||||
disable_individual_offload(interface, feature).await;
|
||||
disable_individual_offload(interface, feature);
|
||||
}
|
||||
|
||||
let _ = Command::new("/sbin/ethtool")
|
||||
@@ -47,8 +42,7 @@ pub async fn ethtool_tweaks(interface: &str, tuning: &Tunables) {
|
||||
"rx-usecs",
|
||||
&format!("\"{}\"", tuning.rx_usecs),
|
||||
])
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
|
||||
let _ = Command::new("/sbin/ethtool")
|
||||
.args([
|
||||
@@ -57,20 +51,17 @@ pub async fn ethtool_tweaks(interface: &str, tuning: &Tunables) {
|
||||
"tx-usecs",
|
||||
&format!("\"{}\"", tuning.tx_usecs),
|
||||
])
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
|
||||
if tuning.disable_rxvlan {
|
||||
let _ = Command::new("/sbin/ethtool")
|
||||
.args(["-K", interface, "rxvlan", "off"])
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
}
|
||||
|
||||
if tuning.disable_txvlan {
|
||||
let _ = Command::new("/sbin/ethtool")
|
||||
.args(["-K", interface, "txvlan", "off"])
|
||||
.output()
|
||||
.await;
|
||||
.output();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user