1#![doc = "netdev configuration over generic netlink.\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 = "netdev";
17pub const PROTONAME_CSTR: &CStr = c"netdev";
18#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
19#[derive(Debug, Clone, Copy)]
20pub enum XdpAct {
21 #[doc = "XDP features set supported by all drivers (XDP_ABORTED, XDP_DROP,\nXDP_PASS, XDP_TX)\n"]
22 Basic = 1 << 0,
23 #[doc = "The netdev supports XDP_REDIRECT\n"]
24 Redirect = 1 << 1,
25 #[doc = "This feature informs if netdev implements ndo_xdp_xmit callback.\n"]
26 NdoXmit = 1 << 2,
27 #[doc = "This feature informs if netdev supports AF_XDP in zero copy mode.\n"]
28 XskZerocopy = 1 << 3,
29 #[doc = "This feature informs if netdev supports XDP hw offloading.\n"]
30 HwOffload = 1 << 4,
31 #[doc = "This feature informs if netdev implements non-linear XDP buffer support\nin the driver napi callback.\n"]
32 RxSg = 1 << 5,
33 #[doc = "This feature informs if netdev implements non-linear XDP buffer support\nin ndo_xdp_xmit callback.\n"]
34 NdoXmitSg = 1 << 6,
35}
36impl XdpAct {
37 pub fn from_value(value: u64) -> Option<Self> {
38 Some(match value {
39 n if n == 1 << 0 => Self::Basic,
40 n if n == 1 << 1 => Self::Redirect,
41 n if n == 1 << 2 => Self::NdoXmit,
42 n if n == 1 << 3 => Self::XskZerocopy,
43 n if n == 1 << 4 => Self::HwOffload,
44 n if n == 1 << 5 => Self::RxSg,
45 n if n == 1 << 6 => Self::NdoXmitSg,
46 _ => return None,
47 })
48 }
49}
50#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
51#[derive(Debug, Clone, Copy)]
52pub enum XdpRxMetadata {
53 #[doc = "Device is capable of exposing receive HW timestamp via\nbpf_xdp_metadata_rx_timestamp().\n"]
54 Timestamp = 1 << 0,
55 #[doc = "Device is capable of exposing receive packet hash via\nbpf_xdp_metadata_rx_hash().\n"]
56 Hash = 1 << 1,
57 #[doc = "Device is capable of exposing receive packet VLAN tag via\nbpf_xdp_metadata_rx_vlan_tag().\n"]
58 VlanTag = 1 << 2,
59}
60impl XdpRxMetadata {
61 pub fn from_value(value: u64) -> Option<Self> {
62 Some(match value {
63 n if n == 1 << 0 => Self::Timestamp,
64 n if n == 1 << 1 => Self::Hash,
65 n if n == 1 << 2 => Self::VlanTag,
66 _ => return None,
67 })
68 }
69}
70#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
71#[derive(Debug, Clone, Copy)]
72pub enum XskFlags {
73 #[doc = "HW timestamping egress packets is supported by the driver.\n"]
74 TxTimestamp = 1 << 0,
75 #[doc = "L3 checksum HW offload is supported by the driver.\n"]
76 TxChecksum = 1 << 1,
77 #[doc = "Launch time HW offload is supported by the driver.\n"]
78 TxLaunchTimeFifo = 1 << 2,
79}
80impl XskFlags {
81 pub fn from_value(value: u64) -> Option<Self> {
82 Some(match value {
83 n if n == 1 << 0 => Self::TxTimestamp,
84 n if n == 1 << 1 => Self::TxChecksum,
85 n if n == 1 << 2 => Self::TxLaunchTimeFifo,
86 _ => return None,
87 })
88 }
89}
90#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
91#[derive(Debug, Clone, Copy)]
92pub enum QueueType {
93 Rx = 0,
94 Tx = 1,
95}
96impl QueueType {
97 pub fn from_value(value: u64) -> Option<Self> {
98 Some(match value {
99 0 => Self::Rx,
100 1 => Self::Tx,
101 _ => return None,
102 })
103 }
104}
105#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
106#[derive(Debug, Clone, Copy)]
107pub enum QstatsScope {
108 Queue = 1 << 0,
109}
110impl QstatsScope {
111 pub fn from_value(value: u64) -> Option<Self> {
112 Some(match value {
113 n if n == 1 << 0 => Self::Queue,
114 _ => return None,
115 })
116 }
117}
118#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
119#[derive(Debug, Clone, Copy)]
120pub enum NapiThreaded {
121 Disabled = 0,
122 Enabled = 1,
123 BusyPoll = 2,
124}
125impl NapiThreaded {
126 pub fn from_value(value: u64) -> Option<Self> {
127 Some(match value {
128 0 => Self::Disabled,
129 1 => Self::Enabled,
130 2 => Self::BusyPoll,
131 _ => return None,
132 })
133 }
134}
135#[derive(Clone)]
136pub enum Dev<'a> {
137 #[doc = "netdev ifindex\n"]
138 Ifindex(u32),
139 Pad(&'a [u8]),
140 #[doc = "Bitmask of enabled xdp-features.\n\nAssociated type: [`XdpAct`] (enum)"]
141 XdpFeatures(u64),
142 #[doc = "max fragment count supported by ZC driver\n"]
143 XdpZcMaxSegs(u32),
144 #[doc = "Bitmask of supported XDP receive metadata features. See\nDocumentation/networking/xdp-rx-metadata.rst for more details.\n\nAssociated type: [`XdpRxMetadata`] (enum)"]
145 XdpRxMetadataFeatures(u64),
146 #[doc = "Bitmask of enabled AF_XDP features.\n\nAssociated type: [`XskFlags`] (enum)"]
147 XskFeatures(u64),
148}
149impl<'a> IterableDev<'a> {
150 #[doc = "netdev ifindex\n"]
151 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
152 let mut iter = self.clone();
153 iter.pos = 0;
154 for attr in iter {
155 if let Ok(Dev::Ifindex(val)) = attr {
156 return Ok(val);
157 }
158 }
159 Err(ErrorContext::new_missing(
160 "Dev",
161 "Ifindex",
162 self.orig_loc,
163 self.buf.as_ptr() as usize,
164 ))
165 }
166 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
167 let mut iter = self.clone();
168 iter.pos = 0;
169 for attr in iter {
170 if let Ok(Dev::Pad(val)) = attr {
171 return Ok(val);
172 }
173 }
174 Err(ErrorContext::new_missing(
175 "Dev",
176 "Pad",
177 self.orig_loc,
178 self.buf.as_ptr() as usize,
179 ))
180 }
181 #[doc = "Bitmask of enabled xdp-features.\n\nAssociated type: [`XdpAct`] (enum)"]
182 pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
183 let mut iter = self.clone();
184 iter.pos = 0;
185 for attr in iter {
186 if let Ok(Dev::XdpFeatures(val)) = attr {
187 return Ok(val);
188 }
189 }
190 Err(ErrorContext::new_missing(
191 "Dev",
192 "XdpFeatures",
193 self.orig_loc,
194 self.buf.as_ptr() as usize,
195 ))
196 }
197 #[doc = "max fragment count supported by ZC driver\n"]
198 pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
199 let mut iter = self.clone();
200 iter.pos = 0;
201 for attr in iter {
202 if let Ok(Dev::XdpZcMaxSegs(val)) = attr {
203 return Ok(val);
204 }
205 }
206 Err(ErrorContext::new_missing(
207 "Dev",
208 "XdpZcMaxSegs",
209 self.orig_loc,
210 self.buf.as_ptr() as usize,
211 ))
212 }
213 #[doc = "Bitmask of supported XDP receive metadata features. See\nDocumentation/networking/xdp-rx-metadata.rst for more details.\n\nAssociated type: [`XdpRxMetadata`] (enum)"]
214 pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
215 let mut iter = self.clone();
216 iter.pos = 0;
217 for attr in iter {
218 if let Ok(Dev::XdpRxMetadataFeatures(val)) = attr {
219 return Ok(val);
220 }
221 }
222 Err(ErrorContext::new_missing(
223 "Dev",
224 "XdpRxMetadataFeatures",
225 self.orig_loc,
226 self.buf.as_ptr() as usize,
227 ))
228 }
229 #[doc = "Bitmask of enabled AF_XDP features.\n\nAssociated type: [`XskFlags`] (enum)"]
230 pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
231 let mut iter = self.clone();
232 iter.pos = 0;
233 for attr in iter {
234 if let Ok(Dev::XskFeatures(val)) = attr {
235 return Ok(val);
236 }
237 }
238 Err(ErrorContext::new_missing(
239 "Dev",
240 "XskFeatures",
241 self.orig_loc,
242 self.buf.as_ptr() as usize,
243 ))
244 }
245}
246impl Dev<'_> {
247 pub fn new<'a>(buf: &'a [u8]) -> IterableDev<'a> {
248 IterableDev::with_loc(buf, buf.as_ptr() as usize)
249 }
250 fn attr_from_type(r#type: u16) -> Option<&'static str> {
251 let res = match r#type {
252 1u16 => "Ifindex",
253 2u16 => "Pad",
254 3u16 => "XdpFeatures",
255 4u16 => "XdpZcMaxSegs",
256 5u16 => "XdpRxMetadataFeatures",
257 6u16 => "XskFeatures",
258 _ => return None,
259 };
260 Some(res)
261 }
262}
263#[derive(Clone, Copy, Default)]
264pub struct IterableDev<'a> {
265 buf: &'a [u8],
266 pos: usize,
267 orig_loc: usize,
268}
269impl<'a> IterableDev<'a> {
270 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
271 Self {
272 buf,
273 pos: 0,
274 orig_loc,
275 }
276 }
277 pub fn get_buf(&self) -> &'a [u8] {
278 self.buf
279 }
280}
281impl<'a> Iterator for IterableDev<'a> {
282 type Item = Result<Dev<'a>, ErrorContext>;
283 fn next(&mut self) -> Option<Self::Item> {
284 let mut pos;
285 let mut r#type;
286 loop {
287 pos = self.pos;
288 r#type = None;
289 if self.buf.len() == self.pos {
290 return None;
291 }
292 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
293 self.pos = self.buf.len();
294 break;
295 };
296 r#type = Some(header.r#type);
297 let res = match header.r#type {
298 1u16 => Dev::Ifindex({
299 let res = parse_u32(next);
300 let Some(val) = res else { break };
301 val
302 }),
303 2u16 => Dev::Pad({
304 let res = Some(next);
305 let Some(val) = res else { break };
306 val
307 }),
308 3u16 => Dev::XdpFeatures({
309 let res = parse_u64(next);
310 let Some(val) = res else { break };
311 val
312 }),
313 4u16 => Dev::XdpZcMaxSegs({
314 let res = parse_u32(next);
315 let Some(val) = res else { break };
316 val
317 }),
318 5u16 => Dev::XdpRxMetadataFeatures({
319 let res = parse_u64(next);
320 let Some(val) = res else { break };
321 val
322 }),
323 6u16 => Dev::XskFeatures({
324 let res = parse_u64(next);
325 let Some(val) = res else { break };
326 val
327 }),
328 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
329 n => continue,
330 };
331 return Some(Ok(res));
332 }
333 Some(Err(ErrorContext::new(
334 "Dev",
335 r#type.and_then(|t| Dev::attr_from_type(t)),
336 self.orig_loc,
337 self.buf.as_ptr().wrapping_add(pos) as usize,
338 )))
339 }
340}
341impl<'a> std::fmt::Debug for IterableDev<'_> {
342 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
343 let mut fmt = f.debug_struct("Dev");
344 for attr in self.clone() {
345 let attr = match attr {
346 Ok(a) => a,
347 Err(err) => {
348 fmt.finish()?;
349 f.write_str("Err(")?;
350 err.fmt(f)?;
351 return f.write_str(")");
352 }
353 };
354 match attr {
355 Dev::Ifindex(val) => fmt.field("Ifindex", &val),
356 Dev::Pad(val) => fmt.field("Pad", &val),
357 Dev::XdpFeatures(val) => {
358 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
359 }
360 Dev::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
361 Dev::XdpRxMetadataFeatures(val) => fmt.field(
362 "XdpRxMetadataFeatures",
363 &FormatFlags(val.into(), XdpRxMetadata::from_value),
364 ),
365 Dev::XskFeatures(val) => fmt.field(
366 "XskFeatures",
367 &FormatFlags(val.into(), XskFlags::from_value),
368 ),
369 };
370 }
371 fmt.finish()
372 }
373}
374impl IterableDev<'_> {
375 pub fn lookup_attr(
376 &self,
377 offset: usize,
378 missing_type: Option<u16>,
379 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
380 let mut stack = Vec::new();
381 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
382 if missing_type.is_some() && cur == offset {
383 stack.push(("Dev", offset));
384 return (stack, missing_type.and_then(|t| Dev::attr_from_type(t)));
385 }
386 if cur > offset || cur + self.buf.len() < offset {
387 return (stack, None);
388 }
389 let mut attrs = self.clone();
390 let mut last_off = cur + attrs.pos;
391 while let Some(attr) = attrs.next() {
392 let Ok(attr) = attr else { break };
393 match attr {
394 Dev::Ifindex(val) => {
395 if last_off == offset {
396 stack.push(("Ifindex", last_off));
397 break;
398 }
399 }
400 Dev::Pad(val) => {
401 if last_off == offset {
402 stack.push(("Pad", last_off));
403 break;
404 }
405 }
406 Dev::XdpFeatures(val) => {
407 if last_off == offset {
408 stack.push(("XdpFeatures", last_off));
409 break;
410 }
411 }
412 Dev::XdpZcMaxSegs(val) => {
413 if last_off == offset {
414 stack.push(("XdpZcMaxSegs", last_off));
415 break;
416 }
417 }
418 Dev::XdpRxMetadataFeatures(val) => {
419 if last_off == offset {
420 stack.push(("XdpRxMetadataFeatures", last_off));
421 break;
422 }
423 }
424 Dev::XskFeatures(val) => {
425 if last_off == offset {
426 stack.push(("XskFeatures", last_off));
427 break;
428 }
429 }
430 _ => {}
431 };
432 last_off = cur + attrs.pos;
433 }
434 if !stack.is_empty() {
435 stack.push(("Dev", cur));
436 }
437 (stack, None)
438 }
439}
440#[derive(Clone)]
441pub enum IoUringProviderInfo {}
442impl<'a> IterableIoUringProviderInfo<'a> {}
443impl IoUringProviderInfo {
444 pub fn new<'a>(buf: &'a [u8]) -> IterableIoUringProviderInfo<'a> {
445 IterableIoUringProviderInfo::with_loc(buf, buf.as_ptr() as usize)
446 }
447 fn attr_from_type(r#type: u16) -> Option<&'static str> {
448 None
449 }
450}
451#[derive(Clone, Copy, Default)]
452pub struct IterableIoUringProviderInfo<'a> {
453 buf: &'a [u8],
454 pos: usize,
455 orig_loc: usize,
456}
457impl<'a> IterableIoUringProviderInfo<'a> {
458 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
459 Self {
460 buf,
461 pos: 0,
462 orig_loc,
463 }
464 }
465 pub fn get_buf(&self) -> &'a [u8] {
466 self.buf
467 }
468}
469impl<'a> Iterator for IterableIoUringProviderInfo<'a> {
470 type Item = Result<IoUringProviderInfo, ErrorContext>;
471 fn next(&mut self) -> Option<Self::Item> {
472 let mut pos;
473 let mut r#type;
474 loop {
475 pos = self.pos;
476 r#type = None;
477 if self.buf.len() == self.pos {
478 return None;
479 }
480 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
481 self.pos = self.buf.len();
482 break;
483 };
484 r#type = Some(header.r#type);
485 let res = match header.r#type {
486 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
487 n => continue,
488 };
489 return Some(Ok(res));
490 }
491 Some(Err(ErrorContext::new(
492 "IoUringProviderInfo",
493 r#type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
494 self.orig_loc,
495 self.buf.as_ptr().wrapping_add(pos) as usize,
496 )))
497 }
498}
499impl std::fmt::Debug for IterableIoUringProviderInfo<'_> {
500 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
501 let mut fmt = f.debug_struct("IoUringProviderInfo");
502 for attr in self.clone() {
503 let attr = match attr {
504 Ok(a) => a,
505 Err(err) => {
506 fmt.finish()?;
507 f.write_str("Err(")?;
508 err.fmt(f)?;
509 return f.write_str(")");
510 }
511 };
512 match attr {};
513 }
514 fmt.finish()
515 }
516}
517impl IterableIoUringProviderInfo<'_> {
518 pub fn lookup_attr(
519 &self,
520 offset: usize,
521 missing_type: Option<u16>,
522 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
523 let mut stack = Vec::new();
524 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
525 if missing_type.is_some() && cur == offset {
526 stack.push(("IoUringProviderInfo", offset));
527 return (
528 stack,
529 missing_type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
530 );
531 }
532 (stack, None)
533 }
534}
535#[derive(Clone)]
536pub enum PagePool<'a> {
537 #[doc = "Unique ID of a Page Pool instance.\n"]
538 Id(u32),
539 #[doc = "ifindex of the netdev to which the pool belongs. May not be reported if\nthe page pool was allocated for a netdev which got destroyed already\n(page pools may outlast their netdevs because they wait for all memory\nto be returned).\n"]
540 Ifindex(u32),
541 #[doc = "Id of NAPI using this Page Pool instance.\n"]
542 NapiId(u32),
543 #[doc = "Number of outstanding references to this page pool (allocated but yet to\nbe freed pages). Allocated pages may be held in socket receive queues,\ndriver receive ring, page pool recycling ring, the page pool cache, etc.\n"]
544 Inflight(u32),
545 #[doc = "Amount of memory held by inflight pages.\n"]
546 InflightMem(u32),
547 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by the driver.\nOnce detached Page Pool can no longer be used to allocate memory. Page\nPools wait for all the memory allocated from them to be freed before\ntruly disappearing. \\\"Detached\\\" Page Pools cannot be \\\"re-attached\\\",\nthey are just waiting to disappear. Attribute is absent if Page Pool has\nnot been detached, and can still be used to allocate new memory.\n"]
548 DetachTime(u32),
549 #[doc = "ID of the dmabuf this page-pool is attached to.\n"]
550 Dmabuf(u32),
551 #[doc = "io-uring memory provider information.\n"]
552 IoUring(IterableIoUringProviderInfo<'a>),
553}
554impl<'a> IterablePagePool<'a> {
555 #[doc = "Unique ID of a Page Pool instance.\n"]
556 pub fn get_id(&self) -> Result<u32, ErrorContext> {
557 let mut iter = self.clone();
558 iter.pos = 0;
559 for attr in iter {
560 if let Ok(PagePool::Id(val)) = attr {
561 return Ok(val);
562 }
563 }
564 Err(ErrorContext::new_missing(
565 "PagePool",
566 "Id",
567 self.orig_loc,
568 self.buf.as_ptr() as usize,
569 ))
570 }
571 #[doc = "ifindex of the netdev to which the pool belongs. May not be reported if\nthe page pool was allocated for a netdev which got destroyed already\n(page pools may outlast their netdevs because they wait for all memory\nto be returned).\n"]
572 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
573 let mut iter = self.clone();
574 iter.pos = 0;
575 for attr in iter {
576 if let Ok(PagePool::Ifindex(val)) = attr {
577 return Ok(val);
578 }
579 }
580 Err(ErrorContext::new_missing(
581 "PagePool",
582 "Ifindex",
583 self.orig_loc,
584 self.buf.as_ptr() as usize,
585 ))
586 }
587 #[doc = "Id of NAPI using this Page Pool instance.\n"]
588 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
589 let mut iter = self.clone();
590 iter.pos = 0;
591 for attr in iter {
592 if let Ok(PagePool::NapiId(val)) = attr {
593 return Ok(val);
594 }
595 }
596 Err(ErrorContext::new_missing(
597 "PagePool",
598 "NapiId",
599 self.orig_loc,
600 self.buf.as_ptr() as usize,
601 ))
602 }
603 #[doc = "Number of outstanding references to this page pool (allocated but yet to\nbe freed pages). Allocated pages may be held in socket receive queues,\ndriver receive ring, page pool recycling ring, the page pool cache, etc.\n"]
604 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
605 let mut iter = self.clone();
606 iter.pos = 0;
607 for attr in iter {
608 if let Ok(PagePool::Inflight(val)) = attr {
609 return Ok(val);
610 }
611 }
612 Err(ErrorContext::new_missing(
613 "PagePool",
614 "Inflight",
615 self.orig_loc,
616 self.buf.as_ptr() as usize,
617 ))
618 }
619 #[doc = "Amount of memory held by inflight pages.\n"]
620 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
621 let mut iter = self.clone();
622 iter.pos = 0;
623 for attr in iter {
624 if let Ok(PagePool::InflightMem(val)) = attr {
625 return Ok(val);
626 }
627 }
628 Err(ErrorContext::new_missing(
629 "PagePool",
630 "InflightMem",
631 self.orig_loc,
632 self.buf.as_ptr() as usize,
633 ))
634 }
635 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by the driver.\nOnce detached Page Pool can no longer be used to allocate memory. Page\nPools wait for all the memory allocated from them to be freed before\ntruly disappearing. \\\"Detached\\\" Page Pools cannot be \\\"re-attached\\\",\nthey are just waiting to disappear. Attribute is absent if Page Pool has\nnot been detached, and can still be used to allocate new memory.\n"]
636 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
637 let mut iter = self.clone();
638 iter.pos = 0;
639 for attr in iter {
640 if let Ok(PagePool::DetachTime(val)) = attr {
641 return Ok(val);
642 }
643 }
644 Err(ErrorContext::new_missing(
645 "PagePool",
646 "DetachTime",
647 self.orig_loc,
648 self.buf.as_ptr() as usize,
649 ))
650 }
651 #[doc = "ID of the dmabuf this page-pool is attached to.\n"]
652 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
653 let mut iter = self.clone();
654 iter.pos = 0;
655 for attr in iter {
656 if let Ok(PagePool::Dmabuf(val)) = attr {
657 return Ok(val);
658 }
659 }
660 Err(ErrorContext::new_missing(
661 "PagePool",
662 "Dmabuf",
663 self.orig_loc,
664 self.buf.as_ptr() as usize,
665 ))
666 }
667 #[doc = "io-uring memory provider information.\n"]
668 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
669 let mut iter = self.clone();
670 iter.pos = 0;
671 for attr in iter {
672 if let Ok(PagePool::IoUring(val)) = attr {
673 return Ok(val);
674 }
675 }
676 Err(ErrorContext::new_missing(
677 "PagePool",
678 "IoUring",
679 self.orig_loc,
680 self.buf.as_ptr() as usize,
681 ))
682 }
683}
684impl PagePool<'_> {
685 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
686 IterablePagePool::with_loc(buf, buf.as_ptr() as usize)
687 }
688 fn attr_from_type(r#type: u16) -> Option<&'static str> {
689 let res = match r#type {
690 1u16 => "Id",
691 2u16 => "Ifindex",
692 3u16 => "NapiId",
693 4u16 => "Inflight",
694 5u16 => "InflightMem",
695 6u16 => "DetachTime",
696 7u16 => "Dmabuf",
697 8u16 => "IoUring",
698 _ => return None,
699 };
700 Some(res)
701 }
702}
703#[derive(Clone, Copy, Default)]
704pub struct IterablePagePool<'a> {
705 buf: &'a [u8],
706 pos: usize,
707 orig_loc: usize,
708}
709impl<'a> IterablePagePool<'a> {
710 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
711 Self {
712 buf,
713 pos: 0,
714 orig_loc,
715 }
716 }
717 pub fn get_buf(&self) -> &'a [u8] {
718 self.buf
719 }
720}
721impl<'a> Iterator for IterablePagePool<'a> {
722 type Item = Result<PagePool<'a>, ErrorContext>;
723 fn next(&mut self) -> Option<Self::Item> {
724 let mut pos;
725 let mut r#type;
726 loop {
727 pos = self.pos;
728 r#type = None;
729 if self.buf.len() == self.pos {
730 return None;
731 }
732 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
733 self.pos = self.buf.len();
734 break;
735 };
736 r#type = Some(header.r#type);
737 let res = match header.r#type {
738 1u16 => PagePool::Id({
739 let res = parse_u32(next);
740 let Some(val) = res else { break };
741 val
742 }),
743 2u16 => PagePool::Ifindex({
744 let res = parse_u32(next);
745 let Some(val) = res else { break };
746 val
747 }),
748 3u16 => PagePool::NapiId({
749 let res = parse_u32(next);
750 let Some(val) = res else { break };
751 val
752 }),
753 4u16 => PagePool::Inflight({
754 let res = parse_u32(next);
755 let Some(val) = res else { break };
756 val
757 }),
758 5u16 => PagePool::InflightMem({
759 let res = parse_u32(next);
760 let Some(val) = res else { break };
761 val
762 }),
763 6u16 => PagePool::DetachTime({
764 let res = parse_u32(next);
765 let Some(val) = res else { break };
766 val
767 }),
768 7u16 => PagePool::Dmabuf({
769 let res = parse_u32(next);
770 let Some(val) = res else { break };
771 val
772 }),
773 8u16 => PagePool::IoUring({
774 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
775 let Some(val) = res else { break };
776 val
777 }),
778 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
779 n => continue,
780 };
781 return Some(Ok(res));
782 }
783 Some(Err(ErrorContext::new(
784 "PagePool",
785 r#type.and_then(|t| PagePool::attr_from_type(t)),
786 self.orig_loc,
787 self.buf.as_ptr().wrapping_add(pos) as usize,
788 )))
789 }
790}
791impl<'a> std::fmt::Debug for IterablePagePool<'_> {
792 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
793 let mut fmt = f.debug_struct("PagePool");
794 for attr in self.clone() {
795 let attr = match attr {
796 Ok(a) => a,
797 Err(err) => {
798 fmt.finish()?;
799 f.write_str("Err(")?;
800 err.fmt(f)?;
801 return f.write_str(")");
802 }
803 };
804 match attr {
805 PagePool::Id(val) => fmt.field("Id", &val),
806 PagePool::Ifindex(val) => fmt.field("Ifindex", &val),
807 PagePool::NapiId(val) => fmt.field("NapiId", &val),
808 PagePool::Inflight(val) => fmt.field("Inflight", &val),
809 PagePool::InflightMem(val) => fmt.field("InflightMem", &val),
810 PagePool::DetachTime(val) => fmt.field("DetachTime", &val),
811 PagePool::Dmabuf(val) => fmt.field("Dmabuf", &val),
812 PagePool::IoUring(val) => fmt.field("IoUring", &val),
813 };
814 }
815 fmt.finish()
816 }
817}
818impl IterablePagePool<'_> {
819 pub fn lookup_attr(
820 &self,
821 offset: usize,
822 missing_type: Option<u16>,
823 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
824 let mut stack = Vec::new();
825 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
826 if missing_type.is_some() && cur == offset {
827 stack.push(("PagePool", offset));
828 return (
829 stack,
830 missing_type.and_then(|t| PagePool::attr_from_type(t)),
831 );
832 }
833 if cur > offset || cur + self.buf.len() < offset {
834 return (stack, None);
835 }
836 let mut attrs = self.clone();
837 let mut last_off = cur + attrs.pos;
838 let mut missing = None;
839 while let Some(attr) = attrs.next() {
840 let Ok(attr) = attr else { break };
841 match attr {
842 PagePool::Id(val) => {
843 if last_off == offset {
844 stack.push(("Id", last_off));
845 break;
846 }
847 }
848 PagePool::Ifindex(val) => {
849 if last_off == offset {
850 stack.push(("Ifindex", last_off));
851 break;
852 }
853 }
854 PagePool::NapiId(val) => {
855 if last_off == offset {
856 stack.push(("NapiId", last_off));
857 break;
858 }
859 }
860 PagePool::Inflight(val) => {
861 if last_off == offset {
862 stack.push(("Inflight", last_off));
863 break;
864 }
865 }
866 PagePool::InflightMem(val) => {
867 if last_off == offset {
868 stack.push(("InflightMem", last_off));
869 break;
870 }
871 }
872 PagePool::DetachTime(val) => {
873 if last_off == offset {
874 stack.push(("DetachTime", last_off));
875 break;
876 }
877 }
878 PagePool::Dmabuf(val) => {
879 if last_off == offset {
880 stack.push(("Dmabuf", last_off));
881 break;
882 }
883 }
884 PagePool::IoUring(val) => {
885 (stack, missing) = val.lookup_attr(offset, missing_type);
886 if !stack.is_empty() {
887 break;
888 }
889 }
890 _ => {}
891 };
892 last_off = cur + attrs.pos;
893 }
894 if !stack.is_empty() {
895 stack.push(("PagePool", cur));
896 }
897 (stack, missing)
898 }
899}
900#[derive(Clone)]
901pub enum PagePoolInfo {
902 #[doc = "Unique ID of a Page Pool instance.\n"]
903 Id(u32),
904 #[doc = "ifindex of the netdev to which the pool belongs. May not be reported if\nthe page pool was allocated for a netdev which got destroyed already\n(page pools may outlast their netdevs because they wait for all memory\nto be returned).\n"]
905 Ifindex(u32),
906}
907impl<'a> IterablePagePoolInfo<'a> {
908 #[doc = "Unique ID of a Page Pool instance.\n"]
909 pub fn get_id(&self) -> Result<u32, ErrorContext> {
910 let mut iter = self.clone();
911 iter.pos = 0;
912 for attr in iter {
913 if let Ok(PagePoolInfo::Id(val)) = attr {
914 return Ok(val);
915 }
916 }
917 Err(ErrorContext::new_missing(
918 "PagePoolInfo",
919 "Id",
920 self.orig_loc,
921 self.buf.as_ptr() as usize,
922 ))
923 }
924 #[doc = "ifindex of the netdev to which the pool belongs. May not be reported if\nthe page pool was allocated for a netdev which got destroyed already\n(page pools may outlast their netdevs because they wait for all memory\nto be returned).\n"]
925 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
926 let mut iter = self.clone();
927 iter.pos = 0;
928 for attr in iter {
929 if let Ok(PagePoolInfo::Ifindex(val)) = attr {
930 return Ok(val);
931 }
932 }
933 Err(ErrorContext::new_missing(
934 "PagePoolInfo",
935 "Ifindex",
936 self.orig_loc,
937 self.buf.as_ptr() as usize,
938 ))
939 }
940}
941impl PagePoolInfo {
942 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolInfo<'a> {
943 IterablePagePoolInfo::with_loc(buf, buf.as_ptr() as usize)
944 }
945 fn attr_from_type(r#type: u16) -> Option<&'static str> {
946 PagePool::attr_from_type(r#type)
947 }
948}
949#[derive(Clone, Copy, Default)]
950pub struct IterablePagePoolInfo<'a> {
951 buf: &'a [u8],
952 pos: usize,
953 orig_loc: usize,
954}
955impl<'a> IterablePagePoolInfo<'a> {
956 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
957 Self {
958 buf,
959 pos: 0,
960 orig_loc,
961 }
962 }
963 pub fn get_buf(&self) -> &'a [u8] {
964 self.buf
965 }
966}
967impl<'a> Iterator for IterablePagePoolInfo<'a> {
968 type Item = Result<PagePoolInfo, ErrorContext>;
969 fn next(&mut self) -> Option<Self::Item> {
970 let mut pos;
971 let mut r#type;
972 loop {
973 pos = self.pos;
974 r#type = None;
975 if self.buf.len() == self.pos {
976 return None;
977 }
978 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
979 self.pos = self.buf.len();
980 break;
981 };
982 r#type = Some(header.r#type);
983 let res = match header.r#type {
984 1u16 => PagePoolInfo::Id({
985 let res = parse_u32(next);
986 let Some(val) = res else { break };
987 val
988 }),
989 2u16 => PagePoolInfo::Ifindex({
990 let res = parse_u32(next);
991 let Some(val) = res else { break };
992 val
993 }),
994 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
995 n => continue,
996 };
997 return Some(Ok(res));
998 }
999 Some(Err(ErrorContext::new(
1000 "PagePoolInfo",
1001 r#type.and_then(|t| PagePoolInfo::attr_from_type(t)),
1002 self.orig_loc,
1003 self.buf.as_ptr().wrapping_add(pos) as usize,
1004 )))
1005 }
1006}
1007impl std::fmt::Debug for IterablePagePoolInfo<'_> {
1008 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1009 let mut fmt = f.debug_struct("PagePoolInfo");
1010 for attr in self.clone() {
1011 let attr = match attr {
1012 Ok(a) => a,
1013 Err(err) => {
1014 fmt.finish()?;
1015 f.write_str("Err(")?;
1016 err.fmt(f)?;
1017 return f.write_str(")");
1018 }
1019 };
1020 match attr {
1021 PagePoolInfo::Id(val) => fmt.field("Id", &val),
1022 PagePoolInfo::Ifindex(val) => fmt.field("Ifindex", &val),
1023 };
1024 }
1025 fmt.finish()
1026 }
1027}
1028impl IterablePagePoolInfo<'_> {
1029 pub fn lookup_attr(
1030 &self,
1031 offset: usize,
1032 missing_type: Option<u16>,
1033 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1034 let mut stack = Vec::new();
1035 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1036 if missing_type.is_some() && cur == offset {
1037 stack.push(("PagePoolInfo", offset));
1038 return (
1039 stack,
1040 missing_type.and_then(|t| PagePoolInfo::attr_from_type(t)),
1041 );
1042 }
1043 if cur > offset || cur + self.buf.len() < offset {
1044 return (stack, None);
1045 }
1046 let mut attrs = self.clone();
1047 let mut last_off = cur + attrs.pos;
1048 while let Some(attr) = attrs.next() {
1049 let Ok(attr) = attr else { break };
1050 match attr {
1051 PagePoolInfo::Id(val) => {
1052 if last_off == offset {
1053 stack.push(("Id", last_off));
1054 break;
1055 }
1056 }
1057 PagePoolInfo::Ifindex(val) => {
1058 if last_off == offset {
1059 stack.push(("Ifindex", last_off));
1060 break;
1061 }
1062 }
1063 _ => {}
1064 };
1065 last_off = cur + attrs.pos;
1066 }
1067 if !stack.is_empty() {
1068 stack.push(("PagePoolInfo", cur));
1069 }
1070 (stack, None)
1071 }
1072}
1073#[derive(Clone)]
1074pub enum PagePoolStats<'a> {
1075 #[doc = "Page pool identifying information.\n"]
1076 Info(IterablePagePoolInfo<'a>),
1077 AllocFast(u32),
1078 AllocSlow(u32),
1079 AllocSlowHighOrder(u32),
1080 AllocEmpty(u32),
1081 AllocRefill(u32),
1082 AllocWaive(u32),
1083 RecycleCached(u32),
1084 RecycleCacheFull(u32),
1085 RecycleRing(u32),
1086 RecycleRingFull(u32),
1087 RecycleReleasedRefcnt(u32),
1088}
1089impl<'a> IterablePagePoolStats<'a> {
1090 #[doc = "Page pool identifying information.\n"]
1091 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
1092 let mut iter = self.clone();
1093 iter.pos = 0;
1094 for attr in iter {
1095 if let Ok(PagePoolStats::Info(val)) = attr {
1096 return Ok(val);
1097 }
1098 }
1099 Err(ErrorContext::new_missing(
1100 "PagePoolStats",
1101 "Info",
1102 self.orig_loc,
1103 self.buf.as_ptr() as usize,
1104 ))
1105 }
1106 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
1107 let mut iter = self.clone();
1108 iter.pos = 0;
1109 for attr in iter {
1110 if let Ok(PagePoolStats::AllocFast(val)) = attr {
1111 return Ok(val);
1112 }
1113 }
1114 Err(ErrorContext::new_missing(
1115 "PagePoolStats",
1116 "AllocFast",
1117 self.orig_loc,
1118 self.buf.as_ptr() as usize,
1119 ))
1120 }
1121 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
1122 let mut iter = self.clone();
1123 iter.pos = 0;
1124 for attr in iter {
1125 if let Ok(PagePoolStats::AllocSlow(val)) = attr {
1126 return Ok(val);
1127 }
1128 }
1129 Err(ErrorContext::new_missing(
1130 "PagePoolStats",
1131 "AllocSlow",
1132 self.orig_loc,
1133 self.buf.as_ptr() as usize,
1134 ))
1135 }
1136 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
1137 let mut iter = self.clone();
1138 iter.pos = 0;
1139 for attr in iter {
1140 if let Ok(PagePoolStats::AllocSlowHighOrder(val)) = attr {
1141 return Ok(val);
1142 }
1143 }
1144 Err(ErrorContext::new_missing(
1145 "PagePoolStats",
1146 "AllocSlowHighOrder",
1147 self.orig_loc,
1148 self.buf.as_ptr() as usize,
1149 ))
1150 }
1151 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
1152 let mut iter = self.clone();
1153 iter.pos = 0;
1154 for attr in iter {
1155 if let Ok(PagePoolStats::AllocEmpty(val)) = attr {
1156 return Ok(val);
1157 }
1158 }
1159 Err(ErrorContext::new_missing(
1160 "PagePoolStats",
1161 "AllocEmpty",
1162 self.orig_loc,
1163 self.buf.as_ptr() as usize,
1164 ))
1165 }
1166 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
1167 let mut iter = self.clone();
1168 iter.pos = 0;
1169 for attr in iter {
1170 if let Ok(PagePoolStats::AllocRefill(val)) = attr {
1171 return Ok(val);
1172 }
1173 }
1174 Err(ErrorContext::new_missing(
1175 "PagePoolStats",
1176 "AllocRefill",
1177 self.orig_loc,
1178 self.buf.as_ptr() as usize,
1179 ))
1180 }
1181 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
1182 let mut iter = self.clone();
1183 iter.pos = 0;
1184 for attr in iter {
1185 if let Ok(PagePoolStats::AllocWaive(val)) = attr {
1186 return Ok(val);
1187 }
1188 }
1189 Err(ErrorContext::new_missing(
1190 "PagePoolStats",
1191 "AllocWaive",
1192 self.orig_loc,
1193 self.buf.as_ptr() as usize,
1194 ))
1195 }
1196 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
1197 let mut iter = self.clone();
1198 iter.pos = 0;
1199 for attr in iter {
1200 if let Ok(PagePoolStats::RecycleCached(val)) = attr {
1201 return Ok(val);
1202 }
1203 }
1204 Err(ErrorContext::new_missing(
1205 "PagePoolStats",
1206 "RecycleCached",
1207 self.orig_loc,
1208 self.buf.as_ptr() as usize,
1209 ))
1210 }
1211 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
1212 let mut iter = self.clone();
1213 iter.pos = 0;
1214 for attr in iter {
1215 if let Ok(PagePoolStats::RecycleCacheFull(val)) = attr {
1216 return Ok(val);
1217 }
1218 }
1219 Err(ErrorContext::new_missing(
1220 "PagePoolStats",
1221 "RecycleCacheFull",
1222 self.orig_loc,
1223 self.buf.as_ptr() as usize,
1224 ))
1225 }
1226 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
1227 let mut iter = self.clone();
1228 iter.pos = 0;
1229 for attr in iter {
1230 if let Ok(PagePoolStats::RecycleRing(val)) = attr {
1231 return Ok(val);
1232 }
1233 }
1234 Err(ErrorContext::new_missing(
1235 "PagePoolStats",
1236 "RecycleRing",
1237 self.orig_loc,
1238 self.buf.as_ptr() as usize,
1239 ))
1240 }
1241 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
1242 let mut iter = self.clone();
1243 iter.pos = 0;
1244 for attr in iter {
1245 if let Ok(PagePoolStats::RecycleRingFull(val)) = attr {
1246 return Ok(val);
1247 }
1248 }
1249 Err(ErrorContext::new_missing(
1250 "PagePoolStats",
1251 "RecycleRingFull",
1252 self.orig_loc,
1253 self.buf.as_ptr() as usize,
1254 ))
1255 }
1256 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
1257 let mut iter = self.clone();
1258 iter.pos = 0;
1259 for attr in iter {
1260 if let Ok(PagePoolStats::RecycleReleasedRefcnt(val)) = attr {
1261 return Ok(val);
1262 }
1263 }
1264 Err(ErrorContext::new_missing(
1265 "PagePoolStats",
1266 "RecycleReleasedRefcnt",
1267 self.orig_loc,
1268 self.buf.as_ptr() as usize,
1269 ))
1270 }
1271}
1272impl PagePoolStats<'_> {
1273 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
1274 IterablePagePoolStats::with_loc(buf, buf.as_ptr() as usize)
1275 }
1276 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1277 let res = match r#type {
1278 1u16 => "Info",
1279 8u16 => "AllocFast",
1280 9u16 => "AllocSlow",
1281 10u16 => "AllocSlowHighOrder",
1282 11u16 => "AllocEmpty",
1283 12u16 => "AllocRefill",
1284 13u16 => "AllocWaive",
1285 14u16 => "RecycleCached",
1286 15u16 => "RecycleCacheFull",
1287 16u16 => "RecycleRing",
1288 17u16 => "RecycleRingFull",
1289 18u16 => "RecycleReleasedRefcnt",
1290 _ => return None,
1291 };
1292 Some(res)
1293 }
1294}
1295#[derive(Clone, Copy, Default)]
1296pub struct IterablePagePoolStats<'a> {
1297 buf: &'a [u8],
1298 pos: usize,
1299 orig_loc: usize,
1300}
1301impl<'a> IterablePagePoolStats<'a> {
1302 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1303 Self {
1304 buf,
1305 pos: 0,
1306 orig_loc,
1307 }
1308 }
1309 pub fn get_buf(&self) -> &'a [u8] {
1310 self.buf
1311 }
1312}
1313impl<'a> Iterator for IterablePagePoolStats<'a> {
1314 type Item = Result<PagePoolStats<'a>, ErrorContext>;
1315 fn next(&mut self) -> Option<Self::Item> {
1316 let mut pos;
1317 let mut r#type;
1318 loop {
1319 pos = self.pos;
1320 r#type = None;
1321 if self.buf.len() == self.pos {
1322 return None;
1323 }
1324 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1325 self.pos = self.buf.len();
1326 break;
1327 };
1328 r#type = Some(header.r#type);
1329 let res = match header.r#type {
1330 1u16 => PagePoolStats::Info({
1331 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
1332 let Some(val) = res else { break };
1333 val
1334 }),
1335 8u16 => PagePoolStats::AllocFast({
1336 let res = parse_u32(next);
1337 let Some(val) = res else { break };
1338 val
1339 }),
1340 9u16 => PagePoolStats::AllocSlow({
1341 let res = parse_u32(next);
1342 let Some(val) = res else { break };
1343 val
1344 }),
1345 10u16 => PagePoolStats::AllocSlowHighOrder({
1346 let res = parse_u32(next);
1347 let Some(val) = res else { break };
1348 val
1349 }),
1350 11u16 => PagePoolStats::AllocEmpty({
1351 let res = parse_u32(next);
1352 let Some(val) = res else { break };
1353 val
1354 }),
1355 12u16 => PagePoolStats::AllocRefill({
1356 let res = parse_u32(next);
1357 let Some(val) = res else { break };
1358 val
1359 }),
1360 13u16 => PagePoolStats::AllocWaive({
1361 let res = parse_u32(next);
1362 let Some(val) = res else { break };
1363 val
1364 }),
1365 14u16 => PagePoolStats::RecycleCached({
1366 let res = parse_u32(next);
1367 let Some(val) = res else { break };
1368 val
1369 }),
1370 15u16 => PagePoolStats::RecycleCacheFull({
1371 let res = parse_u32(next);
1372 let Some(val) = res else { break };
1373 val
1374 }),
1375 16u16 => PagePoolStats::RecycleRing({
1376 let res = parse_u32(next);
1377 let Some(val) = res else { break };
1378 val
1379 }),
1380 17u16 => PagePoolStats::RecycleRingFull({
1381 let res = parse_u32(next);
1382 let Some(val) = res else { break };
1383 val
1384 }),
1385 18u16 => PagePoolStats::RecycleReleasedRefcnt({
1386 let res = parse_u32(next);
1387 let Some(val) = res else { break };
1388 val
1389 }),
1390 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1391 n => continue,
1392 };
1393 return Some(Ok(res));
1394 }
1395 Some(Err(ErrorContext::new(
1396 "PagePoolStats",
1397 r#type.and_then(|t| PagePoolStats::attr_from_type(t)),
1398 self.orig_loc,
1399 self.buf.as_ptr().wrapping_add(pos) as usize,
1400 )))
1401 }
1402}
1403impl<'a> std::fmt::Debug for IterablePagePoolStats<'_> {
1404 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1405 let mut fmt = f.debug_struct("PagePoolStats");
1406 for attr in self.clone() {
1407 let attr = match attr {
1408 Ok(a) => a,
1409 Err(err) => {
1410 fmt.finish()?;
1411 f.write_str("Err(")?;
1412 err.fmt(f)?;
1413 return f.write_str(")");
1414 }
1415 };
1416 match attr {
1417 PagePoolStats::Info(val) => fmt.field("Info", &val),
1418 PagePoolStats::AllocFast(val) => fmt.field("AllocFast", &val),
1419 PagePoolStats::AllocSlow(val) => fmt.field("AllocSlow", &val),
1420 PagePoolStats::AllocSlowHighOrder(val) => fmt.field("AllocSlowHighOrder", &val),
1421 PagePoolStats::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
1422 PagePoolStats::AllocRefill(val) => fmt.field("AllocRefill", &val),
1423 PagePoolStats::AllocWaive(val) => fmt.field("AllocWaive", &val),
1424 PagePoolStats::RecycleCached(val) => fmt.field("RecycleCached", &val),
1425 PagePoolStats::RecycleCacheFull(val) => fmt.field("RecycleCacheFull", &val),
1426 PagePoolStats::RecycleRing(val) => fmt.field("RecycleRing", &val),
1427 PagePoolStats::RecycleRingFull(val) => fmt.field("RecycleRingFull", &val),
1428 PagePoolStats::RecycleReleasedRefcnt(val) => {
1429 fmt.field("RecycleReleasedRefcnt", &val)
1430 }
1431 };
1432 }
1433 fmt.finish()
1434 }
1435}
1436impl IterablePagePoolStats<'_> {
1437 pub fn lookup_attr(
1438 &self,
1439 offset: usize,
1440 missing_type: Option<u16>,
1441 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1442 let mut stack = Vec::new();
1443 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1444 if missing_type.is_some() && cur == offset {
1445 stack.push(("PagePoolStats", offset));
1446 return (
1447 stack,
1448 missing_type.and_then(|t| PagePoolStats::attr_from_type(t)),
1449 );
1450 }
1451 if cur > offset || cur + self.buf.len() < offset {
1452 return (stack, None);
1453 }
1454 let mut attrs = self.clone();
1455 let mut last_off = cur + attrs.pos;
1456 let mut missing = None;
1457 while let Some(attr) = attrs.next() {
1458 let Ok(attr) = attr else { break };
1459 match attr {
1460 PagePoolStats::Info(val) => {
1461 (stack, missing) = val.lookup_attr(offset, missing_type);
1462 if !stack.is_empty() {
1463 break;
1464 }
1465 }
1466 PagePoolStats::AllocFast(val) => {
1467 if last_off == offset {
1468 stack.push(("AllocFast", last_off));
1469 break;
1470 }
1471 }
1472 PagePoolStats::AllocSlow(val) => {
1473 if last_off == offset {
1474 stack.push(("AllocSlow", last_off));
1475 break;
1476 }
1477 }
1478 PagePoolStats::AllocSlowHighOrder(val) => {
1479 if last_off == offset {
1480 stack.push(("AllocSlowHighOrder", last_off));
1481 break;
1482 }
1483 }
1484 PagePoolStats::AllocEmpty(val) => {
1485 if last_off == offset {
1486 stack.push(("AllocEmpty", last_off));
1487 break;
1488 }
1489 }
1490 PagePoolStats::AllocRefill(val) => {
1491 if last_off == offset {
1492 stack.push(("AllocRefill", last_off));
1493 break;
1494 }
1495 }
1496 PagePoolStats::AllocWaive(val) => {
1497 if last_off == offset {
1498 stack.push(("AllocWaive", last_off));
1499 break;
1500 }
1501 }
1502 PagePoolStats::RecycleCached(val) => {
1503 if last_off == offset {
1504 stack.push(("RecycleCached", last_off));
1505 break;
1506 }
1507 }
1508 PagePoolStats::RecycleCacheFull(val) => {
1509 if last_off == offset {
1510 stack.push(("RecycleCacheFull", last_off));
1511 break;
1512 }
1513 }
1514 PagePoolStats::RecycleRing(val) => {
1515 if last_off == offset {
1516 stack.push(("RecycleRing", last_off));
1517 break;
1518 }
1519 }
1520 PagePoolStats::RecycleRingFull(val) => {
1521 if last_off == offset {
1522 stack.push(("RecycleRingFull", last_off));
1523 break;
1524 }
1525 }
1526 PagePoolStats::RecycleReleasedRefcnt(val) => {
1527 if last_off == offset {
1528 stack.push(("RecycleReleasedRefcnt", last_off));
1529 break;
1530 }
1531 }
1532 _ => {}
1533 };
1534 last_off = cur + attrs.pos;
1535 }
1536 if !stack.is_empty() {
1537 stack.push(("PagePoolStats", cur));
1538 }
1539 (stack, missing)
1540 }
1541}
1542#[derive(Clone)]
1543pub enum Napi {
1544 #[doc = "ifindex of the netdevice to which NAPI instance belongs.\n"]
1545 Ifindex(u32),
1546 #[doc = "ID of the NAPI instance.\n"]
1547 Id(u32),
1548 #[doc = "The associated interrupt vector number for the napi\n"]
1549 Irq(u32),
1550 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded\nmode. If NAPI is not in threaded mode (i.e. uses normal softirq\ncontext), the attribute will be absent.\n"]
1551 Pid(u32),
1552 #[doc = "The number of consecutive empty polls before IRQ deferral ends and\nhardware IRQs are re-enabled.\n"]
1553 DeferHardIrqs(u32),
1554 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer\nwhich schedules NAPI processing. Additionally, a non-zero value will\nalso prevent GRO from flushing recent super-frames at the end of a NAPI\ncycle. This may add receive latency in exchange for reducing the number\nof frames processed by the network stack.\n"]
1555 GroFlushTimeout(u32),
1556 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if\nevent polling finds events\n"]
1557 IrqSuspendTimeout(u32),
1558 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If\nthis is set to enabled then the NAPI context operates in threaded\npolling mode. If this is set to busy-poll, then the threaded polling\nmode also busy polls.\n\nAssociated type: [`NapiThreaded`] (enum)"]
1559 Threaded(u32),
1560}
1561impl<'a> IterableNapi<'a> {
1562 #[doc = "ifindex of the netdevice to which NAPI instance belongs.\n"]
1563 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1564 let mut iter = self.clone();
1565 iter.pos = 0;
1566 for attr in iter {
1567 if let Ok(Napi::Ifindex(val)) = attr {
1568 return Ok(val);
1569 }
1570 }
1571 Err(ErrorContext::new_missing(
1572 "Napi",
1573 "Ifindex",
1574 self.orig_loc,
1575 self.buf.as_ptr() as usize,
1576 ))
1577 }
1578 #[doc = "ID of the NAPI instance.\n"]
1579 pub fn get_id(&self) -> Result<u32, ErrorContext> {
1580 let mut iter = self.clone();
1581 iter.pos = 0;
1582 for attr in iter {
1583 if let Ok(Napi::Id(val)) = attr {
1584 return Ok(val);
1585 }
1586 }
1587 Err(ErrorContext::new_missing(
1588 "Napi",
1589 "Id",
1590 self.orig_loc,
1591 self.buf.as_ptr() as usize,
1592 ))
1593 }
1594 #[doc = "The associated interrupt vector number for the napi\n"]
1595 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
1596 let mut iter = self.clone();
1597 iter.pos = 0;
1598 for attr in iter {
1599 if let Ok(Napi::Irq(val)) = attr {
1600 return Ok(val);
1601 }
1602 }
1603 Err(ErrorContext::new_missing(
1604 "Napi",
1605 "Irq",
1606 self.orig_loc,
1607 self.buf.as_ptr() as usize,
1608 ))
1609 }
1610 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded\nmode. If NAPI is not in threaded mode (i.e. uses normal softirq\ncontext), the attribute will be absent.\n"]
1611 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
1612 let mut iter = self.clone();
1613 iter.pos = 0;
1614 for attr in iter {
1615 if let Ok(Napi::Pid(val)) = attr {
1616 return Ok(val);
1617 }
1618 }
1619 Err(ErrorContext::new_missing(
1620 "Napi",
1621 "Pid",
1622 self.orig_loc,
1623 self.buf.as_ptr() as usize,
1624 ))
1625 }
1626 #[doc = "The number of consecutive empty polls before IRQ deferral ends and\nhardware IRQs are re-enabled.\n"]
1627 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
1628 let mut iter = self.clone();
1629 iter.pos = 0;
1630 for attr in iter {
1631 if let Ok(Napi::DeferHardIrqs(val)) = attr {
1632 return Ok(val);
1633 }
1634 }
1635 Err(ErrorContext::new_missing(
1636 "Napi",
1637 "DeferHardIrqs",
1638 self.orig_loc,
1639 self.buf.as_ptr() as usize,
1640 ))
1641 }
1642 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer\nwhich schedules NAPI processing. Additionally, a non-zero value will\nalso prevent GRO from flushing recent super-frames at the end of a NAPI\ncycle. This may add receive latency in exchange for reducing the number\nof frames processed by the network stack.\n"]
1643 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
1644 let mut iter = self.clone();
1645 iter.pos = 0;
1646 for attr in iter {
1647 if let Ok(Napi::GroFlushTimeout(val)) = attr {
1648 return Ok(val);
1649 }
1650 }
1651 Err(ErrorContext::new_missing(
1652 "Napi",
1653 "GroFlushTimeout",
1654 self.orig_loc,
1655 self.buf.as_ptr() as usize,
1656 ))
1657 }
1658 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if\nevent polling finds events\n"]
1659 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
1660 let mut iter = self.clone();
1661 iter.pos = 0;
1662 for attr in iter {
1663 if let Ok(Napi::IrqSuspendTimeout(val)) = attr {
1664 return Ok(val);
1665 }
1666 }
1667 Err(ErrorContext::new_missing(
1668 "Napi",
1669 "IrqSuspendTimeout",
1670 self.orig_loc,
1671 self.buf.as_ptr() as usize,
1672 ))
1673 }
1674 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If\nthis is set to enabled then the NAPI context operates in threaded\npolling mode. If this is set to busy-poll, then the threaded polling\nmode also busy polls.\n\nAssociated type: [`NapiThreaded`] (enum)"]
1675 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
1676 let mut iter = self.clone();
1677 iter.pos = 0;
1678 for attr in iter {
1679 if let Ok(Napi::Threaded(val)) = attr {
1680 return Ok(val);
1681 }
1682 }
1683 Err(ErrorContext::new_missing(
1684 "Napi",
1685 "Threaded",
1686 self.orig_loc,
1687 self.buf.as_ptr() as usize,
1688 ))
1689 }
1690}
1691impl Napi {
1692 pub fn new<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
1693 IterableNapi::with_loc(buf, buf.as_ptr() as usize)
1694 }
1695 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1696 let res = match r#type {
1697 1u16 => "Ifindex",
1698 2u16 => "Id",
1699 3u16 => "Irq",
1700 4u16 => "Pid",
1701 5u16 => "DeferHardIrqs",
1702 6u16 => "GroFlushTimeout",
1703 7u16 => "IrqSuspendTimeout",
1704 8u16 => "Threaded",
1705 _ => return None,
1706 };
1707 Some(res)
1708 }
1709}
1710#[derive(Clone, Copy, Default)]
1711pub struct IterableNapi<'a> {
1712 buf: &'a [u8],
1713 pos: usize,
1714 orig_loc: usize,
1715}
1716impl<'a> IterableNapi<'a> {
1717 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1718 Self {
1719 buf,
1720 pos: 0,
1721 orig_loc,
1722 }
1723 }
1724 pub fn get_buf(&self) -> &'a [u8] {
1725 self.buf
1726 }
1727}
1728impl<'a> Iterator for IterableNapi<'a> {
1729 type Item = Result<Napi, ErrorContext>;
1730 fn next(&mut self) -> Option<Self::Item> {
1731 let mut pos;
1732 let mut r#type;
1733 loop {
1734 pos = self.pos;
1735 r#type = None;
1736 if self.buf.len() == self.pos {
1737 return None;
1738 }
1739 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1740 self.pos = self.buf.len();
1741 break;
1742 };
1743 r#type = Some(header.r#type);
1744 let res = match header.r#type {
1745 1u16 => Napi::Ifindex({
1746 let res = parse_u32(next);
1747 let Some(val) = res else { break };
1748 val
1749 }),
1750 2u16 => Napi::Id({
1751 let res = parse_u32(next);
1752 let Some(val) = res else { break };
1753 val
1754 }),
1755 3u16 => Napi::Irq({
1756 let res = parse_u32(next);
1757 let Some(val) = res else { break };
1758 val
1759 }),
1760 4u16 => Napi::Pid({
1761 let res = parse_u32(next);
1762 let Some(val) = res else { break };
1763 val
1764 }),
1765 5u16 => Napi::DeferHardIrqs({
1766 let res = parse_u32(next);
1767 let Some(val) = res else { break };
1768 val
1769 }),
1770 6u16 => Napi::GroFlushTimeout({
1771 let res = parse_u32(next);
1772 let Some(val) = res else { break };
1773 val
1774 }),
1775 7u16 => Napi::IrqSuspendTimeout({
1776 let res = parse_u32(next);
1777 let Some(val) = res else { break };
1778 val
1779 }),
1780 8u16 => Napi::Threaded({
1781 let res = parse_u32(next);
1782 let Some(val) = res else { break };
1783 val
1784 }),
1785 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1786 n => continue,
1787 };
1788 return Some(Ok(res));
1789 }
1790 Some(Err(ErrorContext::new(
1791 "Napi",
1792 r#type.and_then(|t| Napi::attr_from_type(t)),
1793 self.orig_loc,
1794 self.buf.as_ptr().wrapping_add(pos) as usize,
1795 )))
1796 }
1797}
1798impl std::fmt::Debug for IterableNapi<'_> {
1799 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1800 let mut fmt = f.debug_struct("Napi");
1801 for attr in self.clone() {
1802 let attr = match attr {
1803 Ok(a) => a,
1804 Err(err) => {
1805 fmt.finish()?;
1806 f.write_str("Err(")?;
1807 err.fmt(f)?;
1808 return f.write_str(")");
1809 }
1810 };
1811 match attr {
1812 Napi::Ifindex(val) => fmt.field("Ifindex", &val),
1813 Napi::Id(val) => fmt.field("Id", &val),
1814 Napi::Irq(val) => fmt.field("Irq", &val),
1815 Napi::Pid(val) => fmt.field("Pid", &val),
1816 Napi::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
1817 Napi::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
1818 Napi::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
1819 Napi::Threaded(val) => fmt.field(
1820 "Threaded",
1821 &FormatEnum(val.into(), NapiThreaded::from_value),
1822 ),
1823 };
1824 }
1825 fmt.finish()
1826 }
1827}
1828impl IterableNapi<'_> {
1829 pub fn lookup_attr(
1830 &self,
1831 offset: usize,
1832 missing_type: Option<u16>,
1833 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1834 let mut stack = Vec::new();
1835 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1836 if missing_type.is_some() && cur == offset {
1837 stack.push(("Napi", offset));
1838 return (stack, missing_type.and_then(|t| Napi::attr_from_type(t)));
1839 }
1840 if cur > offset || cur + self.buf.len() < offset {
1841 return (stack, None);
1842 }
1843 let mut attrs = self.clone();
1844 let mut last_off = cur + attrs.pos;
1845 while let Some(attr) = attrs.next() {
1846 let Ok(attr) = attr else { break };
1847 match attr {
1848 Napi::Ifindex(val) => {
1849 if last_off == offset {
1850 stack.push(("Ifindex", last_off));
1851 break;
1852 }
1853 }
1854 Napi::Id(val) => {
1855 if last_off == offset {
1856 stack.push(("Id", last_off));
1857 break;
1858 }
1859 }
1860 Napi::Irq(val) => {
1861 if last_off == offset {
1862 stack.push(("Irq", last_off));
1863 break;
1864 }
1865 }
1866 Napi::Pid(val) => {
1867 if last_off == offset {
1868 stack.push(("Pid", last_off));
1869 break;
1870 }
1871 }
1872 Napi::DeferHardIrqs(val) => {
1873 if last_off == offset {
1874 stack.push(("DeferHardIrqs", last_off));
1875 break;
1876 }
1877 }
1878 Napi::GroFlushTimeout(val) => {
1879 if last_off == offset {
1880 stack.push(("GroFlushTimeout", last_off));
1881 break;
1882 }
1883 }
1884 Napi::IrqSuspendTimeout(val) => {
1885 if last_off == offset {
1886 stack.push(("IrqSuspendTimeout", last_off));
1887 break;
1888 }
1889 }
1890 Napi::Threaded(val) => {
1891 if last_off == offset {
1892 stack.push(("Threaded", last_off));
1893 break;
1894 }
1895 }
1896 _ => {}
1897 };
1898 last_off = cur + attrs.pos;
1899 }
1900 if !stack.is_empty() {
1901 stack.push(("Napi", cur));
1902 }
1903 (stack, None)
1904 }
1905}
1906#[derive(Clone)]
1907pub enum XskInfo {}
1908impl<'a> IterableXskInfo<'a> {}
1909impl XskInfo {
1910 pub fn new<'a>(buf: &'a [u8]) -> IterableXskInfo<'a> {
1911 IterableXskInfo::with_loc(buf, buf.as_ptr() as usize)
1912 }
1913 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1914 None
1915 }
1916}
1917#[derive(Clone, Copy, Default)]
1918pub struct IterableXskInfo<'a> {
1919 buf: &'a [u8],
1920 pos: usize,
1921 orig_loc: usize,
1922}
1923impl<'a> IterableXskInfo<'a> {
1924 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1925 Self {
1926 buf,
1927 pos: 0,
1928 orig_loc,
1929 }
1930 }
1931 pub fn get_buf(&self) -> &'a [u8] {
1932 self.buf
1933 }
1934}
1935impl<'a> Iterator for IterableXskInfo<'a> {
1936 type Item = Result<XskInfo, ErrorContext>;
1937 fn next(&mut self) -> Option<Self::Item> {
1938 let mut pos;
1939 let mut r#type;
1940 loop {
1941 pos = self.pos;
1942 r#type = None;
1943 if self.buf.len() == self.pos {
1944 return None;
1945 }
1946 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1947 self.pos = self.buf.len();
1948 break;
1949 };
1950 r#type = Some(header.r#type);
1951 let res = match header.r#type {
1952 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1953 n => continue,
1954 };
1955 return Some(Ok(res));
1956 }
1957 Some(Err(ErrorContext::new(
1958 "XskInfo",
1959 r#type.and_then(|t| XskInfo::attr_from_type(t)),
1960 self.orig_loc,
1961 self.buf.as_ptr().wrapping_add(pos) as usize,
1962 )))
1963 }
1964}
1965impl std::fmt::Debug for IterableXskInfo<'_> {
1966 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1967 let mut fmt = f.debug_struct("XskInfo");
1968 for attr in self.clone() {
1969 let attr = match attr {
1970 Ok(a) => a,
1971 Err(err) => {
1972 fmt.finish()?;
1973 f.write_str("Err(")?;
1974 err.fmt(f)?;
1975 return f.write_str(")");
1976 }
1977 };
1978 match attr {};
1979 }
1980 fmt.finish()
1981 }
1982}
1983impl IterableXskInfo<'_> {
1984 pub fn lookup_attr(
1985 &self,
1986 offset: usize,
1987 missing_type: Option<u16>,
1988 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1989 let mut stack = Vec::new();
1990 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1991 if missing_type.is_some() && cur == offset {
1992 stack.push(("XskInfo", offset));
1993 return (stack, missing_type.and_then(|t| XskInfo::attr_from_type(t)));
1994 }
1995 (stack, None)
1996 }
1997}
1998#[derive(Clone)]
1999pub enum Queue<'a> {
2000 #[doc = "Queue index; most queue types are indexed like a C array, with indexes\nstarting at 0 and ending at queue count - 1. Queue indexes are scoped to\nan interface and queue type.\n"]
2001 Id(u32),
2002 #[doc = "ifindex of the netdevice to which the queue belongs.\n"]
2003 Ifindex(u32),
2004 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP\nTX queues allocated in the kernel are not linked to NAPIs and thus not\nlisted. AF_XDP queues will have more information set in the xsk\nattribute.\n\nAssociated type: [`QueueType`] (enum)"]
2005 Type(u32),
2006 #[doc = "ID of the NAPI instance which services this queue.\n"]
2007 NapiId(u32),
2008 #[doc = "ID of the dmabuf attached to this queue, if any.\n"]
2009 Dmabuf(u32),
2010 #[doc = "io_uring memory provider information.\n"]
2011 IoUring(IterableIoUringProviderInfo<'a>),
2012 #[doc = "XSK information for this queue, if any.\n"]
2013 Xsk(IterableXskInfo<'a>),
2014 #[doc = "A queue from a virtual device can have a lease which refers to another\nqueue from a physical device. This is useful for memory providers and\nAF_XDP operations which take an ifindex and queue id to allow\napplications to bind against virtual devices in containers.\n"]
2015 Lease(IterableLease<'a>),
2016}
2017impl<'a> IterableQueue<'a> {
2018 #[doc = "Queue index; most queue types are indexed like a C array, with indexes\nstarting at 0 and ending at queue count - 1. Queue indexes are scoped to\nan interface and queue type.\n"]
2019 pub fn get_id(&self) -> Result<u32, ErrorContext> {
2020 let mut iter = self.clone();
2021 iter.pos = 0;
2022 for attr in iter {
2023 if let Ok(Queue::Id(val)) = attr {
2024 return Ok(val);
2025 }
2026 }
2027 Err(ErrorContext::new_missing(
2028 "Queue",
2029 "Id",
2030 self.orig_loc,
2031 self.buf.as_ptr() as usize,
2032 ))
2033 }
2034 #[doc = "ifindex of the netdevice to which the queue belongs.\n"]
2035 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2036 let mut iter = self.clone();
2037 iter.pos = 0;
2038 for attr in iter {
2039 if let Ok(Queue::Ifindex(val)) = attr {
2040 return Ok(val);
2041 }
2042 }
2043 Err(ErrorContext::new_missing(
2044 "Queue",
2045 "Ifindex",
2046 self.orig_loc,
2047 self.buf.as_ptr() as usize,
2048 ))
2049 }
2050 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP\nTX queues allocated in the kernel are not linked to NAPIs and thus not\nlisted. AF_XDP queues will have more information set in the xsk\nattribute.\n\nAssociated type: [`QueueType`] (enum)"]
2051 pub fn get_type(&self) -> Result<u32, ErrorContext> {
2052 let mut iter = self.clone();
2053 iter.pos = 0;
2054 for attr in iter {
2055 if let Ok(Queue::Type(val)) = attr {
2056 return Ok(val);
2057 }
2058 }
2059 Err(ErrorContext::new_missing(
2060 "Queue",
2061 "Type",
2062 self.orig_loc,
2063 self.buf.as_ptr() as usize,
2064 ))
2065 }
2066 #[doc = "ID of the NAPI instance which services this queue.\n"]
2067 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
2068 let mut iter = self.clone();
2069 iter.pos = 0;
2070 for attr in iter {
2071 if let Ok(Queue::NapiId(val)) = attr {
2072 return Ok(val);
2073 }
2074 }
2075 Err(ErrorContext::new_missing(
2076 "Queue",
2077 "NapiId",
2078 self.orig_loc,
2079 self.buf.as_ptr() as usize,
2080 ))
2081 }
2082 #[doc = "ID of the dmabuf attached to this queue, if any.\n"]
2083 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
2084 let mut iter = self.clone();
2085 iter.pos = 0;
2086 for attr in iter {
2087 if let Ok(Queue::Dmabuf(val)) = attr {
2088 return Ok(val);
2089 }
2090 }
2091 Err(ErrorContext::new_missing(
2092 "Queue",
2093 "Dmabuf",
2094 self.orig_loc,
2095 self.buf.as_ptr() as usize,
2096 ))
2097 }
2098 #[doc = "io_uring memory provider information.\n"]
2099 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
2100 let mut iter = self.clone();
2101 iter.pos = 0;
2102 for attr in iter {
2103 if let Ok(Queue::IoUring(val)) = attr {
2104 return Ok(val);
2105 }
2106 }
2107 Err(ErrorContext::new_missing(
2108 "Queue",
2109 "IoUring",
2110 self.orig_loc,
2111 self.buf.as_ptr() as usize,
2112 ))
2113 }
2114 #[doc = "XSK information for this queue, if any.\n"]
2115 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
2116 let mut iter = self.clone();
2117 iter.pos = 0;
2118 for attr in iter {
2119 if let Ok(Queue::Xsk(val)) = attr {
2120 return Ok(val);
2121 }
2122 }
2123 Err(ErrorContext::new_missing(
2124 "Queue",
2125 "Xsk",
2126 self.orig_loc,
2127 self.buf.as_ptr() as usize,
2128 ))
2129 }
2130 #[doc = "A queue from a virtual device can have a lease which refers to another\nqueue from a physical device. This is useful for memory providers and\nAF_XDP operations which take an ifindex and queue id to allow\napplications to bind against virtual devices in containers.\n"]
2131 pub fn get_lease(&self) -> Result<IterableLease<'a>, ErrorContext> {
2132 let mut iter = self.clone();
2133 iter.pos = 0;
2134 for attr in iter {
2135 if let Ok(Queue::Lease(val)) = attr {
2136 return Ok(val);
2137 }
2138 }
2139 Err(ErrorContext::new_missing(
2140 "Queue",
2141 "Lease",
2142 self.orig_loc,
2143 self.buf.as_ptr() as usize,
2144 ))
2145 }
2146}
2147impl Queue<'_> {
2148 pub fn new<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
2149 IterableQueue::with_loc(buf, buf.as_ptr() as usize)
2150 }
2151 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2152 let res = match r#type {
2153 1u16 => "Id",
2154 2u16 => "Ifindex",
2155 3u16 => "Type",
2156 4u16 => "NapiId",
2157 5u16 => "Dmabuf",
2158 6u16 => "IoUring",
2159 7u16 => "Xsk",
2160 8u16 => "Lease",
2161 _ => return None,
2162 };
2163 Some(res)
2164 }
2165}
2166#[derive(Clone, Copy, Default)]
2167pub struct IterableQueue<'a> {
2168 buf: &'a [u8],
2169 pos: usize,
2170 orig_loc: usize,
2171}
2172impl<'a> IterableQueue<'a> {
2173 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2174 Self {
2175 buf,
2176 pos: 0,
2177 orig_loc,
2178 }
2179 }
2180 pub fn get_buf(&self) -> &'a [u8] {
2181 self.buf
2182 }
2183}
2184impl<'a> Iterator for IterableQueue<'a> {
2185 type Item = Result<Queue<'a>, ErrorContext>;
2186 fn next(&mut self) -> Option<Self::Item> {
2187 let mut pos;
2188 let mut r#type;
2189 loop {
2190 pos = self.pos;
2191 r#type = None;
2192 if self.buf.len() == self.pos {
2193 return None;
2194 }
2195 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2196 self.pos = self.buf.len();
2197 break;
2198 };
2199 r#type = Some(header.r#type);
2200 let res = match header.r#type {
2201 1u16 => Queue::Id({
2202 let res = parse_u32(next);
2203 let Some(val) = res else { break };
2204 val
2205 }),
2206 2u16 => Queue::Ifindex({
2207 let res = parse_u32(next);
2208 let Some(val) = res else { break };
2209 val
2210 }),
2211 3u16 => Queue::Type({
2212 let res = parse_u32(next);
2213 let Some(val) = res else { break };
2214 val
2215 }),
2216 4u16 => Queue::NapiId({
2217 let res = parse_u32(next);
2218 let Some(val) = res else { break };
2219 val
2220 }),
2221 5u16 => Queue::Dmabuf({
2222 let res = parse_u32(next);
2223 let Some(val) = res else { break };
2224 val
2225 }),
2226 6u16 => Queue::IoUring({
2227 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
2228 let Some(val) = res else { break };
2229 val
2230 }),
2231 7u16 => Queue::Xsk({
2232 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
2233 let Some(val) = res else { break };
2234 val
2235 }),
2236 8u16 => Queue::Lease({
2237 let res = Some(IterableLease::with_loc(next, self.orig_loc));
2238 let Some(val) = res else { break };
2239 val
2240 }),
2241 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2242 n => continue,
2243 };
2244 return Some(Ok(res));
2245 }
2246 Some(Err(ErrorContext::new(
2247 "Queue",
2248 r#type.and_then(|t| Queue::attr_from_type(t)),
2249 self.orig_loc,
2250 self.buf.as_ptr().wrapping_add(pos) as usize,
2251 )))
2252 }
2253}
2254impl<'a> std::fmt::Debug for IterableQueue<'_> {
2255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2256 let mut fmt = f.debug_struct("Queue");
2257 for attr in self.clone() {
2258 let attr = match attr {
2259 Ok(a) => a,
2260 Err(err) => {
2261 fmt.finish()?;
2262 f.write_str("Err(")?;
2263 err.fmt(f)?;
2264 return f.write_str(")");
2265 }
2266 };
2267 match attr {
2268 Queue::Id(val) => fmt.field("Id", &val),
2269 Queue::Ifindex(val) => fmt.field("Ifindex", &val),
2270 Queue::Type(val) => {
2271 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
2272 }
2273 Queue::NapiId(val) => fmt.field("NapiId", &val),
2274 Queue::Dmabuf(val) => fmt.field("Dmabuf", &val),
2275 Queue::IoUring(val) => fmt.field("IoUring", &val),
2276 Queue::Xsk(val) => fmt.field("Xsk", &val),
2277 Queue::Lease(val) => fmt.field("Lease", &val),
2278 };
2279 }
2280 fmt.finish()
2281 }
2282}
2283impl IterableQueue<'_> {
2284 pub fn lookup_attr(
2285 &self,
2286 offset: usize,
2287 missing_type: Option<u16>,
2288 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2289 let mut stack = Vec::new();
2290 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2291 if missing_type.is_some() && cur == offset {
2292 stack.push(("Queue", offset));
2293 return (stack, missing_type.and_then(|t| Queue::attr_from_type(t)));
2294 }
2295 if cur > offset || cur + self.buf.len() < offset {
2296 return (stack, None);
2297 }
2298 let mut attrs = self.clone();
2299 let mut last_off = cur + attrs.pos;
2300 let mut missing = None;
2301 while let Some(attr) = attrs.next() {
2302 let Ok(attr) = attr else { break };
2303 match attr {
2304 Queue::Id(val) => {
2305 if last_off == offset {
2306 stack.push(("Id", last_off));
2307 break;
2308 }
2309 }
2310 Queue::Ifindex(val) => {
2311 if last_off == offset {
2312 stack.push(("Ifindex", last_off));
2313 break;
2314 }
2315 }
2316 Queue::Type(val) => {
2317 if last_off == offset {
2318 stack.push(("Type", last_off));
2319 break;
2320 }
2321 }
2322 Queue::NapiId(val) => {
2323 if last_off == offset {
2324 stack.push(("NapiId", last_off));
2325 break;
2326 }
2327 }
2328 Queue::Dmabuf(val) => {
2329 if last_off == offset {
2330 stack.push(("Dmabuf", last_off));
2331 break;
2332 }
2333 }
2334 Queue::IoUring(val) => {
2335 (stack, missing) = val.lookup_attr(offset, missing_type);
2336 if !stack.is_empty() {
2337 break;
2338 }
2339 }
2340 Queue::Xsk(val) => {
2341 (stack, missing) = val.lookup_attr(offset, missing_type);
2342 if !stack.is_empty() {
2343 break;
2344 }
2345 }
2346 Queue::Lease(val) => {
2347 (stack, missing) = val.lookup_attr(offset, missing_type);
2348 if !stack.is_empty() {
2349 break;
2350 }
2351 }
2352 _ => {}
2353 };
2354 last_off = cur + attrs.pos;
2355 }
2356 if !stack.is_empty() {
2357 stack.push(("Queue", cur));
2358 }
2359 (stack, missing)
2360 }
2361}
2362#[derive(Clone)]
2363pub enum Qstats {
2364 #[doc = "ifindex of the netdevice to which stats belong.\n"]
2365 Ifindex(u32),
2366 #[doc = "Queue type as rx, tx, for queue-id.\n\nAssociated type: [`QueueType`] (enum)"]
2367 QueueType(u32),
2368 #[doc = "Queue ID, if stats are scoped to a single queue instance.\n"]
2369 QueueId(u32),
2370 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: [`QstatsScope`] (enum)"]
2371 Scope(u32),
2372 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer of the\nstack, so packets consumed by XDP are still counted here.\n"]
2373 RxPackets(u32),
2374 #[doc = "Successfully received bytes, see [rx-packets]{.title-ref}.\n"]
2375 RxBytes(u32),
2376 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means the\ndevice has issued a DMA completion for the packet).\n"]
2377 TxPackets(u32),
2378 #[doc = "Successfully sent bytes, see [tx-packets]{.title-ref}.\n"]
2379 TxBytes(u32),
2380 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending on\ndriver implementation and whether system recovers quickly.\n"]
2381 RxAllocFail(u32),
2382 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
2383 RxHwDrops(u32),
2384 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2385 RxHwDropOverruns(u32),
2386 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE.\n"]
2387 RxCsumComplete(u32),
2388 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY.\n"]
2389 RxCsumUnnecessary(u32),
2390 #[doc = "Number of packets that were not checksummed by device.\n"]
2391 RxCsumNone(u32),
2392 #[doc = "Number of packets with bad checksum. The packets are not discarded, but\nstill delivered to the stack.\n"]
2393 RxCsumBad(u32),
2394 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice feature,\nLRO-coalesced packets are not counted.\n"]
2395 RxHwGroPackets(u32),
2396 #[doc = "See [rx-hw-gro-packets]{.title-ref}.\n"]
2397 RxHwGroBytes(u32),
2398 #[doc = "Number of packets that were coalesced to bigger packetss with the HW-GRO\nnetdevice feature. LRO-coalesced packets are not counted.\n"]
2399 RxHwGroWirePackets(u32),
2400 #[doc = "See [rx-hw-gro-wire-packets]{.title-ref}.\n"]
2401 RxHwGroWireBytes(u32),
2402 #[doc = "Number of the packets dropped by the device due to the received packets\nbitrate exceeding the device rate limit.\n"]
2403 RxHwDropRatelimits(u32),
2404 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
2405 TxHwDrops(u32),
2406 #[doc = "Number of packets dropped because they were invalid or malformed.\n"]
2407 TxHwDropErrors(u32),
2408 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2409 TxCsumNone(u32),
2410 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
2411 TxNeedsCsum(u32),
2412 #[doc = "Number of packets that necessitated segmentation into smaller packets by\nthe device.\n"]
2413 TxHwGsoPackets(u32),
2414 #[doc = "See [tx-hw-gso-packets]{.title-ref}.\n"]
2415 TxHwGsoBytes(u32),
2416 #[doc = "Number of wire-sized packets generated by processing\n[tx-hw-gso-packets]{.title-ref}\n"]
2417 TxHwGsoWirePackets(u32),
2418 #[doc = "See [tx-hw-gso-wire-packets]{.title-ref}.\n"]
2419 TxHwGsoWireBytes(u32),
2420 #[doc = "Number of the packets dropped by the device due to the transmit packets\nbitrate exceeding the device rate limit.\n"]
2421 TxHwDropRatelimits(u32),
2422 #[doc = "Number of times driver paused accepting new tx packets from the stack to\nthis queue, because the queue was full. Note that if BQL is supported\nand enabled on the device the networking stack will avoid queuing a lot\nof data at once.\n"]
2423 TxStop(u32),
2424 #[doc = "Number of times driver re-started accepting send requests to this queue\nfrom the stack.\n"]
2425 TxWake(u32),
2426}
2427impl<'a> IterableQstats<'a> {
2428 #[doc = "ifindex of the netdevice to which stats belong.\n"]
2429 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2430 let mut iter = self.clone();
2431 iter.pos = 0;
2432 for attr in iter {
2433 if let Ok(Qstats::Ifindex(val)) = attr {
2434 return Ok(val);
2435 }
2436 }
2437 Err(ErrorContext::new_missing(
2438 "Qstats",
2439 "Ifindex",
2440 self.orig_loc,
2441 self.buf.as_ptr() as usize,
2442 ))
2443 }
2444 #[doc = "Queue type as rx, tx, for queue-id.\n\nAssociated type: [`QueueType`] (enum)"]
2445 pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
2446 let mut iter = self.clone();
2447 iter.pos = 0;
2448 for attr in iter {
2449 if let Ok(Qstats::QueueType(val)) = attr {
2450 return Ok(val);
2451 }
2452 }
2453 Err(ErrorContext::new_missing(
2454 "Qstats",
2455 "QueueType",
2456 self.orig_loc,
2457 self.buf.as_ptr() as usize,
2458 ))
2459 }
2460 #[doc = "Queue ID, if stats are scoped to a single queue instance.\n"]
2461 pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
2462 let mut iter = self.clone();
2463 iter.pos = 0;
2464 for attr in iter {
2465 if let Ok(Qstats::QueueId(val)) = attr {
2466 return Ok(val);
2467 }
2468 }
2469 Err(ErrorContext::new_missing(
2470 "Qstats",
2471 "QueueId",
2472 self.orig_loc,
2473 self.buf.as_ptr() as usize,
2474 ))
2475 }
2476 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: [`QstatsScope`] (enum)"]
2477 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
2478 let mut iter = self.clone();
2479 iter.pos = 0;
2480 for attr in iter {
2481 if let Ok(Qstats::Scope(val)) = attr {
2482 return Ok(val);
2483 }
2484 }
2485 Err(ErrorContext::new_missing(
2486 "Qstats",
2487 "Scope",
2488 self.orig_loc,
2489 self.buf.as_ptr() as usize,
2490 ))
2491 }
2492 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer of the\nstack, so packets consumed by XDP are still counted here.\n"]
2493 pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
2494 let mut iter = self.clone();
2495 iter.pos = 0;
2496 for attr in iter {
2497 if let Ok(Qstats::RxPackets(val)) = attr {
2498 return Ok(val);
2499 }
2500 }
2501 Err(ErrorContext::new_missing(
2502 "Qstats",
2503 "RxPackets",
2504 self.orig_loc,
2505 self.buf.as_ptr() as usize,
2506 ))
2507 }
2508 #[doc = "Successfully received bytes, see [rx-packets]{.title-ref}.\n"]
2509 pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
2510 let mut iter = self.clone();
2511 iter.pos = 0;
2512 for attr in iter {
2513 if let Ok(Qstats::RxBytes(val)) = attr {
2514 return Ok(val);
2515 }
2516 }
2517 Err(ErrorContext::new_missing(
2518 "Qstats",
2519 "RxBytes",
2520 self.orig_loc,
2521 self.buf.as_ptr() as usize,
2522 ))
2523 }
2524 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means the\ndevice has issued a DMA completion for the packet).\n"]
2525 pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
2526 let mut iter = self.clone();
2527 iter.pos = 0;
2528 for attr in iter {
2529 if let Ok(Qstats::TxPackets(val)) = attr {
2530 return Ok(val);
2531 }
2532 }
2533 Err(ErrorContext::new_missing(
2534 "Qstats",
2535 "TxPackets",
2536 self.orig_loc,
2537 self.buf.as_ptr() as usize,
2538 ))
2539 }
2540 #[doc = "Successfully sent bytes, see [tx-packets]{.title-ref}.\n"]
2541 pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
2542 let mut iter = self.clone();
2543 iter.pos = 0;
2544 for attr in iter {
2545 if let Ok(Qstats::TxBytes(val)) = attr {
2546 return Ok(val);
2547 }
2548 }
2549 Err(ErrorContext::new_missing(
2550 "Qstats",
2551 "TxBytes",
2552 self.orig_loc,
2553 self.buf.as_ptr() as usize,
2554 ))
2555 }
2556 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending on\ndriver implementation and whether system recovers quickly.\n"]
2557 pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
2558 let mut iter = self.clone();
2559 iter.pos = 0;
2560 for attr in iter {
2561 if let Ok(Qstats::RxAllocFail(val)) = attr {
2562 return Ok(val);
2563 }
2564 }
2565 Err(ErrorContext::new_missing(
2566 "Qstats",
2567 "RxAllocFail",
2568 self.orig_loc,
2569 self.buf.as_ptr() as usize,
2570 ))
2571 }
2572 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
2573 pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
2574 let mut iter = self.clone();
2575 iter.pos = 0;
2576 for attr in iter {
2577 if let Ok(Qstats::RxHwDrops(val)) = attr {
2578 return Ok(val);
2579 }
2580 }
2581 Err(ErrorContext::new_missing(
2582 "Qstats",
2583 "RxHwDrops",
2584 self.orig_loc,
2585 self.buf.as_ptr() as usize,
2586 ))
2587 }
2588 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2589 pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
2590 let mut iter = self.clone();
2591 iter.pos = 0;
2592 for attr in iter {
2593 if let Ok(Qstats::RxHwDropOverruns(val)) = attr {
2594 return Ok(val);
2595 }
2596 }
2597 Err(ErrorContext::new_missing(
2598 "Qstats",
2599 "RxHwDropOverruns",
2600 self.orig_loc,
2601 self.buf.as_ptr() as usize,
2602 ))
2603 }
2604 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE.\n"]
2605 pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
2606 let mut iter = self.clone();
2607 iter.pos = 0;
2608 for attr in iter {
2609 if let Ok(Qstats::RxCsumComplete(val)) = attr {
2610 return Ok(val);
2611 }
2612 }
2613 Err(ErrorContext::new_missing(
2614 "Qstats",
2615 "RxCsumComplete",
2616 self.orig_loc,
2617 self.buf.as_ptr() as usize,
2618 ))
2619 }
2620 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY.\n"]
2621 pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
2622 let mut iter = self.clone();
2623 iter.pos = 0;
2624 for attr in iter {
2625 if let Ok(Qstats::RxCsumUnnecessary(val)) = attr {
2626 return Ok(val);
2627 }
2628 }
2629 Err(ErrorContext::new_missing(
2630 "Qstats",
2631 "RxCsumUnnecessary",
2632 self.orig_loc,
2633 self.buf.as_ptr() as usize,
2634 ))
2635 }
2636 #[doc = "Number of packets that were not checksummed by device.\n"]
2637 pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
2638 let mut iter = self.clone();
2639 iter.pos = 0;
2640 for attr in iter {
2641 if let Ok(Qstats::RxCsumNone(val)) = attr {
2642 return Ok(val);
2643 }
2644 }
2645 Err(ErrorContext::new_missing(
2646 "Qstats",
2647 "RxCsumNone",
2648 self.orig_loc,
2649 self.buf.as_ptr() as usize,
2650 ))
2651 }
2652 #[doc = "Number of packets with bad checksum. The packets are not discarded, but\nstill delivered to the stack.\n"]
2653 pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
2654 let mut iter = self.clone();
2655 iter.pos = 0;
2656 for attr in iter {
2657 if let Ok(Qstats::RxCsumBad(val)) = attr {
2658 return Ok(val);
2659 }
2660 }
2661 Err(ErrorContext::new_missing(
2662 "Qstats",
2663 "RxCsumBad",
2664 self.orig_loc,
2665 self.buf.as_ptr() as usize,
2666 ))
2667 }
2668 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice feature,\nLRO-coalesced packets are not counted.\n"]
2669 pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
2670 let mut iter = self.clone();
2671 iter.pos = 0;
2672 for attr in iter {
2673 if let Ok(Qstats::RxHwGroPackets(val)) = attr {
2674 return Ok(val);
2675 }
2676 }
2677 Err(ErrorContext::new_missing(
2678 "Qstats",
2679 "RxHwGroPackets",
2680 self.orig_loc,
2681 self.buf.as_ptr() as usize,
2682 ))
2683 }
2684 #[doc = "See [rx-hw-gro-packets]{.title-ref}.\n"]
2685 pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
2686 let mut iter = self.clone();
2687 iter.pos = 0;
2688 for attr in iter {
2689 if let Ok(Qstats::RxHwGroBytes(val)) = attr {
2690 return Ok(val);
2691 }
2692 }
2693 Err(ErrorContext::new_missing(
2694 "Qstats",
2695 "RxHwGroBytes",
2696 self.orig_loc,
2697 self.buf.as_ptr() as usize,
2698 ))
2699 }
2700 #[doc = "Number of packets that were coalesced to bigger packetss with the HW-GRO\nnetdevice feature. LRO-coalesced packets are not counted.\n"]
2701 pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
2702 let mut iter = self.clone();
2703 iter.pos = 0;
2704 for attr in iter {
2705 if let Ok(Qstats::RxHwGroWirePackets(val)) = attr {
2706 return Ok(val);
2707 }
2708 }
2709 Err(ErrorContext::new_missing(
2710 "Qstats",
2711 "RxHwGroWirePackets",
2712 self.orig_loc,
2713 self.buf.as_ptr() as usize,
2714 ))
2715 }
2716 #[doc = "See [rx-hw-gro-wire-packets]{.title-ref}.\n"]
2717 pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
2718 let mut iter = self.clone();
2719 iter.pos = 0;
2720 for attr in iter {
2721 if let Ok(Qstats::RxHwGroWireBytes(val)) = attr {
2722 return Ok(val);
2723 }
2724 }
2725 Err(ErrorContext::new_missing(
2726 "Qstats",
2727 "RxHwGroWireBytes",
2728 self.orig_loc,
2729 self.buf.as_ptr() as usize,
2730 ))
2731 }
2732 #[doc = "Number of the packets dropped by the device due to the received packets\nbitrate exceeding the device rate limit.\n"]
2733 pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2734 let mut iter = self.clone();
2735 iter.pos = 0;
2736 for attr in iter {
2737 if let Ok(Qstats::RxHwDropRatelimits(val)) = attr {
2738 return Ok(val);
2739 }
2740 }
2741 Err(ErrorContext::new_missing(
2742 "Qstats",
2743 "RxHwDropRatelimits",
2744 self.orig_loc,
2745 self.buf.as_ptr() as usize,
2746 ))
2747 }
2748 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
2749 pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
2750 let mut iter = self.clone();
2751 iter.pos = 0;
2752 for attr in iter {
2753 if let Ok(Qstats::TxHwDrops(val)) = attr {
2754 return Ok(val);
2755 }
2756 }
2757 Err(ErrorContext::new_missing(
2758 "Qstats",
2759 "TxHwDrops",
2760 self.orig_loc,
2761 self.buf.as_ptr() as usize,
2762 ))
2763 }
2764 #[doc = "Number of packets dropped because they were invalid or malformed.\n"]
2765 pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
2766 let mut iter = self.clone();
2767 iter.pos = 0;
2768 for attr in iter {
2769 if let Ok(Qstats::TxHwDropErrors(val)) = attr {
2770 return Ok(val);
2771 }
2772 }
2773 Err(ErrorContext::new_missing(
2774 "Qstats",
2775 "TxHwDropErrors",
2776 self.orig_loc,
2777 self.buf.as_ptr() as usize,
2778 ))
2779 }
2780 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2781 pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
2782 let mut iter = self.clone();
2783 iter.pos = 0;
2784 for attr in iter {
2785 if let Ok(Qstats::TxCsumNone(val)) = attr {
2786 return Ok(val);
2787 }
2788 }
2789 Err(ErrorContext::new_missing(
2790 "Qstats",
2791 "TxCsumNone",
2792 self.orig_loc,
2793 self.buf.as_ptr() as usize,
2794 ))
2795 }
2796 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
2797 pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
2798 let mut iter = self.clone();
2799 iter.pos = 0;
2800 for attr in iter {
2801 if let Ok(Qstats::TxNeedsCsum(val)) = attr {
2802 return Ok(val);
2803 }
2804 }
2805 Err(ErrorContext::new_missing(
2806 "Qstats",
2807 "TxNeedsCsum",
2808 self.orig_loc,
2809 self.buf.as_ptr() as usize,
2810 ))
2811 }
2812 #[doc = "Number of packets that necessitated segmentation into smaller packets by\nthe device.\n"]
2813 pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
2814 let mut iter = self.clone();
2815 iter.pos = 0;
2816 for attr in iter {
2817 if let Ok(Qstats::TxHwGsoPackets(val)) = attr {
2818 return Ok(val);
2819 }
2820 }
2821 Err(ErrorContext::new_missing(
2822 "Qstats",
2823 "TxHwGsoPackets",
2824 self.orig_loc,
2825 self.buf.as_ptr() as usize,
2826 ))
2827 }
2828 #[doc = "See [tx-hw-gso-packets]{.title-ref}.\n"]
2829 pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
2830 let mut iter = self.clone();
2831 iter.pos = 0;
2832 for attr in iter {
2833 if let Ok(Qstats::TxHwGsoBytes(val)) = attr {
2834 return Ok(val);
2835 }
2836 }
2837 Err(ErrorContext::new_missing(
2838 "Qstats",
2839 "TxHwGsoBytes",
2840 self.orig_loc,
2841 self.buf.as_ptr() as usize,
2842 ))
2843 }
2844 #[doc = "Number of wire-sized packets generated by processing\n[tx-hw-gso-packets]{.title-ref}\n"]
2845 pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
2846 let mut iter = self.clone();
2847 iter.pos = 0;
2848 for attr in iter {
2849 if let Ok(Qstats::TxHwGsoWirePackets(val)) = attr {
2850 return Ok(val);
2851 }
2852 }
2853 Err(ErrorContext::new_missing(
2854 "Qstats",
2855 "TxHwGsoWirePackets",
2856 self.orig_loc,
2857 self.buf.as_ptr() as usize,
2858 ))
2859 }
2860 #[doc = "See [tx-hw-gso-wire-packets]{.title-ref}.\n"]
2861 pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
2862 let mut iter = self.clone();
2863 iter.pos = 0;
2864 for attr in iter {
2865 if let Ok(Qstats::TxHwGsoWireBytes(val)) = attr {
2866 return Ok(val);
2867 }
2868 }
2869 Err(ErrorContext::new_missing(
2870 "Qstats",
2871 "TxHwGsoWireBytes",
2872 self.orig_loc,
2873 self.buf.as_ptr() as usize,
2874 ))
2875 }
2876 #[doc = "Number of the packets dropped by the device due to the transmit packets\nbitrate exceeding the device rate limit.\n"]
2877 pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2878 let mut iter = self.clone();
2879 iter.pos = 0;
2880 for attr in iter {
2881 if let Ok(Qstats::TxHwDropRatelimits(val)) = attr {
2882 return Ok(val);
2883 }
2884 }
2885 Err(ErrorContext::new_missing(
2886 "Qstats",
2887 "TxHwDropRatelimits",
2888 self.orig_loc,
2889 self.buf.as_ptr() as usize,
2890 ))
2891 }
2892 #[doc = "Number of times driver paused accepting new tx packets from the stack to\nthis queue, because the queue was full. Note that if BQL is supported\nand enabled on the device the networking stack will avoid queuing a lot\nof data at once.\n"]
2893 pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
2894 let mut iter = self.clone();
2895 iter.pos = 0;
2896 for attr in iter {
2897 if let Ok(Qstats::TxStop(val)) = attr {
2898 return Ok(val);
2899 }
2900 }
2901 Err(ErrorContext::new_missing(
2902 "Qstats",
2903 "TxStop",
2904 self.orig_loc,
2905 self.buf.as_ptr() as usize,
2906 ))
2907 }
2908 #[doc = "Number of times driver re-started accepting send requests to this queue\nfrom the stack.\n"]
2909 pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
2910 let mut iter = self.clone();
2911 iter.pos = 0;
2912 for attr in iter {
2913 if let Ok(Qstats::TxWake(val)) = attr {
2914 return Ok(val);
2915 }
2916 }
2917 Err(ErrorContext::new_missing(
2918 "Qstats",
2919 "TxWake",
2920 self.orig_loc,
2921 self.buf.as_ptr() as usize,
2922 ))
2923 }
2924}
2925impl Qstats {
2926 pub fn new<'a>(buf: &'a [u8]) -> IterableQstats<'a> {
2927 IterableQstats::with_loc(buf, buf.as_ptr() as usize)
2928 }
2929 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2930 let res = match r#type {
2931 1u16 => "Ifindex",
2932 2u16 => "QueueType",
2933 3u16 => "QueueId",
2934 4u16 => "Scope",
2935 8u16 => "RxPackets",
2936 9u16 => "RxBytes",
2937 10u16 => "TxPackets",
2938 11u16 => "TxBytes",
2939 12u16 => "RxAllocFail",
2940 13u16 => "RxHwDrops",
2941 14u16 => "RxHwDropOverruns",
2942 15u16 => "RxCsumComplete",
2943 16u16 => "RxCsumUnnecessary",
2944 17u16 => "RxCsumNone",
2945 18u16 => "RxCsumBad",
2946 19u16 => "RxHwGroPackets",
2947 20u16 => "RxHwGroBytes",
2948 21u16 => "RxHwGroWirePackets",
2949 22u16 => "RxHwGroWireBytes",
2950 23u16 => "RxHwDropRatelimits",
2951 24u16 => "TxHwDrops",
2952 25u16 => "TxHwDropErrors",
2953 26u16 => "TxCsumNone",
2954 27u16 => "TxNeedsCsum",
2955 28u16 => "TxHwGsoPackets",
2956 29u16 => "TxHwGsoBytes",
2957 30u16 => "TxHwGsoWirePackets",
2958 31u16 => "TxHwGsoWireBytes",
2959 32u16 => "TxHwDropRatelimits",
2960 33u16 => "TxStop",
2961 34u16 => "TxWake",
2962 _ => return None,
2963 };
2964 Some(res)
2965 }
2966}
2967#[derive(Clone, Copy, Default)]
2968pub struct IterableQstats<'a> {
2969 buf: &'a [u8],
2970 pos: usize,
2971 orig_loc: usize,
2972}
2973impl<'a> IterableQstats<'a> {
2974 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2975 Self {
2976 buf,
2977 pos: 0,
2978 orig_loc,
2979 }
2980 }
2981 pub fn get_buf(&self) -> &'a [u8] {
2982 self.buf
2983 }
2984}
2985impl<'a> Iterator for IterableQstats<'a> {
2986 type Item = Result<Qstats, ErrorContext>;
2987 fn next(&mut self) -> Option<Self::Item> {
2988 let mut pos;
2989 let mut r#type;
2990 loop {
2991 pos = self.pos;
2992 r#type = None;
2993 if self.buf.len() == self.pos {
2994 return None;
2995 }
2996 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2997 self.pos = self.buf.len();
2998 break;
2999 };
3000 r#type = Some(header.r#type);
3001 let res = match header.r#type {
3002 1u16 => Qstats::Ifindex({
3003 let res = parse_u32(next);
3004 let Some(val) = res else { break };
3005 val
3006 }),
3007 2u16 => Qstats::QueueType({
3008 let res = parse_u32(next);
3009 let Some(val) = res else { break };
3010 val
3011 }),
3012 3u16 => Qstats::QueueId({
3013 let res = parse_u32(next);
3014 let Some(val) = res else { break };
3015 val
3016 }),
3017 4u16 => Qstats::Scope({
3018 let res = parse_u32(next);
3019 let Some(val) = res else { break };
3020 val
3021 }),
3022 8u16 => Qstats::RxPackets({
3023 let res = parse_u32(next);
3024 let Some(val) = res else { break };
3025 val
3026 }),
3027 9u16 => Qstats::RxBytes({
3028 let res = parse_u32(next);
3029 let Some(val) = res else { break };
3030 val
3031 }),
3032 10u16 => Qstats::TxPackets({
3033 let res = parse_u32(next);
3034 let Some(val) = res else { break };
3035 val
3036 }),
3037 11u16 => Qstats::TxBytes({
3038 let res = parse_u32(next);
3039 let Some(val) = res else { break };
3040 val
3041 }),
3042 12u16 => Qstats::RxAllocFail({
3043 let res = parse_u32(next);
3044 let Some(val) = res else { break };
3045 val
3046 }),
3047 13u16 => Qstats::RxHwDrops({
3048 let res = parse_u32(next);
3049 let Some(val) = res else { break };
3050 val
3051 }),
3052 14u16 => Qstats::RxHwDropOverruns({
3053 let res = parse_u32(next);
3054 let Some(val) = res else { break };
3055 val
3056 }),
3057 15u16 => Qstats::RxCsumComplete({
3058 let res = parse_u32(next);
3059 let Some(val) = res else { break };
3060 val
3061 }),
3062 16u16 => Qstats::RxCsumUnnecessary({
3063 let res = parse_u32(next);
3064 let Some(val) = res else { break };
3065 val
3066 }),
3067 17u16 => Qstats::RxCsumNone({
3068 let res = parse_u32(next);
3069 let Some(val) = res else { break };
3070 val
3071 }),
3072 18u16 => Qstats::RxCsumBad({
3073 let res = parse_u32(next);
3074 let Some(val) = res else { break };
3075 val
3076 }),
3077 19u16 => Qstats::RxHwGroPackets({
3078 let res = parse_u32(next);
3079 let Some(val) = res else { break };
3080 val
3081 }),
3082 20u16 => Qstats::RxHwGroBytes({
3083 let res = parse_u32(next);
3084 let Some(val) = res else { break };
3085 val
3086 }),
3087 21u16 => Qstats::RxHwGroWirePackets({
3088 let res = parse_u32(next);
3089 let Some(val) = res else { break };
3090 val
3091 }),
3092 22u16 => Qstats::RxHwGroWireBytes({
3093 let res = parse_u32(next);
3094 let Some(val) = res else { break };
3095 val
3096 }),
3097 23u16 => Qstats::RxHwDropRatelimits({
3098 let res = parse_u32(next);
3099 let Some(val) = res else { break };
3100 val
3101 }),
3102 24u16 => Qstats::TxHwDrops({
3103 let res = parse_u32(next);
3104 let Some(val) = res else { break };
3105 val
3106 }),
3107 25u16 => Qstats::TxHwDropErrors({
3108 let res = parse_u32(next);
3109 let Some(val) = res else { break };
3110 val
3111 }),
3112 26u16 => Qstats::TxCsumNone({
3113 let res = parse_u32(next);
3114 let Some(val) = res else { break };
3115 val
3116 }),
3117 27u16 => Qstats::TxNeedsCsum({
3118 let res = parse_u32(next);
3119 let Some(val) = res else { break };
3120 val
3121 }),
3122 28u16 => Qstats::TxHwGsoPackets({
3123 let res = parse_u32(next);
3124 let Some(val) = res else { break };
3125 val
3126 }),
3127 29u16 => Qstats::TxHwGsoBytes({
3128 let res = parse_u32(next);
3129 let Some(val) = res else { break };
3130 val
3131 }),
3132 30u16 => Qstats::TxHwGsoWirePackets({
3133 let res = parse_u32(next);
3134 let Some(val) = res else { break };
3135 val
3136 }),
3137 31u16 => Qstats::TxHwGsoWireBytes({
3138 let res = parse_u32(next);
3139 let Some(val) = res else { break };
3140 val
3141 }),
3142 32u16 => Qstats::TxHwDropRatelimits({
3143 let res = parse_u32(next);
3144 let Some(val) = res else { break };
3145 val
3146 }),
3147 33u16 => Qstats::TxStop({
3148 let res = parse_u32(next);
3149 let Some(val) = res else { break };
3150 val
3151 }),
3152 34u16 => Qstats::TxWake({
3153 let res = parse_u32(next);
3154 let Some(val) = res else { break };
3155 val
3156 }),
3157 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3158 n => continue,
3159 };
3160 return Some(Ok(res));
3161 }
3162 Some(Err(ErrorContext::new(
3163 "Qstats",
3164 r#type.and_then(|t| Qstats::attr_from_type(t)),
3165 self.orig_loc,
3166 self.buf.as_ptr().wrapping_add(pos) as usize,
3167 )))
3168 }
3169}
3170impl std::fmt::Debug for IterableQstats<'_> {
3171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3172 let mut fmt = f.debug_struct("Qstats");
3173 for attr in self.clone() {
3174 let attr = match attr {
3175 Ok(a) => a,
3176 Err(err) => {
3177 fmt.finish()?;
3178 f.write_str("Err(")?;
3179 err.fmt(f)?;
3180 return f.write_str(")");
3181 }
3182 };
3183 match attr {
3184 Qstats::Ifindex(val) => fmt.field("Ifindex", &val),
3185 Qstats::QueueType(val) => {
3186 fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
3187 }
3188 Qstats::QueueId(val) => fmt.field("QueueId", &val),
3189 Qstats::Scope(val) => {
3190 fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
3191 }
3192 Qstats::RxPackets(val) => fmt.field("RxPackets", &val),
3193 Qstats::RxBytes(val) => fmt.field("RxBytes", &val),
3194 Qstats::TxPackets(val) => fmt.field("TxPackets", &val),
3195 Qstats::TxBytes(val) => fmt.field("TxBytes", &val),
3196 Qstats::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
3197 Qstats::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
3198 Qstats::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
3199 Qstats::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
3200 Qstats::RxCsumUnnecessary(val) => fmt.field("RxCsumUnnecessary", &val),
3201 Qstats::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
3202 Qstats::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
3203 Qstats::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
3204 Qstats::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
3205 Qstats::RxHwGroWirePackets(val) => fmt.field("RxHwGroWirePackets", &val),
3206 Qstats::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
3207 Qstats::RxHwDropRatelimits(val) => fmt.field("RxHwDropRatelimits", &val),
3208 Qstats::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
3209 Qstats::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
3210 Qstats::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
3211 Qstats::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
3212 Qstats::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
3213 Qstats::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
3214 Qstats::TxHwGsoWirePackets(val) => fmt.field("TxHwGsoWirePackets", &val),
3215 Qstats::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
3216 Qstats::TxHwDropRatelimits(val) => fmt.field("TxHwDropRatelimits", &val),
3217 Qstats::TxStop(val) => fmt.field("TxStop", &val),
3218 Qstats::TxWake(val) => fmt.field("TxWake", &val),
3219 };
3220 }
3221 fmt.finish()
3222 }
3223}
3224impl IterableQstats<'_> {
3225 pub fn lookup_attr(
3226 &self,
3227 offset: usize,
3228 missing_type: Option<u16>,
3229 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3230 let mut stack = Vec::new();
3231 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3232 if missing_type.is_some() && cur == offset {
3233 stack.push(("Qstats", offset));
3234 return (stack, missing_type.and_then(|t| Qstats::attr_from_type(t)));
3235 }
3236 if cur > offset || cur + self.buf.len() < offset {
3237 return (stack, None);
3238 }
3239 let mut attrs = self.clone();
3240 let mut last_off = cur + attrs.pos;
3241 while let Some(attr) = attrs.next() {
3242 let Ok(attr) = attr else { break };
3243 match attr {
3244 Qstats::Ifindex(val) => {
3245 if last_off == offset {
3246 stack.push(("Ifindex", last_off));
3247 break;
3248 }
3249 }
3250 Qstats::QueueType(val) => {
3251 if last_off == offset {
3252 stack.push(("QueueType", last_off));
3253 break;
3254 }
3255 }
3256 Qstats::QueueId(val) => {
3257 if last_off == offset {
3258 stack.push(("QueueId", last_off));
3259 break;
3260 }
3261 }
3262 Qstats::Scope(val) => {
3263 if last_off == offset {
3264 stack.push(("Scope", last_off));
3265 break;
3266 }
3267 }
3268 Qstats::RxPackets(val) => {
3269 if last_off == offset {
3270 stack.push(("RxPackets", last_off));
3271 break;
3272 }
3273 }
3274 Qstats::RxBytes(val) => {
3275 if last_off == offset {
3276 stack.push(("RxBytes", last_off));
3277 break;
3278 }
3279 }
3280 Qstats::TxPackets(val) => {
3281 if last_off == offset {
3282 stack.push(("TxPackets", last_off));
3283 break;
3284 }
3285 }
3286 Qstats::TxBytes(val) => {
3287 if last_off == offset {
3288 stack.push(("TxBytes", last_off));
3289 break;
3290 }
3291 }
3292 Qstats::RxAllocFail(val) => {
3293 if last_off == offset {
3294 stack.push(("RxAllocFail", last_off));
3295 break;
3296 }
3297 }
3298 Qstats::RxHwDrops(val) => {
3299 if last_off == offset {
3300 stack.push(("RxHwDrops", last_off));
3301 break;
3302 }
3303 }
3304 Qstats::RxHwDropOverruns(val) => {
3305 if last_off == offset {
3306 stack.push(("RxHwDropOverruns", last_off));
3307 break;
3308 }
3309 }
3310 Qstats::RxCsumComplete(val) => {
3311 if last_off == offset {
3312 stack.push(("RxCsumComplete", last_off));
3313 break;
3314 }
3315 }
3316 Qstats::RxCsumUnnecessary(val) => {
3317 if last_off == offset {
3318 stack.push(("RxCsumUnnecessary", last_off));
3319 break;
3320 }
3321 }
3322 Qstats::RxCsumNone(val) => {
3323 if last_off == offset {
3324 stack.push(("RxCsumNone", last_off));
3325 break;
3326 }
3327 }
3328 Qstats::RxCsumBad(val) => {
3329 if last_off == offset {
3330 stack.push(("RxCsumBad", last_off));
3331 break;
3332 }
3333 }
3334 Qstats::RxHwGroPackets(val) => {
3335 if last_off == offset {
3336 stack.push(("RxHwGroPackets", last_off));
3337 break;
3338 }
3339 }
3340 Qstats::RxHwGroBytes(val) => {
3341 if last_off == offset {
3342 stack.push(("RxHwGroBytes", last_off));
3343 break;
3344 }
3345 }
3346 Qstats::RxHwGroWirePackets(val) => {
3347 if last_off == offset {
3348 stack.push(("RxHwGroWirePackets", last_off));
3349 break;
3350 }
3351 }
3352 Qstats::RxHwGroWireBytes(val) => {
3353 if last_off == offset {
3354 stack.push(("RxHwGroWireBytes", last_off));
3355 break;
3356 }
3357 }
3358 Qstats::RxHwDropRatelimits(val) => {
3359 if last_off == offset {
3360 stack.push(("RxHwDropRatelimits", last_off));
3361 break;
3362 }
3363 }
3364 Qstats::TxHwDrops(val) => {
3365 if last_off == offset {
3366 stack.push(("TxHwDrops", last_off));
3367 break;
3368 }
3369 }
3370 Qstats::TxHwDropErrors(val) => {
3371 if last_off == offset {
3372 stack.push(("TxHwDropErrors", last_off));
3373 break;
3374 }
3375 }
3376 Qstats::TxCsumNone(val) => {
3377 if last_off == offset {
3378 stack.push(("TxCsumNone", last_off));
3379 break;
3380 }
3381 }
3382 Qstats::TxNeedsCsum(val) => {
3383 if last_off == offset {
3384 stack.push(("TxNeedsCsum", last_off));
3385 break;
3386 }
3387 }
3388 Qstats::TxHwGsoPackets(val) => {
3389 if last_off == offset {
3390 stack.push(("TxHwGsoPackets", last_off));
3391 break;
3392 }
3393 }
3394 Qstats::TxHwGsoBytes(val) => {
3395 if last_off == offset {
3396 stack.push(("TxHwGsoBytes", last_off));
3397 break;
3398 }
3399 }
3400 Qstats::TxHwGsoWirePackets(val) => {
3401 if last_off == offset {
3402 stack.push(("TxHwGsoWirePackets", last_off));
3403 break;
3404 }
3405 }
3406 Qstats::TxHwGsoWireBytes(val) => {
3407 if last_off == offset {
3408 stack.push(("TxHwGsoWireBytes", last_off));
3409 break;
3410 }
3411 }
3412 Qstats::TxHwDropRatelimits(val) => {
3413 if last_off == offset {
3414 stack.push(("TxHwDropRatelimits", last_off));
3415 break;
3416 }
3417 }
3418 Qstats::TxStop(val) => {
3419 if last_off == offset {
3420 stack.push(("TxStop", last_off));
3421 break;
3422 }
3423 }
3424 Qstats::TxWake(val) => {
3425 if last_off == offset {
3426 stack.push(("TxWake", last_off));
3427 break;
3428 }
3429 }
3430 _ => {}
3431 };
3432 last_off = cur + attrs.pos;
3433 }
3434 if !stack.is_empty() {
3435 stack.push(("Qstats", cur));
3436 }
3437 (stack, None)
3438 }
3439}
3440#[derive(Clone)]
3441pub enum QueueId {
3442 #[doc = "Queue index; most queue types are indexed like a C array, with indexes\nstarting at 0 and ending at queue count - 1. Queue indexes are scoped to\nan interface and queue type.\n"]
3443 Id(u32),
3444 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP\nTX queues allocated in the kernel are not linked to NAPIs and thus not\nlisted. AF_XDP queues will have more information set in the xsk\nattribute.\n\nAssociated type: [`QueueType`] (enum)"]
3445 Type(u32),
3446}
3447impl<'a> IterableQueueId<'a> {
3448 #[doc = "Queue index; most queue types are indexed like a C array, with indexes\nstarting at 0 and ending at queue count - 1. Queue indexes are scoped to\nan interface and queue type.\n"]
3449 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3450 let mut iter = self.clone();
3451 iter.pos = 0;
3452 for attr in iter {
3453 if let Ok(QueueId::Id(val)) = attr {
3454 return Ok(val);
3455 }
3456 }
3457 Err(ErrorContext::new_missing(
3458 "QueueId",
3459 "Id",
3460 self.orig_loc,
3461 self.buf.as_ptr() as usize,
3462 ))
3463 }
3464 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP\nTX queues allocated in the kernel are not linked to NAPIs and thus not\nlisted. AF_XDP queues will have more information set in the xsk\nattribute.\n\nAssociated type: [`QueueType`] (enum)"]
3465 pub fn get_type(&self) -> Result<u32, ErrorContext> {
3466 let mut iter = self.clone();
3467 iter.pos = 0;
3468 for attr in iter {
3469 if let Ok(QueueId::Type(val)) = attr {
3470 return Ok(val);
3471 }
3472 }
3473 Err(ErrorContext::new_missing(
3474 "QueueId",
3475 "Type",
3476 self.orig_loc,
3477 self.buf.as_ptr() as usize,
3478 ))
3479 }
3480}
3481impl QueueId {
3482 pub fn new<'a>(buf: &'a [u8]) -> IterableQueueId<'a> {
3483 IterableQueueId::with_loc(buf, buf.as_ptr() as usize)
3484 }
3485 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3486 Queue::attr_from_type(r#type)
3487 }
3488}
3489#[derive(Clone, Copy, Default)]
3490pub struct IterableQueueId<'a> {
3491 buf: &'a [u8],
3492 pos: usize,
3493 orig_loc: usize,
3494}
3495impl<'a> IterableQueueId<'a> {
3496 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3497 Self {
3498 buf,
3499 pos: 0,
3500 orig_loc,
3501 }
3502 }
3503 pub fn get_buf(&self) -> &'a [u8] {
3504 self.buf
3505 }
3506}
3507impl<'a> Iterator for IterableQueueId<'a> {
3508 type Item = Result<QueueId, ErrorContext>;
3509 fn next(&mut self) -> Option<Self::Item> {
3510 let mut pos;
3511 let mut r#type;
3512 loop {
3513 pos = self.pos;
3514 r#type = None;
3515 if self.buf.len() == self.pos {
3516 return None;
3517 }
3518 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3519 self.pos = self.buf.len();
3520 break;
3521 };
3522 r#type = Some(header.r#type);
3523 let res = match header.r#type {
3524 1u16 => QueueId::Id({
3525 let res = parse_u32(next);
3526 let Some(val) = res else { break };
3527 val
3528 }),
3529 3u16 => QueueId::Type({
3530 let res = parse_u32(next);
3531 let Some(val) = res else { break };
3532 val
3533 }),
3534 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3535 n => continue,
3536 };
3537 return Some(Ok(res));
3538 }
3539 Some(Err(ErrorContext::new(
3540 "QueueId",
3541 r#type.and_then(|t| QueueId::attr_from_type(t)),
3542 self.orig_loc,
3543 self.buf.as_ptr().wrapping_add(pos) as usize,
3544 )))
3545 }
3546}
3547impl std::fmt::Debug for IterableQueueId<'_> {
3548 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3549 let mut fmt = f.debug_struct("QueueId");
3550 for attr in self.clone() {
3551 let attr = match attr {
3552 Ok(a) => a,
3553 Err(err) => {
3554 fmt.finish()?;
3555 f.write_str("Err(")?;
3556 err.fmt(f)?;
3557 return f.write_str(")");
3558 }
3559 };
3560 match attr {
3561 QueueId::Id(val) => fmt.field("Id", &val),
3562 QueueId::Type(val) => {
3563 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
3564 }
3565 };
3566 }
3567 fmt.finish()
3568 }
3569}
3570impl IterableQueueId<'_> {
3571 pub fn lookup_attr(
3572 &self,
3573 offset: usize,
3574 missing_type: Option<u16>,
3575 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3576 let mut stack = Vec::new();
3577 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3578 if missing_type.is_some() && cur == offset {
3579 stack.push(("QueueId", offset));
3580 return (stack, missing_type.and_then(|t| QueueId::attr_from_type(t)));
3581 }
3582 if cur > offset || cur + self.buf.len() < offset {
3583 return (stack, None);
3584 }
3585 let mut attrs = self.clone();
3586 let mut last_off = cur + attrs.pos;
3587 while let Some(attr) = attrs.next() {
3588 let Ok(attr) = attr else { break };
3589 match attr {
3590 QueueId::Id(val) => {
3591 if last_off == offset {
3592 stack.push(("Id", last_off));
3593 break;
3594 }
3595 }
3596 QueueId::Type(val) => {
3597 if last_off == offset {
3598 stack.push(("Type", last_off));
3599 break;
3600 }
3601 }
3602 _ => {}
3603 };
3604 last_off = cur + attrs.pos;
3605 }
3606 if !stack.is_empty() {
3607 stack.push(("QueueId", cur));
3608 }
3609 (stack, None)
3610 }
3611}
3612#[derive(Clone)]
3613pub enum Lease<'a> {
3614 #[doc = "The netdev ifindex to lease the queue from.\n"]
3615 Ifindex(u32),
3616 #[doc = "The netdev queue to lease from.\n"]
3617 Queue(IterableQueueId<'a>),
3618 #[doc = "The network namespace id of the netdev.\n"]
3619 NetnsId(i32),
3620}
3621impl<'a> IterableLease<'a> {
3622 #[doc = "The netdev ifindex to lease the queue from.\n"]
3623 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
3624 let mut iter = self.clone();
3625 iter.pos = 0;
3626 for attr in iter {
3627 if let Ok(Lease::Ifindex(val)) = attr {
3628 return Ok(val);
3629 }
3630 }
3631 Err(ErrorContext::new_missing(
3632 "Lease",
3633 "Ifindex",
3634 self.orig_loc,
3635 self.buf.as_ptr() as usize,
3636 ))
3637 }
3638 #[doc = "The netdev queue to lease from.\n"]
3639 pub fn get_queue(&self) -> Result<IterableQueueId<'a>, ErrorContext> {
3640 let mut iter = self.clone();
3641 iter.pos = 0;
3642 for attr in iter {
3643 if let Ok(Lease::Queue(val)) = attr {
3644 return Ok(val);
3645 }
3646 }
3647 Err(ErrorContext::new_missing(
3648 "Lease",
3649 "Queue",
3650 self.orig_loc,
3651 self.buf.as_ptr() as usize,
3652 ))
3653 }
3654 #[doc = "The network namespace id of the netdev.\n"]
3655 pub fn get_netns_id(&self) -> Result<i32, ErrorContext> {
3656 let mut iter = self.clone();
3657 iter.pos = 0;
3658 for attr in iter {
3659 if let Ok(Lease::NetnsId(val)) = attr {
3660 return Ok(val);
3661 }
3662 }
3663 Err(ErrorContext::new_missing(
3664 "Lease",
3665 "NetnsId",
3666 self.orig_loc,
3667 self.buf.as_ptr() as usize,
3668 ))
3669 }
3670}
3671impl Lease<'_> {
3672 pub fn new<'a>(buf: &'a [u8]) -> IterableLease<'a> {
3673 IterableLease::with_loc(buf, buf.as_ptr() as usize)
3674 }
3675 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3676 let res = match r#type {
3677 1u16 => "Ifindex",
3678 2u16 => "Queue",
3679 3u16 => "NetnsId",
3680 _ => return None,
3681 };
3682 Some(res)
3683 }
3684}
3685#[derive(Clone, Copy, Default)]
3686pub struct IterableLease<'a> {
3687 buf: &'a [u8],
3688 pos: usize,
3689 orig_loc: usize,
3690}
3691impl<'a> IterableLease<'a> {
3692 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3693 Self {
3694 buf,
3695 pos: 0,
3696 orig_loc,
3697 }
3698 }
3699 pub fn get_buf(&self) -> &'a [u8] {
3700 self.buf
3701 }
3702}
3703impl<'a> Iterator for IterableLease<'a> {
3704 type Item = Result<Lease<'a>, ErrorContext>;
3705 fn next(&mut self) -> Option<Self::Item> {
3706 let mut pos;
3707 let mut r#type;
3708 loop {
3709 pos = self.pos;
3710 r#type = None;
3711 if self.buf.len() == self.pos {
3712 return None;
3713 }
3714 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3715 self.pos = self.buf.len();
3716 break;
3717 };
3718 r#type = Some(header.r#type);
3719 let res = match header.r#type {
3720 1u16 => Lease::Ifindex({
3721 let res = parse_u32(next);
3722 let Some(val) = res else { break };
3723 val
3724 }),
3725 2u16 => Lease::Queue({
3726 let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
3727 let Some(val) = res else { break };
3728 val
3729 }),
3730 3u16 => Lease::NetnsId({
3731 let res = parse_i32(next);
3732 let Some(val) = res else { break };
3733 val
3734 }),
3735 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3736 n => continue,
3737 };
3738 return Some(Ok(res));
3739 }
3740 Some(Err(ErrorContext::new(
3741 "Lease",
3742 r#type.and_then(|t| Lease::attr_from_type(t)),
3743 self.orig_loc,
3744 self.buf.as_ptr().wrapping_add(pos) as usize,
3745 )))
3746 }
3747}
3748impl<'a> std::fmt::Debug for IterableLease<'_> {
3749 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3750 let mut fmt = f.debug_struct("Lease");
3751 for attr in self.clone() {
3752 let attr = match attr {
3753 Ok(a) => a,
3754 Err(err) => {
3755 fmt.finish()?;
3756 f.write_str("Err(")?;
3757 err.fmt(f)?;
3758 return f.write_str(")");
3759 }
3760 };
3761 match attr {
3762 Lease::Ifindex(val) => fmt.field("Ifindex", &val),
3763 Lease::Queue(val) => fmt.field("Queue", &val),
3764 Lease::NetnsId(val) => fmt.field("NetnsId", &val),
3765 };
3766 }
3767 fmt.finish()
3768 }
3769}
3770impl IterableLease<'_> {
3771 pub fn lookup_attr(
3772 &self,
3773 offset: usize,
3774 missing_type: Option<u16>,
3775 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3776 let mut stack = Vec::new();
3777 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3778 if missing_type.is_some() && cur == offset {
3779 stack.push(("Lease", offset));
3780 return (stack, missing_type.and_then(|t| Lease::attr_from_type(t)));
3781 }
3782 if cur > offset || cur + self.buf.len() < offset {
3783 return (stack, None);
3784 }
3785 let mut attrs = self.clone();
3786 let mut last_off = cur + attrs.pos;
3787 let mut missing = None;
3788 while let Some(attr) = attrs.next() {
3789 let Ok(attr) = attr else { break };
3790 match attr {
3791 Lease::Ifindex(val) => {
3792 if last_off == offset {
3793 stack.push(("Ifindex", last_off));
3794 break;
3795 }
3796 }
3797 Lease::Queue(val) => {
3798 (stack, missing) = val.lookup_attr(offset, missing_type);
3799 if !stack.is_empty() {
3800 break;
3801 }
3802 }
3803 Lease::NetnsId(val) => {
3804 if last_off == offset {
3805 stack.push(("NetnsId", last_off));
3806 break;
3807 }
3808 }
3809 _ => {}
3810 };
3811 last_off = cur + attrs.pos;
3812 }
3813 if !stack.is_empty() {
3814 stack.push(("Lease", cur));
3815 }
3816 (stack, missing)
3817 }
3818}
3819#[derive(Clone)]
3820pub enum Dmabuf<'a> {
3821 #[doc = "netdev ifindex to bind the dmabuf to.\n"]
3822 Ifindex(u32),
3823 #[doc = "receive queues to bind the dmabuf to.\n\nAttribute may repeat multiple times (treat it as array)"]
3824 Queues(IterableQueueId<'a>),
3825 #[doc = "dmabuf file descriptor to bind.\n"]
3826 Fd(u32),
3827 #[doc = "id of the dmabuf binding\n"]
3828 Id(u32),
3829}
3830impl<'a> IterableDmabuf<'a> {
3831 #[doc = "netdev ifindex to bind the dmabuf to.\n"]
3832 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
3833 let mut iter = self.clone();
3834 iter.pos = 0;
3835 for attr in iter {
3836 if let Ok(Dmabuf::Ifindex(val)) = attr {
3837 return Ok(val);
3838 }
3839 }
3840 Err(ErrorContext::new_missing(
3841 "Dmabuf",
3842 "Ifindex",
3843 self.orig_loc,
3844 self.buf.as_ptr() as usize,
3845 ))
3846 }
3847 #[doc = "receive queues to bind the dmabuf to.\n\nAttribute may repeat multiple times (treat it as array)"]
3848 pub fn get_queues(&self) -> MultiAttrIterable<Self, Dmabuf<'a>, IterableQueueId<'a>> {
3849 MultiAttrIterable::new(self.clone(), |variant| {
3850 if let Dmabuf::Queues(val) = variant {
3851 Some(val)
3852 } else {
3853 None
3854 }
3855 })
3856 }
3857 #[doc = "dmabuf file descriptor to bind.\n"]
3858 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
3859 let mut iter = self.clone();
3860 iter.pos = 0;
3861 for attr in iter {
3862 if let Ok(Dmabuf::Fd(val)) = attr {
3863 return Ok(val);
3864 }
3865 }
3866 Err(ErrorContext::new_missing(
3867 "Dmabuf",
3868 "Fd",
3869 self.orig_loc,
3870 self.buf.as_ptr() as usize,
3871 ))
3872 }
3873 #[doc = "id of the dmabuf binding\n"]
3874 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3875 let mut iter = self.clone();
3876 iter.pos = 0;
3877 for attr in iter {
3878 if let Ok(Dmabuf::Id(val)) = attr {
3879 return Ok(val);
3880 }
3881 }
3882 Err(ErrorContext::new_missing(
3883 "Dmabuf",
3884 "Id",
3885 self.orig_loc,
3886 self.buf.as_ptr() as usize,
3887 ))
3888 }
3889}
3890impl Dmabuf<'_> {
3891 pub fn new<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
3892 IterableDmabuf::with_loc(buf, buf.as_ptr() as usize)
3893 }
3894 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3895 let res = match r#type {
3896 1u16 => "Ifindex",
3897 2u16 => "Queues",
3898 3u16 => "Fd",
3899 4u16 => "Id",
3900 _ => return None,
3901 };
3902 Some(res)
3903 }
3904}
3905#[derive(Clone, Copy, Default)]
3906pub struct IterableDmabuf<'a> {
3907 buf: &'a [u8],
3908 pos: usize,
3909 orig_loc: usize,
3910}
3911impl<'a> IterableDmabuf<'a> {
3912 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3913 Self {
3914 buf,
3915 pos: 0,
3916 orig_loc,
3917 }
3918 }
3919 pub fn get_buf(&self) -> &'a [u8] {
3920 self.buf
3921 }
3922}
3923impl<'a> Iterator for IterableDmabuf<'a> {
3924 type Item = Result<Dmabuf<'a>, ErrorContext>;
3925 fn next(&mut self) -> Option<Self::Item> {
3926 let mut pos;
3927 let mut r#type;
3928 loop {
3929 pos = self.pos;
3930 r#type = None;
3931 if self.buf.len() == self.pos {
3932 return None;
3933 }
3934 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3935 self.pos = self.buf.len();
3936 break;
3937 };
3938 r#type = Some(header.r#type);
3939 let res = match header.r#type {
3940 1u16 => Dmabuf::Ifindex({
3941 let res = parse_u32(next);
3942 let Some(val) = res else { break };
3943 val
3944 }),
3945 2u16 => Dmabuf::Queues({
3946 let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
3947 let Some(val) = res else { break };
3948 val
3949 }),
3950 3u16 => Dmabuf::Fd({
3951 let res = parse_u32(next);
3952 let Some(val) = res else { break };
3953 val
3954 }),
3955 4u16 => Dmabuf::Id({
3956 let res = parse_u32(next);
3957 let Some(val) = res else { break };
3958 val
3959 }),
3960 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3961 n => continue,
3962 };
3963 return Some(Ok(res));
3964 }
3965 Some(Err(ErrorContext::new(
3966 "Dmabuf",
3967 r#type.and_then(|t| Dmabuf::attr_from_type(t)),
3968 self.orig_loc,
3969 self.buf.as_ptr().wrapping_add(pos) as usize,
3970 )))
3971 }
3972}
3973impl<'a> std::fmt::Debug for IterableDmabuf<'_> {
3974 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3975 let mut fmt = f.debug_struct("Dmabuf");
3976 for attr in self.clone() {
3977 let attr = match attr {
3978 Ok(a) => a,
3979 Err(err) => {
3980 fmt.finish()?;
3981 f.write_str("Err(")?;
3982 err.fmt(f)?;
3983 return f.write_str(")");
3984 }
3985 };
3986 match attr {
3987 Dmabuf::Ifindex(val) => fmt.field("Ifindex", &val),
3988 Dmabuf::Queues(val) => fmt.field("Queues", &val),
3989 Dmabuf::Fd(val) => fmt.field("Fd", &val),
3990 Dmabuf::Id(val) => fmt.field("Id", &val),
3991 };
3992 }
3993 fmt.finish()
3994 }
3995}
3996impl IterableDmabuf<'_> {
3997 pub fn lookup_attr(
3998 &self,
3999 offset: usize,
4000 missing_type: Option<u16>,
4001 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4002 let mut stack = Vec::new();
4003 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4004 if missing_type.is_some() && cur == offset {
4005 stack.push(("Dmabuf", offset));
4006 return (stack, missing_type.and_then(|t| Dmabuf::attr_from_type(t)));
4007 }
4008 if cur > offset || cur + self.buf.len() < offset {
4009 return (stack, None);
4010 }
4011 let mut attrs = self.clone();
4012 let mut last_off = cur + attrs.pos;
4013 let mut missing = None;
4014 while let Some(attr) = attrs.next() {
4015 let Ok(attr) = attr else { break };
4016 match attr {
4017 Dmabuf::Ifindex(val) => {
4018 if last_off == offset {
4019 stack.push(("Ifindex", last_off));
4020 break;
4021 }
4022 }
4023 Dmabuf::Queues(val) => {
4024 (stack, missing) = val.lookup_attr(offset, missing_type);
4025 if !stack.is_empty() {
4026 break;
4027 }
4028 }
4029 Dmabuf::Fd(val) => {
4030 if last_off == offset {
4031 stack.push(("Fd", last_off));
4032 break;
4033 }
4034 }
4035 Dmabuf::Id(val) => {
4036 if last_off == offset {
4037 stack.push(("Id", last_off));
4038 break;
4039 }
4040 }
4041 _ => {}
4042 };
4043 last_off = cur + attrs.pos;
4044 }
4045 if !stack.is_empty() {
4046 stack.push(("Dmabuf", cur));
4047 }
4048 (stack, missing)
4049 }
4050}
4051pub struct PushDev<Prev: Rec> {
4052 pub(crate) prev: Option<Prev>,
4053 pub(crate) header_offset: Option<usize>,
4054}
4055impl<Prev: Rec> Rec for PushDev<Prev> {
4056 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4057 self.prev.as_mut().unwrap().as_rec_mut()
4058 }
4059 fn as_rec(&self) -> &Vec<u8> {
4060 self.prev.as_ref().unwrap().as_rec()
4061 }
4062}
4063impl<Prev: Rec> PushDev<Prev> {
4064 pub fn new(prev: Prev) -> Self {
4065 Self {
4066 prev: Some(prev),
4067 header_offset: None,
4068 }
4069 }
4070 pub fn end_nested(mut self) -> Prev {
4071 let mut prev = self.prev.take().unwrap();
4072 if let Some(header_offset) = &self.header_offset {
4073 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4074 }
4075 prev
4076 }
4077 #[doc = "netdev ifindex\n"]
4078 pub fn push_ifindex(mut self, value: u32) -> Self {
4079 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4080 self.as_rec_mut().extend(value.to_ne_bytes());
4081 self
4082 }
4083 pub fn push_pad(mut self, value: &[u8]) -> Self {
4084 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
4085 self.as_rec_mut().extend(value);
4086 self
4087 }
4088 #[doc = "Bitmask of enabled xdp-features.\n\nAssociated type: [`XdpAct`] (enum)"]
4089 pub fn push_xdp_features(mut self, value: u64) -> Self {
4090 push_header(self.as_rec_mut(), 3u16, 8 as u16);
4091 self.as_rec_mut().extend(value.to_ne_bytes());
4092 self
4093 }
4094 #[doc = "max fragment count supported by ZC driver\n"]
4095 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
4096 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4097 self.as_rec_mut().extend(value.to_ne_bytes());
4098 self
4099 }
4100 #[doc = "Bitmask of supported XDP receive metadata features. See\nDocumentation/networking/xdp-rx-metadata.rst for more details.\n\nAssociated type: [`XdpRxMetadata`] (enum)"]
4101 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
4102 push_header(self.as_rec_mut(), 5u16, 8 as u16);
4103 self.as_rec_mut().extend(value.to_ne_bytes());
4104 self
4105 }
4106 #[doc = "Bitmask of enabled AF_XDP features.\n\nAssociated type: [`XskFlags`] (enum)"]
4107 pub fn push_xsk_features(mut self, value: u64) -> Self {
4108 push_header(self.as_rec_mut(), 6u16, 8 as u16);
4109 self.as_rec_mut().extend(value.to_ne_bytes());
4110 self
4111 }
4112}
4113impl<Prev: Rec> Drop for PushDev<Prev> {
4114 fn drop(&mut self) {
4115 if let Some(prev) = &mut self.prev {
4116 if let Some(header_offset) = &self.header_offset {
4117 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4118 }
4119 }
4120 }
4121}
4122pub struct PushIoUringProviderInfo<Prev: Rec> {
4123 pub(crate) prev: Option<Prev>,
4124 pub(crate) header_offset: Option<usize>,
4125}
4126impl<Prev: Rec> Rec for PushIoUringProviderInfo<Prev> {
4127 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4128 self.prev.as_mut().unwrap().as_rec_mut()
4129 }
4130 fn as_rec(&self) -> &Vec<u8> {
4131 self.prev.as_ref().unwrap().as_rec()
4132 }
4133}
4134impl<Prev: Rec> PushIoUringProviderInfo<Prev> {
4135 pub fn new(prev: Prev) -> Self {
4136 Self {
4137 prev: Some(prev),
4138 header_offset: None,
4139 }
4140 }
4141 pub fn end_nested(mut self) -> Prev {
4142 let mut prev = self.prev.take().unwrap();
4143 if let Some(header_offset) = &self.header_offset {
4144 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4145 }
4146 prev
4147 }
4148}
4149impl<Prev: Rec> Drop for PushIoUringProviderInfo<Prev> {
4150 fn drop(&mut self) {
4151 if let Some(prev) = &mut self.prev {
4152 if let Some(header_offset) = &self.header_offset {
4153 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4154 }
4155 }
4156 }
4157}
4158pub struct PushPagePool<Prev: Rec> {
4159 pub(crate) prev: Option<Prev>,
4160 pub(crate) header_offset: Option<usize>,
4161}
4162impl<Prev: Rec> Rec for PushPagePool<Prev> {
4163 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4164 self.prev.as_mut().unwrap().as_rec_mut()
4165 }
4166 fn as_rec(&self) -> &Vec<u8> {
4167 self.prev.as_ref().unwrap().as_rec()
4168 }
4169}
4170impl<Prev: Rec> PushPagePool<Prev> {
4171 pub fn new(prev: Prev) -> Self {
4172 Self {
4173 prev: Some(prev),
4174 header_offset: None,
4175 }
4176 }
4177 pub fn end_nested(mut self) -> Prev {
4178 let mut prev = self.prev.take().unwrap();
4179 if let Some(header_offset) = &self.header_offset {
4180 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4181 }
4182 prev
4183 }
4184 #[doc = "Unique ID of a Page Pool instance.\n"]
4185 pub fn push_id(mut self, value: u32) -> Self {
4186 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4187 self.as_rec_mut().extend(value.to_ne_bytes());
4188 self
4189 }
4190 #[doc = "ifindex of the netdev to which the pool belongs. May not be reported if\nthe page pool was allocated for a netdev which got destroyed already\n(page pools may outlast their netdevs because they wait for all memory\nto be returned).\n"]
4191 pub fn push_ifindex(mut self, value: u32) -> Self {
4192 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4193 self.as_rec_mut().extend(value.to_ne_bytes());
4194 self
4195 }
4196 #[doc = "Id of NAPI using this Page Pool instance.\n"]
4197 pub fn push_napi_id(mut self, value: u32) -> Self {
4198 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4199 self.as_rec_mut().extend(value.to_ne_bytes());
4200 self
4201 }
4202 #[doc = "Number of outstanding references to this page pool (allocated but yet to\nbe freed pages). Allocated pages may be held in socket receive queues,\ndriver receive ring, page pool recycling ring, the page pool cache, etc.\n"]
4203 pub fn push_inflight(mut self, value: u32) -> Self {
4204 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4205 self.as_rec_mut().extend(value.to_ne_bytes());
4206 self
4207 }
4208 #[doc = "Amount of memory held by inflight pages.\n"]
4209 pub fn push_inflight_mem(mut self, value: u32) -> Self {
4210 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4211 self.as_rec_mut().extend(value.to_ne_bytes());
4212 self
4213 }
4214 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by the driver.\nOnce detached Page Pool can no longer be used to allocate memory. Page\nPools wait for all the memory allocated from them to be freed before\ntruly disappearing. \\\"Detached\\\" Page Pools cannot be \\\"re-attached\\\",\nthey are just waiting to disappear. Attribute is absent if Page Pool has\nnot been detached, and can still be used to allocate new memory.\n"]
4215 pub fn push_detach_time(mut self, value: u32) -> Self {
4216 push_header(self.as_rec_mut(), 6u16, 4 as u16);
4217 self.as_rec_mut().extend(value.to_ne_bytes());
4218 self
4219 }
4220 #[doc = "ID of the dmabuf this page-pool is attached to.\n"]
4221 pub fn push_dmabuf(mut self, value: u32) -> Self {
4222 push_header(self.as_rec_mut(), 7u16, 4 as u16);
4223 self.as_rec_mut().extend(value.to_ne_bytes());
4224 self
4225 }
4226 #[doc = "io-uring memory provider information.\n"]
4227 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
4228 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
4229 PushIoUringProviderInfo {
4230 prev: Some(self),
4231 header_offset: Some(header_offset),
4232 }
4233 }
4234}
4235impl<Prev: Rec> Drop for PushPagePool<Prev> {
4236 fn drop(&mut self) {
4237 if let Some(prev) = &mut self.prev {
4238 if let Some(header_offset) = &self.header_offset {
4239 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4240 }
4241 }
4242 }
4243}
4244pub struct PushPagePoolInfo<Prev: Rec> {
4245 pub(crate) prev: Option<Prev>,
4246 pub(crate) header_offset: Option<usize>,
4247}
4248impl<Prev: Rec> Rec for PushPagePoolInfo<Prev> {
4249 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4250 self.prev.as_mut().unwrap().as_rec_mut()
4251 }
4252 fn as_rec(&self) -> &Vec<u8> {
4253 self.prev.as_ref().unwrap().as_rec()
4254 }
4255}
4256impl<Prev: Rec> PushPagePoolInfo<Prev> {
4257 pub fn new(prev: Prev) -> Self {
4258 Self {
4259 prev: Some(prev),
4260 header_offset: None,
4261 }
4262 }
4263 pub fn end_nested(mut self) -> Prev {
4264 let mut prev = self.prev.take().unwrap();
4265 if let Some(header_offset) = &self.header_offset {
4266 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4267 }
4268 prev
4269 }
4270 #[doc = "Unique ID of a Page Pool instance.\n"]
4271 pub fn push_id(mut self, value: u32) -> Self {
4272 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4273 self.as_rec_mut().extend(value.to_ne_bytes());
4274 self
4275 }
4276 #[doc = "ifindex of the netdev to which the pool belongs. May not be reported if\nthe page pool was allocated for a netdev which got destroyed already\n(page pools may outlast their netdevs because they wait for all memory\nto be returned).\n"]
4277 pub fn push_ifindex(mut self, value: u32) -> Self {
4278 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4279 self.as_rec_mut().extend(value.to_ne_bytes());
4280 self
4281 }
4282}
4283impl<Prev: Rec> Drop for PushPagePoolInfo<Prev> {
4284 fn drop(&mut self) {
4285 if let Some(prev) = &mut self.prev {
4286 if let Some(header_offset) = &self.header_offset {
4287 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4288 }
4289 }
4290 }
4291}
4292pub struct PushPagePoolStats<Prev: Rec> {
4293 pub(crate) prev: Option<Prev>,
4294 pub(crate) header_offset: Option<usize>,
4295}
4296impl<Prev: Rec> Rec for PushPagePoolStats<Prev> {
4297 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4298 self.prev.as_mut().unwrap().as_rec_mut()
4299 }
4300 fn as_rec(&self) -> &Vec<u8> {
4301 self.prev.as_ref().unwrap().as_rec()
4302 }
4303}
4304impl<Prev: Rec> PushPagePoolStats<Prev> {
4305 pub fn new(prev: Prev) -> Self {
4306 Self {
4307 prev: Some(prev),
4308 header_offset: None,
4309 }
4310 }
4311 pub fn end_nested(mut self) -> Prev {
4312 let mut prev = self.prev.take().unwrap();
4313 if let Some(header_offset) = &self.header_offset {
4314 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4315 }
4316 prev
4317 }
4318 #[doc = "Page pool identifying information.\n"]
4319 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
4320 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4321 PushPagePoolInfo {
4322 prev: Some(self),
4323 header_offset: Some(header_offset),
4324 }
4325 }
4326 pub fn push_alloc_fast(mut self, value: u32) -> Self {
4327 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4328 self.as_rec_mut().extend(value.to_ne_bytes());
4329 self
4330 }
4331 pub fn push_alloc_slow(mut self, value: u32) -> Self {
4332 push_header(self.as_rec_mut(), 9u16, 4 as u16);
4333 self.as_rec_mut().extend(value.to_ne_bytes());
4334 self
4335 }
4336 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
4337 push_header(self.as_rec_mut(), 10u16, 4 as u16);
4338 self.as_rec_mut().extend(value.to_ne_bytes());
4339 self
4340 }
4341 pub fn push_alloc_empty(mut self, value: u32) -> Self {
4342 push_header(self.as_rec_mut(), 11u16, 4 as u16);
4343 self.as_rec_mut().extend(value.to_ne_bytes());
4344 self
4345 }
4346 pub fn push_alloc_refill(mut self, value: u32) -> Self {
4347 push_header(self.as_rec_mut(), 12u16, 4 as u16);
4348 self.as_rec_mut().extend(value.to_ne_bytes());
4349 self
4350 }
4351 pub fn push_alloc_waive(mut self, value: u32) -> Self {
4352 push_header(self.as_rec_mut(), 13u16, 4 as u16);
4353 self.as_rec_mut().extend(value.to_ne_bytes());
4354 self
4355 }
4356 pub fn push_recycle_cached(mut self, value: u32) -> Self {
4357 push_header(self.as_rec_mut(), 14u16, 4 as u16);
4358 self.as_rec_mut().extend(value.to_ne_bytes());
4359 self
4360 }
4361 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
4362 push_header(self.as_rec_mut(), 15u16, 4 as u16);
4363 self.as_rec_mut().extend(value.to_ne_bytes());
4364 self
4365 }
4366 pub fn push_recycle_ring(mut self, value: u32) -> Self {
4367 push_header(self.as_rec_mut(), 16u16, 4 as u16);
4368 self.as_rec_mut().extend(value.to_ne_bytes());
4369 self
4370 }
4371 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
4372 push_header(self.as_rec_mut(), 17u16, 4 as u16);
4373 self.as_rec_mut().extend(value.to_ne_bytes());
4374 self
4375 }
4376 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
4377 push_header(self.as_rec_mut(), 18u16, 4 as u16);
4378 self.as_rec_mut().extend(value.to_ne_bytes());
4379 self
4380 }
4381}
4382impl<Prev: Rec> Drop for PushPagePoolStats<Prev> {
4383 fn drop(&mut self) {
4384 if let Some(prev) = &mut self.prev {
4385 if let Some(header_offset) = &self.header_offset {
4386 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4387 }
4388 }
4389 }
4390}
4391pub struct PushNapi<Prev: Rec> {
4392 pub(crate) prev: Option<Prev>,
4393 pub(crate) header_offset: Option<usize>,
4394}
4395impl<Prev: Rec> Rec for PushNapi<Prev> {
4396 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4397 self.prev.as_mut().unwrap().as_rec_mut()
4398 }
4399 fn as_rec(&self) -> &Vec<u8> {
4400 self.prev.as_ref().unwrap().as_rec()
4401 }
4402}
4403impl<Prev: Rec> PushNapi<Prev> {
4404 pub fn new(prev: Prev) -> Self {
4405 Self {
4406 prev: Some(prev),
4407 header_offset: None,
4408 }
4409 }
4410 pub fn end_nested(mut self) -> Prev {
4411 let mut prev = self.prev.take().unwrap();
4412 if let Some(header_offset) = &self.header_offset {
4413 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4414 }
4415 prev
4416 }
4417 #[doc = "ifindex of the netdevice to which NAPI instance belongs.\n"]
4418 pub fn push_ifindex(mut self, value: u32) -> Self {
4419 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4420 self.as_rec_mut().extend(value.to_ne_bytes());
4421 self
4422 }
4423 #[doc = "ID of the NAPI instance.\n"]
4424 pub fn push_id(mut self, value: u32) -> Self {
4425 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4426 self.as_rec_mut().extend(value.to_ne_bytes());
4427 self
4428 }
4429 #[doc = "The associated interrupt vector number for the napi\n"]
4430 pub fn push_irq(mut self, value: u32) -> Self {
4431 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4432 self.as_rec_mut().extend(value.to_ne_bytes());
4433 self
4434 }
4435 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded\nmode. If NAPI is not in threaded mode (i.e. uses normal softirq\ncontext), the attribute will be absent.\n"]
4436 pub fn push_pid(mut self, value: u32) -> Self {
4437 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4438 self.as_rec_mut().extend(value.to_ne_bytes());
4439 self
4440 }
4441 #[doc = "The number of consecutive empty polls before IRQ deferral ends and\nhardware IRQs are re-enabled.\n"]
4442 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
4443 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4444 self.as_rec_mut().extend(value.to_ne_bytes());
4445 self
4446 }
4447 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer\nwhich schedules NAPI processing. Additionally, a non-zero value will\nalso prevent GRO from flushing recent super-frames at the end of a NAPI\ncycle. This may add receive latency in exchange for reducing the number\nof frames processed by the network stack.\n"]
4448 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
4449 push_header(self.as_rec_mut(), 6u16, 4 as u16);
4450 self.as_rec_mut().extend(value.to_ne_bytes());
4451 self
4452 }
4453 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if\nevent polling finds events\n"]
4454 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
4455 push_header(self.as_rec_mut(), 7u16, 4 as u16);
4456 self.as_rec_mut().extend(value.to_ne_bytes());
4457 self
4458 }
4459 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If\nthis is set to enabled then the NAPI context operates in threaded\npolling mode. If this is set to busy-poll, then the threaded polling\nmode also busy polls.\n\nAssociated type: [`NapiThreaded`] (enum)"]
4460 pub fn push_threaded(mut self, value: u32) -> Self {
4461 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4462 self.as_rec_mut().extend(value.to_ne_bytes());
4463 self
4464 }
4465}
4466impl<Prev: Rec> Drop for PushNapi<Prev> {
4467 fn drop(&mut self) {
4468 if let Some(prev) = &mut self.prev {
4469 if let Some(header_offset) = &self.header_offset {
4470 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4471 }
4472 }
4473 }
4474}
4475pub struct PushXskInfo<Prev: Rec> {
4476 pub(crate) prev: Option<Prev>,
4477 pub(crate) header_offset: Option<usize>,
4478}
4479impl<Prev: Rec> Rec for PushXskInfo<Prev> {
4480 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4481 self.prev.as_mut().unwrap().as_rec_mut()
4482 }
4483 fn as_rec(&self) -> &Vec<u8> {
4484 self.prev.as_ref().unwrap().as_rec()
4485 }
4486}
4487impl<Prev: Rec> PushXskInfo<Prev> {
4488 pub fn new(prev: Prev) -> Self {
4489 Self {
4490 prev: Some(prev),
4491 header_offset: None,
4492 }
4493 }
4494 pub fn end_nested(mut self) -> Prev {
4495 let mut prev = self.prev.take().unwrap();
4496 if let Some(header_offset) = &self.header_offset {
4497 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4498 }
4499 prev
4500 }
4501}
4502impl<Prev: Rec> Drop for PushXskInfo<Prev> {
4503 fn drop(&mut self) {
4504 if let Some(prev) = &mut self.prev {
4505 if let Some(header_offset) = &self.header_offset {
4506 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4507 }
4508 }
4509 }
4510}
4511pub struct PushQueue<Prev: Rec> {
4512 pub(crate) prev: Option<Prev>,
4513 pub(crate) header_offset: Option<usize>,
4514}
4515impl<Prev: Rec> Rec for PushQueue<Prev> {
4516 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4517 self.prev.as_mut().unwrap().as_rec_mut()
4518 }
4519 fn as_rec(&self) -> &Vec<u8> {
4520 self.prev.as_ref().unwrap().as_rec()
4521 }
4522}
4523impl<Prev: Rec> PushQueue<Prev> {
4524 pub fn new(prev: Prev) -> Self {
4525 Self {
4526 prev: Some(prev),
4527 header_offset: None,
4528 }
4529 }
4530 pub fn end_nested(mut self) -> Prev {
4531 let mut prev = self.prev.take().unwrap();
4532 if let Some(header_offset) = &self.header_offset {
4533 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4534 }
4535 prev
4536 }
4537 #[doc = "Queue index; most queue types are indexed like a C array, with indexes\nstarting at 0 and ending at queue count - 1. Queue indexes are scoped to\nan interface and queue type.\n"]
4538 pub fn push_id(mut self, value: u32) -> Self {
4539 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4540 self.as_rec_mut().extend(value.to_ne_bytes());
4541 self
4542 }
4543 #[doc = "ifindex of the netdevice to which the queue belongs.\n"]
4544 pub fn push_ifindex(mut self, value: u32) -> Self {
4545 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4546 self.as_rec_mut().extend(value.to_ne_bytes());
4547 self
4548 }
4549 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP\nTX queues allocated in the kernel are not linked to NAPIs and thus not\nlisted. AF_XDP queues will have more information set in the xsk\nattribute.\n\nAssociated type: [`QueueType`] (enum)"]
4550 pub fn push_type(mut self, value: u32) -> Self {
4551 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4552 self.as_rec_mut().extend(value.to_ne_bytes());
4553 self
4554 }
4555 #[doc = "ID of the NAPI instance which services this queue.\n"]
4556 pub fn push_napi_id(mut self, value: u32) -> Self {
4557 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4558 self.as_rec_mut().extend(value.to_ne_bytes());
4559 self
4560 }
4561 #[doc = "ID of the dmabuf attached to this queue, if any.\n"]
4562 pub fn push_dmabuf(mut self, value: u32) -> Self {
4563 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4564 self.as_rec_mut().extend(value.to_ne_bytes());
4565 self
4566 }
4567 #[doc = "io_uring memory provider information.\n"]
4568 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
4569 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
4570 PushIoUringProviderInfo {
4571 prev: Some(self),
4572 header_offset: Some(header_offset),
4573 }
4574 }
4575 #[doc = "XSK information for this queue, if any.\n"]
4576 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
4577 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
4578 PushXskInfo {
4579 prev: Some(self),
4580 header_offset: Some(header_offset),
4581 }
4582 }
4583 #[doc = "A queue from a virtual device can have a lease which refers to another\nqueue from a physical device. This is useful for memory providers and\nAF_XDP operations which take an ifindex and queue id to allow\napplications to bind against virtual devices in containers.\n"]
4584 pub fn nested_lease(mut self) -> PushLease<Self> {
4585 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
4586 PushLease {
4587 prev: Some(self),
4588 header_offset: Some(header_offset),
4589 }
4590 }
4591}
4592impl<Prev: Rec> Drop for PushQueue<Prev> {
4593 fn drop(&mut self) {
4594 if let Some(prev) = &mut self.prev {
4595 if let Some(header_offset) = &self.header_offset {
4596 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4597 }
4598 }
4599 }
4600}
4601pub struct PushQstats<Prev: Rec> {
4602 pub(crate) prev: Option<Prev>,
4603 pub(crate) header_offset: Option<usize>,
4604}
4605impl<Prev: Rec> Rec for PushQstats<Prev> {
4606 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4607 self.prev.as_mut().unwrap().as_rec_mut()
4608 }
4609 fn as_rec(&self) -> &Vec<u8> {
4610 self.prev.as_ref().unwrap().as_rec()
4611 }
4612}
4613impl<Prev: Rec> PushQstats<Prev> {
4614 pub fn new(prev: Prev) -> Self {
4615 Self {
4616 prev: Some(prev),
4617 header_offset: None,
4618 }
4619 }
4620 pub fn end_nested(mut self) -> Prev {
4621 let mut prev = self.prev.take().unwrap();
4622 if let Some(header_offset) = &self.header_offset {
4623 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4624 }
4625 prev
4626 }
4627 #[doc = "ifindex of the netdevice to which stats belong.\n"]
4628 pub fn push_ifindex(mut self, value: u32) -> Self {
4629 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4630 self.as_rec_mut().extend(value.to_ne_bytes());
4631 self
4632 }
4633 #[doc = "Queue type as rx, tx, for queue-id.\n\nAssociated type: [`QueueType`] (enum)"]
4634 pub fn push_queue_type(mut self, value: u32) -> Self {
4635 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4636 self.as_rec_mut().extend(value.to_ne_bytes());
4637 self
4638 }
4639 #[doc = "Queue ID, if stats are scoped to a single queue instance.\n"]
4640 pub fn push_queue_id(mut self, value: u32) -> Self {
4641 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4642 self.as_rec_mut().extend(value.to_ne_bytes());
4643 self
4644 }
4645 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: [`QstatsScope`] (enum)"]
4646 pub fn push_scope(mut self, value: u32) -> Self {
4647 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4648 self.as_rec_mut().extend(value.to_ne_bytes());
4649 self
4650 }
4651 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer of the\nstack, so packets consumed by XDP are still counted here.\n"]
4652 pub fn push_rx_packets(mut self, value: u32) -> Self {
4653 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4654 self.as_rec_mut().extend(value.to_ne_bytes());
4655 self
4656 }
4657 #[doc = "Successfully received bytes, see [rx-packets]{.title-ref}.\n"]
4658 pub fn push_rx_bytes(mut self, value: u32) -> Self {
4659 push_header(self.as_rec_mut(), 9u16, 4 as u16);
4660 self.as_rec_mut().extend(value.to_ne_bytes());
4661 self
4662 }
4663 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means the\ndevice has issued a DMA completion for the packet).\n"]
4664 pub fn push_tx_packets(mut self, value: u32) -> Self {
4665 push_header(self.as_rec_mut(), 10u16, 4 as u16);
4666 self.as_rec_mut().extend(value.to_ne_bytes());
4667 self
4668 }
4669 #[doc = "Successfully sent bytes, see [tx-packets]{.title-ref}.\n"]
4670 pub fn push_tx_bytes(mut self, value: u32) -> Self {
4671 push_header(self.as_rec_mut(), 11u16, 4 as u16);
4672 self.as_rec_mut().extend(value.to_ne_bytes());
4673 self
4674 }
4675 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending on\ndriver implementation and whether system recovers quickly.\n"]
4676 pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
4677 push_header(self.as_rec_mut(), 12u16, 4 as u16);
4678 self.as_rec_mut().extend(value.to_ne_bytes());
4679 self
4680 }
4681 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
4682 pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
4683 push_header(self.as_rec_mut(), 13u16, 4 as u16);
4684 self.as_rec_mut().extend(value.to_ne_bytes());
4685 self
4686 }
4687 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
4688 pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
4689 push_header(self.as_rec_mut(), 14u16, 4 as u16);
4690 self.as_rec_mut().extend(value.to_ne_bytes());
4691 self
4692 }
4693 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE.\n"]
4694 pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
4695 push_header(self.as_rec_mut(), 15u16, 4 as u16);
4696 self.as_rec_mut().extend(value.to_ne_bytes());
4697 self
4698 }
4699 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY.\n"]
4700 pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
4701 push_header(self.as_rec_mut(), 16u16, 4 as u16);
4702 self.as_rec_mut().extend(value.to_ne_bytes());
4703 self
4704 }
4705 #[doc = "Number of packets that were not checksummed by device.\n"]
4706 pub fn push_rx_csum_none(mut self, value: u32) -> Self {
4707 push_header(self.as_rec_mut(), 17u16, 4 as u16);
4708 self.as_rec_mut().extend(value.to_ne_bytes());
4709 self
4710 }
4711 #[doc = "Number of packets with bad checksum. The packets are not discarded, but\nstill delivered to the stack.\n"]
4712 pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
4713 push_header(self.as_rec_mut(), 18u16, 4 as u16);
4714 self.as_rec_mut().extend(value.to_ne_bytes());
4715 self
4716 }
4717 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice feature,\nLRO-coalesced packets are not counted.\n"]
4718 pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
4719 push_header(self.as_rec_mut(), 19u16, 4 as u16);
4720 self.as_rec_mut().extend(value.to_ne_bytes());
4721 self
4722 }
4723 #[doc = "See [rx-hw-gro-packets]{.title-ref}.\n"]
4724 pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
4725 push_header(self.as_rec_mut(), 20u16, 4 as u16);
4726 self.as_rec_mut().extend(value.to_ne_bytes());
4727 self
4728 }
4729 #[doc = "Number of packets that were coalesced to bigger packetss with the HW-GRO\nnetdevice feature. LRO-coalesced packets are not counted.\n"]
4730 pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
4731 push_header(self.as_rec_mut(), 21u16, 4 as u16);
4732 self.as_rec_mut().extend(value.to_ne_bytes());
4733 self
4734 }
4735 #[doc = "See [rx-hw-gro-wire-packets]{.title-ref}.\n"]
4736 pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
4737 push_header(self.as_rec_mut(), 22u16, 4 as u16);
4738 self.as_rec_mut().extend(value.to_ne_bytes());
4739 self
4740 }
4741 #[doc = "Number of the packets dropped by the device due to the received packets\nbitrate exceeding the device rate limit.\n"]
4742 pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4743 push_header(self.as_rec_mut(), 23u16, 4 as u16);
4744 self.as_rec_mut().extend(value.to_ne_bytes());
4745 self
4746 }
4747 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
4748 pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
4749 push_header(self.as_rec_mut(), 24u16, 4 as u16);
4750 self.as_rec_mut().extend(value.to_ne_bytes());
4751 self
4752 }
4753 #[doc = "Number of packets dropped because they were invalid or malformed.\n"]
4754 pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
4755 push_header(self.as_rec_mut(), 25u16, 4 as u16);
4756 self.as_rec_mut().extend(value.to_ne_bytes());
4757 self
4758 }
4759 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
4760 pub fn push_tx_csum_none(mut self, value: u32) -> Self {
4761 push_header(self.as_rec_mut(), 26u16, 4 as u16);
4762 self.as_rec_mut().extend(value.to_ne_bytes());
4763 self
4764 }
4765 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
4766 pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
4767 push_header(self.as_rec_mut(), 27u16, 4 as u16);
4768 self.as_rec_mut().extend(value.to_ne_bytes());
4769 self
4770 }
4771 #[doc = "Number of packets that necessitated segmentation into smaller packets by\nthe device.\n"]
4772 pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
4773 push_header(self.as_rec_mut(), 28u16, 4 as u16);
4774 self.as_rec_mut().extend(value.to_ne_bytes());
4775 self
4776 }
4777 #[doc = "See [tx-hw-gso-packets]{.title-ref}.\n"]
4778 pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
4779 push_header(self.as_rec_mut(), 29u16, 4 as u16);
4780 self.as_rec_mut().extend(value.to_ne_bytes());
4781 self
4782 }
4783 #[doc = "Number of wire-sized packets generated by processing\n[tx-hw-gso-packets]{.title-ref}\n"]
4784 pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
4785 push_header(self.as_rec_mut(), 30u16, 4 as u16);
4786 self.as_rec_mut().extend(value.to_ne_bytes());
4787 self
4788 }
4789 #[doc = "See [tx-hw-gso-wire-packets]{.title-ref}.\n"]
4790 pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
4791 push_header(self.as_rec_mut(), 31u16, 4 as u16);
4792 self.as_rec_mut().extend(value.to_ne_bytes());
4793 self
4794 }
4795 #[doc = "Number of the packets dropped by the device due to the transmit packets\nbitrate exceeding the device rate limit.\n"]
4796 pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4797 push_header(self.as_rec_mut(), 32u16, 4 as u16);
4798 self.as_rec_mut().extend(value.to_ne_bytes());
4799 self
4800 }
4801 #[doc = "Number of times driver paused accepting new tx packets from the stack to\nthis queue, because the queue was full. Note that if BQL is supported\nand enabled on the device the networking stack will avoid queuing a lot\nof data at once.\n"]
4802 pub fn push_tx_stop(mut self, value: u32) -> Self {
4803 push_header(self.as_rec_mut(), 33u16, 4 as u16);
4804 self.as_rec_mut().extend(value.to_ne_bytes());
4805 self
4806 }
4807 #[doc = "Number of times driver re-started accepting send requests to this queue\nfrom the stack.\n"]
4808 pub fn push_tx_wake(mut self, value: u32) -> Self {
4809 push_header(self.as_rec_mut(), 34u16, 4 as u16);
4810 self.as_rec_mut().extend(value.to_ne_bytes());
4811 self
4812 }
4813}
4814impl<Prev: Rec> Drop for PushQstats<Prev> {
4815 fn drop(&mut self) {
4816 if let Some(prev) = &mut self.prev {
4817 if let Some(header_offset) = &self.header_offset {
4818 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4819 }
4820 }
4821 }
4822}
4823pub struct PushQueueId<Prev: Rec> {
4824 pub(crate) prev: Option<Prev>,
4825 pub(crate) header_offset: Option<usize>,
4826}
4827impl<Prev: Rec> Rec for PushQueueId<Prev> {
4828 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4829 self.prev.as_mut().unwrap().as_rec_mut()
4830 }
4831 fn as_rec(&self) -> &Vec<u8> {
4832 self.prev.as_ref().unwrap().as_rec()
4833 }
4834}
4835impl<Prev: Rec> PushQueueId<Prev> {
4836 pub fn new(prev: Prev) -> Self {
4837 Self {
4838 prev: Some(prev),
4839 header_offset: None,
4840 }
4841 }
4842 pub fn end_nested(mut self) -> Prev {
4843 let mut prev = self.prev.take().unwrap();
4844 if let Some(header_offset) = &self.header_offset {
4845 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4846 }
4847 prev
4848 }
4849 #[doc = "Queue index; most queue types are indexed like a C array, with indexes\nstarting at 0 and ending at queue count - 1. Queue indexes are scoped to\nan interface and queue type.\n"]
4850 pub fn push_id(mut self, value: u32) -> Self {
4851 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4852 self.as_rec_mut().extend(value.to_ne_bytes());
4853 self
4854 }
4855 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP\nTX queues allocated in the kernel are not linked to NAPIs and thus not\nlisted. AF_XDP queues will have more information set in the xsk\nattribute.\n\nAssociated type: [`QueueType`] (enum)"]
4856 pub fn push_type(mut self, value: u32) -> Self {
4857 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4858 self.as_rec_mut().extend(value.to_ne_bytes());
4859 self
4860 }
4861}
4862impl<Prev: Rec> Drop for PushQueueId<Prev> {
4863 fn drop(&mut self) {
4864 if let Some(prev) = &mut self.prev {
4865 if let Some(header_offset) = &self.header_offset {
4866 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4867 }
4868 }
4869 }
4870}
4871pub struct PushLease<Prev: Rec> {
4872 pub(crate) prev: Option<Prev>,
4873 pub(crate) header_offset: Option<usize>,
4874}
4875impl<Prev: Rec> Rec for PushLease<Prev> {
4876 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4877 self.prev.as_mut().unwrap().as_rec_mut()
4878 }
4879 fn as_rec(&self) -> &Vec<u8> {
4880 self.prev.as_ref().unwrap().as_rec()
4881 }
4882}
4883impl<Prev: Rec> PushLease<Prev> {
4884 pub fn new(prev: Prev) -> Self {
4885 Self {
4886 prev: Some(prev),
4887 header_offset: None,
4888 }
4889 }
4890 pub fn end_nested(mut self) -> Prev {
4891 let mut prev = self.prev.take().unwrap();
4892 if let Some(header_offset) = &self.header_offset {
4893 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4894 }
4895 prev
4896 }
4897 #[doc = "The netdev ifindex to lease the queue from.\n"]
4898 pub fn push_ifindex(mut self, value: u32) -> Self {
4899 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4900 self.as_rec_mut().extend(value.to_ne_bytes());
4901 self
4902 }
4903 #[doc = "The netdev queue to lease from.\n"]
4904 pub fn nested_queue(mut self) -> PushQueueId<Self> {
4905 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
4906 PushQueueId {
4907 prev: Some(self),
4908 header_offset: Some(header_offset),
4909 }
4910 }
4911 #[doc = "The network namespace id of the netdev.\n"]
4912 pub fn push_netns_id(mut self, value: i32) -> Self {
4913 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4914 self.as_rec_mut().extend(value.to_ne_bytes());
4915 self
4916 }
4917}
4918impl<Prev: Rec> Drop for PushLease<Prev> {
4919 fn drop(&mut self) {
4920 if let Some(prev) = &mut self.prev {
4921 if let Some(header_offset) = &self.header_offset {
4922 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4923 }
4924 }
4925 }
4926}
4927pub struct PushDmabuf<Prev: Rec> {
4928 pub(crate) prev: Option<Prev>,
4929 pub(crate) header_offset: Option<usize>,
4930}
4931impl<Prev: Rec> Rec for PushDmabuf<Prev> {
4932 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4933 self.prev.as_mut().unwrap().as_rec_mut()
4934 }
4935 fn as_rec(&self) -> &Vec<u8> {
4936 self.prev.as_ref().unwrap().as_rec()
4937 }
4938}
4939impl<Prev: Rec> PushDmabuf<Prev> {
4940 pub fn new(prev: Prev) -> Self {
4941 Self {
4942 prev: Some(prev),
4943 header_offset: None,
4944 }
4945 }
4946 pub fn end_nested(mut self) -> Prev {
4947 let mut prev = self.prev.take().unwrap();
4948 if let Some(header_offset) = &self.header_offset {
4949 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4950 }
4951 prev
4952 }
4953 #[doc = "netdev ifindex to bind the dmabuf to.\n"]
4954 pub fn push_ifindex(mut self, value: u32) -> Self {
4955 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4956 self.as_rec_mut().extend(value.to_ne_bytes());
4957 self
4958 }
4959 #[doc = "receive queues to bind the dmabuf to.\n\nAttribute may repeat multiple times (treat it as array)"]
4960 pub fn nested_queues(mut self) -> PushQueueId<Self> {
4961 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
4962 PushQueueId {
4963 prev: Some(self),
4964 header_offset: Some(header_offset),
4965 }
4966 }
4967 #[doc = "dmabuf file descriptor to bind.\n"]
4968 pub fn push_fd(mut self, value: u32) -> Self {
4969 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4970 self.as_rec_mut().extend(value.to_ne_bytes());
4971 self
4972 }
4973 #[doc = "id of the dmabuf binding\n"]
4974 pub fn push_id(mut self, value: u32) -> Self {
4975 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4976 self.as_rec_mut().extend(value.to_ne_bytes());
4977 self
4978 }
4979}
4980impl<Prev: Rec> Drop for PushDmabuf<Prev> {
4981 fn drop(&mut self) {
4982 if let Some(prev) = &mut self.prev {
4983 if let Some(header_offset) = &self.header_offset {
4984 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4985 }
4986 }
4987 }
4988}
4989#[doc = "Notify attributes:\n- [`.get_ifindex()`](IterableDev::get_ifindex)\n- [`.get_xdp_features()`](IterableDev::get_xdp_features)\n- [`.get_xdp_zc_max_segs()`](IterableDev::get_xdp_zc_max_segs)\n- [`.get_xdp_rx_metadata_features()`](IterableDev::get_xdp_rx_metadata_features)\n- [`.get_xsk_features()`](IterableDev::get_xsk_features)\n"]
4990#[derive(Debug)]
4991pub struct OpDevAddNotif;
4992impl OpDevAddNotif {
4993 pub const CMD: u8 = 2u8;
4994 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
4995 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
4996 IterableDev::with_loc(attrs, buf.as_ptr() as usize)
4997 }
4998}
4999#[doc = "Notify attributes:\n- [`.get_ifindex()`](IterableDev::get_ifindex)\n- [`.get_xdp_features()`](IterableDev::get_xdp_features)\n- [`.get_xdp_zc_max_segs()`](IterableDev::get_xdp_zc_max_segs)\n- [`.get_xdp_rx_metadata_features()`](IterableDev::get_xdp_rx_metadata_features)\n- [`.get_xsk_features()`](IterableDev::get_xsk_features)\n"]
5000#[derive(Debug)]
5001pub struct OpDevDelNotif;
5002impl OpDevDelNotif {
5003 pub const CMD: u8 = 3u8;
5004 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
5005 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5006 IterableDev::with_loc(attrs, buf.as_ptr() as usize)
5007 }
5008}
5009#[doc = "Notify attributes:\n- [`.get_ifindex()`](IterableDev::get_ifindex)\n- [`.get_xdp_features()`](IterableDev::get_xdp_features)\n- [`.get_xdp_zc_max_segs()`](IterableDev::get_xdp_zc_max_segs)\n- [`.get_xdp_rx_metadata_features()`](IterableDev::get_xdp_rx_metadata_features)\n- [`.get_xsk_features()`](IterableDev::get_xsk_features)\n"]
5010#[derive(Debug)]
5011pub struct OpDevChangeNotif;
5012impl OpDevChangeNotif {
5013 pub const CMD: u8 = 4u8;
5014 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
5015 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5016 IterableDev::with_loc(attrs, buf.as_ptr() as usize)
5017 }
5018}
5019#[doc = "Notify attributes:\n- [`.get_id()`](IterablePagePool::get_id)\n- [`.get_ifindex()`](IterablePagePool::get_ifindex)\n- [`.get_napi_id()`](IterablePagePool::get_napi_id)\n- [`.get_inflight()`](IterablePagePool::get_inflight)\n- [`.get_inflight_mem()`](IterablePagePool::get_inflight_mem)\n- [`.get_detach_time()`](IterablePagePool::get_detach_time)\n- [`.get_dmabuf()`](IterablePagePool::get_dmabuf)\n- [`.get_io_uring()`](IterablePagePool::get_io_uring)\n"]
5020#[derive(Debug)]
5021pub struct OpPagePoolAddNotif;
5022impl OpPagePoolAddNotif {
5023 pub const CMD: u8 = 6u8;
5024 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
5025 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5026 IterablePagePool::with_loc(attrs, buf.as_ptr() as usize)
5027 }
5028}
5029#[doc = "Notify attributes:\n- [`.get_id()`](IterablePagePool::get_id)\n- [`.get_ifindex()`](IterablePagePool::get_ifindex)\n- [`.get_napi_id()`](IterablePagePool::get_napi_id)\n- [`.get_inflight()`](IterablePagePool::get_inflight)\n- [`.get_inflight_mem()`](IterablePagePool::get_inflight_mem)\n- [`.get_detach_time()`](IterablePagePool::get_detach_time)\n- [`.get_dmabuf()`](IterablePagePool::get_dmabuf)\n- [`.get_io_uring()`](IterablePagePool::get_io_uring)\n"]
5030#[derive(Debug)]
5031pub struct OpPagePoolDelNotif;
5032impl OpPagePoolDelNotif {
5033 pub const CMD: u8 = 7u8;
5034 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
5035 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5036 IterablePagePool::with_loc(attrs, buf.as_ptr() as usize)
5037 }
5038}
5039#[doc = "Notify attributes:\n- [`.get_id()`](IterablePagePool::get_id)\n- [`.get_ifindex()`](IterablePagePool::get_ifindex)\n- [`.get_napi_id()`](IterablePagePool::get_napi_id)\n- [`.get_inflight()`](IterablePagePool::get_inflight)\n- [`.get_inflight_mem()`](IterablePagePool::get_inflight_mem)\n- [`.get_detach_time()`](IterablePagePool::get_detach_time)\n- [`.get_dmabuf()`](IterablePagePool::get_dmabuf)\n- [`.get_io_uring()`](IterablePagePool::get_io_uring)\n"]
5040#[derive(Debug)]
5041pub struct OpPagePoolChangeNotif;
5042impl OpPagePoolChangeNotif {
5043 pub const CMD: u8 = 8u8;
5044 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
5045 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5046 IterablePagePool::with_loc(attrs, buf.as_ptr() as usize)
5047 }
5048}
5049pub struct NotifGroup;
5050impl NotifGroup {
5051 #[doc = "Notifications:\n- [`OpDevAddNotif`]\n- [`OpDevDelNotif`]\n- [`OpDevChangeNotif`]\n"]
5052 pub const MGMT: &str = "mgmt";
5053 #[doc = "Notifications:\n- [`OpDevAddNotif`]\n- [`OpDevDelNotif`]\n- [`OpDevChangeNotif`]\n"]
5054 pub const MGMT_CSTR: &CStr = c"mgmt";
5055 #[doc = "Notifications:\n- [`OpPagePoolAddNotif`]\n- [`OpPagePoolDelNotif`]\n- [`OpPagePoolChangeNotif`]\n"]
5056 pub const PAGE_POOL: &str = "page-pool";
5057 #[doc = "Notifications:\n- [`OpPagePoolAddNotif`]\n- [`OpPagePoolDelNotif`]\n- [`OpPagePoolChangeNotif`]\n"]
5058 pub const PAGE_POOL_CSTR: &CStr = c"page-pool";
5059}
5060#[doc = "Get / dump information about a netdev.\n\nReply attributes:\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_xdp_features()](IterableDev::get_xdp_features)\n- [.get_xdp_zc_max_segs()](IterableDev::get_xdp_zc_max_segs)\n- [.get_xdp_rx_metadata_features()](IterableDev::get_xdp_rx_metadata_features)\n- [.get_xsk_features()](IterableDev::get_xsk_features)\n\n"]
5061#[derive(Debug)]
5062pub struct OpDevGetDump<'r> {
5063 request: Request<'r>,
5064}
5065impl<'r> OpDevGetDump<'r> {
5066 pub fn new(mut request: Request<'r>) -> Self {
5067 Self::write_header(request.buf_mut());
5068 Self {
5069 request: request.set_dump(),
5070 }
5071 }
5072 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
5073 Self::write_header(buf);
5074 PushDev::new(buf)
5075 }
5076 pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
5077 PushDev::new(self.request.buf_mut())
5078 }
5079 pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
5080 PushDev::new(self.request.buf)
5081 }
5082 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
5083 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5084 IterableDev::with_loc(attrs, buf.as_ptr() as usize)
5085 }
5086 fn write_header<Prev: Rec>(prev: &mut Prev) {
5087 let mut header = BuiltinNfgenmsg::new();
5088 header.cmd = 1u8;
5089 header.version = 1u8;
5090 prev.as_rec_mut().extend(header.as_slice());
5091 }
5092}
5093impl NetlinkRequest for OpDevGetDump<'_> {
5094 fn protocol(&self) -> Protocol {
5095 Protocol::Generic("netdev".as_bytes())
5096 }
5097 fn flags(&self) -> u16 {
5098 self.request.flags
5099 }
5100 fn payload(&self) -> &[u8] {
5101 self.request.buf()
5102 }
5103 type ReplyType<'buf> = IterableDev<'buf>;
5104 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5105 Self::decode_request(buf)
5106 }
5107 fn lookup(
5108 buf: &[u8],
5109 offset: usize,
5110 missing_type: Option<u16>,
5111 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5112 Self::decode_request(buf).lookup_attr(offset, missing_type)
5113 }
5114}
5115#[doc = "Get / dump information about a netdev.\n\nRequest attributes:\n- [.push_ifindex()](PushDev::push_ifindex)\n\nReply attributes:\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_xdp_features()](IterableDev::get_xdp_features)\n- [.get_xdp_zc_max_segs()](IterableDev::get_xdp_zc_max_segs)\n- [.get_xdp_rx_metadata_features()](IterableDev::get_xdp_rx_metadata_features)\n- [.get_xsk_features()](IterableDev::get_xsk_features)\n\n"]
5116#[derive(Debug)]
5117pub struct OpDevGetDo<'r> {
5118 request: Request<'r>,
5119}
5120impl<'r> OpDevGetDo<'r> {
5121 pub fn new(mut request: Request<'r>) -> Self {
5122 Self::write_header(request.buf_mut());
5123 Self { request: request }
5124 }
5125 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
5126 Self::write_header(buf);
5127 PushDev::new(buf)
5128 }
5129 pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
5130 PushDev::new(self.request.buf_mut())
5131 }
5132 pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
5133 PushDev::new(self.request.buf)
5134 }
5135 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
5136 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5137 IterableDev::with_loc(attrs, buf.as_ptr() as usize)
5138 }
5139 fn write_header<Prev: Rec>(prev: &mut Prev) {
5140 let mut header = BuiltinNfgenmsg::new();
5141 header.cmd = 1u8;
5142 header.version = 1u8;
5143 prev.as_rec_mut().extend(header.as_slice());
5144 }
5145}
5146impl NetlinkRequest for OpDevGetDo<'_> {
5147 fn protocol(&self) -> Protocol {
5148 Protocol::Generic("netdev".as_bytes())
5149 }
5150 fn flags(&self) -> u16 {
5151 self.request.flags
5152 }
5153 fn payload(&self) -> &[u8] {
5154 self.request.buf()
5155 }
5156 type ReplyType<'buf> = IterableDev<'buf>;
5157 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5158 Self::decode_request(buf)
5159 }
5160 fn lookup(
5161 buf: &[u8],
5162 offset: usize,
5163 missing_type: Option<u16>,
5164 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5165 Self::decode_request(buf).lookup_attr(offset, missing_type)
5166 }
5167}
5168#[doc = "Get / dump information about Page Pools. Only Page Pools associated by\nthe driver with a net_device can be listed. ifindex will not be reported\nif the net_device no longer exists.\n\nRequest attributes:\n- [.push_ifindex()](PushPagePool::push_ifindex)\n\nReply attributes:\n- [.get_id()](IterablePagePool::get_id)\n- [.get_ifindex()](IterablePagePool::get_ifindex)\n- [.get_napi_id()](IterablePagePool::get_napi_id)\n- [.get_inflight()](IterablePagePool::get_inflight)\n- [.get_inflight_mem()](IterablePagePool::get_inflight_mem)\n- [.get_detach_time()](IterablePagePool::get_detach_time)\n- [.get_dmabuf()](IterablePagePool::get_dmabuf)\n- [.get_io_uring()](IterablePagePool::get_io_uring)\n\n"]
5169#[derive(Debug)]
5170pub struct OpPagePoolGetDump<'r> {
5171 request: Request<'r>,
5172}
5173impl<'r> OpPagePoolGetDump<'r> {
5174 pub fn new(mut request: Request<'r>) -> Self {
5175 Self::write_header(request.buf_mut());
5176 Self {
5177 request: request.set_dump(),
5178 }
5179 }
5180 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPagePool<&'buf mut Vec<u8>> {
5181 Self::write_header(buf);
5182 PushPagePool::new(buf)
5183 }
5184 pub fn encode(&mut self) -> PushPagePool<&mut Vec<u8>> {
5185 PushPagePool::new(self.request.buf_mut())
5186 }
5187 pub fn into_encoder(self) -> PushPagePool<RequestBuf<'r>> {
5188 PushPagePool::new(self.request.buf)
5189 }
5190 pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
5191 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5192 IterablePagePool::with_loc(attrs, buf.as_ptr() as usize)
5193 }
5194 fn write_header<Prev: Rec>(prev: &mut Prev) {
5195 let mut header = BuiltinNfgenmsg::new();
5196 header.cmd = 5u8;
5197 header.version = 1u8;
5198 prev.as_rec_mut().extend(header.as_slice());
5199 }
5200}
5201impl NetlinkRequest for OpPagePoolGetDump<'_> {
5202 fn protocol(&self) -> Protocol {
5203 Protocol::Generic("netdev".as_bytes())
5204 }
5205 fn flags(&self) -> u16 {
5206 self.request.flags
5207 }
5208 fn payload(&self) -> &[u8] {
5209 self.request.buf()
5210 }
5211 type ReplyType<'buf> = IterablePagePool<'buf>;
5212 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5213 Self::decode_request(buf)
5214 }
5215 fn lookup(
5216 buf: &[u8],
5217 offset: usize,
5218 missing_type: Option<u16>,
5219 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5220 Self::decode_request(buf).lookup_attr(offset, missing_type)
5221 }
5222}
5223#[doc = "Get / dump information about Page Pools. Only Page Pools associated by\nthe driver with a net_device can be listed. ifindex will not be reported\nif the net_device no longer exists.\n\nRequest attributes:\n- [.push_id()](PushPagePool::push_id)\n\nReply attributes:\n- [.get_id()](IterablePagePool::get_id)\n- [.get_ifindex()](IterablePagePool::get_ifindex)\n- [.get_napi_id()](IterablePagePool::get_napi_id)\n- [.get_inflight()](IterablePagePool::get_inflight)\n- [.get_inflight_mem()](IterablePagePool::get_inflight_mem)\n- [.get_detach_time()](IterablePagePool::get_detach_time)\n- [.get_dmabuf()](IterablePagePool::get_dmabuf)\n- [.get_io_uring()](IterablePagePool::get_io_uring)\n\n"]
5224#[derive(Debug)]
5225pub struct OpPagePoolGetDo<'r> {
5226 request: Request<'r>,
5227}
5228impl<'r> OpPagePoolGetDo<'r> {
5229 pub fn new(mut request: Request<'r>) -> Self {
5230 Self::write_header(request.buf_mut());
5231 Self { request: request }
5232 }
5233 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPagePool<&'buf mut Vec<u8>> {
5234 Self::write_header(buf);
5235 PushPagePool::new(buf)
5236 }
5237 pub fn encode(&mut self) -> PushPagePool<&mut Vec<u8>> {
5238 PushPagePool::new(self.request.buf_mut())
5239 }
5240 pub fn into_encoder(self) -> PushPagePool<RequestBuf<'r>> {
5241 PushPagePool::new(self.request.buf)
5242 }
5243 pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
5244 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5245 IterablePagePool::with_loc(attrs, buf.as_ptr() as usize)
5246 }
5247 fn write_header<Prev: Rec>(prev: &mut Prev) {
5248 let mut header = BuiltinNfgenmsg::new();
5249 header.cmd = 5u8;
5250 header.version = 1u8;
5251 prev.as_rec_mut().extend(header.as_slice());
5252 }
5253}
5254impl NetlinkRequest for OpPagePoolGetDo<'_> {
5255 fn protocol(&self) -> Protocol {
5256 Protocol::Generic("netdev".as_bytes())
5257 }
5258 fn flags(&self) -> u16 {
5259 self.request.flags
5260 }
5261 fn payload(&self) -> &[u8] {
5262 self.request.buf()
5263 }
5264 type ReplyType<'buf> = IterablePagePool<'buf>;
5265 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5266 Self::decode_request(buf)
5267 }
5268 fn lookup(
5269 buf: &[u8],
5270 offset: usize,
5271 missing_type: Option<u16>,
5272 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5273 Self::decode_request(buf).lookup_attr(offset, missing_type)
5274 }
5275}
5276#[doc = "Get page pool statistics.\n\nRequest attributes:\n- [.nested_info()](PushPagePoolStats::nested_info)\n\nReply attributes:\n- [.get_info()](IterablePagePoolStats::get_info)\n- [.get_alloc_fast()](IterablePagePoolStats::get_alloc_fast)\n- [.get_alloc_slow()](IterablePagePoolStats::get_alloc_slow)\n- [.get_alloc_slow_high_order()](IterablePagePoolStats::get_alloc_slow_high_order)\n- [.get_alloc_empty()](IterablePagePoolStats::get_alloc_empty)\n- [.get_alloc_refill()](IterablePagePoolStats::get_alloc_refill)\n- [.get_alloc_waive()](IterablePagePoolStats::get_alloc_waive)\n- [.get_recycle_cached()](IterablePagePoolStats::get_recycle_cached)\n- [.get_recycle_cache_full()](IterablePagePoolStats::get_recycle_cache_full)\n- [.get_recycle_ring()](IterablePagePoolStats::get_recycle_ring)\n- [.get_recycle_ring_full()](IterablePagePoolStats::get_recycle_ring_full)\n- [.get_recycle_released_refcnt()](IterablePagePoolStats::get_recycle_released_refcnt)\n\n"]
5277#[derive(Debug)]
5278pub struct OpPagePoolStatsGetDump<'r> {
5279 request: Request<'r>,
5280}
5281impl<'r> OpPagePoolStatsGetDump<'r> {
5282 pub fn new(mut request: Request<'r>) -> Self {
5283 Self::write_header(request.buf_mut());
5284 Self {
5285 request: request.set_dump(),
5286 }
5287 }
5288 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPagePoolStats<&'buf mut Vec<u8>> {
5289 Self::write_header(buf);
5290 PushPagePoolStats::new(buf)
5291 }
5292 pub fn encode(&mut self) -> PushPagePoolStats<&mut Vec<u8>> {
5293 PushPagePoolStats::new(self.request.buf_mut())
5294 }
5295 pub fn into_encoder(self) -> PushPagePoolStats<RequestBuf<'r>> {
5296 PushPagePoolStats::new(self.request.buf)
5297 }
5298 pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
5299 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5300 IterablePagePoolStats::with_loc(attrs, buf.as_ptr() as usize)
5301 }
5302 fn write_header<Prev: Rec>(prev: &mut Prev) {
5303 let mut header = BuiltinNfgenmsg::new();
5304 header.cmd = 9u8;
5305 header.version = 1u8;
5306 prev.as_rec_mut().extend(header.as_slice());
5307 }
5308}
5309impl NetlinkRequest for OpPagePoolStatsGetDump<'_> {
5310 fn protocol(&self) -> Protocol {
5311 Protocol::Generic("netdev".as_bytes())
5312 }
5313 fn flags(&self) -> u16 {
5314 self.request.flags
5315 }
5316 fn payload(&self) -> &[u8] {
5317 self.request.buf()
5318 }
5319 type ReplyType<'buf> = IterablePagePoolStats<'buf>;
5320 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5321 Self::decode_request(buf)
5322 }
5323 fn lookup(
5324 buf: &[u8],
5325 offset: usize,
5326 missing_type: Option<u16>,
5327 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5328 Self::decode_request(buf).lookup_attr(offset, missing_type)
5329 }
5330}
5331#[doc = "Get page pool statistics.\n\nRequest attributes:\n- [.nested_info()](PushPagePoolStats::nested_info)\n\nReply attributes:\n- [.get_info()](IterablePagePoolStats::get_info)\n- [.get_alloc_fast()](IterablePagePoolStats::get_alloc_fast)\n- [.get_alloc_slow()](IterablePagePoolStats::get_alloc_slow)\n- [.get_alloc_slow_high_order()](IterablePagePoolStats::get_alloc_slow_high_order)\n- [.get_alloc_empty()](IterablePagePoolStats::get_alloc_empty)\n- [.get_alloc_refill()](IterablePagePoolStats::get_alloc_refill)\n- [.get_alloc_waive()](IterablePagePoolStats::get_alloc_waive)\n- [.get_recycle_cached()](IterablePagePoolStats::get_recycle_cached)\n- [.get_recycle_cache_full()](IterablePagePoolStats::get_recycle_cache_full)\n- [.get_recycle_ring()](IterablePagePoolStats::get_recycle_ring)\n- [.get_recycle_ring_full()](IterablePagePoolStats::get_recycle_ring_full)\n- [.get_recycle_released_refcnt()](IterablePagePoolStats::get_recycle_released_refcnt)\n\n"]
5332#[derive(Debug)]
5333pub struct OpPagePoolStatsGetDo<'r> {
5334 request: Request<'r>,
5335}
5336impl<'r> OpPagePoolStatsGetDo<'r> {
5337 pub fn new(mut request: Request<'r>) -> Self {
5338 Self::write_header(request.buf_mut());
5339 Self { request: request }
5340 }
5341 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPagePoolStats<&'buf mut Vec<u8>> {
5342 Self::write_header(buf);
5343 PushPagePoolStats::new(buf)
5344 }
5345 pub fn encode(&mut self) -> PushPagePoolStats<&mut Vec<u8>> {
5346 PushPagePoolStats::new(self.request.buf_mut())
5347 }
5348 pub fn into_encoder(self) -> PushPagePoolStats<RequestBuf<'r>> {
5349 PushPagePoolStats::new(self.request.buf)
5350 }
5351 pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
5352 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5353 IterablePagePoolStats::with_loc(attrs, buf.as_ptr() as usize)
5354 }
5355 fn write_header<Prev: Rec>(prev: &mut Prev) {
5356 let mut header = BuiltinNfgenmsg::new();
5357 header.cmd = 9u8;
5358 header.version = 1u8;
5359 prev.as_rec_mut().extend(header.as_slice());
5360 }
5361}
5362impl NetlinkRequest for OpPagePoolStatsGetDo<'_> {
5363 fn protocol(&self) -> Protocol {
5364 Protocol::Generic("netdev".as_bytes())
5365 }
5366 fn flags(&self) -> u16 {
5367 self.request.flags
5368 }
5369 fn payload(&self) -> &[u8] {
5370 self.request.buf()
5371 }
5372 type ReplyType<'buf> = IterablePagePoolStats<'buf>;
5373 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5374 Self::decode_request(buf)
5375 }
5376 fn lookup(
5377 buf: &[u8],
5378 offset: usize,
5379 missing_type: Option<u16>,
5380 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5381 Self::decode_request(buf).lookup_attr(offset, missing_type)
5382 }
5383}
5384#[doc = "Get queue information from the kernel. Only configured queues will be\nreported (as opposed to all available hardware queues).\n\nRequest attributes:\n- [.push_ifindex()](PushQueue::push_ifindex)\n\nReply attributes:\n- [.get_id()](IterableQueue::get_id)\n- [.get_ifindex()](IterableQueue::get_ifindex)\n- [.get_type()](IterableQueue::get_type)\n- [.get_napi_id()](IterableQueue::get_napi_id)\n- [.get_dmabuf()](IterableQueue::get_dmabuf)\n- [.get_io_uring()](IterableQueue::get_io_uring)\n- [.get_xsk()](IterableQueue::get_xsk)\n- [.get_lease()](IterableQueue::get_lease)\n\n"]
5385#[derive(Debug)]
5386pub struct OpQueueGetDump<'r> {
5387 request: Request<'r>,
5388}
5389impl<'r> OpQueueGetDump<'r> {
5390 pub fn new(mut request: Request<'r>) -> Self {
5391 Self::write_header(request.buf_mut());
5392 Self {
5393 request: request.set_dump(),
5394 }
5395 }
5396 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushQueue<&'buf mut Vec<u8>> {
5397 Self::write_header(buf);
5398 PushQueue::new(buf)
5399 }
5400 pub fn encode(&mut self) -> PushQueue<&mut Vec<u8>> {
5401 PushQueue::new(self.request.buf_mut())
5402 }
5403 pub fn into_encoder(self) -> PushQueue<RequestBuf<'r>> {
5404 PushQueue::new(self.request.buf)
5405 }
5406 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
5407 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5408 IterableQueue::with_loc(attrs, buf.as_ptr() as usize)
5409 }
5410 fn write_header<Prev: Rec>(prev: &mut Prev) {
5411 let mut header = BuiltinNfgenmsg::new();
5412 header.cmd = 10u8;
5413 header.version = 1u8;
5414 prev.as_rec_mut().extend(header.as_slice());
5415 }
5416}
5417impl NetlinkRequest for OpQueueGetDump<'_> {
5418 fn protocol(&self) -> Protocol {
5419 Protocol::Generic("netdev".as_bytes())
5420 }
5421 fn flags(&self) -> u16 {
5422 self.request.flags
5423 }
5424 fn payload(&self) -> &[u8] {
5425 self.request.buf()
5426 }
5427 type ReplyType<'buf> = IterableQueue<'buf>;
5428 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5429 Self::decode_request(buf)
5430 }
5431 fn lookup(
5432 buf: &[u8],
5433 offset: usize,
5434 missing_type: Option<u16>,
5435 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5436 Self::decode_request(buf).lookup_attr(offset, missing_type)
5437 }
5438}
5439#[doc = "Get queue information from the kernel. Only configured queues will be\nreported (as opposed to all available hardware queues).\n\nRequest attributes:\n- [.push_id()](PushQueue::push_id)\n- [.push_ifindex()](PushQueue::push_ifindex)\n- [.push_type()](PushQueue::push_type)\n\nReply attributes:\n- [.get_id()](IterableQueue::get_id)\n- [.get_ifindex()](IterableQueue::get_ifindex)\n- [.get_type()](IterableQueue::get_type)\n- [.get_napi_id()](IterableQueue::get_napi_id)\n- [.get_dmabuf()](IterableQueue::get_dmabuf)\n- [.get_io_uring()](IterableQueue::get_io_uring)\n- [.get_xsk()](IterableQueue::get_xsk)\n- [.get_lease()](IterableQueue::get_lease)\n\n"]
5440#[derive(Debug)]
5441pub struct OpQueueGetDo<'r> {
5442 request: Request<'r>,
5443}
5444impl<'r> OpQueueGetDo<'r> {
5445 pub fn new(mut request: Request<'r>) -> Self {
5446 Self::write_header(request.buf_mut());
5447 Self { request: request }
5448 }
5449 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushQueue<&'buf mut Vec<u8>> {
5450 Self::write_header(buf);
5451 PushQueue::new(buf)
5452 }
5453 pub fn encode(&mut self) -> PushQueue<&mut Vec<u8>> {
5454 PushQueue::new(self.request.buf_mut())
5455 }
5456 pub fn into_encoder(self) -> PushQueue<RequestBuf<'r>> {
5457 PushQueue::new(self.request.buf)
5458 }
5459 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
5460 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5461 IterableQueue::with_loc(attrs, buf.as_ptr() as usize)
5462 }
5463 fn write_header<Prev: Rec>(prev: &mut Prev) {
5464 let mut header = BuiltinNfgenmsg::new();
5465 header.cmd = 10u8;
5466 header.version = 1u8;
5467 prev.as_rec_mut().extend(header.as_slice());
5468 }
5469}
5470impl NetlinkRequest for OpQueueGetDo<'_> {
5471 fn protocol(&self) -> Protocol {
5472 Protocol::Generic("netdev".as_bytes())
5473 }
5474 fn flags(&self) -> u16 {
5475 self.request.flags
5476 }
5477 fn payload(&self) -> &[u8] {
5478 self.request.buf()
5479 }
5480 type ReplyType<'buf> = IterableQueue<'buf>;
5481 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5482 Self::decode_request(buf)
5483 }
5484 fn lookup(
5485 buf: &[u8],
5486 offset: usize,
5487 missing_type: Option<u16>,
5488 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5489 Self::decode_request(buf).lookup_attr(offset, missing_type)
5490 }
5491}
5492#[doc = "Get information about NAPI instances configured on the system.\n\nRequest attributes:\n- [.push_ifindex()](PushNapi::push_ifindex)\n\nReply attributes:\n- [.get_ifindex()](IterableNapi::get_ifindex)\n- [.get_id()](IterableNapi::get_id)\n- [.get_irq()](IterableNapi::get_irq)\n- [.get_pid()](IterableNapi::get_pid)\n- [.get_defer_hard_irqs()](IterableNapi::get_defer_hard_irqs)\n- [.get_gro_flush_timeout()](IterableNapi::get_gro_flush_timeout)\n- [.get_irq_suspend_timeout()](IterableNapi::get_irq_suspend_timeout)\n- [.get_threaded()](IterableNapi::get_threaded)\n\n"]
5493#[derive(Debug)]
5494pub struct OpNapiGetDump<'r> {
5495 request: Request<'r>,
5496}
5497impl<'r> OpNapiGetDump<'r> {
5498 pub fn new(mut request: Request<'r>) -> Self {
5499 Self::write_header(request.buf_mut());
5500 Self {
5501 request: request.set_dump(),
5502 }
5503 }
5504 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNapi<&'buf mut Vec<u8>> {
5505 Self::write_header(buf);
5506 PushNapi::new(buf)
5507 }
5508 pub fn encode(&mut self) -> PushNapi<&mut Vec<u8>> {
5509 PushNapi::new(self.request.buf_mut())
5510 }
5511 pub fn into_encoder(self) -> PushNapi<RequestBuf<'r>> {
5512 PushNapi::new(self.request.buf)
5513 }
5514 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
5515 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5516 IterableNapi::with_loc(attrs, buf.as_ptr() as usize)
5517 }
5518 fn write_header<Prev: Rec>(prev: &mut Prev) {
5519 let mut header = BuiltinNfgenmsg::new();
5520 header.cmd = 11u8;
5521 header.version = 1u8;
5522 prev.as_rec_mut().extend(header.as_slice());
5523 }
5524}
5525impl NetlinkRequest for OpNapiGetDump<'_> {
5526 fn protocol(&self) -> Protocol {
5527 Protocol::Generic("netdev".as_bytes())
5528 }
5529 fn flags(&self) -> u16 {
5530 self.request.flags
5531 }
5532 fn payload(&self) -> &[u8] {
5533 self.request.buf()
5534 }
5535 type ReplyType<'buf> = IterableNapi<'buf>;
5536 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5537 Self::decode_request(buf)
5538 }
5539 fn lookup(
5540 buf: &[u8],
5541 offset: usize,
5542 missing_type: Option<u16>,
5543 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5544 Self::decode_request(buf).lookup_attr(offset, missing_type)
5545 }
5546}
5547#[doc = "Get information about NAPI instances configured on the system.\n\nRequest attributes:\n- [.push_id()](PushNapi::push_id)\n\nReply attributes:\n- [.get_ifindex()](IterableNapi::get_ifindex)\n- [.get_id()](IterableNapi::get_id)\n- [.get_irq()](IterableNapi::get_irq)\n- [.get_pid()](IterableNapi::get_pid)\n- [.get_defer_hard_irqs()](IterableNapi::get_defer_hard_irqs)\n- [.get_gro_flush_timeout()](IterableNapi::get_gro_flush_timeout)\n- [.get_irq_suspend_timeout()](IterableNapi::get_irq_suspend_timeout)\n- [.get_threaded()](IterableNapi::get_threaded)\n\n"]
5548#[derive(Debug)]
5549pub struct OpNapiGetDo<'r> {
5550 request: Request<'r>,
5551}
5552impl<'r> OpNapiGetDo<'r> {
5553 pub fn new(mut request: Request<'r>) -> Self {
5554 Self::write_header(request.buf_mut());
5555 Self { request: request }
5556 }
5557 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNapi<&'buf mut Vec<u8>> {
5558 Self::write_header(buf);
5559 PushNapi::new(buf)
5560 }
5561 pub fn encode(&mut self) -> PushNapi<&mut Vec<u8>> {
5562 PushNapi::new(self.request.buf_mut())
5563 }
5564 pub fn into_encoder(self) -> PushNapi<RequestBuf<'r>> {
5565 PushNapi::new(self.request.buf)
5566 }
5567 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
5568 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5569 IterableNapi::with_loc(attrs, buf.as_ptr() as usize)
5570 }
5571 fn write_header<Prev: Rec>(prev: &mut Prev) {
5572 let mut header = BuiltinNfgenmsg::new();
5573 header.cmd = 11u8;
5574 header.version = 1u8;
5575 prev.as_rec_mut().extend(header.as_slice());
5576 }
5577}
5578impl NetlinkRequest for OpNapiGetDo<'_> {
5579 fn protocol(&self) -> Protocol {
5580 Protocol::Generic("netdev".as_bytes())
5581 }
5582 fn flags(&self) -> u16 {
5583 self.request.flags
5584 }
5585 fn payload(&self) -> &[u8] {
5586 self.request.buf()
5587 }
5588 type ReplyType<'buf> = IterableNapi<'buf>;
5589 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5590 Self::decode_request(buf)
5591 }
5592 fn lookup(
5593 buf: &[u8],
5594 offset: usize,
5595 missing_type: Option<u16>,
5596 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5597 Self::decode_request(buf).lookup_attr(offset, missing_type)
5598 }
5599}
5600#[doc = "Get / dump fine grained statistics. Which statistics are reported\ndepends on the device and the driver, and whether the driver stores\nsoftware counters per-queue.\n\nRequest attributes:\n- [.push_ifindex()](PushQstats::push_ifindex)\n- [.push_scope()](PushQstats::push_scope)\n\nReply attributes:\n- [.get_ifindex()](IterableQstats::get_ifindex)\n- [.get_queue_type()](IterableQstats::get_queue_type)\n- [.get_queue_id()](IterableQstats::get_queue_id)\n- [.get_rx_packets()](IterableQstats::get_rx_packets)\n- [.get_rx_bytes()](IterableQstats::get_rx_bytes)\n- [.get_tx_packets()](IterableQstats::get_tx_packets)\n- [.get_tx_bytes()](IterableQstats::get_tx_bytes)\n- [.get_rx_alloc_fail()](IterableQstats::get_rx_alloc_fail)\n- [.get_rx_hw_drops()](IterableQstats::get_rx_hw_drops)\n- [.get_rx_hw_drop_overruns()](IterableQstats::get_rx_hw_drop_overruns)\n- [.get_rx_csum_complete()](IterableQstats::get_rx_csum_complete)\n- [.get_rx_csum_unnecessary()](IterableQstats::get_rx_csum_unnecessary)\n- [.get_rx_csum_none()](IterableQstats::get_rx_csum_none)\n- [.get_rx_csum_bad()](IterableQstats::get_rx_csum_bad)\n- [.get_rx_hw_gro_packets()](IterableQstats::get_rx_hw_gro_packets)\n- [.get_rx_hw_gro_bytes()](IterableQstats::get_rx_hw_gro_bytes)\n- [.get_rx_hw_gro_wire_packets()](IterableQstats::get_rx_hw_gro_wire_packets)\n- [.get_rx_hw_gro_wire_bytes()](IterableQstats::get_rx_hw_gro_wire_bytes)\n- [.get_rx_hw_drop_ratelimits()](IterableQstats::get_rx_hw_drop_ratelimits)\n- [.get_tx_hw_drops()](IterableQstats::get_tx_hw_drops)\n- [.get_tx_hw_drop_errors()](IterableQstats::get_tx_hw_drop_errors)\n- [.get_tx_csum_none()](IterableQstats::get_tx_csum_none)\n- [.get_tx_needs_csum()](IterableQstats::get_tx_needs_csum)\n- [.get_tx_hw_gso_packets()](IterableQstats::get_tx_hw_gso_packets)\n- [.get_tx_hw_gso_bytes()](IterableQstats::get_tx_hw_gso_bytes)\n- [.get_tx_hw_gso_wire_packets()](IterableQstats::get_tx_hw_gso_wire_packets)\n- [.get_tx_hw_gso_wire_bytes()](IterableQstats::get_tx_hw_gso_wire_bytes)\n- [.get_tx_hw_drop_ratelimits()](IterableQstats::get_tx_hw_drop_ratelimits)\n- [.get_tx_stop()](IterableQstats::get_tx_stop)\n- [.get_tx_wake()](IterableQstats::get_tx_wake)\n\n"]
5601#[derive(Debug)]
5602pub struct OpQstatsGetDump<'r> {
5603 request: Request<'r>,
5604}
5605impl<'r> OpQstatsGetDump<'r> {
5606 pub fn new(mut request: Request<'r>) -> Self {
5607 Self::write_header(request.buf_mut());
5608 Self {
5609 request: request.set_dump(),
5610 }
5611 }
5612 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushQstats<&'buf mut Vec<u8>> {
5613 Self::write_header(buf);
5614 PushQstats::new(buf)
5615 }
5616 pub fn encode(&mut self) -> PushQstats<&mut Vec<u8>> {
5617 PushQstats::new(self.request.buf_mut())
5618 }
5619 pub fn into_encoder(self) -> PushQstats<RequestBuf<'r>> {
5620 PushQstats::new(self.request.buf)
5621 }
5622 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableQstats<'a> {
5623 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5624 IterableQstats::with_loc(attrs, buf.as_ptr() as usize)
5625 }
5626 fn write_header<Prev: Rec>(prev: &mut Prev) {
5627 let mut header = BuiltinNfgenmsg::new();
5628 header.cmd = 12u8;
5629 header.version = 1u8;
5630 prev.as_rec_mut().extend(header.as_slice());
5631 }
5632}
5633impl NetlinkRequest for OpQstatsGetDump<'_> {
5634 fn protocol(&self) -> Protocol {
5635 Protocol::Generic("netdev".as_bytes())
5636 }
5637 fn flags(&self) -> u16 {
5638 self.request.flags
5639 }
5640 fn payload(&self) -> &[u8] {
5641 self.request.buf()
5642 }
5643 type ReplyType<'buf> = IterableQstats<'buf>;
5644 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5645 Self::decode_request(buf)
5646 }
5647 fn lookup(
5648 buf: &[u8],
5649 offset: usize,
5650 missing_type: Option<u16>,
5651 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5652 Self::decode_request(buf).lookup_attr(offset, missing_type)
5653 }
5654}
5655#[doc = "Bind dmabuf to netdev\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushDmabuf::push_ifindex)\n- [.nested_queues()](PushDmabuf::nested_queues)\n- [.push_fd()](PushDmabuf::push_fd)\n\nReply attributes:\n- [.get_id()](IterableDmabuf::get_id)\n\n"]
5656#[derive(Debug)]
5657pub struct OpBindRxDo<'r> {
5658 request: Request<'r>,
5659}
5660impl<'r> OpBindRxDo<'r> {
5661 pub fn new(mut request: Request<'r>) -> Self {
5662 Self::write_header(request.buf_mut());
5663 Self { request: request }
5664 }
5665 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDmabuf<&'buf mut Vec<u8>> {
5666 Self::write_header(buf);
5667 PushDmabuf::new(buf)
5668 }
5669 pub fn encode(&mut self) -> PushDmabuf<&mut Vec<u8>> {
5670 PushDmabuf::new(self.request.buf_mut())
5671 }
5672 pub fn into_encoder(self) -> PushDmabuf<RequestBuf<'r>> {
5673 PushDmabuf::new(self.request.buf)
5674 }
5675 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
5676 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5677 IterableDmabuf::with_loc(attrs, buf.as_ptr() as usize)
5678 }
5679 fn write_header<Prev: Rec>(prev: &mut Prev) {
5680 let mut header = BuiltinNfgenmsg::new();
5681 header.cmd = 13u8;
5682 header.version = 1u8;
5683 prev.as_rec_mut().extend(header.as_slice());
5684 }
5685}
5686impl NetlinkRequest for OpBindRxDo<'_> {
5687 fn protocol(&self) -> Protocol {
5688 Protocol::Generic("netdev".as_bytes())
5689 }
5690 fn flags(&self) -> u16 {
5691 self.request.flags
5692 }
5693 fn payload(&self) -> &[u8] {
5694 self.request.buf()
5695 }
5696 type ReplyType<'buf> = IterableDmabuf<'buf>;
5697 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5698 Self::decode_request(buf)
5699 }
5700 fn lookup(
5701 buf: &[u8],
5702 offset: usize,
5703 missing_type: Option<u16>,
5704 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5705 Self::decode_request(buf).lookup_attr(offset, missing_type)
5706 }
5707}
5708#[doc = "Set configurable NAPI instance settings.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushNapi::push_id)\n- [.push_defer_hard_irqs()](PushNapi::push_defer_hard_irqs)\n- [.push_gro_flush_timeout()](PushNapi::push_gro_flush_timeout)\n- [.push_irq_suspend_timeout()](PushNapi::push_irq_suspend_timeout)\n- [.push_threaded()](PushNapi::push_threaded)\n\n"]
5709#[derive(Debug)]
5710pub struct OpNapiSetDo<'r> {
5711 request: Request<'r>,
5712}
5713impl<'r> OpNapiSetDo<'r> {
5714 pub fn new(mut request: Request<'r>) -> Self {
5715 Self::write_header(request.buf_mut());
5716 Self { request: request }
5717 }
5718 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushNapi<&'buf mut Vec<u8>> {
5719 Self::write_header(buf);
5720 PushNapi::new(buf)
5721 }
5722 pub fn encode(&mut self) -> PushNapi<&mut Vec<u8>> {
5723 PushNapi::new(self.request.buf_mut())
5724 }
5725 pub fn into_encoder(self) -> PushNapi<RequestBuf<'r>> {
5726 PushNapi::new(self.request.buf)
5727 }
5728 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
5729 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5730 IterableNapi::with_loc(attrs, buf.as_ptr() as usize)
5731 }
5732 fn write_header<Prev: Rec>(prev: &mut Prev) {
5733 let mut header = BuiltinNfgenmsg::new();
5734 header.cmd = 14u8;
5735 header.version = 1u8;
5736 prev.as_rec_mut().extend(header.as_slice());
5737 }
5738}
5739impl NetlinkRequest for OpNapiSetDo<'_> {
5740 fn protocol(&self) -> Protocol {
5741 Protocol::Generic("netdev".as_bytes())
5742 }
5743 fn flags(&self) -> u16 {
5744 self.request.flags
5745 }
5746 fn payload(&self) -> &[u8] {
5747 self.request.buf()
5748 }
5749 type ReplyType<'buf> = IterableNapi<'buf>;
5750 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5751 Self::decode_request(buf)
5752 }
5753 fn lookup(
5754 buf: &[u8],
5755 offset: usize,
5756 missing_type: Option<u16>,
5757 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5758 Self::decode_request(buf).lookup_attr(offset, missing_type)
5759 }
5760}
5761#[doc = "Bind dmabuf to netdev for TX\n\nRequest attributes:\n- [.push_ifindex()](PushDmabuf::push_ifindex)\n- [.push_fd()](PushDmabuf::push_fd)\n\nReply attributes:\n- [.get_id()](IterableDmabuf::get_id)\n\n"]
5762#[derive(Debug)]
5763pub struct OpBindTxDo<'r> {
5764 request: Request<'r>,
5765}
5766impl<'r> OpBindTxDo<'r> {
5767 pub fn new(mut request: Request<'r>) -> Self {
5768 Self::write_header(request.buf_mut());
5769 Self { request: request }
5770 }
5771 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDmabuf<&'buf mut Vec<u8>> {
5772 Self::write_header(buf);
5773 PushDmabuf::new(buf)
5774 }
5775 pub fn encode(&mut self) -> PushDmabuf<&mut Vec<u8>> {
5776 PushDmabuf::new(self.request.buf_mut())
5777 }
5778 pub fn into_encoder(self) -> PushDmabuf<RequestBuf<'r>> {
5779 PushDmabuf::new(self.request.buf)
5780 }
5781 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
5782 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5783 IterableDmabuf::with_loc(attrs, buf.as_ptr() as usize)
5784 }
5785 fn write_header<Prev: Rec>(prev: &mut Prev) {
5786 let mut header = BuiltinNfgenmsg::new();
5787 header.cmd = 15u8;
5788 header.version = 1u8;
5789 prev.as_rec_mut().extend(header.as_slice());
5790 }
5791}
5792impl NetlinkRequest for OpBindTxDo<'_> {
5793 fn protocol(&self) -> Protocol {
5794 Protocol::Generic("netdev".as_bytes())
5795 }
5796 fn flags(&self) -> u16 {
5797 self.request.flags
5798 }
5799 fn payload(&self) -> &[u8] {
5800 self.request.buf()
5801 }
5802 type ReplyType<'buf> = IterableDmabuf<'buf>;
5803 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5804 Self::decode_request(buf)
5805 }
5806 fn lookup(
5807 buf: &[u8],
5808 offset: usize,
5809 missing_type: Option<u16>,
5810 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5811 Self::decode_request(buf).lookup_attr(offset, missing_type)
5812 }
5813}
5814#[doc = "Create a new queue for the given netdevice. Whether this operation is\nsupported depends on the device and the driver.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushQueue::push_ifindex)\n- [.push_type()](PushQueue::push_type)\n- [.nested_lease()](PushQueue::nested_lease)\n\nReply attributes:\n- [.get_id()](IterableQueue::get_id)\n\n"]
5815#[derive(Debug)]
5816pub struct OpQueueCreateDo<'r> {
5817 request: Request<'r>,
5818}
5819impl<'r> OpQueueCreateDo<'r> {
5820 pub fn new(mut request: Request<'r>) -> Self {
5821 Self::write_header(request.buf_mut());
5822 Self { request: request }
5823 }
5824 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushQueue<&'buf mut Vec<u8>> {
5825 Self::write_header(buf);
5826 PushQueue::new(buf)
5827 }
5828 pub fn encode(&mut self) -> PushQueue<&mut Vec<u8>> {
5829 PushQueue::new(self.request.buf_mut())
5830 }
5831 pub fn into_encoder(self) -> PushQueue<RequestBuf<'r>> {
5832 PushQueue::new(self.request.buf)
5833 }
5834 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
5835 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
5836 IterableQueue::with_loc(attrs, buf.as_ptr() as usize)
5837 }
5838 fn write_header<Prev: Rec>(prev: &mut Prev) {
5839 let mut header = BuiltinNfgenmsg::new();
5840 header.cmd = 16u8;
5841 header.version = 1u8;
5842 prev.as_rec_mut().extend(header.as_slice());
5843 }
5844}
5845impl NetlinkRequest for OpQueueCreateDo<'_> {
5846 fn protocol(&self) -> Protocol {
5847 Protocol::Generic("netdev".as_bytes())
5848 }
5849 fn flags(&self) -> u16 {
5850 self.request.flags
5851 }
5852 fn payload(&self) -> &[u8] {
5853 self.request.buf()
5854 }
5855 type ReplyType<'buf> = IterableQueue<'buf>;
5856 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5857 Self::decode_request(buf)
5858 }
5859 fn lookup(
5860 buf: &[u8],
5861 offset: usize,
5862 missing_type: Option<u16>,
5863 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5864 Self::decode_request(buf).lookup_attr(offset, missing_type)
5865 }
5866}
5867use crate::traits::LookupFn;
5868use crate::utils::RequestBuf;
5869#[derive(Debug)]
5870pub struct Request<'buf> {
5871 buf: RequestBuf<'buf>,
5872 flags: u16,
5873 writeback: Option<&'buf mut Option<RequestInfo>>,
5874}
5875#[allow(unused)]
5876#[derive(Debug, Clone)]
5877pub struct RequestInfo {
5878 protocol: Protocol,
5879 flags: u16,
5880 name: &'static str,
5881 lookup: LookupFn,
5882}
5883impl Request<'static> {
5884 pub fn new() -> Self {
5885 Self::new_from_buf(Vec::new())
5886 }
5887 pub fn new_from_buf(buf: Vec<u8>) -> Self {
5888 Self {
5889 flags: 0,
5890 buf: RequestBuf::Own(buf),
5891 writeback: None,
5892 }
5893 }
5894 pub fn into_buf(self) -> Vec<u8> {
5895 match self.buf {
5896 RequestBuf::Own(buf) => buf,
5897 _ => unreachable!(),
5898 }
5899 }
5900}
5901impl<'buf> Request<'buf> {
5902 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
5903 buf.clear();
5904 Self::new_extend(buf)
5905 }
5906 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
5907 Self {
5908 flags: 0,
5909 buf: RequestBuf::Ref(buf),
5910 writeback: None,
5911 }
5912 }
5913 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
5914 let Some(writeback) = &mut self.writeback else {
5915 return;
5916 };
5917 **writeback = Some(RequestInfo {
5918 protocol,
5919 flags: self.flags,
5920 name,
5921 lookup,
5922 })
5923 }
5924 pub fn buf(&self) -> &Vec<u8> {
5925 self.buf.buf()
5926 }
5927 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
5928 self.buf.buf_mut()
5929 }
5930 #[doc = "Set `NLM_F_CREATE` flag"]
5931 pub fn set_create(mut self) -> Self {
5932 self.flags |= consts::NLM_F_CREATE as u16;
5933 self
5934 }
5935 #[doc = "Set `NLM_F_EXCL` flag"]
5936 pub fn set_excl(mut self) -> Self {
5937 self.flags |= consts::NLM_F_EXCL as u16;
5938 self
5939 }
5940 #[doc = "Set `NLM_F_REPLACE` flag"]
5941 pub fn set_replace(mut self) -> Self {
5942 self.flags |= consts::NLM_F_REPLACE as u16;
5943 self
5944 }
5945 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
5946 pub fn set_change(self) -> Self {
5947 self.set_create().set_replace()
5948 }
5949 #[doc = "Set `NLM_F_APPEND` flag"]
5950 pub fn set_append(mut self) -> Self {
5951 self.flags |= consts::NLM_F_APPEND as u16;
5952 self
5953 }
5954 #[doc = "Set `self.flags |= flags`"]
5955 pub fn set_flags(mut self, flags: u16) -> Self {
5956 self.flags |= flags;
5957 self
5958 }
5959 #[doc = "Set `self.flags ^= self.flags & flags`"]
5960 pub fn unset_flags(mut self, flags: u16) -> Self {
5961 self.flags ^= self.flags & flags;
5962 self
5963 }
5964 #[doc = "Set `NLM_F_DUMP` flag"]
5965 fn set_dump(mut self) -> Self {
5966 self.flags |= consts::NLM_F_DUMP as u16;
5967 self
5968 }
5969 #[doc = "Get / dump information about a netdev.\n\nReply attributes:\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_xdp_features()](IterableDev::get_xdp_features)\n- [.get_xdp_zc_max_segs()](IterableDev::get_xdp_zc_max_segs)\n- [.get_xdp_rx_metadata_features()](IterableDev::get_xdp_rx_metadata_features)\n- [.get_xsk_features()](IterableDev::get_xsk_features)\n\n"]
5970 pub fn op_dev_get_dump(self) -> OpDevGetDump<'buf> {
5971 let mut res = OpDevGetDump::new(self);
5972 res.request
5973 .do_writeback(res.protocol(), "op-dev-get-dump", OpDevGetDump::lookup);
5974 res
5975 }
5976 #[doc = "Get / dump information about a netdev.\n\nRequest attributes:\n- [.push_ifindex()](PushDev::push_ifindex)\n\nReply attributes:\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_xdp_features()](IterableDev::get_xdp_features)\n- [.get_xdp_zc_max_segs()](IterableDev::get_xdp_zc_max_segs)\n- [.get_xdp_rx_metadata_features()](IterableDev::get_xdp_rx_metadata_features)\n- [.get_xsk_features()](IterableDev::get_xsk_features)\n\n"]
5977 pub fn op_dev_get_do(self) -> OpDevGetDo<'buf> {
5978 let mut res = OpDevGetDo::new(self);
5979 res.request
5980 .do_writeback(res.protocol(), "op-dev-get-do", OpDevGetDo::lookup);
5981 res
5982 }
5983 #[doc = "Get / dump information about Page Pools. Only Page Pools associated by\nthe driver with a net_device can be listed. ifindex will not be reported\nif the net_device no longer exists.\n\nRequest attributes:\n- [.push_ifindex()](PushPagePool::push_ifindex)\n\nReply attributes:\n- [.get_id()](IterablePagePool::get_id)\n- [.get_ifindex()](IterablePagePool::get_ifindex)\n- [.get_napi_id()](IterablePagePool::get_napi_id)\n- [.get_inflight()](IterablePagePool::get_inflight)\n- [.get_inflight_mem()](IterablePagePool::get_inflight_mem)\n- [.get_detach_time()](IterablePagePool::get_detach_time)\n- [.get_dmabuf()](IterablePagePool::get_dmabuf)\n- [.get_io_uring()](IterablePagePool::get_io_uring)\n\n"]
5984 pub fn op_page_pool_get_dump(self) -> OpPagePoolGetDump<'buf> {
5985 let mut res = OpPagePoolGetDump::new(self);
5986 res.request.do_writeback(
5987 res.protocol(),
5988 "op-page-pool-get-dump",
5989 OpPagePoolGetDump::lookup,
5990 );
5991 res
5992 }
5993 #[doc = "Get / dump information about Page Pools. Only Page Pools associated by\nthe driver with a net_device can be listed. ifindex will not be reported\nif the net_device no longer exists.\n\nRequest attributes:\n- [.push_id()](PushPagePool::push_id)\n\nReply attributes:\n- [.get_id()](IterablePagePool::get_id)\n- [.get_ifindex()](IterablePagePool::get_ifindex)\n- [.get_napi_id()](IterablePagePool::get_napi_id)\n- [.get_inflight()](IterablePagePool::get_inflight)\n- [.get_inflight_mem()](IterablePagePool::get_inflight_mem)\n- [.get_detach_time()](IterablePagePool::get_detach_time)\n- [.get_dmabuf()](IterablePagePool::get_dmabuf)\n- [.get_io_uring()](IterablePagePool::get_io_uring)\n\n"]
5994 pub fn op_page_pool_get_do(self) -> OpPagePoolGetDo<'buf> {
5995 let mut res = OpPagePoolGetDo::new(self);
5996 res.request.do_writeback(
5997 res.protocol(),
5998 "op-page-pool-get-do",
5999 OpPagePoolGetDo::lookup,
6000 );
6001 res
6002 }
6003 #[doc = "Get page pool statistics.\n\nRequest attributes:\n- [.nested_info()](PushPagePoolStats::nested_info)\n\nReply attributes:\n- [.get_info()](IterablePagePoolStats::get_info)\n- [.get_alloc_fast()](IterablePagePoolStats::get_alloc_fast)\n- [.get_alloc_slow()](IterablePagePoolStats::get_alloc_slow)\n- [.get_alloc_slow_high_order()](IterablePagePoolStats::get_alloc_slow_high_order)\n- [.get_alloc_empty()](IterablePagePoolStats::get_alloc_empty)\n- [.get_alloc_refill()](IterablePagePoolStats::get_alloc_refill)\n- [.get_alloc_waive()](IterablePagePoolStats::get_alloc_waive)\n- [.get_recycle_cached()](IterablePagePoolStats::get_recycle_cached)\n- [.get_recycle_cache_full()](IterablePagePoolStats::get_recycle_cache_full)\n- [.get_recycle_ring()](IterablePagePoolStats::get_recycle_ring)\n- [.get_recycle_ring_full()](IterablePagePoolStats::get_recycle_ring_full)\n- [.get_recycle_released_refcnt()](IterablePagePoolStats::get_recycle_released_refcnt)\n\n"]
6004 pub fn op_page_pool_stats_get_dump(self) -> OpPagePoolStatsGetDump<'buf> {
6005 let mut res = OpPagePoolStatsGetDump::new(self);
6006 res.request.do_writeback(
6007 res.protocol(),
6008 "op-page-pool-stats-get-dump",
6009 OpPagePoolStatsGetDump::lookup,
6010 );
6011 res
6012 }
6013 #[doc = "Get page pool statistics.\n\nRequest attributes:\n- [.nested_info()](PushPagePoolStats::nested_info)\n\nReply attributes:\n- [.get_info()](IterablePagePoolStats::get_info)\n- [.get_alloc_fast()](IterablePagePoolStats::get_alloc_fast)\n- [.get_alloc_slow()](IterablePagePoolStats::get_alloc_slow)\n- [.get_alloc_slow_high_order()](IterablePagePoolStats::get_alloc_slow_high_order)\n- [.get_alloc_empty()](IterablePagePoolStats::get_alloc_empty)\n- [.get_alloc_refill()](IterablePagePoolStats::get_alloc_refill)\n- [.get_alloc_waive()](IterablePagePoolStats::get_alloc_waive)\n- [.get_recycle_cached()](IterablePagePoolStats::get_recycle_cached)\n- [.get_recycle_cache_full()](IterablePagePoolStats::get_recycle_cache_full)\n- [.get_recycle_ring()](IterablePagePoolStats::get_recycle_ring)\n- [.get_recycle_ring_full()](IterablePagePoolStats::get_recycle_ring_full)\n- [.get_recycle_released_refcnt()](IterablePagePoolStats::get_recycle_released_refcnt)\n\n"]
6014 pub fn op_page_pool_stats_get_do(self) -> OpPagePoolStatsGetDo<'buf> {
6015 let mut res = OpPagePoolStatsGetDo::new(self);
6016 res.request.do_writeback(
6017 res.protocol(),
6018 "op-page-pool-stats-get-do",
6019 OpPagePoolStatsGetDo::lookup,
6020 );
6021 res
6022 }
6023 #[doc = "Get queue information from the kernel. Only configured queues will be\nreported (as opposed to all available hardware queues).\n\nRequest attributes:\n- [.push_ifindex()](PushQueue::push_ifindex)\n\nReply attributes:\n- [.get_id()](IterableQueue::get_id)\n- [.get_ifindex()](IterableQueue::get_ifindex)\n- [.get_type()](IterableQueue::get_type)\n- [.get_napi_id()](IterableQueue::get_napi_id)\n- [.get_dmabuf()](IterableQueue::get_dmabuf)\n- [.get_io_uring()](IterableQueue::get_io_uring)\n- [.get_xsk()](IterableQueue::get_xsk)\n- [.get_lease()](IterableQueue::get_lease)\n\n"]
6024 pub fn op_queue_get_dump(self) -> OpQueueGetDump<'buf> {
6025 let mut res = OpQueueGetDump::new(self);
6026 res.request
6027 .do_writeback(res.protocol(), "op-queue-get-dump", OpQueueGetDump::lookup);
6028 res
6029 }
6030 #[doc = "Get queue information from the kernel. Only configured queues will be\nreported (as opposed to all available hardware queues).\n\nRequest attributes:\n- [.push_id()](PushQueue::push_id)\n- [.push_ifindex()](PushQueue::push_ifindex)\n- [.push_type()](PushQueue::push_type)\n\nReply attributes:\n- [.get_id()](IterableQueue::get_id)\n- [.get_ifindex()](IterableQueue::get_ifindex)\n- [.get_type()](IterableQueue::get_type)\n- [.get_napi_id()](IterableQueue::get_napi_id)\n- [.get_dmabuf()](IterableQueue::get_dmabuf)\n- [.get_io_uring()](IterableQueue::get_io_uring)\n- [.get_xsk()](IterableQueue::get_xsk)\n- [.get_lease()](IterableQueue::get_lease)\n\n"]
6031 pub fn op_queue_get_do(self) -> OpQueueGetDo<'buf> {
6032 let mut res = OpQueueGetDo::new(self);
6033 res.request
6034 .do_writeback(res.protocol(), "op-queue-get-do", OpQueueGetDo::lookup);
6035 res
6036 }
6037 #[doc = "Get information about NAPI instances configured on the system.\n\nRequest attributes:\n- [.push_ifindex()](PushNapi::push_ifindex)\n\nReply attributes:\n- [.get_ifindex()](IterableNapi::get_ifindex)\n- [.get_id()](IterableNapi::get_id)\n- [.get_irq()](IterableNapi::get_irq)\n- [.get_pid()](IterableNapi::get_pid)\n- [.get_defer_hard_irqs()](IterableNapi::get_defer_hard_irqs)\n- [.get_gro_flush_timeout()](IterableNapi::get_gro_flush_timeout)\n- [.get_irq_suspend_timeout()](IterableNapi::get_irq_suspend_timeout)\n- [.get_threaded()](IterableNapi::get_threaded)\n\n"]
6038 pub fn op_napi_get_dump(self) -> OpNapiGetDump<'buf> {
6039 let mut res = OpNapiGetDump::new(self);
6040 res.request
6041 .do_writeback(res.protocol(), "op-napi-get-dump", OpNapiGetDump::lookup);
6042 res
6043 }
6044 #[doc = "Get information about NAPI instances configured on the system.\n\nRequest attributes:\n- [.push_id()](PushNapi::push_id)\n\nReply attributes:\n- [.get_ifindex()](IterableNapi::get_ifindex)\n- [.get_id()](IterableNapi::get_id)\n- [.get_irq()](IterableNapi::get_irq)\n- [.get_pid()](IterableNapi::get_pid)\n- [.get_defer_hard_irqs()](IterableNapi::get_defer_hard_irqs)\n- [.get_gro_flush_timeout()](IterableNapi::get_gro_flush_timeout)\n- [.get_irq_suspend_timeout()](IterableNapi::get_irq_suspend_timeout)\n- [.get_threaded()](IterableNapi::get_threaded)\n\n"]
6045 pub fn op_napi_get_do(self) -> OpNapiGetDo<'buf> {
6046 let mut res = OpNapiGetDo::new(self);
6047 res.request
6048 .do_writeback(res.protocol(), "op-napi-get-do", OpNapiGetDo::lookup);
6049 res
6050 }
6051 #[doc = "Get / dump fine grained statistics. Which statistics are reported\ndepends on the device and the driver, and whether the driver stores\nsoftware counters per-queue.\n\nRequest attributes:\n- [.push_ifindex()](PushQstats::push_ifindex)\n- [.push_scope()](PushQstats::push_scope)\n\nReply attributes:\n- [.get_ifindex()](IterableQstats::get_ifindex)\n- [.get_queue_type()](IterableQstats::get_queue_type)\n- [.get_queue_id()](IterableQstats::get_queue_id)\n- [.get_rx_packets()](IterableQstats::get_rx_packets)\n- [.get_rx_bytes()](IterableQstats::get_rx_bytes)\n- [.get_tx_packets()](IterableQstats::get_tx_packets)\n- [.get_tx_bytes()](IterableQstats::get_tx_bytes)\n- [.get_rx_alloc_fail()](IterableQstats::get_rx_alloc_fail)\n- [.get_rx_hw_drops()](IterableQstats::get_rx_hw_drops)\n- [.get_rx_hw_drop_overruns()](IterableQstats::get_rx_hw_drop_overruns)\n- [.get_rx_csum_complete()](IterableQstats::get_rx_csum_complete)\n- [.get_rx_csum_unnecessary()](IterableQstats::get_rx_csum_unnecessary)\n- [.get_rx_csum_none()](IterableQstats::get_rx_csum_none)\n- [.get_rx_csum_bad()](IterableQstats::get_rx_csum_bad)\n- [.get_rx_hw_gro_packets()](IterableQstats::get_rx_hw_gro_packets)\n- [.get_rx_hw_gro_bytes()](IterableQstats::get_rx_hw_gro_bytes)\n- [.get_rx_hw_gro_wire_packets()](IterableQstats::get_rx_hw_gro_wire_packets)\n- [.get_rx_hw_gro_wire_bytes()](IterableQstats::get_rx_hw_gro_wire_bytes)\n- [.get_rx_hw_drop_ratelimits()](IterableQstats::get_rx_hw_drop_ratelimits)\n- [.get_tx_hw_drops()](IterableQstats::get_tx_hw_drops)\n- [.get_tx_hw_drop_errors()](IterableQstats::get_tx_hw_drop_errors)\n- [.get_tx_csum_none()](IterableQstats::get_tx_csum_none)\n- [.get_tx_needs_csum()](IterableQstats::get_tx_needs_csum)\n- [.get_tx_hw_gso_packets()](IterableQstats::get_tx_hw_gso_packets)\n- [.get_tx_hw_gso_bytes()](IterableQstats::get_tx_hw_gso_bytes)\n- [.get_tx_hw_gso_wire_packets()](IterableQstats::get_tx_hw_gso_wire_packets)\n- [.get_tx_hw_gso_wire_bytes()](IterableQstats::get_tx_hw_gso_wire_bytes)\n- [.get_tx_hw_drop_ratelimits()](IterableQstats::get_tx_hw_drop_ratelimits)\n- [.get_tx_stop()](IterableQstats::get_tx_stop)\n- [.get_tx_wake()](IterableQstats::get_tx_wake)\n\n"]
6052 pub fn op_qstats_get_dump(self) -> OpQstatsGetDump<'buf> {
6053 let mut res = OpQstatsGetDump::new(self);
6054 res.request.do_writeback(
6055 res.protocol(),
6056 "op-qstats-get-dump",
6057 OpQstatsGetDump::lookup,
6058 );
6059 res
6060 }
6061 #[doc = "Bind dmabuf to netdev\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushDmabuf::push_ifindex)\n- [.nested_queues()](PushDmabuf::nested_queues)\n- [.push_fd()](PushDmabuf::push_fd)\n\nReply attributes:\n- [.get_id()](IterableDmabuf::get_id)\n\n"]
6062 pub fn op_bind_rx_do(self) -> OpBindRxDo<'buf> {
6063 let mut res = OpBindRxDo::new(self);
6064 res.request
6065 .do_writeback(res.protocol(), "op-bind-rx-do", OpBindRxDo::lookup);
6066 res
6067 }
6068 #[doc = "Set configurable NAPI instance settings.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushNapi::push_id)\n- [.push_defer_hard_irqs()](PushNapi::push_defer_hard_irqs)\n- [.push_gro_flush_timeout()](PushNapi::push_gro_flush_timeout)\n- [.push_irq_suspend_timeout()](PushNapi::push_irq_suspend_timeout)\n- [.push_threaded()](PushNapi::push_threaded)\n\n"]
6069 pub fn op_napi_set_do(self) -> OpNapiSetDo<'buf> {
6070 let mut res = OpNapiSetDo::new(self);
6071 res.request
6072 .do_writeback(res.protocol(), "op-napi-set-do", OpNapiSetDo::lookup);
6073 res
6074 }
6075 #[doc = "Bind dmabuf to netdev for TX\n\nRequest attributes:\n- [.push_ifindex()](PushDmabuf::push_ifindex)\n- [.push_fd()](PushDmabuf::push_fd)\n\nReply attributes:\n- [.get_id()](IterableDmabuf::get_id)\n\n"]
6076 pub fn op_bind_tx_do(self) -> OpBindTxDo<'buf> {
6077 let mut res = OpBindTxDo::new(self);
6078 res.request
6079 .do_writeback(res.protocol(), "op-bind-tx-do", OpBindTxDo::lookup);
6080 res
6081 }
6082 #[doc = "Create a new queue for the given netdevice. Whether this operation is\nsupported depends on the device and the driver.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushQueue::push_ifindex)\n- [.push_type()](PushQueue::push_type)\n- [.nested_lease()](PushQueue::nested_lease)\n\nReply attributes:\n- [.get_id()](IterableQueue::get_id)\n\n"]
6083 pub fn op_queue_create_do(self) -> OpQueueCreateDo<'buf> {
6084 let mut res = OpQueueCreateDo::new(self);
6085 res.request.do_writeback(
6086 res.protocol(),
6087 "op-queue-create-do",
6088 OpQueueCreateDo::lookup,
6089 );
6090 res
6091 }
6092}
6093#[cfg(test)]
6094mod generated_tests {
6095 use super::*;
6096 #[test]
6097 fn tests() {
6098 let _ = IterableDev::get_ifindex;
6099 let _ = IterableDev::get_xdp_features;
6100 let _ = IterableDev::get_xdp_rx_metadata_features;
6101 let _ = IterableDev::get_xdp_zc_max_segs;
6102 let _ = IterableDev::get_xsk_features;
6103 let _ = IterableDmabuf::get_id;
6104 let _ = IterableNapi::get_defer_hard_irqs;
6105 let _ = IterableNapi::get_gro_flush_timeout;
6106 let _ = IterableNapi::get_id;
6107 let _ = IterableNapi::get_ifindex;
6108 let _ = IterableNapi::get_irq;
6109 let _ = IterableNapi::get_irq_suspend_timeout;
6110 let _ = IterableNapi::get_pid;
6111 let _ = IterableNapi::get_threaded;
6112 let _ = IterablePagePool::get_detach_time;
6113 let _ = IterablePagePool::get_dmabuf;
6114 let _ = IterablePagePool::get_id;
6115 let _ = IterablePagePool::get_ifindex;
6116 let _ = IterablePagePool::get_inflight;
6117 let _ = IterablePagePool::get_inflight_mem;
6118 let _ = IterablePagePool::get_io_uring;
6119 let _ = IterablePagePool::get_napi_id;
6120 let _ = IterablePagePoolStats::get_alloc_empty;
6121 let _ = IterablePagePoolStats::get_alloc_fast;
6122 let _ = IterablePagePoolStats::get_alloc_refill;
6123 let _ = IterablePagePoolStats::get_alloc_slow;
6124 let _ = IterablePagePoolStats::get_alloc_slow_high_order;
6125 let _ = IterablePagePoolStats::get_alloc_waive;
6126 let _ = IterablePagePoolStats::get_info;
6127 let _ = IterablePagePoolStats::get_recycle_cache_full;
6128 let _ = IterablePagePoolStats::get_recycle_cached;
6129 let _ = IterablePagePoolStats::get_recycle_released_refcnt;
6130 let _ = IterablePagePoolStats::get_recycle_ring;
6131 let _ = IterablePagePoolStats::get_recycle_ring_full;
6132 let _ = IterableQstats::get_ifindex;
6133 let _ = IterableQstats::get_queue_id;
6134 let _ = IterableQstats::get_queue_type;
6135 let _ = IterableQstats::get_rx_alloc_fail;
6136 let _ = IterableQstats::get_rx_bytes;
6137 let _ = IterableQstats::get_rx_csum_bad;
6138 let _ = IterableQstats::get_rx_csum_complete;
6139 let _ = IterableQstats::get_rx_csum_none;
6140 let _ = IterableQstats::get_rx_csum_unnecessary;
6141 let _ = IterableQstats::get_rx_hw_drop_overruns;
6142 let _ = IterableQstats::get_rx_hw_drop_ratelimits;
6143 let _ = IterableQstats::get_rx_hw_drops;
6144 let _ = IterableQstats::get_rx_hw_gro_bytes;
6145 let _ = IterableQstats::get_rx_hw_gro_packets;
6146 let _ = IterableQstats::get_rx_hw_gro_wire_bytes;
6147 let _ = IterableQstats::get_rx_hw_gro_wire_packets;
6148 let _ = IterableQstats::get_rx_packets;
6149 let _ = IterableQstats::get_tx_bytes;
6150 let _ = IterableQstats::get_tx_csum_none;
6151 let _ = IterableQstats::get_tx_hw_drop_errors;
6152 let _ = IterableQstats::get_tx_hw_drop_ratelimits;
6153 let _ = IterableQstats::get_tx_hw_drops;
6154 let _ = IterableQstats::get_tx_hw_gso_bytes;
6155 let _ = IterableQstats::get_tx_hw_gso_packets;
6156 let _ = IterableQstats::get_tx_hw_gso_wire_bytes;
6157 let _ = IterableQstats::get_tx_hw_gso_wire_packets;
6158 let _ = IterableQstats::get_tx_needs_csum;
6159 let _ = IterableQstats::get_tx_packets;
6160 let _ = IterableQstats::get_tx_stop;
6161 let _ = IterableQstats::get_tx_wake;
6162 let _ = IterableQueue::get_dmabuf;
6163 let _ = IterableQueue::get_id;
6164 let _ = IterableQueue::get_ifindex;
6165 let _ = IterableQueue::get_io_uring;
6166 let _ = IterableQueue::get_lease;
6167 let _ = IterableQueue::get_napi_id;
6168 let _ = IterableQueue::get_type;
6169 let _ = IterableQueue::get_xsk;
6170 let _ = OpDevAddNotif;
6171 let _ = OpDevChangeNotif;
6172 let _ = OpDevDelNotif;
6173 let _ = OpPagePoolAddNotif;
6174 let _ = OpPagePoolChangeNotif;
6175 let _ = OpPagePoolDelNotif;
6176 let _ = PushDev::<&mut Vec<u8>>::push_ifindex;
6177 let _ = PushDmabuf::<&mut Vec<u8>>::nested_queues;
6178 let _ = PushDmabuf::<&mut Vec<u8>>::push_fd;
6179 let _ = PushDmabuf::<&mut Vec<u8>>::push_ifindex;
6180 let _ = PushNapi::<&mut Vec<u8>>::push_defer_hard_irqs;
6181 let _ = PushNapi::<&mut Vec<u8>>::push_gro_flush_timeout;
6182 let _ = PushNapi::<&mut Vec<u8>>::push_id;
6183 let _ = PushNapi::<&mut Vec<u8>>::push_ifindex;
6184 let _ = PushNapi::<&mut Vec<u8>>::push_irq_suspend_timeout;
6185 let _ = PushNapi::<&mut Vec<u8>>::push_threaded;
6186 let _ = PushPagePool::<&mut Vec<u8>>::push_id;
6187 let _ = PushPagePool::<&mut Vec<u8>>::push_ifindex;
6188 let _ = PushPagePoolStats::<&mut Vec<u8>>::nested_info;
6189 let _ = PushQstats::<&mut Vec<u8>>::push_ifindex;
6190 let _ = PushQstats::<&mut Vec<u8>>::push_scope;
6191 let _ = PushQueue::<&mut Vec<u8>>::nested_lease;
6192 let _ = PushQueue::<&mut Vec<u8>>::push_id;
6193 let _ = PushQueue::<&mut Vec<u8>>::push_ifindex;
6194 let _ = PushQueue::<&mut Vec<u8>>::push_type;
6195 }
6196}