netlink_tc/class/
htb.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{errors::TcError, types::*};
4
5/// Defined in `include/uapi/linux/pkt_sched.h`.
6#[derive(Default, Debug, PartialEq)]
7pub struct Htb {
8    pub parms: Option<HtbOpt>,
9    pub init: Option<HtbGlob>,
10    pub ctab: Vec<u8>,
11    pub rtab: Vec<u8>,
12    pub direct_qlen: Option<u32>,
13    pub rate64: Option<u64>,
14    pub ceil64: Option<u64>,
15}
16
17/// Defined in `include/uapi/linux/pkt_sched.h` as `struct tc_htb_opt`.
18#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
19pub struct HtbOpt {
20    pub rate: RateSpec,
21    pub ceil: RateSpec,
22    pub buffer: u32,
23    pub cbuffer: u32,
24    pub quantum: u32,
25    pub level: u32,
26    pub prio: u32,
27}
28
29/// Defined in `include/uapi/linux/pkt_sched.h` as `struct tc_htb_glob`.
30#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
31pub struct HtbGlob {
32    pub version: u32,
33    pub rate2quantum: u32,
34    pub defcls: u32,
35    pub debug: u32,
36    pub direct_pkts: u32,
37}
38
39/// Defined in `include/uapi/linux/pkt_sched.h` as `struct tc_htb_xstats`.
40#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
41pub struct HtbXstats {
42    pub lends: u32,
43    pub borrows: u32,
44    pub giants: u32,
45    pub tokens: u32,
46    pub ctokens: u32,
47}
48
49pub enum TcaHtb {
50    Unspec = 0,
51    Parms,
52    Init,
53    Ctab,
54    Rtab,
55    DirectQlen,
56    Rate64,
57    Ceil64,
58    Pad,
59    Max,
60}
61
62impl From<u16> for TcaHtb {
63    fn from(v: u16) -> Self {
64        match v {
65            0 => TcaHtb::Unspec,
66            1 => TcaHtb::Parms,
67            2 => TcaHtb::Init,
68            3 => TcaHtb::Ctab,
69            4 => TcaHtb::Rtab,
70            5 => TcaHtb::DirectQlen,
71            6 => TcaHtb::Rate64,
72            7 => TcaHtb::Ceil64,
73            8 => TcaHtb::Pad,
74            _ => TcaHtb::Max,
75        }
76    }
77}
78
79impl Htb {
80    pub fn new(opts: Vec<TcOption>) -> Self {
81        unmarshal_htb(opts)
82    }
83}
84
85impl HtbXstats {
86    pub fn new(bytes: &[u8]) -> Result<Self, TcError> {
87        unmarshal_htb_xstats(bytes)
88    }
89}
90
91fn unmarshal_htb(opts: Vec<TcOption>) -> Htb {
92    let mut htb = Htb::default();
93
94    for opt in opts {
95        let kind = TcaHtb::from(opt.kind);
96        match kind {
97            TcaHtb::Parms => htb.parms = unmarshal_htb_opt(opt.bytes.as_slice()).ok(),
98            TcaHtb::Init => htb.init = unmarshal_htb_glob(opt.bytes.as_slice()).ok(),
99            TcaHtb::Ctab => htb.ctab = opt.bytes,
100            TcaHtb::Rtab => htb.rtab = opt.bytes,
101            TcaHtb::DirectQlen => {
102                htb.direct_qlen = {
103                    if opt.bytes.len() < 4 {
104                        // TODO: log error
105                        None
106                    } else {
107                        Some(u32::from_ne_bytes(opt.bytes[0..4].try_into().unwrap()))
108                    }
109                }
110            }
111            TcaHtb::Rate64 => {
112                htb.rate64 = {
113                    if opt.bytes.len() < 8 {
114                        // TODO: log error
115                        None
116                    } else {
117                        Some(u64::from_ne_bytes(opt.bytes[0..8].try_into().unwrap()))
118                    }
119                }
120            }
121            TcaHtb::Ceil64 => {
122                htb.ceil64 = {
123                    if opt.bytes.len() < 8 {
124                        // TODO: log error
125                        None
126                    } else {
127                        Some(u64::from_ne_bytes(opt.bytes[0..8].try_into().unwrap()))
128                    }
129                }
130            }
131            _ => (),
132        }
133    }
134
135    htb
136}
137
138fn unmarshal_htb_opt(bytes: &[u8]) -> Result<HtbOpt, TcError> {
139    bincode::deserialize(bytes).map_err(TcError::UnmarshalStruct)
140}
141
142fn unmarshal_htb_glob(bytes: &[u8]) -> Result<HtbGlob, TcError> {
143    bincode::deserialize(bytes).map_err(TcError::UnmarshalStruct)
144}
145
146fn unmarshal_htb_xstats(bytes: &[u8]) -> Result<HtbXstats, TcError> {
147    bincode::deserialize(bytes).map_err(TcError::UnmarshalStruct)
148}