1use crate::tc::TcError;
4use byteorder::{ByteOrder, NativeEndian};
5use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
6use netlink_packet_utils::parsers::{parse_u32, parse_u8};
7use netlink_packet_utils::traits::{Emitable, Parseable};
8use netlink_packet_utils::DecodeError;
9
10#[derive(Debug, PartialEq, Eq, Clone)]
11#[non_exhaustive]
12pub struct TcQdiscFqCodel {}
13
14impl TcQdiscFqCodel {
15 pub(crate) const KIND: &'static str = "fq_codel";
16}
17
18const TC_FQ_CODEL_QD_STATS_LEN: usize = 36;
19const TC_FQ_CODEL_CL_STATS_LEN: usize = 24;
20
21const TCA_FQ_CODEL_XSTATS_QDISC: u32 = 0;
22const TCA_FQ_CODEL_XSTATS_CLASS: u32 = 1;
23
24#[derive(Debug, PartialEq, Eq, Clone)]
25#[non_exhaustive]
26pub enum TcFqCodelXstats {
27 Qdisc(TcFqCodelQdStats),
28 Class(TcFqCodelClStats),
29 Other(Vec<u8>),
30}
31
32impl<T: AsRef<[u8]> + ?Sized> Parseable<T> for TcFqCodelXstats {
33 type Error = TcError;
34 fn parse(buf: &T) -> Result<Self, TcError> {
35 if buf.as_ref().len() < 4 {
36 return Err(TcError::InvalidXstatsLength(buf.as_ref().len()));
37 }
38 let mut buf_type_bytes = [0; 4];
39 buf_type_bytes.copy_from_slice(&buf.as_ref()[0..4]);
40
41 let buf_type = u32::from_ne_bytes(buf_type_bytes);
42
43 match buf_type {
44 TCA_FQ_CODEL_XSTATS_QDISC => {
45 Ok(Self::Qdisc(
47 TcFqCodelQdStats::parse(&TcFqCodelQdStatsBuffer::new(&buf.as_ref()[4..]))
48 .unwrap(),
49 ))
50 }
51 TCA_FQ_CODEL_XSTATS_CLASS => {
52 Ok(Self::Class(
54 TcFqCodelClStats::parse(&TcFqCodelClStatsBuffer::new(&buf.as_ref()[4..]))
55 .unwrap(),
56 ))
57 }
58 _ => Ok(Self::Other(buf.as_ref().to_vec())),
59 }
60 }
61}
62
63impl Emitable for TcFqCodelXstats {
64 fn buffer_len(&self) -> usize {
65 match self {
66 Self::Qdisc(_) => TC_FQ_CODEL_QD_STATS_LEN + std::mem::size_of::<u32>(),
67 Self::Class(_) => TC_FQ_CODEL_CL_STATS_LEN + std::mem::size_of::<u32>(),
68 Self::Other(v) => v.len(),
69 }
70 }
71
72 fn emit(&self, buffer: &mut [u8]) {
73 match self {
74 Self::Qdisc(v) => {
75 buffer[0..4].copy_from_slice(&TCA_FQ_CODEL_XSTATS_QDISC.to_ne_bytes());
76 v.emit(&mut buffer[4..]);
77 }
78 Self::Class(v) => {
79 buffer[0..4].copy_from_slice(&TCA_FQ_CODEL_XSTATS_CLASS.to_ne_bytes());
80 v.emit(&mut buffer[4..]);
81 }
82 Self::Other(v) => buffer.copy_from_slice(v.as_slice()),
83 }
84 }
85}
86
87#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
88#[non_exhaustive]
89pub struct TcFqCodelQdStats {
90 pub maxpacket: u32,
91 pub drop_overlimit: u32,
92 pub ecn_mark: u32,
93 pub new_flow_count: u32,
94 pub new_flows_len: u32,
95 pub old_flows_len: u32,
96 pub ce_mark: u32,
97 pub memory_usage: u32,
98 pub drop_overmemory: u32,
99}
100
101buffer!(TcFqCodelQdStatsBuffer(TC_FQ_CODEL_QD_STATS_LEN) {
102 maxpacket: (u32, 0..4),
103 drop_overlimit: (u32, 4..8),
104 ecn_mark: (u32, 8..12),
105 new_flow_count: (u32, 12..16),
106 new_flows_len: (u32, 16..20),
107 old_flows_len: (u32, 20..24),
108 ce_mark: (u32, 24..28),
109 memory_usage: (u32, 28..32),
110 drop_overmemory: (u32,32..36),
111});
112
113impl<T: AsRef<[u8]>> Parseable<TcFqCodelQdStatsBuffer<T>> for TcFqCodelQdStats {
114 type Error = ();
115 fn parse(buf: &TcFqCodelQdStatsBuffer<T>) -> Result<Self, ()> {
116 Ok(Self {
117 maxpacket: buf.maxpacket(),
118 drop_overlimit: buf.drop_overlimit(),
119 ecn_mark: buf.ecn_mark(),
120 new_flow_count: buf.new_flow_count(),
121 new_flows_len: buf.new_flows_len(),
122 old_flows_len: buf.old_flows_len(),
123 ce_mark: buf.ce_mark(),
124 memory_usage: buf.memory_usage(),
125 drop_overmemory: buf.drop_overmemory(),
126 })
127 }
128}
129
130impl Emitable for TcFqCodelQdStats {
131 fn buffer_len(&self) -> usize {
132 TC_FQ_CODEL_QD_STATS_LEN + std::mem::size_of::<u32>()
133 }
134
135 fn emit(&self, buffer: &mut [u8]) {
136 let mut buffer = TcFqCodelQdStatsBuffer::new(buffer);
137 buffer.set_maxpacket(self.maxpacket);
138 buffer.set_drop_overlimit(self.drop_overlimit);
139 buffer.set_ecn_mark(self.ecn_mark);
140 buffer.set_new_flow_count(self.new_flow_count);
141 buffer.set_new_flows_len(self.new_flows_len);
142 buffer.set_old_flows_len(self.old_flows_len);
143 buffer.set_ce_mark(self.ce_mark);
144 buffer.set_memory_usage(self.memory_usage);
145 buffer.set_drop_overmemory(self.drop_overmemory);
146 }
147}
148
149#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
150#[non_exhaustive]
151pub struct TcFqCodelClStats {
152 deficit: i32,
153 ldelay: u32,
154 count: u32,
155 lastcount: u32,
156 dropping: u32,
157 drop_next: i32,
158}
159
160buffer!(TcFqCodelClStatsBuffer(TC_FQ_CODEL_CL_STATS_LEN) {
161 deficit: (i32, 0..4),
162 ldelay: (u32,4..8),
163 count: (u32, 8..12),
164 lastcount: (u32, 12..16),
165 dropping: (u32, 16..20),
166 drop_next: (i32, 20..24),
167});
168
169impl<T: AsRef<[u8]>> Parseable<TcFqCodelClStatsBuffer<T>> for TcFqCodelClStats {
170 type Error = DecodeError;
171 fn parse(buf: &TcFqCodelClStatsBuffer<T>) -> Result<Self, DecodeError> {
172 Ok(Self {
173 deficit: buf.deficit(),
174 ldelay: buf.ldelay(),
175 count: buf.count(),
176 lastcount: buf.lastcount(),
177 dropping: buf.dropping(),
178 drop_next: buf.drop_next(),
179 })
180 }
181}
182
183impl Emitable for TcFqCodelClStats {
184 fn buffer_len(&self) -> usize {
185 TC_FQ_CODEL_CL_STATS_LEN + std::mem::size_of::<u32>()
186 }
187
188 fn emit(&self, buffer: &mut [u8]) {
189 let mut buffer = TcFqCodelClStatsBuffer::new(buffer);
190 buffer.set_deficit(self.deficit);
191 buffer.set_ldelay(self.ldelay);
192 buffer.set_count(self.count);
193 buffer.set_lastcount(self.lastcount);
194 buffer.set_dropping(self.dropping);
195 buffer.set_drop_next(self.drop_next);
196 }
197}
198
199const TCA_FQ_CODEL_TARGET: u16 = 1;
200const TCA_FQ_CODEL_LIMIT: u16 = 2;
201const TCA_FQ_CODEL_INTERVAL: u16 = 3;
202const TCA_FQ_CODEL_ECN: u16 = 4;
203const TCA_FQ_CODEL_FLOWS: u16 = 5;
204const TCA_FQ_CODEL_QUANTUM: u16 = 6;
205const TCA_FQ_CODEL_CE_THRESHOLD: u16 = 7;
206const TCA_FQ_CODEL_DROP_BATCH_SIZE: u16 = 8;
207const TCA_FQ_CODEL_MEMORY_LIMIT: u16 = 9;
208const TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR: u16 = 10;
209const TCA_FQ_CODEL_CE_THRESHOLD_MASK: u16 = 11;
210
211#[derive(Debug, PartialEq, Eq, Clone)]
212#[non_exhaustive]
213pub enum TcQdiscFqCodelOption {
214 Target(u32),
215 Limit(u32),
216 Interval(u32),
217 Ecn(u32),
218 Flows(u32),
219 Quantum(u32),
220 CeThreshold(u32),
221 DropBatchSize(u32),
222 MemoryLimit(u32),
223 CeThresholdSelector(u8),
224 CeThresholdMask(u8),
225 Other(DefaultNla),
226}
227
228impl Nla for TcQdiscFqCodelOption {
229 fn value_len(&self) -> usize {
230 match self {
231 Self::Target(_)
232 | Self::Limit(_)
233 | Self::Interval(_)
234 | Self::Ecn(_)
235 | Self::Flows(_)
236 | Self::Quantum(_)
237 | Self::CeThreshold(_)
238 | Self::DropBatchSize(_)
239 | Self::MemoryLimit(_) => 4,
240 Self::CeThresholdSelector(_) | Self::CeThresholdMask(_) => 1,
241 Self::Other(attr) => attr.value_len(),
242 }
243 }
244
245 fn emit_value(&self, buffer: &mut [u8]) {
246 match self {
247 Self::Target(d)
248 | Self::Limit(d)
249 | Self::Interval(d)
250 | Self::Ecn(d)
251 | Self::Flows(d)
252 | Self::Quantum(d)
253 | Self::CeThreshold(d)
254 | Self::DropBatchSize(d)
255 | Self::MemoryLimit(d) => NativeEndian::write_u32(buffer, *d),
256 Self::CeThresholdSelector(d) | Self::CeThresholdMask(d) => buffer[0] = *d,
257 Self::Other(attr) => attr.emit_value(buffer),
258 }
259 }
260
261 fn kind(&self) -> u16 {
262 match self {
263 Self::Target(_) => TCA_FQ_CODEL_TARGET,
264 Self::Limit(_) => TCA_FQ_CODEL_LIMIT,
265 Self::Interval(_) => TCA_FQ_CODEL_INTERVAL,
266 Self::Ecn(_) => TCA_FQ_CODEL_ECN,
267 Self::Flows(_) => TCA_FQ_CODEL_FLOWS,
268 Self::Quantum(_) => TCA_FQ_CODEL_QUANTUM,
269 Self::CeThreshold(_) => TCA_FQ_CODEL_CE_THRESHOLD,
270 Self::DropBatchSize(_) => TCA_FQ_CODEL_DROP_BATCH_SIZE,
271 Self::MemoryLimit(_) => TCA_FQ_CODEL_MEMORY_LIMIT,
272 Self::CeThresholdSelector(_) => TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR,
273 Self::CeThresholdMask(_) => TCA_FQ_CODEL_CE_THRESHOLD_MASK,
274 Self::Other(attr) => attr.kind(),
275 }
276 }
277}
278
279impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for TcQdiscFqCodelOption {
280 type Error = TcError;
281 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, TcError> {
282 let payload = buf.value();
283 Ok(match buf.kind() {
284 TCA_FQ_CODEL_TARGET => {
285 Self::Target(parse_u32(payload).map_err(|error| TcError::InvalidValue {
286 kind: "TCA_FQ_CODEL_TARGET",
287 error,
288 })?)
289 }
290 TCA_FQ_CODEL_LIMIT => Self::Limit(
291 parse_u32(payload)
292 .map_err(|error| TcError::InvalidValue { kind: "TCA_FQ_CODEL_LIMIT", error })?,
293 ),
294 TCA_FQ_CODEL_INTERVAL => {
295 Self::Interval(parse_u32(payload).map_err(|error| TcError::InvalidValue {
296 kind: "TCA_FQ_CODEL_INTERVAL",
297 error,
298 })?)
299 }
300 TCA_FQ_CODEL_ECN => Self::Ecn(
301 parse_u32(payload)
302 .map_err(|error| TcError::InvalidValue { kind: "TCA_FQ_CODEL_ECN", error })?,
303 ),
304 TCA_FQ_CODEL_FLOWS => Self::Flows(
305 parse_u32(payload)
306 .map_err(|error| TcError::InvalidValue { kind: "TCA_FQ_CODEL_FLOWS", error })?,
307 ),
308 TCA_FQ_CODEL_QUANTUM => {
309 Self::Quantum(parse_u32(payload).map_err(|error| TcError::InvalidValue {
310 kind: "TCA_FQ_CODEL_QUANTUM",
311 error,
312 })?)
313 }
314 TCA_FQ_CODEL_CE_THRESHOLD => {
315 Self::CeThreshold(parse_u32(payload).map_err(|error| TcError::InvalidValue {
316 kind: "TCA_FQ_CODEL_CE_THRESHOLD",
317 error,
318 })?)
319 }
320 TCA_FQ_CODEL_DROP_BATCH_SIZE => {
321 Self::DropBatchSize(parse_u32(payload).map_err(|error| TcError::InvalidValue {
322 kind: "TCA_FQ_CODEL_DROP_BATCH_SIZE",
323 error,
324 })?)
325 }
326 TCA_FQ_CODEL_MEMORY_LIMIT => {
327 Self::MemoryLimit(parse_u32(payload).map_err(|error| TcError::InvalidValue {
328 kind: "TCA_FQ_CODEL_MEMORY_LIMIT",
329 error,
330 })?)
331 }
332 TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR => {
333 Self::CeThresholdSelector(parse_u8(payload).map_err(|error| {
334 TcError::InvalidValue { kind: "TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR", error }
335 })?)
336 }
337 TCA_FQ_CODEL_CE_THRESHOLD_MASK => {
338 Self::CeThresholdMask(parse_u8(payload).map_err(|error| TcError::InvalidValue {
339 kind: "TCA_FQ_CODEL_CE_THRESHOLD_MASK",
340 error,
341 })?)
342 }
343 kind => Self::Other(
344 DefaultNla::parse(buf).map_err(|error| TcError::UnknownNla { kind, error })?,
345 ),
346 })
347 }
348}