mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Port map_txq_config_base_setup from C to Rust
The previous C function was pretty simple, it'd been left as C for fast porting. It's now a safe (other than the syscall, which is properly wrapped) Rust function.
This commit is contained in:
@@ -246,70 +246,3 @@ int tc_attach_ingress(int ifindex, bool verbose, struct lqos_kern *obj)
|
|||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************/
|
|
||||||
|
|
||||||
static inline unsigned int bpf_num_possible_cpus(void)
|
|
||||||
{
|
|
||||||
static const char *fcpu = "/sys/devices/system/cpu/possible";
|
|
||||||
unsigned int start, end, possible_cpus = 0;
|
|
||||||
char buff[128];
|
|
||||||
FILE *fp;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
fp = fopen(fcpu, "r");
|
|
||||||
if (!fp) {
|
|
||||||
printf("Failed to open %s: '%s'!\n", fcpu, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (fgets(buff, sizeof(buff), fp)) {
|
|
||||||
n = sscanf(buff, "%u-%u", &start, &end);
|
|
||||||
if (n == 0) {
|
|
||||||
printf("Failed to retrieve # possible CPUs!\n");
|
|
||||||
exit(1);
|
|
||||||
} else if (n == 1) {
|
|
||||||
end = start;
|
|
||||||
}
|
|
||||||
possible_cpus = start == 0 ? end + 1 : 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return possible_cpus;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct txq_config {
|
|
||||||
/* lookup key: __u32 cpu; */
|
|
||||||
__u16 queue_mapping;
|
|
||||||
__u16 htb_major;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool map_txq_config_base_setup(int map_fd) {
|
|
||||||
unsigned int possible_cpus = bpf_num_possible_cpus();
|
|
||||||
struct txq_config txq_cfg;
|
|
||||||
__u32 cpu;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (map_fd < 0) {
|
|
||||||
fprintf(stderr, "ERR: (bad map_fd:%d) "
|
|
||||||
"cannot proceed without access to txq_config map\n",
|
|
||||||
map_fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cpu = 0; cpu < possible_cpus; cpu++) {
|
|
||||||
txq_cfg.queue_mapping = cpu + 1;
|
|
||||||
txq_cfg.htb_major = cpu + 1;
|
|
||||||
|
|
||||||
err = bpf_map_update_elem(map_fd, &cpu, &txq_cfg, 0);
|
|
||||||
if (err) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERR: %s() updating cpu-key:%d err(%d):%s\n",
|
|
||||||
__func__, cpu, errno, strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -8,5 +8,4 @@ extern int tc_detach_egress(int ifindex, bool verbose, bool flush_hook, const ch
|
|||||||
extern int tc_attach_ingress(int ifindex, bool verbose, struct lqos_kern *obj);
|
extern int tc_attach_ingress(int ifindex, bool verbose, struct lqos_kern *obj);
|
||||||
extern int tc_detach_ingress(int ifindex, bool verbose, bool flush_hook, const char * ifname);
|
extern int tc_detach_ingress(int ifindex, bool verbose, bool flush_hook, const char * ifname);
|
||||||
extern __u64 max_tracker_ips();
|
extern __u64 max_tracker_ips();
|
||||||
extern bool map_txq_config_base_setup(int map_fd);
|
|
||||||
extern void do_not_print();
|
extern void do_not_print();
|
||||||
@@ -2,8 +2,7 @@ use anyhow::{Error, Result};
|
|||||||
use libbpf_sys::{bpf_map_update_elem, bpf_obj_get};
|
use libbpf_sys::{bpf_map_update_elem, bpf_obj_get};
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::{ffi::CString, os::raw::c_void};
|
use std::{ffi::CString, os::raw::c_void};
|
||||||
|
use crate::{num_possible_cpus, linux::map_txq_config_base_setup};
|
||||||
use crate::num_possible_cpus;
|
|
||||||
|
|
||||||
//* Provides an interface for querying the number of CPUs eBPF can
|
//* Provides an interface for querying the number of CPUs eBPF can
|
||||||
//* see, and marking CPUs as available. Currently marks ALL eBPF
|
//* see, and marking CPUs as available. Currently marks ALL eBPF
|
||||||
@@ -72,14 +71,7 @@ impl CpuMapping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn setup_base_txq_config(&self) -> Result<()> {
|
pub(crate) fn setup_base_txq_config(&self) -> Result<()> {
|
||||||
use crate::lqos_kernel::bpf::map_txq_config_base_setup;
|
Ok(map_txq_config_base_setup(self.fd_txq_config)?)
|
||||||
// Should we shell out to the C and do it the easy way?
|
|
||||||
let result = unsafe { map_txq_config_base_setup(self.fd_txq_config) };
|
|
||||||
if !result {
|
|
||||||
Err(Error::msg("Unable to setup TXQ map"))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//! Ports of C code that is very Linux specific.
|
//! Ports of C code that is very Linux specific.
|
||||||
|
|
||||||
mod possible_cpus;
|
mod possible_cpus;
|
||||||
pub use possible_cpus::num_possible_cpus;
|
mod txq_base_setup;
|
||||||
|
pub use possible_cpus::num_possible_cpus;
|
||||||
|
pub(crate) use txq_base_setup::*;
|
||||||
51
src/rust/lqos_sys/src/linux/txq_base_setup.rs
Normal file
51
src/rust/lqos_sys/src/linux/txq_base_setup.rs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
use std::ffi::c_void;
|
||||||
|
use libbpf_sys::bpf_map_update_elem;
|
||||||
|
use log::error;
|
||||||
|
use thiserror::Error;
|
||||||
|
use crate::num_possible_cpus;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct TxqConfig {
|
||||||
|
/* lookup key: __u32 cpu; */
|
||||||
|
queue_mapping: u16,
|
||||||
|
htb_major: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_txq_config_base_setup(map_fd: i32) -> Result<(), MapTxqConfigError> {
|
||||||
|
let possible_cpus = num_possible_cpus().map_err(|_| MapTxqConfigError::NumCpusError)?;
|
||||||
|
if map_fd < 0 {
|
||||||
|
error!("ERR: (bad map_fd:{map_fd}) cannot proceed without access to txq_config map");
|
||||||
|
return Err(MapTxqConfigError::BadMapFd);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut txq_cfg = TxqConfig::default();
|
||||||
|
for cpu in 0 .. possible_cpus {
|
||||||
|
let cpu_u16: u16 = cpu as u16;
|
||||||
|
txq_cfg.queue_mapping = cpu_u16 + 1;
|
||||||
|
txq_cfg.htb_major = cpu_u16 + 1;
|
||||||
|
|
||||||
|
let key_ptr: *const u32 = &cpu;
|
||||||
|
let val_ptr: *const TxqConfig = &txq_cfg;
|
||||||
|
|
||||||
|
let err = unsafe {
|
||||||
|
bpf_map_update_elem(map_fd, key_ptr as *const c_void, val_ptr as *mut c_void, 0)
|
||||||
|
};
|
||||||
|
if err != 0 {
|
||||||
|
error!("Unable to update TXQ map");
|
||||||
|
return Err(MapTxqConfigError::BpfMapUpdateFail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum MapTxqConfigError {
|
||||||
|
#[error("Unable to determine number of CPUs")]
|
||||||
|
NumCpusError,
|
||||||
|
#[error("Bad Mapped File Descriptor")]
|
||||||
|
BadMapFd,
|
||||||
|
#[error("Unable to insert into map")]
|
||||||
|
BpfMapUpdateFail,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user