1#![doc = "Networking HW rate limiting configuration.\n\nThis API allows configuring HW shapers available on the network devices\nat different levels (queues, network device) and allows arbitrary\nmanipulation of the scheduling tree of the involved shapers.\n\nEach \\@shaper is identified within the given device, by a \\@handle,\ncomprising both a \\@scope and an \\@id.\n\nDepending on the \\@scope value, the shapers are attached to specific HW\nobjects (queues, devices) or, for \\@node scope, represent a scheduling\ngroup, that can be placed in an arbitrary location of the scheduling\ntree.\n\nShapers can be created with two different operations: the \\@set\noperation, to create and update a single \\\"attached\\\" shaper, and the\n\\@group operation, to create and update a scheduling group. Only the\n\\@group operation can create \\@node scope shapers.\n\nExisting shapers can be deleted/reset via the \\@delete operation.\n\nThe user can query the running configuration via the \\@get operation.\n\nDifferent devices can provide different feature sets, e.g. with no\nsupport for complex scheduling hierarchy, or for some shaping\nparameters. The user can introspect the HW capabilities via the\n\\@cap-get operation.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "net-shaper";
17pub const PROTONAME_CSTR: &CStr = c"net-shaper";
18#[doc = "Defines the shaper \\@id interpretation.\n"]
19#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
20#[derive(Debug, Clone, Copy)]
21pub enum Scope {
22 #[doc = "The scope is not specified.\n"]
23 Unspec = 0,
24 #[doc = "The main shaper for the given network device.\n"]
25 Netdev = 1,
26 #[doc = "The shaper is attached to the given device queue, the \\@id represents\nthe queue number.\n"]
27 Queue = 2,
28 #[doc = "The shaper allows grouping of queues or other node shapers; can be\nnested in either \\@netdev shapers or other \\@node shapers, allowing\nplacement in any location of the scheduling tree, except leaves and\nroot.\n"]
29 Node = 3,
30}
31impl Scope {
32 pub fn from_value(value: u64) -> Option<Self> {
33 Some(match value {
34 0 => Self::Unspec,
35 1 => Self::Netdev,
36 2 => Self::Queue,
37 3 => Self::Node,
38 _ => return None,
39 })
40 }
41}
42#[doc = "Different metric supported by the shaper.\n"]
43#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
44#[derive(Debug, Clone, Copy)]
45pub enum Metric {
46 #[doc = "Shaper operates on a bits per second basis.\n"]
47 Bps = 0,
48 #[doc = "Shaper operates on a packets per second basis.\n"]
49 Pps = 1,
50}
51impl Metric {
52 pub fn from_value(value: u64) -> Option<Self> {
53 Some(match value {
54 0 => Self::Bps,
55 1 => Self::Pps,
56 _ => return None,
57 })
58 }
59}
60#[derive(Clone)]
61pub enum NetShaper<'a> {
62 #[doc = "Unique identifier for the given shaper inside the owning device.\n"]
63 Handle(IterableHandle<'a>),
64 #[doc = "Metric used by the given shaper for bw-min, bw-max and burst.\n\nAssociated type: [`Metric`] (enum)"]
65 Metric(u32),
66 #[doc = "Guaranteed bandwidth for the given shaper.\n"]
67 BwMin(u32),
68 #[doc = "Maximum bandwidth for the given shaper or 0 when unlimited.\n"]
69 BwMax(u32),
70 #[doc = "Maximum burst-size for shaping. Should not be interpreted as a quantum.\n"]
71 Burst(u32),
72 #[doc = "Scheduling priority for the given shaper. The priority scheduling is\napplied to sibling shapers.\n"]
73 Priority(u32),
74 #[doc = "Relative weight for round robin scheduling of the given shaper. The\nscheduling is applied to all sibling shapers with the same priority.\n"]
75 Weight(u32),
76 #[doc = "Interface index owning the specified shaper.\n"]
77 Ifindex(u32),
78 #[doc = "Identifier for the parent of the affected shaper. Only needed for\n\\@group operation.\n"]
79 Parent(IterableHandle<'a>),
80 #[doc = "Describes a set of leaves shapers for a \\@group operation.\n\nAttribute may repeat multiple times (treat it as array)"]
81 Leaves(IterableLeafInfo<'a>),
82}
83impl<'a> IterableNetShaper<'a> {
84 #[doc = "Unique identifier for the given shaper inside the owning device.\n"]
85 pub fn get_handle(&self) -> Result<IterableHandle<'a>, ErrorContext> {
86 let mut iter = self.clone();
87 iter.pos = 0;
88 for attr in iter {
89 if let Ok(NetShaper::Handle(val)) = attr {
90 return Ok(val);
91 }
92 }
93 Err(ErrorContext::new_missing(
94 "NetShaper",
95 "Handle",
96 self.orig_loc,
97 self.buf.as_ptr() as usize,
98 ))
99 }
100 #[doc = "Metric used by the given shaper for bw-min, bw-max and burst.\n\nAssociated type: [`Metric`] (enum)"]
101 pub fn get_metric(&self) -> Result<u32, ErrorContext> {
102 let mut iter = self.clone();
103 iter.pos = 0;
104 for attr in iter {
105 if let Ok(NetShaper::Metric(val)) = attr {
106 return Ok(val);
107 }
108 }
109 Err(ErrorContext::new_missing(
110 "NetShaper",
111 "Metric",
112 self.orig_loc,
113 self.buf.as_ptr() as usize,
114 ))
115 }
116 #[doc = "Guaranteed bandwidth for the given shaper.\n"]
117 pub fn get_bw_min(&self) -> Result<u32, ErrorContext> {
118 let mut iter = self.clone();
119 iter.pos = 0;
120 for attr in iter {
121 if let Ok(NetShaper::BwMin(val)) = attr {
122 return Ok(val);
123 }
124 }
125 Err(ErrorContext::new_missing(
126 "NetShaper",
127 "BwMin",
128 self.orig_loc,
129 self.buf.as_ptr() as usize,
130 ))
131 }
132 #[doc = "Maximum bandwidth for the given shaper or 0 when unlimited.\n"]
133 pub fn get_bw_max(&self) -> Result<u32, ErrorContext> {
134 let mut iter = self.clone();
135 iter.pos = 0;
136 for attr in iter {
137 if let Ok(NetShaper::BwMax(val)) = attr {
138 return Ok(val);
139 }
140 }
141 Err(ErrorContext::new_missing(
142 "NetShaper",
143 "BwMax",
144 self.orig_loc,
145 self.buf.as_ptr() as usize,
146 ))
147 }
148 #[doc = "Maximum burst-size for shaping. Should not be interpreted as a quantum.\n"]
149 pub fn get_burst(&self) -> Result<u32, ErrorContext> {
150 let mut iter = self.clone();
151 iter.pos = 0;
152 for attr in iter {
153 if let Ok(NetShaper::Burst(val)) = attr {
154 return Ok(val);
155 }
156 }
157 Err(ErrorContext::new_missing(
158 "NetShaper",
159 "Burst",
160 self.orig_loc,
161 self.buf.as_ptr() as usize,
162 ))
163 }
164 #[doc = "Scheduling priority for the given shaper. The priority scheduling is\napplied to sibling shapers.\n"]
165 pub fn get_priority(&self) -> Result<u32, ErrorContext> {
166 let mut iter = self.clone();
167 iter.pos = 0;
168 for attr in iter {
169 if let Ok(NetShaper::Priority(val)) = attr {
170 return Ok(val);
171 }
172 }
173 Err(ErrorContext::new_missing(
174 "NetShaper",
175 "Priority",
176 self.orig_loc,
177 self.buf.as_ptr() as usize,
178 ))
179 }
180 #[doc = "Relative weight for round robin scheduling of the given shaper. The\nscheduling is applied to all sibling shapers with the same priority.\n"]
181 pub fn get_weight(&self) -> Result<u32, ErrorContext> {
182 let mut iter = self.clone();
183 iter.pos = 0;
184 for attr in iter {
185 if let Ok(NetShaper::Weight(val)) = attr {
186 return Ok(val);
187 }
188 }
189 Err(ErrorContext::new_missing(
190 "NetShaper",
191 "Weight",
192 self.orig_loc,
193 self.buf.as_ptr() as usize,
194 ))
195 }
196 #[doc = "Interface index owning the specified shaper.\n"]
197 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
198 let mut iter = self.clone();
199 iter.pos = 0;
200 for attr in iter {
201 if let Ok(NetShaper::Ifindex(val)) = attr {
202 return Ok(val);
203 }
204 }
205 Err(ErrorContext::new_missing(
206 "NetShaper",
207 "Ifindex",
208 self.orig_loc,
209 self.buf.as_ptr() as usize,
210 ))
211 }
212 #[doc = "Identifier for the parent of the affected shaper. Only needed for\n\\@group operation.\n"]
213 pub fn get_parent(&self) -> Result<IterableHandle<'a>, ErrorContext> {
214 let mut iter = self.clone();
215 iter.pos = 0;
216 for attr in iter {
217 if let Ok(NetShaper::Parent(val)) = attr {
218 return Ok(val);
219 }
220 }
221 Err(ErrorContext::new_missing(
222 "NetShaper",
223 "Parent",
224 self.orig_loc,
225 self.buf.as_ptr() as usize,
226 ))
227 }
228 #[doc = "Describes a set of leaves shapers for a \\@group operation.\n\nAttribute may repeat multiple times (treat it as array)"]
229 pub fn get_leaves(&self) -> MultiAttrIterable<Self, NetShaper<'a>, IterableLeafInfo<'a>> {
230 MultiAttrIterable::new(self.clone(), |variant| {
231 if let NetShaper::Leaves(val) = variant {
232 Some(val)
233 } else {
234 None
235 }
236 })
237 }
238}
239impl NetShaper<'_> {
240 pub fn new<'a>(buf: &'a [u8]) -> IterableNetShaper<'a> {
241 IterableNetShaper::with_loc(buf, buf.as_ptr() as usize)
242 }
243 fn attr_from_type(r#type: u16) -> Option<&'static str> {
244 let res = match r#type {
245 1u16 => "Handle",
246 2u16 => "Metric",
247 3u16 => "BwMin",
248 4u16 => "BwMax",
249 5u16 => "Burst",
250 6u16 => "Priority",
251 7u16 => "Weight",
252 8u16 => "Ifindex",
253 9u16 => "Parent",
254 10u16 => "Leaves",
255 _ => return None,
256 };
257 Some(res)
258 }
259}
260#[derive(Clone, Copy, Default)]
261pub struct IterableNetShaper<'a> {
262 buf: &'a [u8],
263 pos: usize,
264 orig_loc: usize,
265}
266impl<'a> IterableNetShaper<'a> {
267 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
268 Self {
269 buf,
270 pos: 0,
271 orig_loc,
272 }
273 }
274 pub fn get_buf(&self) -> &'a [u8] {
275 self.buf
276 }
277}
278impl<'a> Iterator for IterableNetShaper<'a> {
279 type Item = Result<NetShaper<'a>, ErrorContext>;
280 fn next(&mut self) -> Option<Self::Item> {
281 let mut pos;
282 let mut r#type;
283 loop {
284 pos = self.pos;
285 r#type = None;
286 if self.buf.len() == self.pos {
287 return None;
288 }
289 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
290 self.pos = self.buf.len();
291 break;
292 };
293 r#type = Some(header.r#type);
294 let res = match header.r#type {
295 1u16 => NetShaper::Handle({
296 let res = Some(IterableHandle::with_loc(next, self.orig_loc));
297 let Some(val) = res else { break };
298 val
299 }),
300 2u16 => NetShaper::Metric({
301 let res = parse_u32(next);
302 let Some(val) = res else { break };
303 val
304 }),
305 3u16 => NetShaper::BwMin({
306 let res = parse_u32(next);
307 let Some(val) = res else { break };
308 val
309 }),
310 4u16 => NetShaper::BwMax({
311 let res = parse_u32(next);
312 let Some(val) = res else { break };
313 val
314 }),
315 5u16 => NetShaper::Burst({
316 let res = parse_u32(next);
317 let Some(val) = res else { break };
318 val
319 }),
320 6u16 => NetShaper::Priority({
321 let res = parse_u32(next);
322 let Some(val) = res else { break };
323 val
324 }),
325 7u16 => NetShaper::Weight({
326 let res = parse_u32(next);
327 let Some(val) = res else { break };
328 val
329 }),
330 8u16 => NetShaper::Ifindex({
331 let res = parse_u32(next);
332 let Some(val) = res else { break };
333 val
334 }),
335 9u16 => NetShaper::Parent({
336 let res = Some(IterableHandle::with_loc(next, self.orig_loc));
337 let Some(val) = res else { break };
338 val
339 }),
340 10u16 => NetShaper::Leaves({
341 let res = Some(IterableLeafInfo::with_loc(next, self.orig_loc));
342 let Some(val) = res else { break };
343 val
344 }),
345 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
346 n => continue,
347 };
348 return Some(Ok(res));
349 }
350 Some(Err(ErrorContext::new(
351 "NetShaper",
352 r#type.and_then(|t| NetShaper::attr_from_type(t)),
353 self.orig_loc,
354 self.buf.as_ptr().wrapping_add(pos) as usize,
355 )))
356 }
357}
358impl<'a> std::fmt::Debug for IterableNetShaper<'_> {
359 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360 let mut fmt = f.debug_struct("NetShaper");
361 for attr in self.clone() {
362 let attr = match attr {
363 Ok(a) => a,
364 Err(err) => {
365 fmt.finish()?;
366 f.write_str("Err(")?;
367 err.fmt(f)?;
368 return f.write_str(")");
369 }
370 };
371 match attr {
372 NetShaper::Handle(val) => fmt.field("Handle", &val),
373 NetShaper::Metric(val) => {
374 fmt.field("Metric", &FormatEnum(val.into(), Metric::from_value))
375 }
376 NetShaper::BwMin(val) => fmt.field("BwMin", &val),
377 NetShaper::BwMax(val) => fmt.field("BwMax", &val),
378 NetShaper::Burst(val) => fmt.field("Burst", &val),
379 NetShaper::Priority(val) => fmt.field("Priority", &val),
380 NetShaper::Weight(val) => fmt.field("Weight", &val),
381 NetShaper::Ifindex(val) => fmt.field("Ifindex", &val),
382 NetShaper::Parent(val) => fmt.field("Parent", &val),
383 NetShaper::Leaves(val) => fmt.field("Leaves", &val),
384 };
385 }
386 fmt.finish()
387 }
388}
389impl IterableNetShaper<'_> {
390 pub fn lookup_attr(
391 &self,
392 offset: usize,
393 missing_type: Option<u16>,
394 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
395 let mut stack = Vec::new();
396 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
397 if missing_type.is_some() && cur == offset {
398 stack.push(("NetShaper", offset));
399 return (
400 stack,
401 missing_type.and_then(|t| NetShaper::attr_from_type(t)),
402 );
403 }
404 if cur > offset || cur + self.buf.len() < offset {
405 return (stack, None);
406 }
407 let mut attrs = self.clone();
408 let mut last_off = cur + attrs.pos;
409 let mut missing = None;
410 while let Some(attr) = attrs.next() {
411 let Ok(attr) = attr else { break };
412 match attr {
413 NetShaper::Handle(val) => {
414 (stack, missing) = val.lookup_attr(offset, missing_type);
415 if !stack.is_empty() {
416 break;
417 }
418 }
419 NetShaper::Metric(val) => {
420 if last_off == offset {
421 stack.push(("Metric", last_off));
422 break;
423 }
424 }
425 NetShaper::BwMin(val) => {
426 if last_off == offset {
427 stack.push(("BwMin", last_off));
428 break;
429 }
430 }
431 NetShaper::BwMax(val) => {
432 if last_off == offset {
433 stack.push(("BwMax", last_off));
434 break;
435 }
436 }
437 NetShaper::Burst(val) => {
438 if last_off == offset {
439 stack.push(("Burst", last_off));
440 break;
441 }
442 }
443 NetShaper::Priority(val) => {
444 if last_off == offset {
445 stack.push(("Priority", last_off));
446 break;
447 }
448 }
449 NetShaper::Weight(val) => {
450 if last_off == offset {
451 stack.push(("Weight", last_off));
452 break;
453 }
454 }
455 NetShaper::Ifindex(val) => {
456 if last_off == offset {
457 stack.push(("Ifindex", last_off));
458 break;
459 }
460 }
461 NetShaper::Parent(val) => {
462 (stack, missing) = val.lookup_attr(offset, missing_type);
463 if !stack.is_empty() {
464 break;
465 }
466 }
467 NetShaper::Leaves(val) => {
468 (stack, missing) = val.lookup_attr(offset, missing_type);
469 if !stack.is_empty() {
470 break;
471 }
472 }
473 _ => {}
474 };
475 last_off = cur + attrs.pos;
476 }
477 if !stack.is_empty() {
478 stack.push(("NetShaper", cur));
479 }
480 (stack, missing)
481 }
482}
483#[derive(Clone)]
484pub enum Handle {
485 #[doc = "Defines the shaper \\@id interpretation.\n\nAssociated type: [`Scope`] (enum)"]
486 Scope(u32),
487 #[doc = "Numeric identifier of a shaper. The id semantic depends on the scope.\nFor \\@queue scope it\\'s the queue id and for \\@node scope it\\'s the node\nidentifier.\n"]
488 Id(u32),
489}
490impl<'a> IterableHandle<'a> {
491 #[doc = "Defines the shaper \\@id interpretation.\n\nAssociated type: [`Scope`] (enum)"]
492 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
493 let mut iter = self.clone();
494 iter.pos = 0;
495 for attr in iter {
496 if let Ok(Handle::Scope(val)) = attr {
497 return Ok(val);
498 }
499 }
500 Err(ErrorContext::new_missing(
501 "Handle",
502 "Scope",
503 self.orig_loc,
504 self.buf.as_ptr() as usize,
505 ))
506 }
507 #[doc = "Numeric identifier of a shaper. The id semantic depends on the scope.\nFor \\@queue scope it\\'s the queue id and for \\@node scope it\\'s the node\nidentifier.\n"]
508 pub fn get_id(&self) -> Result<u32, ErrorContext> {
509 let mut iter = self.clone();
510 iter.pos = 0;
511 for attr in iter {
512 if let Ok(Handle::Id(val)) = attr {
513 return Ok(val);
514 }
515 }
516 Err(ErrorContext::new_missing(
517 "Handle",
518 "Id",
519 self.orig_loc,
520 self.buf.as_ptr() as usize,
521 ))
522 }
523}
524impl Handle {
525 pub fn new<'a>(buf: &'a [u8]) -> IterableHandle<'a> {
526 IterableHandle::with_loc(buf, buf.as_ptr() as usize)
527 }
528 fn attr_from_type(r#type: u16) -> Option<&'static str> {
529 let res = match r#type {
530 1u16 => "Scope",
531 2u16 => "Id",
532 _ => return None,
533 };
534 Some(res)
535 }
536}
537#[derive(Clone, Copy, Default)]
538pub struct IterableHandle<'a> {
539 buf: &'a [u8],
540 pos: usize,
541 orig_loc: usize,
542}
543impl<'a> IterableHandle<'a> {
544 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
545 Self {
546 buf,
547 pos: 0,
548 orig_loc,
549 }
550 }
551 pub fn get_buf(&self) -> &'a [u8] {
552 self.buf
553 }
554}
555impl<'a> Iterator for IterableHandle<'a> {
556 type Item = Result<Handle, ErrorContext>;
557 fn next(&mut self) -> Option<Self::Item> {
558 let mut pos;
559 let mut r#type;
560 loop {
561 pos = self.pos;
562 r#type = None;
563 if self.buf.len() == self.pos {
564 return None;
565 }
566 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
567 self.pos = self.buf.len();
568 break;
569 };
570 r#type = Some(header.r#type);
571 let res = match header.r#type {
572 1u16 => Handle::Scope({
573 let res = parse_u32(next);
574 let Some(val) = res else { break };
575 val
576 }),
577 2u16 => Handle::Id({
578 let res = parse_u32(next);
579 let Some(val) = res else { break };
580 val
581 }),
582 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
583 n => continue,
584 };
585 return Some(Ok(res));
586 }
587 Some(Err(ErrorContext::new(
588 "Handle",
589 r#type.and_then(|t| Handle::attr_from_type(t)),
590 self.orig_loc,
591 self.buf.as_ptr().wrapping_add(pos) as usize,
592 )))
593 }
594}
595impl std::fmt::Debug for IterableHandle<'_> {
596 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
597 let mut fmt = f.debug_struct("Handle");
598 for attr in self.clone() {
599 let attr = match attr {
600 Ok(a) => a,
601 Err(err) => {
602 fmt.finish()?;
603 f.write_str("Err(")?;
604 err.fmt(f)?;
605 return f.write_str(")");
606 }
607 };
608 match attr {
609 Handle::Scope(val) => {
610 fmt.field("Scope", &FormatEnum(val.into(), Scope::from_value))
611 }
612 Handle::Id(val) => fmt.field("Id", &val),
613 };
614 }
615 fmt.finish()
616 }
617}
618impl IterableHandle<'_> {
619 pub fn lookup_attr(
620 &self,
621 offset: usize,
622 missing_type: Option<u16>,
623 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
624 let mut stack = Vec::new();
625 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
626 if missing_type.is_some() && cur == offset {
627 stack.push(("Handle", offset));
628 return (stack, missing_type.and_then(|t| Handle::attr_from_type(t)));
629 }
630 if cur > offset || cur + self.buf.len() < offset {
631 return (stack, None);
632 }
633 let mut attrs = self.clone();
634 let mut last_off = cur + attrs.pos;
635 while let Some(attr) = attrs.next() {
636 let Ok(attr) = attr else { break };
637 match attr {
638 Handle::Scope(val) => {
639 if last_off == offset {
640 stack.push(("Scope", last_off));
641 break;
642 }
643 }
644 Handle::Id(val) => {
645 if last_off == offset {
646 stack.push(("Id", last_off));
647 break;
648 }
649 }
650 _ => {}
651 };
652 last_off = cur + attrs.pos;
653 }
654 if !stack.is_empty() {
655 stack.push(("Handle", cur));
656 }
657 (stack, None)
658 }
659}
660#[derive(Clone)]
661pub enum LeafInfo<'a> {
662 #[doc = "Unique identifier for the given shaper inside the owning device.\n"]
663 Handle(IterableHandle<'a>),
664 #[doc = "Scheduling priority for the given shaper. The priority scheduling is\napplied to sibling shapers.\n"]
665 Priority(u32),
666 #[doc = "Relative weight for round robin scheduling of the given shaper. The\nscheduling is applied to all sibling shapers with the same priority.\n"]
667 Weight(u32),
668}
669impl<'a> IterableLeafInfo<'a> {
670 #[doc = "Unique identifier for the given shaper inside the owning device.\n"]
671 pub fn get_handle(&self) -> Result<IterableHandle<'a>, ErrorContext> {
672 let mut iter = self.clone();
673 iter.pos = 0;
674 for attr in iter {
675 if let Ok(LeafInfo::Handle(val)) = attr {
676 return Ok(val);
677 }
678 }
679 Err(ErrorContext::new_missing(
680 "LeafInfo",
681 "Handle",
682 self.orig_loc,
683 self.buf.as_ptr() as usize,
684 ))
685 }
686 #[doc = "Scheduling priority for the given shaper. The priority scheduling is\napplied to sibling shapers.\n"]
687 pub fn get_priority(&self) -> Result<u32, ErrorContext> {
688 let mut iter = self.clone();
689 iter.pos = 0;
690 for attr in iter {
691 if let Ok(LeafInfo::Priority(val)) = attr {
692 return Ok(val);
693 }
694 }
695 Err(ErrorContext::new_missing(
696 "LeafInfo",
697 "Priority",
698 self.orig_loc,
699 self.buf.as_ptr() as usize,
700 ))
701 }
702 #[doc = "Relative weight for round robin scheduling of the given shaper. The\nscheduling is applied to all sibling shapers with the same priority.\n"]
703 pub fn get_weight(&self) -> Result<u32, ErrorContext> {
704 let mut iter = self.clone();
705 iter.pos = 0;
706 for attr in iter {
707 if let Ok(LeafInfo::Weight(val)) = attr {
708 return Ok(val);
709 }
710 }
711 Err(ErrorContext::new_missing(
712 "LeafInfo",
713 "Weight",
714 self.orig_loc,
715 self.buf.as_ptr() as usize,
716 ))
717 }
718}
719impl LeafInfo<'_> {
720 pub fn new<'a>(buf: &'a [u8]) -> IterableLeafInfo<'a> {
721 IterableLeafInfo::with_loc(buf, buf.as_ptr() as usize)
722 }
723 fn attr_from_type(r#type: u16) -> Option<&'static str> {
724 NetShaper::attr_from_type(r#type)
725 }
726}
727#[derive(Clone, Copy, Default)]
728pub struct IterableLeafInfo<'a> {
729 buf: &'a [u8],
730 pos: usize,
731 orig_loc: usize,
732}
733impl<'a> IterableLeafInfo<'a> {
734 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
735 Self {
736 buf,
737 pos: 0,
738 orig_loc,
739 }
740 }
741 pub fn get_buf(&self) -> &'a [u8] {
742 self.buf
743 }
744}
745impl<'a> Iterator for IterableLeafInfo<'a> {
746 type Item = Result<LeafInfo<'a>, ErrorContext>;
747 fn next(&mut self) -> Option<Self::Item> {
748 let mut pos;
749 let mut r#type;
750 loop {
751 pos = self.pos;
752 r#type = None;
753 if self.buf.len() == self.pos {
754 return None;
755 }
756 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
757 self.pos = self.buf.len();
758 break;
759 };
760 r#type = Some(header.r#type);
761 let res = match header.r#type {
762 1u16 => LeafInfo::Handle({
763 let res = Some(IterableHandle::with_loc(next, self.orig_loc));
764 let Some(val) = res else { break };
765 val
766 }),
767 6u16 => LeafInfo::Priority({
768 let res = parse_u32(next);
769 let Some(val) = res else { break };
770 val
771 }),
772 7u16 => LeafInfo::Weight({
773 let res = parse_u32(next);
774 let Some(val) = res else { break };
775 val
776 }),
777 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
778 n => continue,
779 };
780 return Some(Ok(res));
781 }
782 Some(Err(ErrorContext::new(
783 "LeafInfo",
784 r#type.and_then(|t| LeafInfo::attr_from_type(t)),
785 self.orig_loc,
786 self.buf.as_ptr().wrapping_add(pos) as usize,
787 )))
788 }
789}
790impl<'a> std::fmt::Debug for IterableLeafInfo<'_> {
791 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
792 let mut fmt = f.debug_struct("LeafInfo");
793 for attr in self.clone() {
794 let attr = match attr {
795 Ok(a) => a,
796 Err(err) => {
797 fmt.finish()?;
798 f.write_str("Err(")?;
799 err.fmt(f)?;
800 return f.write_str(")");
801 }
802 };
803 match attr {
804 LeafInfo::Handle(val) => fmt.field("Handle", &val),
805 LeafInfo::Priority(val) => fmt.field("Priority", &val),
806 LeafInfo::Weight(val) => fmt.field("Weight", &val),
807 };
808 }
809 fmt.finish()
810 }
811}
812impl IterableLeafInfo<'_> {
813 pub fn lookup_attr(
814 &self,
815 offset: usize,
816 missing_type: Option<u16>,
817 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
818 let mut stack = Vec::new();
819 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
820 if missing_type.is_some() && cur == offset {
821 stack.push(("LeafInfo", offset));
822 return (
823 stack,
824 missing_type.and_then(|t| LeafInfo::attr_from_type(t)),
825 );
826 }
827 if cur > offset || cur + self.buf.len() < offset {
828 return (stack, None);
829 }
830 let mut attrs = self.clone();
831 let mut last_off = cur + attrs.pos;
832 let mut missing = None;
833 while let Some(attr) = attrs.next() {
834 let Ok(attr) = attr else { break };
835 match attr {
836 LeafInfo::Handle(val) => {
837 (stack, missing) = val.lookup_attr(offset, missing_type);
838 if !stack.is_empty() {
839 break;
840 }
841 }
842 LeafInfo::Priority(val) => {
843 if last_off == offset {
844 stack.push(("Priority", last_off));
845 break;
846 }
847 }
848 LeafInfo::Weight(val) => {
849 if last_off == offset {
850 stack.push(("Weight", last_off));
851 break;
852 }
853 }
854 _ => {}
855 };
856 last_off = cur + attrs.pos;
857 }
858 if !stack.is_empty() {
859 stack.push(("LeafInfo", cur));
860 }
861 (stack, missing)
862 }
863}
864#[derive(Clone)]
865pub enum Caps {
866 #[doc = "Interface index queried for shapers capabilities.\n"]
867 Ifindex(u32),
868 #[doc = "The scope to which the queried capabilities apply.\n\nAssociated type: [`Scope`] (enum)"]
869 Scope(u32),
870 #[doc = "The device accepts \\'bps\\' metric for bw-min, bw-max and burst.\n"]
871 SupportMetricBps(()),
872 #[doc = "The device accepts \\'pps\\' metric for bw-min, bw-max and burst.\n"]
873 SupportMetricPps(()),
874 #[doc = "The device supports nesting shaper belonging to this scope below\n\\'node\\' scoped shapers. Only \\'queue\\' and \\'node\\' scope can have flag\n\\'support-nesting\\'.\n"]
875 SupportNesting(()),
876 #[doc = "The device supports a minimum guaranteed B/W.\n"]
877 SupportBwMin(()),
878 #[doc = "The device supports maximum B/W shaping.\n"]
879 SupportBwMax(()),
880 #[doc = "The device supports a maximum burst size.\n"]
881 SupportBurst(()),
882 #[doc = "The device supports priority scheduling.\n"]
883 SupportPriority(()),
884 #[doc = "The device supports weighted round robin scheduling.\n"]
885 SupportWeight(()),
886}
887impl<'a> IterableCaps<'a> {
888 #[doc = "Interface index queried for shapers capabilities.\n"]
889 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
890 let mut iter = self.clone();
891 iter.pos = 0;
892 for attr in iter {
893 if let Ok(Caps::Ifindex(val)) = attr {
894 return Ok(val);
895 }
896 }
897 Err(ErrorContext::new_missing(
898 "Caps",
899 "Ifindex",
900 self.orig_loc,
901 self.buf.as_ptr() as usize,
902 ))
903 }
904 #[doc = "The scope to which the queried capabilities apply.\n\nAssociated type: [`Scope`] (enum)"]
905 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
906 let mut iter = self.clone();
907 iter.pos = 0;
908 for attr in iter {
909 if let Ok(Caps::Scope(val)) = attr {
910 return Ok(val);
911 }
912 }
913 Err(ErrorContext::new_missing(
914 "Caps",
915 "Scope",
916 self.orig_loc,
917 self.buf.as_ptr() as usize,
918 ))
919 }
920 #[doc = "The device accepts \\'bps\\' metric for bw-min, bw-max and burst.\n"]
921 pub fn get_support_metric_bps(&self) -> Result<(), ErrorContext> {
922 let mut iter = self.clone();
923 iter.pos = 0;
924 for attr in iter {
925 if let Ok(Caps::SupportMetricBps(val)) = attr {
926 return Ok(val);
927 }
928 }
929 Err(ErrorContext::new_missing(
930 "Caps",
931 "SupportMetricBps",
932 self.orig_loc,
933 self.buf.as_ptr() as usize,
934 ))
935 }
936 #[doc = "The device accepts \\'pps\\' metric for bw-min, bw-max and burst.\n"]
937 pub fn get_support_metric_pps(&self) -> Result<(), ErrorContext> {
938 let mut iter = self.clone();
939 iter.pos = 0;
940 for attr in iter {
941 if let Ok(Caps::SupportMetricPps(val)) = attr {
942 return Ok(val);
943 }
944 }
945 Err(ErrorContext::new_missing(
946 "Caps",
947 "SupportMetricPps",
948 self.orig_loc,
949 self.buf.as_ptr() as usize,
950 ))
951 }
952 #[doc = "The device supports nesting shaper belonging to this scope below\n\\'node\\' scoped shapers. Only \\'queue\\' and \\'node\\' scope can have flag\n\\'support-nesting\\'.\n"]
953 pub fn get_support_nesting(&self) -> Result<(), ErrorContext> {
954 let mut iter = self.clone();
955 iter.pos = 0;
956 for attr in iter {
957 if let Ok(Caps::SupportNesting(val)) = attr {
958 return Ok(val);
959 }
960 }
961 Err(ErrorContext::new_missing(
962 "Caps",
963 "SupportNesting",
964 self.orig_loc,
965 self.buf.as_ptr() as usize,
966 ))
967 }
968 #[doc = "The device supports a minimum guaranteed B/W.\n"]
969 pub fn get_support_bw_min(&self) -> Result<(), ErrorContext> {
970 let mut iter = self.clone();
971 iter.pos = 0;
972 for attr in iter {
973 if let Ok(Caps::SupportBwMin(val)) = attr {
974 return Ok(val);
975 }
976 }
977 Err(ErrorContext::new_missing(
978 "Caps",
979 "SupportBwMin",
980 self.orig_loc,
981 self.buf.as_ptr() as usize,
982 ))
983 }
984 #[doc = "The device supports maximum B/W shaping.\n"]
985 pub fn get_support_bw_max(&self) -> Result<(), ErrorContext> {
986 let mut iter = self.clone();
987 iter.pos = 0;
988 for attr in iter {
989 if let Ok(Caps::SupportBwMax(val)) = attr {
990 return Ok(val);
991 }
992 }
993 Err(ErrorContext::new_missing(
994 "Caps",
995 "SupportBwMax",
996 self.orig_loc,
997 self.buf.as_ptr() as usize,
998 ))
999 }
1000 #[doc = "The device supports a maximum burst size.\n"]
1001 pub fn get_support_burst(&self) -> Result<(), ErrorContext> {
1002 let mut iter = self.clone();
1003 iter.pos = 0;
1004 for attr in iter {
1005 if let Ok(Caps::SupportBurst(val)) = attr {
1006 return Ok(val);
1007 }
1008 }
1009 Err(ErrorContext::new_missing(
1010 "Caps",
1011 "SupportBurst",
1012 self.orig_loc,
1013 self.buf.as_ptr() as usize,
1014 ))
1015 }
1016 #[doc = "The device supports priority scheduling.\n"]
1017 pub fn get_support_priority(&self) -> Result<(), ErrorContext> {
1018 let mut iter = self.clone();
1019 iter.pos = 0;
1020 for attr in iter {
1021 if let Ok(Caps::SupportPriority(val)) = attr {
1022 return Ok(val);
1023 }
1024 }
1025 Err(ErrorContext::new_missing(
1026 "Caps",
1027 "SupportPriority",
1028 self.orig_loc,
1029 self.buf.as_ptr() as usize,
1030 ))
1031 }
1032 #[doc = "The device supports weighted round robin scheduling.\n"]
1033 pub fn get_support_weight(&self) -> Result<(), ErrorContext> {
1034 let mut iter = self.clone();
1035 iter.pos = 0;
1036 for attr in iter {
1037 if let Ok(Caps::SupportWeight(val)) = attr {
1038 return Ok(val);
1039 }
1040 }
1041 Err(ErrorContext::new_missing(
1042 "Caps",
1043 "SupportWeight",
1044 self.orig_loc,
1045 self.buf.as_ptr() as usize,
1046 ))
1047 }
1048}
1049impl Caps {
1050 pub fn new<'a>(buf: &'a [u8]) -> IterableCaps<'a> {
1051 IterableCaps::with_loc(buf, buf.as_ptr() as usize)
1052 }
1053 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1054 let res = match r#type {
1055 1u16 => "Ifindex",
1056 2u16 => "Scope",
1057 3u16 => "SupportMetricBps",
1058 4u16 => "SupportMetricPps",
1059 5u16 => "SupportNesting",
1060 6u16 => "SupportBwMin",
1061 7u16 => "SupportBwMax",
1062 8u16 => "SupportBurst",
1063 9u16 => "SupportPriority",
1064 10u16 => "SupportWeight",
1065 _ => return None,
1066 };
1067 Some(res)
1068 }
1069}
1070#[derive(Clone, Copy, Default)]
1071pub struct IterableCaps<'a> {
1072 buf: &'a [u8],
1073 pos: usize,
1074 orig_loc: usize,
1075}
1076impl<'a> IterableCaps<'a> {
1077 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1078 Self {
1079 buf,
1080 pos: 0,
1081 orig_loc,
1082 }
1083 }
1084 pub fn get_buf(&self) -> &'a [u8] {
1085 self.buf
1086 }
1087}
1088impl<'a> Iterator for IterableCaps<'a> {
1089 type Item = Result<Caps, ErrorContext>;
1090 fn next(&mut self) -> Option<Self::Item> {
1091 let mut pos;
1092 let mut r#type;
1093 loop {
1094 pos = self.pos;
1095 r#type = None;
1096 if self.buf.len() == self.pos {
1097 return None;
1098 }
1099 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1100 self.pos = self.buf.len();
1101 break;
1102 };
1103 r#type = Some(header.r#type);
1104 let res = match header.r#type {
1105 1u16 => Caps::Ifindex({
1106 let res = parse_u32(next);
1107 let Some(val) = res else { break };
1108 val
1109 }),
1110 2u16 => Caps::Scope({
1111 let res = parse_u32(next);
1112 let Some(val) = res else { break };
1113 val
1114 }),
1115 3u16 => Caps::SupportMetricBps(()),
1116 4u16 => Caps::SupportMetricPps(()),
1117 5u16 => Caps::SupportNesting(()),
1118 6u16 => Caps::SupportBwMin(()),
1119 7u16 => Caps::SupportBwMax(()),
1120 8u16 => Caps::SupportBurst(()),
1121 9u16 => Caps::SupportPriority(()),
1122 10u16 => Caps::SupportWeight(()),
1123 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1124 n => continue,
1125 };
1126 return Some(Ok(res));
1127 }
1128 Some(Err(ErrorContext::new(
1129 "Caps",
1130 r#type.and_then(|t| Caps::attr_from_type(t)),
1131 self.orig_loc,
1132 self.buf.as_ptr().wrapping_add(pos) as usize,
1133 )))
1134 }
1135}
1136impl std::fmt::Debug for IterableCaps<'_> {
1137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1138 let mut fmt = f.debug_struct("Caps");
1139 for attr in self.clone() {
1140 let attr = match attr {
1141 Ok(a) => a,
1142 Err(err) => {
1143 fmt.finish()?;
1144 f.write_str("Err(")?;
1145 err.fmt(f)?;
1146 return f.write_str(")");
1147 }
1148 };
1149 match attr {
1150 Caps::Ifindex(val) => fmt.field("Ifindex", &val),
1151 Caps::Scope(val) => fmt.field("Scope", &FormatEnum(val.into(), Scope::from_value)),
1152 Caps::SupportMetricBps(val) => fmt.field("SupportMetricBps", &val),
1153 Caps::SupportMetricPps(val) => fmt.field("SupportMetricPps", &val),
1154 Caps::SupportNesting(val) => fmt.field("SupportNesting", &val),
1155 Caps::SupportBwMin(val) => fmt.field("SupportBwMin", &val),
1156 Caps::SupportBwMax(val) => fmt.field("SupportBwMax", &val),
1157 Caps::SupportBurst(val) => fmt.field("SupportBurst", &val),
1158 Caps::SupportPriority(val) => fmt.field("SupportPriority", &val),
1159 Caps::SupportWeight(val) => fmt.field("SupportWeight", &val),
1160 };
1161 }
1162 fmt.finish()
1163 }
1164}
1165impl IterableCaps<'_> {
1166 pub fn lookup_attr(
1167 &self,
1168 offset: usize,
1169 missing_type: Option<u16>,
1170 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1171 let mut stack = Vec::new();
1172 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1173 if missing_type.is_some() && cur == offset {
1174 stack.push(("Caps", offset));
1175 return (stack, missing_type.and_then(|t| Caps::attr_from_type(t)));
1176 }
1177 if cur > offset || cur + self.buf.len() < offset {
1178 return (stack, None);
1179 }
1180 let mut attrs = self.clone();
1181 let mut last_off = cur + attrs.pos;
1182 while let Some(attr) = attrs.next() {
1183 let Ok(attr) = attr else { break };
1184 match attr {
1185 Caps::Ifindex(val) => {
1186 if last_off == offset {
1187 stack.push(("Ifindex", last_off));
1188 break;
1189 }
1190 }
1191 Caps::Scope(val) => {
1192 if last_off == offset {
1193 stack.push(("Scope", last_off));
1194 break;
1195 }
1196 }
1197 Caps::SupportMetricBps(val) => {
1198 if last_off == offset {
1199 stack.push(("SupportMetricBps", last_off));
1200 break;
1201 }
1202 }
1203 Caps::SupportMetricPps(val) => {
1204 if last_off == offset {
1205 stack.push(("SupportMetricPps", last_off));
1206 break;
1207 }
1208 }
1209 Caps::SupportNesting(val) => {
1210 if last_off == offset {
1211 stack.push(("SupportNesting", last_off));
1212 break;
1213 }
1214 }
1215 Caps::SupportBwMin(val) => {
1216 if last_off == offset {
1217 stack.push(("SupportBwMin", last_off));
1218 break;
1219 }
1220 }
1221 Caps::SupportBwMax(val) => {
1222 if last_off == offset {
1223 stack.push(("SupportBwMax", last_off));
1224 break;
1225 }
1226 }
1227 Caps::SupportBurst(val) => {
1228 if last_off == offset {
1229 stack.push(("SupportBurst", last_off));
1230 break;
1231 }
1232 }
1233 Caps::SupportPriority(val) => {
1234 if last_off == offset {
1235 stack.push(("SupportPriority", last_off));
1236 break;
1237 }
1238 }
1239 Caps::SupportWeight(val) => {
1240 if last_off == offset {
1241 stack.push(("SupportWeight", last_off));
1242 break;
1243 }
1244 }
1245 _ => {}
1246 };
1247 last_off = cur + attrs.pos;
1248 }
1249 if !stack.is_empty() {
1250 stack.push(("Caps", cur));
1251 }
1252 (stack, None)
1253 }
1254}
1255pub struct PushNetShaper<Prev: Pusher> {
1256 pub(crate) prev: Option<Prev>,
1257 pub(crate) header_offset: Option<usize>,
1258}
1259impl<Prev: Pusher> Pusher for PushNetShaper<Prev> {
1260 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1261 self.prev.as_mut().unwrap().as_vec_mut()
1262 }
1263 fn as_vec(&self) -> &Vec<u8> {
1264 self.prev.as_ref().unwrap().as_vec()
1265 }
1266}
1267impl<Prev: Pusher> PushNetShaper<Prev> {
1268 pub fn new(prev: Prev) -> Self {
1269 Self {
1270 prev: Some(prev),
1271 header_offset: None,
1272 }
1273 }
1274 pub fn end_nested(mut self) -> Prev {
1275 let mut prev = self.prev.take().unwrap();
1276 if let Some(header_offset) = &self.header_offset {
1277 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1278 }
1279 prev
1280 }
1281 #[doc = "Unique identifier for the given shaper inside the owning device.\n"]
1282 pub fn nested_handle(mut self) -> PushHandle<Self> {
1283 let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
1284 PushHandle {
1285 prev: Some(self),
1286 header_offset: Some(header_offset),
1287 }
1288 }
1289 #[doc = "Metric used by the given shaper for bw-min, bw-max and burst.\n\nAssociated type: [`Metric`] (enum)"]
1290 pub fn push_metric(mut self, value: u32) -> Self {
1291 push_header(self.as_vec_mut(), 2u16, 4 as u16);
1292 self.as_vec_mut().extend(value.to_ne_bytes());
1293 self
1294 }
1295 #[doc = "Guaranteed bandwidth for the given shaper.\n"]
1296 pub fn push_bw_min(mut self, value: u32) -> Self {
1297 push_header(self.as_vec_mut(), 3u16, 4 as u16);
1298 self.as_vec_mut().extend(value.to_ne_bytes());
1299 self
1300 }
1301 #[doc = "Maximum bandwidth for the given shaper or 0 when unlimited.\n"]
1302 pub fn push_bw_max(mut self, value: u32) -> Self {
1303 push_header(self.as_vec_mut(), 4u16, 4 as u16);
1304 self.as_vec_mut().extend(value.to_ne_bytes());
1305 self
1306 }
1307 #[doc = "Maximum burst-size for shaping. Should not be interpreted as a quantum.\n"]
1308 pub fn push_burst(mut self, value: u32) -> Self {
1309 push_header(self.as_vec_mut(), 5u16, 4 as u16);
1310 self.as_vec_mut().extend(value.to_ne_bytes());
1311 self
1312 }
1313 #[doc = "Scheduling priority for the given shaper. The priority scheduling is\napplied to sibling shapers.\n"]
1314 pub fn push_priority(mut self, value: u32) -> Self {
1315 push_header(self.as_vec_mut(), 6u16, 4 as u16);
1316 self.as_vec_mut().extend(value.to_ne_bytes());
1317 self
1318 }
1319 #[doc = "Relative weight for round robin scheduling of the given shaper. The\nscheduling is applied to all sibling shapers with the same priority.\n"]
1320 pub fn push_weight(mut self, value: u32) -> Self {
1321 push_header(self.as_vec_mut(), 7u16, 4 as u16);
1322 self.as_vec_mut().extend(value.to_ne_bytes());
1323 self
1324 }
1325 #[doc = "Interface index owning the specified shaper.\n"]
1326 pub fn push_ifindex(mut self, value: u32) -> Self {
1327 push_header(self.as_vec_mut(), 8u16, 4 as u16);
1328 self.as_vec_mut().extend(value.to_ne_bytes());
1329 self
1330 }
1331 #[doc = "Identifier for the parent of the affected shaper. Only needed for\n\\@group operation.\n"]
1332 pub fn nested_parent(mut self) -> PushHandle<Self> {
1333 let header_offset = push_nested_header(self.as_vec_mut(), 9u16);
1334 PushHandle {
1335 prev: Some(self),
1336 header_offset: Some(header_offset),
1337 }
1338 }
1339 #[doc = "Describes a set of leaves shapers for a \\@group operation.\n\nAttribute may repeat multiple times (treat it as array)"]
1340 pub fn nested_leaves(mut self) -> PushLeafInfo<Self> {
1341 let header_offset = push_nested_header(self.as_vec_mut(), 10u16);
1342 PushLeafInfo {
1343 prev: Some(self),
1344 header_offset: Some(header_offset),
1345 }
1346 }
1347}
1348impl<Prev: Pusher> Drop for PushNetShaper<Prev> {
1349 fn drop(&mut self) {
1350 if let Some(prev) = &mut self.prev {
1351 if let Some(header_offset) = &self.header_offset {
1352 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1353 }
1354 }
1355 }
1356}
1357pub struct PushHandle<Prev: Pusher> {
1358 pub(crate) prev: Option<Prev>,
1359 pub(crate) header_offset: Option<usize>,
1360}
1361impl<Prev: Pusher> Pusher for PushHandle<Prev> {
1362 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1363 self.prev.as_mut().unwrap().as_vec_mut()
1364 }
1365 fn as_vec(&self) -> &Vec<u8> {
1366 self.prev.as_ref().unwrap().as_vec()
1367 }
1368}
1369impl<Prev: Pusher> PushHandle<Prev> {
1370 pub fn new(prev: Prev) -> Self {
1371 Self {
1372 prev: Some(prev),
1373 header_offset: None,
1374 }
1375 }
1376 pub fn end_nested(mut self) -> Prev {
1377 let mut prev = self.prev.take().unwrap();
1378 if let Some(header_offset) = &self.header_offset {
1379 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1380 }
1381 prev
1382 }
1383 #[doc = "Defines the shaper \\@id interpretation.\n\nAssociated type: [`Scope`] (enum)"]
1384 pub fn push_scope(mut self, value: u32) -> Self {
1385 push_header(self.as_vec_mut(), 1u16, 4 as u16);
1386 self.as_vec_mut().extend(value.to_ne_bytes());
1387 self
1388 }
1389 #[doc = "Numeric identifier of a shaper. The id semantic depends on the scope.\nFor \\@queue scope it\\'s the queue id and for \\@node scope it\\'s the node\nidentifier.\n"]
1390 pub fn push_id(mut self, value: u32) -> Self {
1391 push_header(self.as_vec_mut(), 2u16, 4 as u16);
1392 self.as_vec_mut().extend(value.to_ne_bytes());
1393 self
1394 }
1395}
1396impl<Prev: Pusher> Drop for PushHandle<Prev> {
1397 fn drop(&mut self) {
1398 if let Some(prev) = &mut self.prev {
1399 if let Some(header_offset) = &self.header_offset {
1400 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1401 }
1402 }
1403 }
1404}
1405pub struct PushLeafInfo<Prev: Pusher> {
1406 pub(crate) prev: Option<Prev>,
1407 pub(crate) header_offset: Option<usize>,
1408}
1409impl<Prev: Pusher> Pusher for PushLeafInfo<Prev> {
1410 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1411 self.prev.as_mut().unwrap().as_vec_mut()
1412 }
1413 fn as_vec(&self) -> &Vec<u8> {
1414 self.prev.as_ref().unwrap().as_vec()
1415 }
1416}
1417impl<Prev: Pusher> PushLeafInfo<Prev> {
1418 pub fn new(prev: Prev) -> Self {
1419 Self {
1420 prev: Some(prev),
1421 header_offset: None,
1422 }
1423 }
1424 pub fn end_nested(mut self) -> Prev {
1425 let mut prev = self.prev.take().unwrap();
1426 if let Some(header_offset) = &self.header_offset {
1427 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1428 }
1429 prev
1430 }
1431 #[doc = "Unique identifier for the given shaper inside the owning device.\n"]
1432 pub fn nested_handle(mut self) -> PushHandle<Self> {
1433 let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
1434 PushHandle {
1435 prev: Some(self),
1436 header_offset: Some(header_offset),
1437 }
1438 }
1439 #[doc = "Scheduling priority for the given shaper. The priority scheduling is\napplied to sibling shapers.\n"]
1440 pub fn push_priority(mut self, value: u32) -> Self {
1441 push_header(self.as_vec_mut(), 6u16, 4 as u16);
1442 self.as_vec_mut().extend(value.to_ne_bytes());
1443 self
1444 }
1445 #[doc = "Relative weight for round robin scheduling of the given shaper. The\nscheduling is applied to all sibling shapers with the same priority.\n"]
1446 pub fn push_weight(mut self, value: u32) -> Self {
1447 push_header(self.as_vec_mut(), 7u16, 4 as u16);
1448 self.as_vec_mut().extend(value.to_ne_bytes());
1449 self
1450 }
1451}
1452impl<Prev: Pusher> Drop for PushLeafInfo<Prev> {
1453 fn drop(&mut self) {
1454 if let Some(prev) = &mut self.prev {
1455 if let Some(header_offset) = &self.header_offset {
1456 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1457 }
1458 }
1459 }
1460}
1461pub struct PushCaps<Prev: Pusher> {
1462 pub(crate) prev: Option<Prev>,
1463 pub(crate) header_offset: Option<usize>,
1464}
1465impl<Prev: Pusher> Pusher for PushCaps<Prev> {
1466 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1467 self.prev.as_mut().unwrap().as_vec_mut()
1468 }
1469 fn as_vec(&self) -> &Vec<u8> {
1470 self.prev.as_ref().unwrap().as_vec()
1471 }
1472}
1473impl<Prev: Pusher> PushCaps<Prev> {
1474 pub fn new(prev: Prev) -> Self {
1475 Self {
1476 prev: Some(prev),
1477 header_offset: None,
1478 }
1479 }
1480 pub fn end_nested(mut self) -> Prev {
1481 let mut prev = self.prev.take().unwrap();
1482 if let Some(header_offset) = &self.header_offset {
1483 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1484 }
1485 prev
1486 }
1487 #[doc = "Interface index queried for shapers capabilities.\n"]
1488 pub fn push_ifindex(mut self, value: u32) -> Self {
1489 push_header(self.as_vec_mut(), 1u16, 4 as u16);
1490 self.as_vec_mut().extend(value.to_ne_bytes());
1491 self
1492 }
1493 #[doc = "The scope to which the queried capabilities apply.\n\nAssociated type: [`Scope`] (enum)"]
1494 pub fn push_scope(mut self, value: u32) -> Self {
1495 push_header(self.as_vec_mut(), 2u16, 4 as u16);
1496 self.as_vec_mut().extend(value.to_ne_bytes());
1497 self
1498 }
1499 #[doc = "The device accepts \\'bps\\' metric for bw-min, bw-max and burst.\n"]
1500 pub fn push_support_metric_bps(mut self, value: ()) -> Self {
1501 push_header(self.as_vec_mut(), 3u16, 0 as u16);
1502 self
1503 }
1504 #[doc = "The device accepts \\'pps\\' metric for bw-min, bw-max and burst.\n"]
1505 pub fn push_support_metric_pps(mut self, value: ()) -> Self {
1506 push_header(self.as_vec_mut(), 4u16, 0 as u16);
1507 self
1508 }
1509 #[doc = "The device supports nesting shaper belonging to this scope below\n\\'node\\' scoped shapers. Only \\'queue\\' and \\'node\\' scope can have flag\n\\'support-nesting\\'.\n"]
1510 pub fn push_support_nesting(mut self, value: ()) -> Self {
1511 push_header(self.as_vec_mut(), 5u16, 0 as u16);
1512 self
1513 }
1514 #[doc = "The device supports a minimum guaranteed B/W.\n"]
1515 pub fn push_support_bw_min(mut self, value: ()) -> Self {
1516 push_header(self.as_vec_mut(), 6u16, 0 as u16);
1517 self
1518 }
1519 #[doc = "The device supports maximum B/W shaping.\n"]
1520 pub fn push_support_bw_max(mut self, value: ()) -> Self {
1521 push_header(self.as_vec_mut(), 7u16, 0 as u16);
1522 self
1523 }
1524 #[doc = "The device supports a maximum burst size.\n"]
1525 pub fn push_support_burst(mut self, value: ()) -> Self {
1526 push_header(self.as_vec_mut(), 8u16, 0 as u16);
1527 self
1528 }
1529 #[doc = "The device supports priority scheduling.\n"]
1530 pub fn push_support_priority(mut self, value: ()) -> Self {
1531 push_header(self.as_vec_mut(), 9u16, 0 as u16);
1532 self
1533 }
1534 #[doc = "The device supports weighted round robin scheduling.\n"]
1535 pub fn push_support_weight(mut self, value: ()) -> Self {
1536 push_header(self.as_vec_mut(), 10u16, 0 as u16);
1537 self
1538 }
1539}
1540impl<Prev: Pusher> Drop for PushCaps<Prev> {
1541 fn drop(&mut self) {
1542 if let Some(prev) = &mut self.prev {
1543 if let Some(header_offset) = &self.header_offset {
1544 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1545 }
1546 }
1547 }
1548}
1549#[doc = "Get information about a shaper for a given device.\n\nRequest attributes:\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\nReply attributes:\n- [.get_handle()](IterableNetShaper::get_handle)\n- [.get_metric()](IterableNetShaper::get_metric)\n- [.get_bw_min()](IterableNetShaper::get_bw_min)\n- [.get_bw_max()](IterableNetShaper::get_bw_max)\n- [.get_burst()](IterableNetShaper::get_burst)\n- [.get_priority()](IterableNetShaper::get_priority)\n- [.get_weight()](IterableNetShaper::get_weight)\n- [.get_ifindex()](IterableNetShaper::get_ifindex)\n- [.get_parent()](IterableNetShaper::get_parent)\n\n"]
1550#[derive(Debug)]
1551pub struct OpGetDump<'r> {
1552 request: Request<'r>,
1553}
1554impl<'r> OpGetDump<'r> {
1555 pub fn new(mut request: Request<'r>) -> Self {
1556 Self::write_header(request.buf_mut());
1557 Self {
1558 request: request.set_dump(),
1559 }
1560 }
1561 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNetShaper<&'buf mut Vec<u8>> {
1562 Self::write_header(buf);
1563 PushNetShaper::new(buf)
1564 }
1565 pub fn encode(&mut self) -> PushNetShaper<&mut Vec<u8>> {
1566 PushNetShaper::new(self.request.buf_mut())
1567 }
1568 pub fn into_encoder(self) -> PushNetShaper<RequestBuf<'r>> {
1569 PushNetShaper::new(self.request.buf)
1570 }
1571 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNetShaper<'a> {
1572 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1573 IterableNetShaper::with_loc(attrs, buf.as_ptr() as usize)
1574 }
1575 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1576 let mut header = BuiltinNfgenmsg::new();
1577 header.cmd = 1u8;
1578 header.version = 1u8;
1579 prev.as_vec_mut().extend(header.as_slice());
1580 }
1581}
1582impl NetlinkRequest for OpGetDump<'_> {
1583 fn protocol(&self) -> Protocol {
1584 Protocol::Generic("net-shaper".as_bytes())
1585 }
1586 fn flags(&self) -> u16 {
1587 self.request.flags
1588 }
1589 fn payload(&self) -> &[u8] {
1590 self.request.buf()
1591 }
1592 type ReplyType<'buf> = IterableNetShaper<'buf>;
1593 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1594 Self::decode_request(buf)
1595 }
1596 fn lookup(
1597 buf: &[u8],
1598 offset: usize,
1599 missing_type: Option<u16>,
1600 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1601 Self::decode_request(buf).lookup_attr(offset, missing_type)
1602 }
1603}
1604#[doc = "Get information about a shaper for a given device.\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\nReply attributes:\n- [.get_handle()](IterableNetShaper::get_handle)\n- [.get_metric()](IterableNetShaper::get_metric)\n- [.get_bw_min()](IterableNetShaper::get_bw_min)\n- [.get_bw_max()](IterableNetShaper::get_bw_max)\n- [.get_burst()](IterableNetShaper::get_burst)\n- [.get_priority()](IterableNetShaper::get_priority)\n- [.get_weight()](IterableNetShaper::get_weight)\n- [.get_ifindex()](IterableNetShaper::get_ifindex)\n- [.get_parent()](IterableNetShaper::get_parent)\n\n"]
1605#[derive(Debug)]
1606pub struct OpGetDo<'r> {
1607 request: Request<'r>,
1608}
1609impl<'r> OpGetDo<'r> {
1610 pub fn new(mut request: Request<'r>) -> Self {
1611 Self::write_header(request.buf_mut());
1612 Self { request: request }
1613 }
1614 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNetShaper<&'buf mut Vec<u8>> {
1615 Self::write_header(buf);
1616 PushNetShaper::new(buf)
1617 }
1618 pub fn encode(&mut self) -> PushNetShaper<&mut Vec<u8>> {
1619 PushNetShaper::new(self.request.buf_mut())
1620 }
1621 pub fn into_encoder(self) -> PushNetShaper<RequestBuf<'r>> {
1622 PushNetShaper::new(self.request.buf)
1623 }
1624 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNetShaper<'a> {
1625 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1626 IterableNetShaper::with_loc(attrs, buf.as_ptr() as usize)
1627 }
1628 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1629 let mut header = BuiltinNfgenmsg::new();
1630 header.cmd = 1u8;
1631 header.version = 1u8;
1632 prev.as_vec_mut().extend(header.as_slice());
1633 }
1634}
1635impl NetlinkRequest for OpGetDo<'_> {
1636 fn protocol(&self) -> Protocol {
1637 Protocol::Generic("net-shaper".as_bytes())
1638 }
1639 fn flags(&self) -> u16 {
1640 self.request.flags
1641 }
1642 fn payload(&self) -> &[u8] {
1643 self.request.buf()
1644 }
1645 type ReplyType<'buf> = IterableNetShaper<'buf>;
1646 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1647 Self::decode_request(buf)
1648 }
1649 fn lookup(
1650 buf: &[u8],
1651 offset: usize,
1652 missing_type: Option<u16>,
1653 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1654 Self::decode_request(buf).lookup_attr(offset, missing_type)
1655 }
1656}
1657#[doc = "Create or update the specified shaper. The set operation can\\'t be used\nto create a \\@node scope shaper, use the \\@group operation instead.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_metric()](PushNetShaper::push_metric)\n- [.push_bw_min()](PushNetShaper::push_bw_min)\n- [.push_bw_max()](PushNetShaper::push_bw_max)\n- [.push_burst()](PushNetShaper::push_burst)\n- [.push_priority()](PushNetShaper::push_priority)\n- [.push_weight()](PushNetShaper::push_weight)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\n"]
1658#[derive(Debug)]
1659pub struct OpSetDo<'r> {
1660 request: Request<'r>,
1661}
1662impl<'r> OpSetDo<'r> {
1663 pub fn new(mut request: Request<'r>) -> Self {
1664 Self::write_header(request.buf_mut());
1665 Self { request: request }
1666 }
1667 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNetShaper<&'buf mut Vec<u8>> {
1668 Self::write_header(buf);
1669 PushNetShaper::new(buf)
1670 }
1671 pub fn encode(&mut self) -> PushNetShaper<&mut Vec<u8>> {
1672 PushNetShaper::new(self.request.buf_mut())
1673 }
1674 pub fn into_encoder(self) -> PushNetShaper<RequestBuf<'r>> {
1675 PushNetShaper::new(self.request.buf)
1676 }
1677 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNetShaper<'a> {
1678 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1679 IterableNetShaper::with_loc(attrs, buf.as_ptr() as usize)
1680 }
1681 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1682 let mut header = BuiltinNfgenmsg::new();
1683 header.cmd = 2u8;
1684 header.version = 1u8;
1685 prev.as_vec_mut().extend(header.as_slice());
1686 }
1687}
1688impl NetlinkRequest for OpSetDo<'_> {
1689 fn protocol(&self) -> Protocol {
1690 Protocol::Generic("net-shaper".as_bytes())
1691 }
1692 fn flags(&self) -> u16 {
1693 self.request.flags
1694 }
1695 fn payload(&self) -> &[u8] {
1696 self.request.buf()
1697 }
1698 type ReplyType<'buf> = IterableNetShaper<'buf>;
1699 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1700 Self::decode_request(buf)
1701 }
1702 fn lookup(
1703 buf: &[u8],
1704 offset: usize,
1705 missing_type: Option<u16>,
1706 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1707 Self::decode_request(buf).lookup_attr(offset, missing_type)
1708 }
1709}
1710#[doc = "Clear (remove) the specified shaper. When deleting a \\@node shaper,\nreattach all the node\\'s leaves to the deleted node\\'s parent. If, after\nthe removal, the parent shaper has no more leaves and the parent shaper\nscope is \\@node, the parent node is deleted, recursively. When deleting\na \\@queue shaper or a \\@netdev shaper, the shaper disappears from the\nhierarchy, but the queue/device can still send traffic: it has an\nimplicit node with infinite bandwidth. The queue\\'s implicit node feeds\nan implicit RR node at the root of the hierarchy.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\n"]
1711#[derive(Debug)]
1712pub struct OpDeleteDo<'r> {
1713 request: Request<'r>,
1714}
1715impl<'r> OpDeleteDo<'r> {
1716 pub fn new(mut request: Request<'r>) -> Self {
1717 Self::write_header(request.buf_mut());
1718 Self { request: request }
1719 }
1720 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNetShaper<&'buf mut Vec<u8>> {
1721 Self::write_header(buf);
1722 PushNetShaper::new(buf)
1723 }
1724 pub fn encode(&mut self) -> PushNetShaper<&mut Vec<u8>> {
1725 PushNetShaper::new(self.request.buf_mut())
1726 }
1727 pub fn into_encoder(self) -> PushNetShaper<RequestBuf<'r>> {
1728 PushNetShaper::new(self.request.buf)
1729 }
1730 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNetShaper<'a> {
1731 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1732 IterableNetShaper::with_loc(attrs, buf.as_ptr() as usize)
1733 }
1734 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1735 let mut header = BuiltinNfgenmsg::new();
1736 header.cmd = 3u8;
1737 header.version = 1u8;
1738 prev.as_vec_mut().extend(header.as_slice());
1739 }
1740}
1741impl NetlinkRequest for OpDeleteDo<'_> {
1742 fn protocol(&self) -> Protocol {
1743 Protocol::Generic("net-shaper".as_bytes())
1744 }
1745 fn flags(&self) -> u16 {
1746 self.request.flags
1747 }
1748 fn payload(&self) -> &[u8] {
1749 self.request.buf()
1750 }
1751 type ReplyType<'buf> = IterableNetShaper<'buf>;
1752 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1753 Self::decode_request(buf)
1754 }
1755 fn lookup(
1756 buf: &[u8],
1757 offset: usize,
1758 missing_type: Option<u16>,
1759 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1760 Self::decode_request(buf).lookup_attr(offset, missing_type)
1761 }
1762}
1763#[doc = "Create or update a scheduling group, attaching the specified \\@leaves\nshapers under the specified node identified by \\@handle. The \\@leaves\nshapers scope must be \\@queue and the node shaper scope must be either\n\\@node or \\@netdev. When the node shaper has \\@node scope, if the\n\\@handle \\@id is not specified, a new shaper of such scope is created,\notherwise the specified node must already exist. When updating an\nexisting node shaper, the specified \\@leaves are added to the existing\nnode; such node will also retain any preexisting leave. The \\@parent\nhandle for a new node shaper defaults to the parent of all the leaves,\nprovided all the leaves share the same parent. Otherwise \\@parent handle\nmust be specified. The user can optionally provide shaping attributes\nfor the node shaper. The operation is atomic, on failure no change is\napplied to the device shaping configuration, otherwise the \\@node shaper\nfull identifier, comprising \\@binding and \\@handle, is provided as the\nreply.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_metric()](PushNetShaper::push_metric)\n- [.push_bw_min()](PushNetShaper::push_bw_min)\n- [.push_bw_max()](PushNetShaper::push_bw_max)\n- [.push_burst()](PushNetShaper::push_burst)\n- [.push_priority()](PushNetShaper::push_priority)\n- [.push_weight()](PushNetShaper::push_weight)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n- [.nested_parent()](PushNetShaper::nested_parent)\n- [.nested_leaves()](PushNetShaper::nested_leaves)\n\nReply attributes:\n- [.get_handle()](IterableNetShaper::get_handle)\n- [.get_ifindex()](IterableNetShaper::get_ifindex)\n\n"]
1764#[derive(Debug)]
1765pub struct OpGroupDo<'r> {
1766 request: Request<'r>,
1767}
1768impl<'r> OpGroupDo<'r> {
1769 pub fn new(mut request: Request<'r>) -> Self {
1770 Self::write_header(request.buf_mut());
1771 Self { request: request }
1772 }
1773 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNetShaper<&'buf mut Vec<u8>> {
1774 Self::write_header(buf);
1775 PushNetShaper::new(buf)
1776 }
1777 pub fn encode(&mut self) -> PushNetShaper<&mut Vec<u8>> {
1778 PushNetShaper::new(self.request.buf_mut())
1779 }
1780 pub fn into_encoder(self) -> PushNetShaper<RequestBuf<'r>> {
1781 PushNetShaper::new(self.request.buf)
1782 }
1783 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNetShaper<'a> {
1784 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1785 IterableNetShaper::with_loc(attrs, buf.as_ptr() as usize)
1786 }
1787 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1788 let mut header = BuiltinNfgenmsg::new();
1789 header.cmd = 4u8;
1790 header.version = 1u8;
1791 prev.as_vec_mut().extend(header.as_slice());
1792 }
1793}
1794impl NetlinkRequest for OpGroupDo<'_> {
1795 fn protocol(&self) -> Protocol {
1796 Protocol::Generic("net-shaper".as_bytes())
1797 }
1798 fn flags(&self) -> u16 {
1799 self.request.flags
1800 }
1801 fn payload(&self) -> &[u8] {
1802 self.request.buf()
1803 }
1804 type ReplyType<'buf> = IterableNetShaper<'buf>;
1805 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1806 Self::decode_request(buf)
1807 }
1808 fn lookup(
1809 buf: &[u8],
1810 offset: usize,
1811 missing_type: Option<u16>,
1812 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1813 Self::decode_request(buf).lookup_attr(offset, missing_type)
1814 }
1815}
1816#[doc = "Get the shaper capabilities supported by the given device for the\nspecified scope.\n\nRequest attributes:\n- [.push_ifindex()](PushCaps::push_ifindex)\n\nReply attributes:\n- [.get_ifindex()](IterableCaps::get_ifindex)\n- [.get_scope()](IterableCaps::get_scope)\n- [.get_support_metric_bps()](IterableCaps::get_support_metric_bps)\n- [.get_support_metric_pps()](IterableCaps::get_support_metric_pps)\n- [.get_support_nesting()](IterableCaps::get_support_nesting)\n- [.get_support_bw_min()](IterableCaps::get_support_bw_min)\n- [.get_support_bw_max()](IterableCaps::get_support_bw_max)\n- [.get_support_burst()](IterableCaps::get_support_burst)\n- [.get_support_priority()](IterableCaps::get_support_priority)\n- [.get_support_weight()](IterableCaps::get_support_weight)\n\n"]
1817#[derive(Debug)]
1818pub struct OpCapGetDump<'r> {
1819 request: Request<'r>,
1820}
1821impl<'r> OpCapGetDump<'r> {
1822 pub fn new(mut request: Request<'r>) -> Self {
1823 Self::write_header(request.buf_mut());
1824 Self {
1825 request: request.set_dump(),
1826 }
1827 }
1828 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushCaps<&'buf mut Vec<u8>> {
1829 Self::write_header(buf);
1830 PushCaps::new(buf)
1831 }
1832 pub fn encode(&mut self) -> PushCaps<&mut Vec<u8>> {
1833 PushCaps::new(self.request.buf_mut())
1834 }
1835 pub fn into_encoder(self) -> PushCaps<RequestBuf<'r>> {
1836 PushCaps::new(self.request.buf)
1837 }
1838 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableCaps<'a> {
1839 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1840 IterableCaps::with_loc(attrs, buf.as_ptr() as usize)
1841 }
1842 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1843 let mut header = BuiltinNfgenmsg::new();
1844 header.cmd = 5u8;
1845 header.version = 1u8;
1846 prev.as_vec_mut().extend(header.as_slice());
1847 }
1848}
1849impl NetlinkRequest for OpCapGetDump<'_> {
1850 fn protocol(&self) -> Protocol {
1851 Protocol::Generic("net-shaper".as_bytes())
1852 }
1853 fn flags(&self) -> u16 {
1854 self.request.flags
1855 }
1856 fn payload(&self) -> &[u8] {
1857 self.request.buf()
1858 }
1859 type ReplyType<'buf> = IterableCaps<'buf>;
1860 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1861 Self::decode_request(buf)
1862 }
1863 fn lookup(
1864 buf: &[u8],
1865 offset: usize,
1866 missing_type: Option<u16>,
1867 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1868 Self::decode_request(buf).lookup_attr(offset, missing_type)
1869 }
1870}
1871#[doc = "Get the shaper capabilities supported by the given device for the\nspecified scope.\n\nRequest attributes:\n- [.push_ifindex()](PushCaps::push_ifindex)\n- [.push_scope()](PushCaps::push_scope)\n\nReply attributes:\n- [.get_ifindex()](IterableCaps::get_ifindex)\n- [.get_scope()](IterableCaps::get_scope)\n- [.get_support_metric_bps()](IterableCaps::get_support_metric_bps)\n- [.get_support_metric_pps()](IterableCaps::get_support_metric_pps)\n- [.get_support_nesting()](IterableCaps::get_support_nesting)\n- [.get_support_bw_min()](IterableCaps::get_support_bw_min)\n- [.get_support_bw_max()](IterableCaps::get_support_bw_max)\n- [.get_support_burst()](IterableCaps::get_support_burst)\n- [.get_support_priority()](IterableCaps::get_support_priority)\n- [.get_support_weight()](IterableCaps::get_support_weight)\n\n"]
1872#[derive(Debug)]
1873pub struct OpCapGetDo<'r> {
1874 request: Request<'r>,
1875}
1876impl<'r> OpCapGetDo<'r> {
1877 pub fn new(mut request: Request<'r>) -> Self {
1878 Self::write_header(request.buf_mut());
1879 Self { request: request }
1880 }
1881 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushCaps<&'buf mut Vec<u8>> {
1882 Self::write_header(buf);
1883 PushCaps::new(buf)
1884 }
1885 pub fn encode(&mut self) -> PushCaps<&mut Vec<u8>> {
1886 PushCaps::new(self.request.buf_mut())
1887 }
1888 pub fn into_encoder(self) -> PushCaps<RequestBuf<'r>> {
1889 PushCaps::new(self.request.buf)
1890 }
1891 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableCaps<'a> {
1892 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1893 IterableCaps::with_loc(attrs, buf.as_ptr() as usize)
1894 }
1895 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1896 let mut header = BuiltinNfgenmsg::new();
1897 header.cmd = 5u8;
1898 header.version = 1u8;
1899 prev.as_vec_mut().extend(header.as_slice());
1900 }
1901}
1902impl NetlinkRequest for OpCapGetDo<'_> {
1903 fn protocol(&self) -> Protocol {
1904 Protocol::Generic("net-shaper".as_bytes())
1905 }
1906 fn flags(&self) -> u16 {
1907 self.request.flags
1908 }
1909 fn payload(&self) -> &[u8] {
1910 self.request.buf()
1911 }
1912 type ReplyType<'buf> = IterableCaps<'buf>;
1913 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1914 Self::decode_request(buf)
1915 }
1916 fn lookup(
1917 buf: &[u8],
1918 offset: usize,
1919 missing_type: Option<u16>,
1920 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1921 Self::decode_request(buf).lookup_attr(offset, missing_type)
1922 }
1923}
1924use crate::traits::LookupFn;
1925use crate::utils::RequestBuf;
1926#[derive(Debug)]
1927pub struct Request<'buf> {
1928 buf: RequestBuf<'buf>,
1929 flags: u16,
1930 writeback: Option<&'buf mut Option<RequestInfo>>,
1931}
1932#[allow(unused)]
1933#[derive(Debug, Clone)]
1934pub struct RequestInfo {
1935 protocol: Protocol,
1936 flags: u16,
1937 name: &'static str,
1938 lookup: LookupFn,
1939}
1940impl Request<'static> {
1941 pub fn new() -> Self {
1942 Self::new_from_buf(Vec::new())
1943 }
1944 pub fn new_from_buf(buf: Vec<u8>) -> Self {
1945 Self {
1946 flags: 0,
1947 buf: RequestBuf::Own(buf),
1948 writeback: None,
1949 }
1950 }
1951 pub fn into_buf(self) -> Vec<u8> {
1952 match self.buf {
1953 RequestBuf::Own(buf) => buf,
1954 _ => unreachable!(),
1955 }
1956 }
1957}
1958impl<'buf> Request<'buf> {
1959 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1960 buf.clear();
1961 Self::new_extend(buf)
1962 }
1963 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1964 Self {
1965 flags: 0,
1966 buf: RequestBuf::Ref(buf),
1967 writeback: None,
1968 }
1969 }
1970 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1971 let Some(writeback) = &mut self.writeback else {
1972 return;
1973 };
1974 **writeback = Some(RequestInfo {
1975 protocol,
1976 flags: self.flags,
1977 name,
1978 lookup,
1979 })
1980 }
1981 pub fn buf(&self) -> &Vec<u8> {
1982 self.buf.buf()
1983 }
1984 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1985 self.buf.buf_mut()
1986 }
1987 #[doc = "Set `NLM_F_CREATE` flag"]
1988 pub fn set_create(mut self) -> Self {
1989 self.flags |= consts::NLM_F_CREATE as u16;
1990 self
1991 }
1992 #[doc = "Set `NLM_F_EXCL` flag"]
1993 pub fn set_excl(mut self) -> Self {
1994 self.flags |= consts::NLM_F_EXCL as u16;
1995 self
1996 }
1997 #[doc = "Set `NLM_F_REPLACE` flag"]
1998 pub fn set_replace(mut self) -> Self {
1999 self.flags |= consts::NLM_F_REPLACE as u16;
2000 self
2001 }
2002 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
2003 pub fn set_change(self) -> Self {
2004 self.set_create().set_replace()
2005 }
2006 #[doc = "Set `NLM_F_APPEND` flag"]
2007 pub fn set_append(mut self) -> Self {
2008 self.flags |= consts::NLM_F_APPEND as u16;
2009 self
2010 }
2011 #[doc = "Set `self.flags |= flags`"]
2012 pub fn set_flags(mut self, flags: u16) -> Self {
2013 self.flags |= flags;
2014 self
2015 }
2016 #[doc = "Set `self.flags ^= self.flags & flags`"]
2017 pub fn unset_flags(mut self, flags: u16) -> Self {
2018 self.flags ^= self.flags & flags;
2019 self
2020 }
2021 #[doc = "Set `NLM_F_DUMP` flag"]
2022 fn set_dump(mut self) -> Self {
2023 self.flags |= consts::NLM_F_DUMP as u16;
2024 self
2025 }
2026 #[doc = "Get information about a shaper for a given device.\n\nRequest attributes:\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\nReply attributes:\n- [.get_handle()](IterableNetShaper::get_handle)\n- [.get_metric()](IterableNetShaper::get_metric)\n- [.get_bw_min()](IterableNetShaper::get_bw_min)\n- [.get_bw_max()](IterableNetShaper::get_bw_max)\n- [.get_burst()](IterableNetShaper::get_burst)\n- [.get_priority()](IterableNetShaper::get_priority)\n- [.get_weight()](IterableNetShaper::get_weight)\n- [.get_ifindex()](IterableNetShaper::get_ifindex)\n- [.get_parent()](IterableNetShaper::get_parent)\n\n"]
2027 pub fn op_get_dump(self) -> OpGetDump<'buf> {
2028 let mut res = OpGetDump::new(self);
2029 res.request
2030 .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
2031 res
2032 }
2033 #[doc = "Get information about a shaper for a given device.\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\nReply attributes:\n- [.get_handle()](IterableNetShaper::get_handle)\n- [.get_metric()](IterableNetShaper::get_metric)\n- [.get_bw_min()](IterableNetShaper::get_bw_min)\n- [.get_bw_max()](IterableNetShaper::get_bw_max)\n- [.get_burst()](IterableNetShaper::get_burst)\n- [.get_priority()](IterableNetShaper::get_priority)\n- [.get_weight()](IterableNetShaper::get_weight)\n- [.get_ifindex()](IterableNetShaper::get_ifindex)\n- [.get_parent()](IterableNetShaper::get_parent)\n\n"]
2034 pub fn op_get_do(self) -> OpGetDo<'buf> {
2035 let mut res = OpGetDo::new(self);
2036 res.request
2037 .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
2038 res
2039 }
2040 #[doc = "Create or update the specified shaper. The set operation can\\'t be used\nto create a \\@node scope shaper, use the \\@group operation instead.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_metric()](PushNetShaper::push_metric)\n- [.push_bw_min()](PushNetShaper::push_bw_min)\n- [.push_bw_max()](PushNetShaper::push_bw_max)\n- [.push_burst()](PushNetShaper::push_burst)\n- [.push_priority()](PushNetShaper::push_priority)\n- [.push_weight()](PushNetShaper::push_weight)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\n"]
2041 pub fn op_set_do(self) -> OpSetDo<'buf> {
2042 let mut res = OpSetDo::new(self);
2043 res.request
2044 .do_writeback(res.protocol(), "op-set-do", OpSetDo::lookup);
2045 res
2046 }
2047 #[doc = "Clear (remove) the specified shaper. When deleting a \\@node shaper,\nreattach all the node\\'s leaves to the deleted node\\'s parent. If, after\nthe removal, the parent shaper has no more leaves and the parent shaper\nscope is \\@node, the parent node is deleted, recursively. When deleting\na \\@queue shaper or a \\@netdev shaper, the shaper disappears from the\nhierarchy, but the queue/device can still send traffic: it has an\nimplicit node with infinite bandwidth. The queue\\'s implicit node feeds\nan implicit RR node at the root of the hierarchy.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n\n"]
2048 pub fn op_delete_do(self) -> OpDeleteDo<'buf> {
2049 let mut res = OpDeleteDo::new(self);
2050 res.request
2051 .do_writeback(res.protocol(), "op-delete-do", OpDeleteDo::lookup);
2052 res
2053 }
2054 #[doc = "Create or update a scheduling group, attaching the specified \\@leaves\nshapers under the specified node identified by \\@handle. The \\@leaves\nshapers scope must be \\@queue and the node shaper scope must be either\n\\@node or \\@netdev. When the node shaper has \\@node scope, if the\n\\@handle \\@id is not specified, a new shaper of such scope is created,\notherwise the specified node must already exist. When updating an\nexisting node shaper, the specified \\@leaves are added to the existing\nnode; such node will also retain any preexisting leave. The \\@parent\nhandle for a new node shaper defaults to the parent of all the leaves,\nprovided all the leaves share the same parent. Otherwise \\@parent handle\nmust be specified. The user can optionally provide shaping attributes\nfor the node shaper. The operation is atomic, on failure no change is\napplied to the device shaping configuration, otherwise the \\@node shaper\nfull identifier, comprising \\@binding and \\@handle, is provided as the\nreply.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_handle()](PushNetShaper::nested_handle)\n- [.push_metric()](PushNetShaper::push_metric)\n- [.push_bw_min()](PushNetShaper::push_bw_min)\n- [.push_bw_max()](PushNetShaper::push_bw_max)\n- [.push_burst()](PushNetShaper::push_burst)\n- [.push_priority()](PushNetShaper::push_priority)\n- [.push_weight()](PushNetShaper::push_weight)\n- [.push_ifindex()](PushNetShaper::push_ifindex)\n- [.nested_parent()](PushNetShaper::nested_parent)\n- [.nested_leaves()](PushNetShaper::nested_leaves)\n\nReply attributes:\n- [.get_handle()](IterableNetShaper::get_handle)\n- [.get_ifindex()](IterableNetShaper::get_ifindex)\n\n"]
2055 pub fn op_group_do(self) -> OpGroupDo<'buf> {
2056 let mut res = OpGroupDo::new(self);
2057 res.request
2058 .do_writeback(res.protocol(), "op-group-do", OpGroupDo::lookup);
2059 res
2060 }
2061 #[doc = "Get the shaper capabilities supported by the given device for the\nspecified scope.\n\nRequest attributes:\n- [.push_ifindex()](PushCaps::push_ifindex)\n\nReply attributes:\n- [.get_ifindex()](IterableCaps::get_ifindex)\n- [.get_scope()](IterableCaps::get_scope)\n- [.get_support_metric_bps()](IterableCaps::get_support_metric_bps)\n- [.get_support_metric_pps()](IterableCaps::get_support_metric_pps)\n- [.get_support_nesting()](IterableCaps::get_support_nesting)\n- [.get_support_bw_min()](IterableCaps::get_support_bw_min)\n- [.get_support_bw_max()](IterableCaps::get_support_bw_max)\n- [.get_support_burst()](IterableCaps::get_support_burst)\n- [.get_support_priority()](IterableCaps::get_support_priority)\n- [.get_support_weight()](IterableCaps::get_support_weight)\n\n"]
2062 pub fn op_cap_get_dump(self) -> OpCapGetDump<'buf> {
2063 let mut res = OpCapGetDump::new(self);
2064 res.request
2065 .do_writeback(res.protocol(), "op-cap-get-dump", OpCapGetDump::lookup);
2066 res
2067 }
2068 #[doc = "Get the shaper capabilities supported by the given device for the\nspecified scope.\n\nRequest attributes:\n- [.push_ifindex()](PushCaps::push_ifindex)\n- [.push_scope()](PushCaps::push_scope)\n\nReply attributes:\n- [.get_ifindex()](IterableCaps::get_ifindex)\n- [.get_scope()](IterableCaps::get_scope)\n- [.get_support_metric_bps()](IterableCaps::get_support_metric_bps)\n- [.get_support_metric_pps()](IterableCaps::get_support_metric_pps)\n- [.get_support_nesting()](IterableCaps::get_support_nesting)\n- [.get_support_bw_min()](IterableCaps::get_support_bw_min)\n- [.get_support_bw_max()](IterableCaps::get_support_bw_max)\n- [.get_support_burst()](IterableCaps::get_support_burst)\n- [.get_support_priority()](IterableCaps::get_support_priority)\n- [.get_support_weight()](IterableCaps::get_support_weight)\n\n"]
2069 pub fn op_cap_get_do(self) -> OpCapGetDo<'buf> {
2070 let mut res = OpCapGetDo::new(self);
2071 res.request
2072 .do_writeback(res.protocol(), "op-cap-get-do", OpCapGetDo::lookup);
2073 res
2074 }
2075}
2076#[cfg(test)]
2077mod generated_tests {
2078 use super::*;
2079 #[test]
2080 fn tests() {
2081 let _ = IterableCaps::get_ifindex;
2082 let _ = IterableCaps::get_scope;
2083 let _ = IterableCaps::get_support_burst;
2084 let _ = IterableCaps::get_support_bw_max;
2085 let _ = IterableCaps::get_support_bw_min;
2086 let _ = IterableCaps::get_support_metric_bps;
2087 let _ = IterableCaps::get_support_metric_pps;
2088 let _ = IterableCaps::get_support_nesting;
2089 let _ = IterableCaps::get_support_priority;
2090 let _ = IterableCaps::get_support_weight;
2091 let _ = IterableNetShaper::get_burst;
2092 let _ = IterableNetShaper::get_bw_max;
2093 let _ = IterableNetShaper::get_bw_min;
2094 let _ = IterableNetShaper::get_handle;
2095 let _ = IterableNetShaper::get_ifindex;
2096 let _ = IterableNetShaper::get_metric;
2097 let _ = IterableNetShaper::get_parent;
2098 let _ = IterableNetShaper::get_priority;
2099 let _ = IterableNetShaper::get_weight;
2100 let _ = PushCaps::<&mut Vec<u8>>::push_ifindex;
2101 let _ = PushCaps::<&mut Vec<u8>>::push_scope;
2102 let _ = PushNetShaper::<&mut Vec<u8>>::nested_handle;
2103 let _ = PushNetShaper::<&mut Vec<u8>>::nested_leaves;
2104 let _ = PushNetShaper::<&mut Vec<u8>>::nested_parent;
2105 let _ = PushNetShaper::<&mut Vec<u8>>::push_burst;
2106 let _ = PushNetShaper::<&mut Vec<u8>>::push_bw_max;
2107 let _ = PushNetShaper::<&mut Vec<u8>>::push_bw_min;
2108 let _ = PushNetShaper::<&mut Vec<u8>>::push_ifindex;
2109 let _ = PushNetShaper::<&mut Vec<u8>>::push_metric;
2110 let _ = PushNetShaper::<&mut Vec<u8>>::push_priority;
2111 let _ = PushNetShaper::<&mut Vec<u8>>::push_weight;
2112 }
2113}