1use serde::{Deserialize, Serialize};
2
3use crate::{errors::TcError, types::*};
4
5#[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#[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#[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#[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 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 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 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}