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:
Herbert Wolverson
2023-03-13 14:47:26 +00:00
parent 93e8afae71
commit 64641c6849
5 changed files with 56 additions and 79 deletions

View File

@@ -246,70 +246,3 @@ int tc_attach_ingress(int ifindex, bool verbose, struct lqos_kern *obj)
out:
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;
}

View File

@@ -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_detach_ingress(int ifindex, bool verbose, bool flush_hook, const char * ifname);
extern __u64 max_tracker_ips();
extern bool map_txq_config_base_setup(int map_fd);
extern void do_not_print();

View File

@@ -2,8 +2,7 @@ use anyhow::{Error, Result};
use libbpf_sys::{bpf_map_update_elem, bpf_obj_get};
use log::info;
use std::{ffi::CString, os::raw::c_void};
use crate::num_possible_cpus;
use crate::{num_possible_cpus, linux::map_txq_config_base_setup};
//* Provides an interface for querying the number of CPUs eBPF can
//* 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<()> {
use crate::lqos_kernel::bpf::map_txq_config_base_setup;
// 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(())
}
Ok(map_txq_config_base_setup(self.fd_txq_config)?)
}
}

View File

@@ -1,4 +1,6 @@
//! Ports of C code that is very Linux specific.
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::*;

View 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,
}