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