Work in progress: transmute netlink cake stats to readable data. Currently uses bytemuck, should be using zerocopy.

This commit is contained in:
Herbert Wolverson
2023-01-21 03:31:48 +00:00
parent 25742c25f6
commit 37355189b9
3 changed files with 149 additions and 9 deletions

12
src/rust/Cargo.lock generated
View File

@@ -621,6 +621,17 @@ dependencies = [
"windows 0.30.0",
]
[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "devise"
version = "0.3.1"
@@ -1631,6 +1642,7 @@ name = "netlink_testing"
version = "0.1.0"
dependencies = [
"bytemuck",
"derivative",
"futures-util",
"rtnetlink",
"tokio",

View File

@@ -8,3 +8,4 @@ tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
rtnetlink = "0"
futures-util = "0.3"
bytemuck = "1"
derivative = "2"

View File

@@ -1,12 +1,14 @@
use std::{time::Instant, str::from_utf8};
use derivative::Derivative;
use rtnetlink::{new_connection, packet::{TcMessage, tc::{Nla, Stats2}}};
use futures_util::TryStreamExt;
#[allow(non_camel_case_types)]
#[derive(Debug)]
#[repr(u8)]
enum TcaCakeStats {
__TCA_CAKE_STATS_INVALID = 0,
TCA_CAKE_STATS_INVALID = 0,
TCA_CAKE_STATS_PAD = 1,
TCA_CAKE_STATS_CAPACITY_ESTIMATE64 = 2,
TCA_CAKE_STATS_MEMORY_LIMIT = 3,
@@ -23,7 +25,43 @@ enum TcaCakeStats {
TCA_CAKE_STATS_DROP_NEXT_US=14,
TCA_CAKE_STATS_P_DROP=15,
TCA_CAKE_STATS_BLUE_TIMER_US=16,
__TCA_CAKE_STATS_MAX=17
TCA_CAKE_STATS_MAX=17
}
impl From<u8> for TcaCakeStats {
fn from(n: u8) -> Self {
match n {
0 => Self::TCA_CAKE_STATS_INVALID,
1 => Self::TCA_CAKE_STATS_PAD,
2 => Self::TCA_CAKE_STATS_CAPACITY_ESTIMATE64,
3 => Self::TCA_CAKE_STATS_MEMORY_LIMIT,
4 => Self::TCA_CAKE_STATS_MEMORY_USED,
5 => Self::TCA_CAKE_STATS_AVG_NETOFF,
6 => Self::TCA_CAKE_STATS_MIN_NETLEN,
7 => Self::TCA_CAKE_STATS_MAX_NETLEN,
8 => Self::TCA_CAKE_STATS_MIN_ADJLEN,
9 => Self::TCA_CAKE_STATS_MAX_ADJLEN,
10 => Self::TCA_CAKE_STATS_TIN_STATS,
11 => Self::TCA_CAKE_STATS_DEFICIT,
12 => Self::TCA_CAKE_STATS_COBALT_COUNT,
13 => Self::TCA_CAKE_STATS_DROPPING,
14 => Self::TCA_CAKE_STATS_DROP_NEXT_US,
15 => Self::TCA_CAKE_STATS_P_DROP,
16 => Self::TCA_CAKE_STATS_BLUE_TIMER_US,
17 => Self::TCA_CAKE_STATS_MAX,
_ => Self::TCA_CAKE_STATS_INVALID,
}
}
}
fn slice_to_num(buff: &[u8]) -> u32 {
u32::from_ne_bytes(
buff.try_into().unwrap())
}
fn slice_to_u16(buff: &[u8]) -> u16 {
u16::from_ne_bytes(
buff.try_into().unwrap())
}
#[tokio::main]
@@ -46,7 +84,7 @@ async fn main() -> Result<(), ()> {
loop {
let msg = format!("{:?}", results[i]);
if msg.contains("cake") {
//println!("{msg}");
println!("{msg}");
for nlas in results[i].nlas.iter() {
match nlas {
Nla::Stats2(o) => {
@@ -55,11 +93,17 @@ async fn main() -> Result<(), ()> {
Stats2::StatsApp(o) => {
println!("{:?}", o);
let mut count = 0;
let size = std::mem::size_of::<CakeStats2>();
println!("Size: {size} (vs buffer size {}", o.len());
let data = bytemuck::cast_slice::<u8, CakeStats2>(&o[0 .. size])[0];
println!("{:#?}", data);
/*let mut count = 0;
while count < o.len() {
let field: TcaCakeStats = o[count].into();
count += std::mem::sizeof<u32>();
}
//let field: TcaCakeStats = TcaCakeStats::from(o[count]);
println!("{}", slice_to_num(&o[count .. count+4]) );
count += 5;
}*/
},
_ => {}
}
@@ -68,10 +112,93 @@ async fn main() -> Result<(), ()> {
_ => {}
}
}
break;
//break;
}
i+=1;
if i > results.len()-1 { break; }
}
Ok(())
}
}
#[repr(C, packed)]
#[derive(Copy, Clone)]
#[derive(Derivative)]
#[derivative(Debug)]
struct CakeStats2 {
capacity: Nla64,
memory_limit: Nla32,
memory_used: Nla32,
avg_netoff: Nla32,
max_netlen: Nla32,
max_adjlen: Nla32,
min_netlen: Nla32,
min_adjlen: Nla32,
#[derivative(Debug="ignore")]
padding: [u8; 20],
tins: [CakeTin; 4],
}
unsafe impl bytemuck::Zeroable for CakeStats2 {}
unsafe impl bytemuck::Pod for CakeStats2 {}
#[repr(C, packed)]
#[derive(Copy, Clone)]
#[derive(Derivative)]
#[derivative(Debug)]
struct CakeTin {
threshold_rate64: Nla64,
sent_bytes64: Nla64,
backlog_bytes: Nla32,
target_us: Nla32,
interval_us: Nla32,
sent_packets: Nla32,
dropped_packets: Nla32,
ecn_marked_packets: Nla32,
acks_dropped_packets: Nla32,
peak_delay_us: Nla32,
avg_delay_us: Nla32,
base_delay_us: Nla32,
way_indirect_hits: Nla32,
way_missed: Nla32,
way_collisions: Nla32,
sparse_flows: Nla32,
bulk_flows: Nla32,
unresponsive_flows: Nla32,
max_skblen: Nla32,
flow_quantum: Nla32,
}
unsafe impl bytemuck::Zeroable for CakeTin {}
unsafe impl bytemuck::Pod for CakeTin {}
#[repr(C, packed)]
#[derive(Copy, Clone)]
#[derive(Derivative)]
#[derivative(Debug)]
struct Nla64 {
#[derivative(Debug="ignore")]
length: u16,
#[derivative(Debug="ignore")]
nla_type: u16,
value: u64,
}
unsafe impl bytemuck::Zeroable for Nla64 {}
unsafe impl bytemuck::Pod for Nla64 {}
#[repr(C, packed)]
#[derive(Copy, Clone)]
#[derive(Derivative)]
#[derivative(Debug)]
struct Nla32 {
#[derivative(Debug="ignore")]
length: u16,
#[derivative(Debug="ignore")]
nla_type: u16,
value: u32,
}
unsafe impl bytemuck::Zeroable for Nla32 {}
unsafe impl bytemuck::Pod for Nla32 {}