Skip to main content

netlink_bindings/netdev/
mod.rs

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