Skip to main content

netlink_bindings/netdev/
mod.rs

1#![doc = "netdev configuration over generic netlink."]
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::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &CStr = c"netdev";
17#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
18#[derive(Debug, Clone, Copy)]
19pub enum XdpAct {
20    #[doc = "XDP features set supported by all drivers (XDP_ABORTED, XDP_DROP, XDP_PASS, XDP_TX)"]
21    Basic = 1 << 0,
22    #[doc = "The netdev supports XDP_REDIRECT"]
23    Redirect = 1 << 1,
24    #[doc = "This feature informs if netdev implements ndo_xdp_xmit callback."]
25    NdoXmit = 1 << 2,
26    #[doc = "This feature informs if netdev supports AF_XDP in zero copy mode."]
27    XskZerocopy = 1 << 3,
28    #[doc = "This feature informs if netdev supports XDP hw offloading."]
29    HwOffload = 1 << 4,
30    #[doc = "This feature informs if netdev implements non-linear XDP buffer support in the driver napi callback."]
31    RxSg = 1 << 5,
32    #[doc = "This feature informs if netdev implements non-linear XDP buffer support in ndo_xdp_xmit callback."]
33    NdoXmitSg = 1 << 6,
34}
35impl XdpAct {
36    pub fn from_value(value: u64) -> Option<Self> {
37        Some(match value {
38            n if n == 1 << 0 => Self::Basic,
39            n if n == 1 << 1 => Self::Redirect,
40            n if n == 1 << 2 => Self::NdoXmit,
41            n if n == 1 << 3 => Self::XskZerocopy,
42            n if n == 1 << 4 => Self::HwOffload,
43            n if n == 1 << 5 => Self::RxSg,
44            n if n == 1 << 6 => Self::NdoXmitSg,
45            _ => return None,
46        })
47    }
48}
49#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
50#[derive(Debug, Clone, Copy)]
51pub enum XdpRxMetadata {
52    #[doc = "Device is capable of exposing receive HW timestamp via\nbpf_xdp_metadata_rx_timestamp().\n"]
53    Timestamp = 1 << 0,
54    #[doc = "Device is capable of exposing receive packet hash via\nbpf_xdp_metadata_rx_hash().\n"]
55    Hash = 1 << 1,
56    #[doc = "Device is capable of exposing receive packet VLAN tag via\nbpf_xdp_metadata_rx_vlan_tag().\n"]
57    VlanTag = 1 << 2,
58}
59impl XdpRxMetadata {
60    pub fn from_value(value: u64) -> Option<Self> {
61        Some(match value {
62            n if n == 1 << 0 => Self::Timestamp,
63            n if n == 1 << 1 => Self::Hash,
64            n if n == 1 << 2 => Self::VlanTag,
65            _ => return None,
66        })
67    }
68}
69#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
70#[derive(Debug, Clone, Copy)]
71pub enum XskFlags {
72    #[doc = "HW timestamping egress packets is supported by the driver."]
73    TxTimestamp = 1 << 0,
74    #[doc = "L3 checksum HW offload is supported by the driver."]
75    TxChecksum = 1 << 1,
76    #[doc = "Launch time HW offload is supported by the driver."]
77    TxLaunchTimeFifo = 1 << 2,
78}
79impl XskFlags {
80    pub fn from_value(value: u64) -> Option<Self> {
81        Some(match value {
82            n if n == 1 << 0 => Self::TxTimestamp,
83            n if n == 1 << 1 => Self::TxChecksum,
84            n if n == 1 << 2 => Self::TxLaunchTimeFifo,
85            _ => return None,
86        })
87    }
88}
89#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
90#[derive(Debug, Clone, Copy)]
91pub enum QueueType {
92    Rx = 0,
93    Tx = 1,
94}
95impl QueueType {
96    pub fn from_value(value: u64) -> Option<Self> {
97        Some(match value {
98            0 => Self::Rx,
99            1 => Self::Tx,
100            _ => return None,
101        })
102    }
103}
104#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
105#[derive(Debug, Clone, Copy)]
106pub enum QstatsScope {
107    Queue = 1 << 0,
108}
109impl QstatsScope {
110    pub fn from_value(value: u64) -> Option<Self> {
111        Some(match value {
112            n if n == 1 << 0 => Self::Queue,
113            _ => return None,
114        })
115    }
116}
117#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
118#[derive(Debug, Clone, Copy)]
119pub enum NapiThreaded {
120    Disabled = 0,
121    Enabled = 1,
122    BusyPoll = 2,
123}
124impl NapiThreaded {
125    pub fn from_value(value: u64) -> Option<Self> {
126        Some(match value {
127            0 => Self::Disabled,
128            1 => Self::Enabled,
129            2 => Self::BusyPoll,
130            _ => return None,
131        })
132    }
133}
134#[derive(Clone)]
135pub enum Dev<'a> {
136    #[doc = "netdev ifindex"]
137    Ifindex(u32),
138    Pad(&'a [u8]),
139    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
140    XdpFeatures(u64),
141    #[doc = "max fragment count supported by ZC driver"]
142    XdpZcMaxSegs(u32),
143    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
144    XdpRxMetadataFeatures(u64),
145    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
146    XskFeatures(u64),
147}
148impl<'a> IterableDev<'a> {
149    #[doc = "netdev ifindex"]
150    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
151        let mut iter = self.clone();
152        iter.pos = 0;
153        for attr in iter {
154            if let Dev::Ifindex(val) = attr? {
155                return Ok(val);
156            }
157        }
158        Err(ErrorContext::new_missing(
159            "Dev",
160            "Ifindex",
161            self.orig_loc,
162            self.buf.as_ptr() as usize,
163        ))
164    }
165    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
166        let mut iter = self.clone();
167        iter.pos = 0;
168        for attr in iter {
169            if let Dev::Pad(val) = attr? {
170                return Ok(val);
171            }
172        }
173        Err(ErrorContext::new_missing(
174            "Dev",
175            "Pad",
176            self.orig_loc,
177            self.buf.as_ptr() as usize,
178        ))
179    }
180    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
181    pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
182        let mut iter = self.clone();
183        iter.pos = 0;
184        for attr in iter {
185            if let Dev::XdpFeatures(val) = attr? {
186                return Ok(val);
187            }
188        }
189        Err(ErrorContext::new_missing(
190            "Dev",
191            "XdpFeatures",
192            self.orig_loc,
193            self.buf.as_ptr() as usize,
194        ))
195    }
196    #[doc = "max fragment count supported by ZC driver"]
197    pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
198        let mut iter = self.clone();
199        iter.pos = 0;
200        for attr in iter {
201            if let Dev::XdpZcMaxSegs(val) = attr? {
202                return Ok(val);
203            }
204        }
205        Err(ErrorContext::new_missing(
206            "Dev",
207            "XdpZcMaxSegs",
208            self.orig_loc,
209            self.buf.as_ptr() as usize,
210        ))
211    }
212    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
213    pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
214        let mut iter = self.clone();
215        iter.pos = 0;
216        for attr in iter {
217            if let Dev::XdpRxMetadataFeatures(val) = attr? {
218                return Ok(val);
219            }
220        }
221        Err(ErrorContext::new_missing(
222            "Dev",
223            "XdpRxMetadataFeatures",
224            self.orig_loc,
225            self.buf.as_ptr() as usize,
226        ))
227    }
228    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
229    pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
230        let mut iter = self.clone();
231        iter.pos = 0;
232        for attr in iter {
233            if let Dev::XskFeatures(val) = attr? {
234                return Ok(val);
235            }
236        }
237        Err(ErrorContext::new_missing(
238            "Dev",
239            "XskFeatures",
240            self.orig_loc,
241            self.buf.as_ptr() as usize,
242        ))
243    }
244}
245impl Dev<'_> {
246    pub fn new<'a>(buf: &'a [u8]) -> IterableDev<'a> {
247        IterableDev::with_loc(buf, buf.as_ptr() as usize)
248    }
249    fn attr_from_type(r#type: u16) -> Option<&'static str> {
250        let res = match r#type {
251            1u16 => "Ifindex",
252            2u16 => "Pad",
253            3u16 => "XdpFeatures",
254            4u16 => "XdpZcMaxSegs",
255            5u16 => "XdpRxMetadataFeatures",
256            6u16 => "XskFeatures",
257            _ => return None,
258        };
259        Some(res)
260    }
261}
262#[derive(Clone, Copy, Default)]
263pub struct IterableDev<'a> {
264    buf: &'a [u8],
265    pos: usize,
266    orig_loc: usize,
267}
268impl<'a> IterableDev<'a> {
269    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
270        Self {
271            buf,
272            pos: 0,
273            orig_loc,
274        }
275    }
276    pub fn get_buf(&self) -> &'a [u8] {
277        self.buf
278    }
279}
280impl<'a> Iterator for IterableDev<'a> {
281    type Item = Result<Dev<'a>, ErrorContext>;
282    fn next(&mut self) -> Option<Self::Item> {
283        let pos = self.pos;
284        let mut r#type;
285        loop {
286            r#type = None;
287            if self.buf.len() == self.pos {
288                return None;
289            }
290            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
291                break;
292            };
293            r#type = Some(header.r#type);
294            let res = match header.r#type {
295                1u16 => Dev::Ifindex({
296                    let res = parse_u32(next);
297                    let Some(val) = res else { break };
298                    val
299                }),
300                2u16 => Dev::Pad({
301                    let res = Some(next);
302                    let Some(val) = res else { break };
303                    val
304                }),
305                3u16 => Dev::XdpFeatures({
306                    let res = parse_u64(next);
307                    let Some(val) = res else { break };
308                    val
309                }),
310                4u16 => Dev::XdpZcMaxSegs({
311                    let res = parse_u32(next);
312                    let Some(val) = res else { break };
313                    val
314                }),
315                5u16 => Dev::XdpRxMetadataFeatures({
316                    let res = parse_u64(next);
317                    let Some(val) = res else { break };
318                    val
319                }),
320                6u16 => Dev::XskFeatures({
321                    let res = parse_u64(next);
322                    let Some(val) = res else { break };
323                    val
324                }),
325                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
326                n => continue,
327            };
328            return Some(Ok(res));
329        }
330        Some(Err(ErrorContext::new(
331            "Dev",
332            r#type.and_then(|t| Dev::attr_from_type(t)),
333            self.orig_loc,
334            self.buf.as_ptr().wrapping_add(pos) as usize,
335        )))
336    }
337}
338impl<'a> std::fmt::Debug for IterableDev<'_> {
339    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340        let mut fmt = f.debug_struct("Dev");
341        for attr in self.clone() {
342            let attr = match attr {
343                Ok(a) => a,
344                Err(err) => {
345                    fmt.finish()?;
346                    f.write_str("Err(")?;
347                    err.fmt(f)?;
348                    return f.write_str(")");
349                }
350            };
351            match attr {
352                Dev::Ifindex(val) => fmt.field("Ifindex", &val),
353                Dev::Pad(val) => fmt.field("Pad", &val),
354                Dev::XdpFeatures(val) => {
355                    fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
356                }
357                Dev::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
358                Dev::XdpRxMetadataFeatures(val) => fmt.field(
359                    "XdpRxMetadataFeatures",
360                    &FormatFlags(val.into(), XdpRxMetadata::from_value),
361                ),
362                Dev::XskFeatures(val) => fmt.field(
363                    "XskFeatures",
364                    &FormatFlags(val.into(), XskFlags::from_value),
365                ),
366            };
367        }
368        fmt.finish()
369    }
370}
371impl IterableDev<'_> {
372    pub fn lookup_attr(
373        &self,
374        offset: usize,
375        missing_type: Option<u16>,
376    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
377        let mut stack = Vec::new();
378        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
379        if cur == offset {
380            stack.push(("Dev", offset));
381            return (stack, missing_type.and_then(|t| Dev::attr_from_type(t)));
382        }
383        if cur > offset || cur + self.buf.len() < offset {
384            return (stack, None);
385        }
386        let mut attrs = self.clone();
387        let mut last_off = cur + attrs.pos;
388        while let Some(attr) = attrs.next() {
389            let Ok(attr) = attr else { break };
390            match attr {
391                Dev::Ifindex(val) => {
392                    if last_off == offset {
393                        stack.push(("Ifindex", last_off));
394                        break;
395                    }
396                }
397                Dev::Pad(val) => {
398                    if last_off == offset {
399                        stack.push(("Pad", last_off));
400                        break;
401                    }
402                }
403                Dev::XdpFeatures(val) => {
404                    if last_off == offset {
405                        stack.push(("XdpFeatures", last_off));
406                        break;
407                    }
408                }
409                Dev::XdpZcMaxSegs(val) => {
410                    if last_off == offset {
411                        stack.push(("XdpZcMaxSegs", last_off));
412                        break;
413                    }
414                }
415                Dev::XdpRxMetadataFeatures(val) => {
416                    if last_off == offset {
417                        stack.push(("XdpRxMetadataFeatures", last_off));
418                        break;
419                    }
420                }
421                Dev::XskFeatures(val) => {
422                    if last_off == offset {
423                        stack.push(("XskFeatures", last_off));
424                        break;
425                    }
426                }
427                _ => {}
428            };
429            last_off = cur + attrs.pos;
430        }
431        if !stack.is_empty() {
432            stack.push(("Dev", cur));
433        }
434        (stack, None)
435    }
436}
437#[derive(Clone)]
438pub enum IoUringProviderInfo {}
439impl<'a> IterableIoUringProviderInfo<'a> {}
440impl IoUringProviderInfo {
441    pub fn new<'a>(buf: &'a [u8]) -> IterableIoUringProviderInfo<'a> {
442        IterableIoUringProviderInfo::with_loc(buf, buf.as_ptr() as usize)
443    }
444    fn attr_from_type(r#type: u16) -> Option<&'static str> {
445        None
446    }
447}
448#[derive(Clone, Copy, Default)]
449pub struct IterableIoUringProviderInfo<'a> {
450    buf: &'a [u8],
451    pos: usize,
452    orig_loc: usize,
453}
454impl<'a> IterableIoUringProviderInfo<'a> {
455    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
456        Self {
457            buf,
458            pos: 0,
459            orig_loc,
460        }
461    }
462    pub fn get_buf(&self) -> &'a [u8] {
463        self.buf
464    }
465}
466impl<'a> Iterator for IterableIoUringProviderInfo<'a> {
467    type Item = Result<IoUringProviderInfo, ErrorContext>;
468    fn next(&mut self) -> Option<Self::Item> {
469        let pos = self.pos;
470        let mut r#type;
471        loop {
472            r#type = None;
473            if self.buf.len() == self.pos {
474                return None;
475            }
476            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
477                break;
478            };
479            r#type = Some(header.r#type);
480            let res = match header.r#type {
481                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
482                n => continue,
483            };
484            return Some(Ok(res));
485        }
486        Some(Err(ErrorContext::new(
487            "IoUringProviderInfo",
488            r#type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
489            self.orig_loc,
490            self.buf.as_ptr().wrapping_add(pos) as usize,
491        )))
492    }
493}
494impl std::fmt::Debug for IterableIoUringProviderInfo<'_> {
495    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
496        let mut fmt = f.debug_struct("IoUringProviderInfo");
497        for attr in self.clone() {
498            let attr = match attr {
499                Ok(a) => a,
500                Err(err) => {
501                    fmt.finish()?;
502                    f.write_str("Err(")?;
503                    err.fmt(f)?;
504                    return f.write_str(")");
505                }
506            };
507            match attr {};
508        }
509        fmt.finish()
510    }
511}
512impl IterableIoUringProviderInfo<'_> {
513    pub fn lookup_attr(
514        &self,
515        offset: usize,
516        missing_type: Option<u16>,
517    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
518        let mut stack = Vec::new();
519        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
520        if cur == offset {
521            stack.push(("IoUringProviderInfo", offset));
522            return (
523                stack,
524                missing_type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
525            );
526        }
527        (stack, None)
528    }
529}
530#[derive(Clone)]
531pub enum PagePool<'a> {
532    #[doc = "Unique ID of a Page Pool instance."]
533    Id(u32),
534    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
535    Ifindex(u32),
536    #[doc = "Id of NAPI using this Page Pool instance."]
537    NapiId(u32),
538    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
539    Inflight(u32),
540    #[doc = "Amount of memory held by inflight pages.\n"]
541    InflightMem(u32),
542    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
543    DetachTime(u32),
544    #[doc = "ID of the dmabuf this page-pool is attached to."]
545    Dmabuf(u32),
546    #[doc = "io-uring memory provider information."]
547    IoUring(IterableIoUringProviderInfo<'a>),
548}
549impl<'a> IterablePagePool<'a> {
550    #[doc = "Unique ID of a Page Pool instance."]
551    pub fn get_id(&self) -> Result<u32, ErrorContext> {
552        let mut iter = self.clone();
553        iter.pos = 0;
554        for attr in iter {
555            if let PagePool::Id(val) = attr? {
556                return Ok(val);
557            }
558        }
559        Err(ErrorContext::new_missing(
560            "PagePool",
561            "Id",
562            self.orig_loc,
563            self.buf.as_ptr() as usize,
564        ))
565    }
566    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
567    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
568        let mut iter = self.clone();
569        iter.pos = 0;
570        for attr in iter {
571            if let PagePool::Ifindex(val) = attr? {
572                return Ok(val);
573            }
574        }
575        Err(ErrorContext::new_missing(
576            "PagePool",
577            "Ifindex",
578            self.orig_loc,
579            self.buf.as_ptr() as usize,
580        ))
581    }
582    #[doc = "Id of NAPI using this Page Pool instance."]
583    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
584        let mut iter = self.clone();
585        iter.pos = 0;
586        for attr in iter {
587            if let PagePool::NapiId(val) = attr? {
588                return Ok(val);
589            }
590        }
591        Err(ErrorContext::new_missing(
592            "PagePool",
593            "NapiId",
594            self.orig_loc,
595            self.buf.as_ptr() as usize,
596        ))
597    }
598    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
599    pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
600        let mut iter = self.clone();
601        iter.pos = 0;
602        for attr in iter {
603            if let PagePool::Inflight(val) = attr? {
604                return Ok(val);
605            }
606        }
607        Err(ErrorContext::new_missing(
608            "PagePool",
609            "Inflight",
610            self.orig_loc,
611            self.buf.as_ptr() as usize,
612        ))
613    }
614    #[doc = "Amount of memory held by inflight pages.\n"]
615    pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
616        let mut iter = self.clone();
617        iter.pos = 0;
618        for attr in iter {
619            if let PagePool::InflightMem(val) = attr? {
620                return Ok(val);
621            }
622        }
623        Err(ErrorContext::new_missing(
624            "PagePool",
625            "InflightMem",
626            self.orig_loc,
627            self.buf.as_ptr() as usize,
628        ))
629    }
630    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
631    pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
632        let mut iter = self.clone();
633        iter.pos = 0;
634        for attr in iter {
635            if let PagePool::DetachTime(val) = attr? {
636                return Ok(val);
637            }
638        }
639        Err(ErrorContext::new_missing(
640            "PagePool",
641            "DetachTime",
642            self.orig_loc,
643            self.buf.as_ptr() as usize,
644        ))
645    }
646    #[doc = "ID of the dmabuf this page-pool is attached to."]
647    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
648        let mut iter = self.clone();
649        iter.pos = 0;
650        for attr in iter {
651            if let PagePool::Dmabuf(val) = attr? {
652                return Ok(val);
653            }
654        }
655        Err(ErrorContext::new_missing(
656            "PagePool",
657            "Dmabuf",
658            self.orig_loc,
659            self.buf.as_ptr() as usize,
660        ))
661    }
662    #[doc = "io-uring memory provider information."]
663    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
664        let mut iter = self.clone();
665        iter.pos = 0;
666        for attr in iter {
667            if let PagePool::IoUring(val) = attr? {
668                return Ok(val);
669            }
670        }
671        Err(ErrorContext::new_missing(
672            "PagePool",
673            "IoUring",
674            self.orig_loc,
675            self.buf.as_ptr() as usize,
676        ))
677    }
678}
679impl PagePool<'_> {
680    pub fn new<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
681        IterablePagePool::with_loc(buf, buf.as_ptr() as usize)
682    }
683    fn attr_from_type(r#type: u16) -> Option<&'static str> {
684        let res = match r#type {
685            1u16 => "Id",
686            2u16 => "Ifindex",
687            3u16 => "NapiId",
688            4u16 => "Inflight",
689            5u16 => "InflightMem",
690            6u16 => "DetachTime",
691            7u16 => "Dmabuf",
692            8u16 => "IoUring",
693            _ => return None,
694        };
695        Some(res)
696    }
697}
698#[derive(Clone, Copy, Default)]
699pub struct IterablePagePool<'a> {
700    buf: &'a [u8],
701    pos: usize,
702    orig_loc: usize,
703}
704impl<'a> IterablePagePool<'a> {
705    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
706        Self {
707            buf,
708            pos: 0,
709            orig_loc,
710        }
711    }
712    pub fn get_buf(&self) -> &'a [u8] {
713        self.buf
714    }
715}
716impl<'a> Iterator for IterablePagePool<'a> {
717    type Item = Result<PagePool<'a>, ErrorContext>;
718    fn next(&mut self) -> Option<Self::Item> {
719        let pos = self.pos;
720        let mut r#type;
721        loop {
722            r#type = None;
723            if self.buf.len() == self.pos {
724                return None;
725            }
726            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
727                break;
728            };
729            r#type = Some(header.r#type);
730            let res = match header.r#type {
731                1u16 => PagePool::Id({
732                    let res = parse_u32(next);
733                    let Some(val) = res else { break };
734                    val
735                }),
736                2u16 => PagePool::Ifindex({
737                    let res = parse_u32(next);
738                    let Some(val) = res else { break };
739                    val
740                }),
741                3u16 => PagePool::NapiId({
742                    let res = parse_u32(next);
743                    let Some(val) = res else { break };
744                    val
745                }),
746                4u16 => PagePool::Inflight({
747                    let res = parse_u32(next);
748                    let Some(val) = res else { break };
749                    val
750                }),
751                5u16 => PagePool::InflightMem({
752                    let res = parse_u32(next);
753                    let Some(val) = res else { break };
754                    val
755                }),
756                6u16 => PagePool::DetachTime({
757                    let res = parse_u32(next);
758                    let Some(val) = res else { break };
759                    val
760                }),
761                7u16 => PagePool::Dmabuf({
762                    let res = parse_u32(next);
763                    let Some(val) = res else { break };
764                    val
765                }),
766                8u16 => PagePool::IoUring({
767                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
768                    let Some(val) = res else { break };
769                    val
770                }),
771                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
772                n => continue,
773            };
774            return Some(Ok(res));
775        }
776        Some(Err(ErrorContext::new(
777            "PagePool",
778            r#type.and_then(|t| PagePool::attr_from_type(t)),
779            self.orig_loc,
780            self.buf.as_ptr().wrapping_add(pos) as usize,
781        )))
782    }
783}
784impl<'a> std::fmt::Debug for IterablePagePool<'_> {
785    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
786        let mut fmt = f.debug_struct("PagePool");
787        for attr in self.clone() {
788            let attr = match attr {
789                Ok(a) => a,
790                Err(err) => {
791                    fmt.finish()?;
792                    f.write_str("Err(")?;
793                    err.fmt(f)?;
794                    return f.write_str(")");
795                }
796            };
797            match attr {
798                PagePool::Id(val) => fmt.field("Id", &val),
799                PagePool::Ifindex(val) => fmt.field("Ifindex", &val),
800                PagePool::NapiId(val) => fmt.field("NapiId", &val),
801                PagePool::Inflight(val) => fmt.field("Inflight", &val),
802                PagePool::InflightMem(val) => fmt.field("InflightMem", &val),
803                PagePool::DetachTime(val) => fmt.field("DetachTime", &val),
804                PagePool::Dmabuf(val) => fmt.field("Dmabuf", &val),
805                PagePool::IoUring(val) => fmt.field("IoUring", &val),
806            };
807        }
808        fmt.finish()
809    }
810}
811impl IterablePagePool<'_> {
812    pub fn lookup_attr(
813        &self,
814        offset: usize,
815        missing_type: Option<u16>,
816    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
817        let mut stack = Vec::new();
818        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
819        if cur == offset {
820            stack.push(("PagePool", offset));
821            return (
822                stack,
823                missing_type.and_then(|t| PagePool::attr_from_type(t)),
824            );
825        }
826        if cur > offset || cur + self.buf.len() < offset {
827            return (stack, None);
828        }
829        let mut attrs = self.clone();
830        let mut last_off = cur + attrs.pos;
831        let mut missing = None;
832        while let Some(attr) = attrs.next() {
833            let Ok(attr) = attr else { break };
834            match attr {
835                PagePool::Id(val) => {
836                    if last_off == offset {
837                        stack.push(("Id", last_off));
838                        break;
839                    }
840                }
841                PagePool::Ifindex(val) => {
842                    if last_off == offset {
843                        stack.push(("Ifindex", last_off));
844                        break;
845                    }
846                }
847                PagePool::NapiId(val) => {
848                    if last_off == offset {
849                        stack.push(("NapiId", last_off));
850                        break;
851                    }
852                }
853                PagePool::Inflight(val) => {
854                    if last_off == offset {
855                        stack.push(("Inflight", last_off));
856                        break;
857                    }
858                }
859                PagePool::InflightMem(val) => {
860                    if last_off == offset {
861                        stack.push(("InflightMem", last_off));
862                        break;
863                    }
864                }
865                PagePool::DetachTime(val) => {
866                    if last_off == offset {
867                        stack.push(("DetachTime", last_off));
868                        break;
869                    }
870                }
871                PagePool::Dmabuf(val) => {
872                    if last_off == offset {
873                        stack.push(("Dmabuf", last_off));
874                        break;
875                    }
876                }
877                PagePool::IoUring(val) => {
878                    (stack, missing) = val.lookup_attr(offset, missing_type);
879                    if !stack.is_empty() {
880                        break;
881                    }
882                }
883                _ => {}
884            };
885            last_off = cur + attrs.pos;
886        }
887        if !stack.is_empty() {
888            stack.push(("PagePool", cur));
889        }
890        (stack, missing)
891    }
892}
893#[derive(Clone)]
894pub enum PagePoolInfo {
895    #[doc = "Unique ID of a Page Pool instance."]
896    Id(u32),
897    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
898    Ifindex(u32),
899}
900impl<'a> IterablePagePoolInfo<'a> {
901    #[doc = "Unique ID of a Page Pool instance."]
902    pub fn get_id(&self) -> Result<u32, ErrorContext> {
903        let mut iter = self.clone();
904        iter.pos = 0;
905        for attr in iter {
906            if let PagePoolInfo::Id(val) = attr? {
907                return Ok(val);
908            }
909        }
910        Err(ErrorContext::new_missing(
911            "PagePoolInfo",
912            "Id",
913            self.orig_loc,
914            self.buf.as_ptr() as usize,
915        ))
916    }
917    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
918    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
919        let mut iter = self.clone();
920        iter.pos = 0;
921        for attr in iter {
922            if let PagePoolInfo::Ifindex(val) = attr? {
923                return Ok(val);
924            }
925        }
926        Err(ErrorContext::new_missing(
927            "PagePoolInfo",
928            "Ifindex",
929            self.orig_loc,
930            self.buf.as_ptr() as usize,
931        ))
932    }
933}
934impl PagePoolInfo {
935    pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolInfo<'a> {
936        IterablePagePoolInfo::with_loc(buf, buf.as_ptr() as usize)
937    }
938    fn attr_from_type(r#type: u16) -> Option<&'static str> {
939        PagePool::attr_from_type(r#type)
940    }
941}
942#[derive(Clone, Copy, Default)]
943pub struct IterablePagePoolInfo<'a> {
944    buf: &'a [u8],
945    pos: usize,
946    orig_loc: usize,
947}
948impl<'a> IterablePagePoolInfo<'a> {
949    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
950        Self {
951            buf,
952            pos: 0,
953            orig_loc,
954        }
955    }
956    pub fn get_buf(&self) -> &'a [u8] {
957        self.buf
958    }
959}
960impl<'a> Iterator for IterablePagePoolInfo<'a> {
961    type Item = Result<PagePoolInfo, ErrorContext>;
962    fn next(&mut self) -> Option<Self::Item> {
963        let pos = self.pos;
964        let mut r#type;
965        loop {
966            r#type = None;
967            if self.buf.len() == self.pos {
968                return None;
969            }
970            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
971                break;
972            };
973            r#type = Some(header.r#type);
974            let res = match header.r#type {
975                1u16 => PagePoolInfo::Id({
976                    let res = parse_u32(next);
977                    let Some(val) = res else { break };
978                    val
979                }),
980                2u16 => PagePoolInfo::Ifindex({
981                    let res = parse_u32(next);
982                    let Some(val) = res else { break };
983                    val
984                }),
985                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
986                n => continue,
987            };
988            return Some(Ok(res));
989        }
990        Some(Err(ErrorContext::new(
991            "PagePoolInfo",
992            r#type.and_then(|t| PagePoolInfo::attr_from_type(t)),
993            self.orig_loc,
994            self.buf.as_ptr().wrapping_add(pos) as usize,
995        )))
996    }
997}
998impl std::fmt::Debug for IterablePagePoolInfo<'_> {
999    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1000        let mut fmt = f.debug_struct("PagePoolInfo");
1001        for attr in self.clone() {
1002            let attr = match attr {
1003                Ok(a) => a,
1004                Err(err) => {
1005                    fmt.finish()?;
1006                    f.write_str("Err(")?;
1007                    err.fmt(f)?;
1008                    return f.write_str(")");
1009                }
1010            };
1011            match attr {
1012                PagePoolInfo::Id(val) => fmt.field("Id", &val),
1013                PagePoolInfo::Ifindex(val) => fmt.field("Ifindex", &val),
1014            };
1015        }
1016        fmt.finish()
1017    }
1018}
1019impl IterablePagePoolInfo<'_> {
1020    pub fn lookup_attr(
1021        &self,
1022        offset: usize,
1023        missing_type: Option<u16>,
1024    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1025        let mut stack = Vec::new();
1026        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1027        if cur == offset {
1028            stack.push(("PagePoolInfo", offset));
1029            return (
1030                stack,
1031                missing_type.and_then(|t| PagePoolInfo::attr_from_type(t)),
1032            );
1033        }
1034        if cur > offset || cur + self.buf.len() < offset {
1035            return (stack, None);
1036        }
1037        let mut attrs = self.clone();
1038        let mut last_off = cur + attrs.pos;
1039        while let Some(attr) = attrs.next() {
1040            let Ok(attr) = attr else { break };
1041            match attr {
1042                PagePoolInfo::Id(val) => {
1043                    if last_off == offset {
1044                        stack.push(("Id", last_off));
1045                        break;
1046                    }
1047                }
1048                PagePoolInfo::Ifindex(val) => {
1049                    if last_off == offset {
1050                        stack.push(("Ifindex", last_off));
1051                        break;
1052                    }
1053                }
1054                _ => {}
1055            };
1056            last_off = cur + attrs.pos;
1057        }
1058        if !stack.is_empty() {
1059            stack.push(("PagePoolInfo", cur));
1060        }
1061        (stack, None)
1062    }
1063}
1064#[derive(Clone)]
1065pub enum PagePoolStats<'a> {
1066    #[doc = "Page pool identifying information."]
1067    Info(IterablePagePoolInfo<'a>),
1068    AllocFast(u32),
1069    AllocSlow(u32),
1070    AllocSlowHighOrder(u32),
1071    AllocEmpty(u32),
1072    AllocRefill(u32),
1073    AllocWaive(u32),
1074    RecycleCached(u32),
1075    RecycleCacheFull(u32),
1076    RecycleRing(u32),
1077    RecycleRingFull(u32),
1078    RecycleReleasedRefcnt(u32),
1079}
1080impl<'a> IterablePagePoolStats<'a> {
1081    #[doc = "Page pool identifying information."]
1082    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
1083        let mut iter = self.clone();
1084        iter.pos = 0;
1085        for attr in iter {
1086            if let PagePoolStats::Info(val) = attr? {
1087                return Ok(val);
1088            }
1089        }
1090        Err(ErrorContext::new_missing(
1091            "PagePoolStats",
1092            "Info",
1093            self.orig_loc,
1094            self.buf.as_ptr() as usize,
1095        ))
1096    }
1097    pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
1098        let mut iter = self.clone();
1099        iter.pos = 0;
1100        for attr in iter {
1101            if let PagePoolStats::AllocFast(val) = attr? {
1102                return Ok(val);
1103            }
1104        }
1105        Err(ErrorContext::new_missing(
1106            "PagePoolStats",
1107            "AllocFast",
1108            self.orig_loc,
1109            self.buf.as_ptr() as usize,
1110        ))
1111    }
1112    pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
1113        let mut iter = self.clone();
1114        iter.pos = 0;
1115        for attr in iter {
1116            if let PagePoolStats::AllocSlow(val) = attr? {
1117                return Ok(val);
1118            }
1119        }
1120        Err(ErrorContext::new_missing(
1121            "PagePoolStats",
1122            "AllocSlow",
1123            self.orig_loc,
1124            self.buf.as_ptr() as usize,
1125        ))
1126    }
1127    pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
1128        let mut iter = self.clone();
1129        iter.pos = 0;
1130        for attr in iter {
1131            if let PagePoolStats::AllocSlowHighOrder(val) = attr? {
1132                return Ok(val);
1133            }
1134        }
1135        Err(ErrorContext::new_missing(
1136            "PagePoolStats",
1137            "AllocSlowHighOrder",
1138            self.orig_loc,
1139            self.buf.as_ptr() as usize,
1140        ))
1141    }
1142    pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
1143        let mut iter = self.clone();
1144        iter.pos = 0;
1145        for attr in iter {
1146            if let PagePoolStats::AllocEmpty(val) = attr? {
1147                return Ok(val);
1148            }
1149        }
1150        Err(ErrorContext::new_missing(
1151            "PagePoolStats",
1152            "AllocEmpty",
1153            self.orig_loc,
1154            self.buf.as_ptr() as usize,
1155        ))
1156    }
1157    pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
1158        let mut iter = self.clone();
1159        iter.pos = 0;
1160        for attr in iter {
1161            if let PagePoolStats::AllocRefill(val) = attr? {
1162                return Ok(val);
1163            }
1164        }
1165        Err(ErrorContext::new_missing(
1166            "PagePoolStats",
1167            "AllocRefill",
1168            self.orig_loc,
1169            self.buf.as_ptr() as usize,
1170        ))
1171    }
1172    pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
1173        let mut iter = self.clone();
1174        iter.pos = 0;
1175        for attr in iter {
1176            if let PagePoolStats::AllocWaive(val) = attr? {
1177                return Ok(val);
1178            }
1179        }
1180        Err(ErrorContext::new_missing(
1181            "PagePoolStats",
1182            "AllocWaive",
1183            self.orig_loc,
1184            self.buf.as_ptr() as usize,
1185        ))
1186    }
1187    pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
1188        let mut iter = self.clone();
1189        iter.pos = 0;
1190        for attr in iter {
1191            if let PagePoolStats::RecycleCached(val) = attr? {
1192                return Ok(val);
1193            }
1194        }
1195        Err(ErrorContext::new_missing(
1196            "PagePoolStats",
1197            "RecycleCached",
1198            self.orig_loc,
1199            self.buf.as_ptr() as usize,
1200        ))
1201    }
1202    pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
1203        let mut iter = self.clone();
1204        iter.pos = 0;
1205        for attr in iter {
1206            if let PagePoolStats::RecycleCacheFull(val) = attr? {
1207                return Ok(val);
1208            }
1209        }
1210        Err(ErrorContext::new_missing(
1211            "PagePoolStats",
1212            "RecycleCacheFull",
1213            self.orig_loc,
1214            self.buf.as_ptr() as usize,
1215        ))
1216    }
1217    pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
1218        let mut iter = self.clone();
1219        iter.pos = 0;
1220        for attr in iter {
1221            if let PagePoolStats::RecycleRing(val) = attr? {
1222                return Ok(val);
1223            }
1224        }
1225        Err(ErrorContext::new_missing(
1226            "PagePoolStats",
1227            "RecycleRing",
1228            self.orig_loc,
1229            self.buf.as_ptr() as usize,
1230        ))
1231    }
1232    pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
1233        let mut iter = self.clone();
1234        iter.pos = 0;
1235        for attr in iter {
1236            if let PagePoolStats::RecycleRingFull(val) = attr? {
1237                return Ok(val);
1238            }
1239        }
1240        Err(ErrorContext::new_missing(
1241            "PagePoolStats",
1242            "RecycleRingFull",
1243            self.orig_loc,
1244            self.buf.as_ptr() as usize,
1245        ))
1246    }
1247    pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
1248        let mut iter = self.clone();
1249        iter.pos = 0;
1250        for attr in iter {
1251            if let PagePoolStats::RecycleReleasedRefcnt(val) = attr? {
1252                return Ok(val);
1253            }
1254        }
1255        Err(ErrorContext::new_missing(
1256            "PagePoolStats",
1257            "RecycleReleasedRefcnt",
1258            self.orig_loc,
1259            self.buf.as_ptr() as usize,
1260        ))
1261    }
1262}
1263impl PagePoolStats<'_> {
1264    pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
1265        IterablePagePoolStats::with_loc(buf, buf.as_ptr() as usize)
1266    }
1267    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1268        let res = match r#type {
1269            1u16 => "Info",
1270            8u16 => "AllocFast",
1271            9u16 => "AllocSlow",
1272            10u16 => "AllocSlowHighOrder",
1273            11u16 => "AllocEmpty",
1274            12u16 => "AllocRefill",
1275            13u16 => "AllocWaive",
1276            14u16 => "RecycleCached",
1277            15u16 => "RecycleCacheFull",
1278            16u16 => "RecycleRing",
1279            17u16 => "RecycleRingFull",
1280            18u16 => "RecycleReleasedRefcnt",
1281            _ => return None,
1282        };
1283        Some(res)
1284    }
1285}
1286#[derive(Clone, Copy, Default)]
1287pub struct IterablePagePoolStats<'a> {
1288    buf: &'a [u8],
1289    pos: usize,
1290    orig_loc: usize,
1291}
1292impl<'a> IterablePagePoolStats<'a> {
1293    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1294        Self {
1295            buf,
1296            pos: 0,
1297            orig_loc,
1298        }
1299    }
1300    pub fn get_buf(&self) -> &'a [u8] {
1301        self.buf
1302    }
1303}
1304impl<'a> Iterator for IterablePagePoolStats<'a> {
1305    type Item = Result<PagePoolStats<'a>, ErrorContext>;
1306    fn next(&mut self) -> Option<Self::Item> {
1307        let pos = self.pos;
1308        let mut r#type;
1309        loop {
1310            r#type = None;
1311            if self.buf.len() == self.pos {
1312                return None;
1313            }
1314            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1315                break;
1316            };
1317            r#type = Some(header.r#type);
1318            let res = match header.r#type {
1319                1u16 => PagePoolStats::Info({
1320                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
1321                    let Some(val) = res else { break };
1322                    val
1323                }),
1324                8u16 => PagePoolStats::AllocFast({
1325                    let res = parse_u32(next);
1326                    let Some(val) = res else { break };
1327                    val
1328                }),
1329                9u16 => PagePoolStats::AllocSlow({
1330                    let res = parse_u32(next);
1331                    let Some(val) = res else { break };
1332                    val
1333                }),
1334                10u16 => PagePoolStats::AllocSlowHighOrder({
1335                    let res = parse_u32(next);
1336                    let Some(val) = res else { break };
1337                    val
1338                }),
1339                11u16 => PagePoolStats::AllocEmpty({
1340                    let res = parse_u32(next);
1341                    let Some(val) = res else { break };
1342                    val
1343                }),
1344                12u16 => PagePoolStats::AllocRefill({
1345                    let res = parse_u32(next);
1346                    let Some(val) = res else { break };
1347                    val
1348                }),
1349                13u16 => PagePoolStats::AllocWaive({
1350                    let res = parse_u32(next);
1351                    let Some(val) = res else { break };
1352                    val
1353                }),
1354                14u16 => PagePoolStats::RecycleCached({
1355                    let res = parse_u32(next);
1356                    let Some(val) = res else { break };
1357                    val
1358                }),
1359                15u16 => PagePoolStats::RecycleCacheFull({
1360                    let res = parse_u32(next);
1361                    let Some(val) = res else { break };
1362                    val
1363                }),
1364                16u16 => PagePoolStats::RecycleRing({
1365                    let res = parse_u32(next);
1366                    let Some(val) = res else { break };
1367                    val
1368                }),
1369                17u16 => PagePoolStats::RecycleRingFull({
1370                    let res = parse_u32(next);
1371                    let Some(val) = res else { break };
1372                    val
1373                }),
1374                18u16 => PagePoolStats::RecycleReleasedRefcnt({
1375                    let res = parse_u32(next);
1376                    let Some(val) = res else { break };
1377                    val
1378                }),
1379                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1380                n => continue,
1381            };
1382            return Some(Ok(res));
1383        }
1384        Some(Err(ErrorContext::new(
1385            "PagePoolStats",
1386            r#type.and_then(|t| PagePoolStats::attr_from_type(t)),
1387            self.orig_loc,
1388            self.buf.as_ptr().wrapping_add(pos) as usize,
1389        )))
1390    }
1391}
1392impl<'a> std::fmt::Debug for IterablePagePoolStats<'_> {
1393    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1394        let mut fmt = f.debug_struct("PagePoolStats");
1395        for attr in self.clone() {
1396            let attr = match attr {
1397                Ok(a) => a,
1398                Err(err) => {
1399                    fmt.finish()?;
1400                    f.write_str("Err(")?;
1401                    err.fmt(f)?;
1402                    return f.write_str(")");
1403                }
1404            };
1405            match attr {
1406                PagePoolStats::Info(val) => fmt.field("Info", &val),
1407                PagePoolStats::AllocFast(val) => fmt.field("AllocFast", &val),
1408                PagePoolStats::AllocSlow(val) => fmt.field("AllocSlow", &val),
1409                PagePoolStats::AllocSlowHighOrder(val) => fmt.field("AllocSlowHighOrder", &val),
1410                PagePoolStats::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
1411                PagePoolStats::AllocRefill(val) => fmt.field("AllocRefill", &val),
1412                PagePoolStats::AllocWaive(val) => fmt.field("AllocWaive", &val),
1413                PagePoolStats::RecycleCached(val) => fmt.field("RecycleCached", &val),
1414                PagePoolStats::RecycleCacheFull(val) => fmt.field("RecycleCacheFull", &val),
1415                PagePoolStats::RecycleRing(val) => fmt.field("RecycleRing", &val),
1416                PagePoolStats::RecycleRingFull(val) => fmt.field("RecycleRingFull", &val),
1417                PagePoolStats::RecycleReleasedRefcnt(val) => {
1418                    fmt.field("RecycleReleasedRefcnt", &val)
1419                }
1420            };
1421        }
1422        fmt.finish()
1423    }
1424}
1425impl IterablePagePoolStats<'_> {
1426    pub fn lookup_attr(
1427        &self,
1428        offset: usize,
1429        missing_type: Option<u16>,
1430    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1431        let mut stack = Vec::new();
1432        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1433        if cur == offset {
1434            stack.push(("PagePoolStats", offset));
1435            return (
1436                stack,
1437                missing_type.and_then(|t| PagePoolStats::attr_from_type(t)),
1438            );
1439        }
1440        if cur > offset || cur + self.buf.len() < offset {
1441            return (stack, None);
1442        }
1443        let mut attrs = self.clone();
1444        let mut last_off = cur + attrs.pos;
1445        let mut missing = None;
1446        while let Some(attr) = attrs.next() {
1447            let Ok(attr) = attr else { break };
1448            match attr {
1449                PagePoolStats::Info(val) => {
1450                    (stack, missing) = val.lookup_attr(offset, missing_type);
1451                    if !stack.is_empty() {
1452                        break;
1453                    }
1454                }
1455                PagePoolStats::AllocFast(val) => {
1456                    if last_off == offset {
1457                        stack.push(("AllocFast", last_off));
1458                        break;
1459                    }
1460                }
1461                PagePoolStats::AllocSlow(val) => {
1462                    if last_off == offset {
1463                        stack.push(("AllocSlow", last_off));
1464                        break;
1465                    }
1466                }
1467                PagePoolStats::AllocSlowHighOrder(val) => {
1468                    if last_off == offset {
1469                        stack.push(("AllocSlowHighOrder", last_off));
1470                        break;
1471                    }
1472                }
1473                PagePoolStats::AllocEmpty(val) => {
1474                    if last_off == offset {
1475                        stack.push(("AllocEmpty", last_off));
1476                        break;
1477                    }
1478                }
1479                PagePoolStats::AllocRefill(val) => {
1480                    if last_off == offset {
1481                        stack.push(("AllocRefill", last_off));
1482                        break;
1483                    }
1484                }
1485                PagePoolStats::AllocWaive(val) => {
1486                    if last_off == offset {
1487                        stack.push(("AllocWaive", last_off));
1488                        break;
1489                    }
1490                }
1491                PagePoolStats::RecycleCached(val) => {
1492                    if last_off == offset {
1493                        stack.push(("RecycleCached", last_off));
1494                        break;
1495                    }
1496                }
1497                PagePoolStats::RecycleCacheFull(val) => {
1498                    if last_off == offset {
1499                        stack.push(("RecycleCacheFull", last_off));
1500                        break;
1501                    }
1502                }
1503                PagePoolStats::RecycleRing(val) => {
1504                    if last_off == offset {
1505                        stack.push(("RecycleRing", last_off));
1506                        break;
1507                    }
1508                }
1509                PagePoolStats::RecycleRingFull(val) => {
1510                    if last_off == offset {
1511                        stack.push(("RecycleRingFull", last_off));
1512                        break;
1513                    }
1514                }
1515                PagePoolStats::RecycleReleasedRefcnt(val) => {
1516                    if last_off == offset {
1517                        stack.push(("RecycleReleasedRefcnt", last_off));
1518                        break;
1519                    }
1520                }
1521                _ => {}
1522            };
1523            last_off = cur + attrs.pos;
1524        }
1525        if !stack.is_empty() {
1526            stack.push(("PagePoolStats", cur));
1527        }
1528        (stack, missing)
1529    }
1530}
1531#[derive(Clone)]
1532pub enum Napi {
1533    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1534    Ifindex(u32),
1535    #[doc = "ID of the NAPI instance."]
1536    Id(u32),
1537    #[doc = "The associated interrupt vector number for the napi"]
1538    Irq(u32),
1539    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
1540    Pid(u32),
1541    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1542    DeferHardIrqs(u32),
1543    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
1544    GroFlushTimeout(u32),
1545    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1546    IrqSuspendTimeout(u32),
1547    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
1548    Threaded(u32),
1549}
1550impl<'a> IterableNapi<'a> {
1551    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1552    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1553        let mut iter = self.clone();
1554        iter.pos = 0;
1555        for attr in iter {
1556            if let Napi::Ifindex(val) = attr? {
1557                return Ok(val);
1558            }
1559        }
1560        Err(ErrorContext::new_missing(
1561            "Napi",
1562            "Ifindex",
1563            self.orig_loc,
1564            self.buf.as_ptr() as usize,
1565        ))
1566    }
1567    #[doc = "ID of the NAPI instance."]
1568    pub fn get_id(&self) -> Result<u32, ErrorContext> {
1569        let mut iter = self.clone();
1570        iter.pos = 0;
1571        for attr in iter {
1572            if let Napi::Id(val) = attr? {
1573                return Ok(val);
1574            }
1575        }
1576        Err(ErrorContext::new_missing(
1577            "Napi",
1578            "Id",
1579            self.orig_loc,
1580            self.buf.as_ptr() as usize,
1581        ))
1582    }
1583    #[doc = "The associated interrupt vector number for the napi"]
1584    pub fn get_irq(&self) -> Result<u32, ErrorContext> {
1585        let mut iter = self.clone();
1586        iter.pos = 0;
1587        for attr in iter {
1588            if let Napi::Irq(val) = attr? {
1589                return Ok(val);
1590            }
1591        }
1592        Err(ErrorContext::new_missing(
1593            "Napi",
1594            "Irq",
1595            self.orig_loc,
1596            self.buf.as_ptr() as usize,
1597        ))
1598    }
1599    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
1600    pub fn get_pid(&self) -> Result<u32, ErrorContext> {
1601        let mut iter = self.clone();
1602        iter.pos = 0;
1603        for attr in iter {
1604            if let Napi::Pid(val) = attr? {
1605                return Ok(val);
1606            }
1607        }
1608        Err(ErrorContext::new_missing(
1609            "Napi",
1610            "Pid",
1611            self.orig_loc,
1612            self.buf.as_ptr() as usize,
1613        ))
1614    }
1615    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1616    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
1617        let mut iter = self.clone();
1618        iter.pos = 0;
1619        for attr in iter {
1620            if let Napi::DeferHardIrqs(val) = attr? {
1621                return Ok(val);
1622            }
1623        }
1624        Err(ErrorContext::new_missing(
1625            "Napi",
1626            "DeferHardIrqs",
1627            self.orig_loc,
1628            self.buf.as_ptr() as usize,
1629        ))
1630    }
1631    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
1632    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
1633        let mut iter = self.clone();
1634        iter.pos = 0;
1635        for attr in iter {
1636            if let Napi::GroFlushTimeout(val) = attr? {
1637                return Ok(val);
1638            }
1639        }
1640        Err(ErrorContext::new_missing(
1641            "Napi",
1642            "GroFlushTimeout",
1643            self.orig_loc,
1644            self.buf.as_ptr() as usize,
1645        ))
1646    }
1647    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1648    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
1649        let mut iter = self.clone();
1650        iter.pos = 0;
1651        for attr in iter {
1652            if let Napi::IrqSuspendTimeout(val) = attr? {
1653                return Ok(val);
1654            }
1655        }
1656        Err(ErrorContext::new_missing(
1657            "Napi",
1658            "IrqSuspendTimeout",
1659            self.orig_loc,
1660            self.buf.as_ptr() as usize,
1661        ))
1662    }
1663    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
1664    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
1665        let mut iter = self.clone();
1666        iter.pos = 0;
1667        for attr in iter {
1668            if let Napi::Threaded(val) = attr? {
1669                return Ok(val);
1670            }
1671        }
1672        Err(ErrorContext::new_missing(
1673            "Napi",
1674            "Threaded",
1675            self.orig_loc,
1676            self.buf.as_ptr() as usize,
1677        ))
1678    }
1679}
1680impl Napi {
1681    pub fn new<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
1682        IterableNapi::with_loc(buf, buf.as_ptr() as usize)
1683    }
1684    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1685        let res = match r#type {
1686            1u16 => "Ifindex",
1687            2u16 => "Id",
1688            3u16 => "Irq",
1689            4u16 => "Pid",
1690            5u16 => "DeferHardIrqs",
1691            6u16 => "GroFlushTimeout",
1692            7u16 => "IrqSuspendTimeout",
1693            8u16 => "Threaded",
1694            _ => return None,
1695        };
1696        Some(res)
1697    }
1698}
1699#[derive(Clone, Copy, Default)]
1700pub struct IterableNapi<'a> {
1701    buf: &'a [u8],
1702    pos: usize,
1703    orig_loc: usize,
1704}
1705impl<'a> IterableNapi<'a> {
1706    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1707        Self {
1708            buf,
1709            pos: 0,
1710            orig_loc,
1711        }
1712    }
1713    pub fn get_buf(&self) -> &'a [u8] {
1714        self.buf
1715    }
1716}
1717impl<'a> Iterator for IterableNapi<'a> {
1718    type Item = Result<Napi, ErrorContext>;
1719    fn next(&mut self) -> Option<Self::Item> {
1720        let pos = self.pos;
1721        let mut r#type;
1722        loop {
1723            r#type = None;
1724            if self.buf.len() == self.pos {
1725                return None;
1726            }
1727            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1728                break;
1729            };
1730            r#type = Some(header.r#type);
1731            let res = match header.r#type {
1732                1u16 => Napi::Ifindex({
1733                    let res = parse_u32(next);
1734                    let Some(val) = res else { break };
1735                    val
1736                }),
1737                2u16 => Napi::Id({
1738                    let res = parse_u32(next);
1739                    let Some(val) = res else { break };
1740                    val
1741                }),
1742                3u16 => Napi::Irq({
1743                    let res = parse_u32(next);
1744                    let Some(val) = res else { break };
1745                    val
1746                }),
1747                4u16 => Napi::Pid({
1748                    let res = parse_u32(next);
1749                    let Some(val) = res else { break };
1750                    val
1751                }),
1752                5u16 => Napi::DeferHardIrqs({
1753                    let res = parse_u32(next);
1754                    let Some(val) = res else { break };
1755                    val
1756                }),
1757                6u16 => Napi::GroFlushTimeout({
1758                    let res = parse_u32(next);
1759                    let Some(val) = res else { break };
1760                    val
1761                }),
1762                7u16 => Napi::IrqSuspendTimeout({
1763                    let res = parse_u32(next);
1764                    let Some(val) = res else { break };
1765                    val
1766                }),
1767                8u16 => Napi::Threaded({
1768                    let res = parse_u32(next);
1769                    let Some(val) = res else { break };
1770                    val
1771                }),
1772                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1773                n => continue,
1774            };
1775            return Some(Ok(res));
1776        }
1777        Some(Err(ErrorContext::new(
1778            "Napi",
1779            r#type.and_then(|t| Napi::attr_from_type(t)),
1780            self.orig_loc,
1781            self.buf.as_ptr().wrapping_add(pos) as usize,
1782        )))
1783    }
1784}
1785impl std::fmt::Debug for IterableNapi<'_> {
1786    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1787        let mut fmt = f.debug_struct("Napi");
1788        for attr in self.clone() {
1789            let attr = match attr {
1790                Ok(a) => a,
1791                Err(err) => {
1792                    fmt.finish()?;
1793                    f.write_str("Err(")?;
1794                    err.fmt(f)?;
1795                    return f.write_str(")");
1796                }
1797            };
1798            match attr {
1799                Napi::Ifindex(val) => fmt.field("Ifindex", &val),
1800                Napi::Id(val) => fmt.field("Id", &val),
1801                Napi::Irq(val) => fmt.field("Irq", &val),
1802                Napi::Pid(val) => fmt.field("Pid", &val),
1803                Napi::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
1804                Napi::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
1805                Napi::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
1806                Napi::Threaded(val) => fmt.field(
1807                    "Threaded",
1808                    &FormatEnum(val.into(), NapiThreaded::from_value),
1809                ),
1810            };
1811        }
1812        fmt.finish()
1813    }
1814}
1815impl IterableNapi<'_> {
1816    pub fn lookup_attr(
1817        &self,
1818        offset: usize,
1819        missing_type: Option<u16>,
1820    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1821        let mut stack = Vec::new();
1822        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1823        if cur == offset {
1824            stack.push(("Napi", offset));
1825            return (stack, missing_type.and_then(|t| Napi::attr_from_type(t)));
1826        }
1827        if cur > offset || cur + self.buf.len() < offset {
1828            return (stack, None);
1829        }
1830        let mut attrs = self.clone();
1831        let mut last_off = cur + attrs.pos;
1832        while let Some(attr) = attrs.next() {
1833            let Ok(attr) = attr else { break };
1834            match attr {
1835                Napi::Ifindex(val) => {
1836                    if last_off == offset {
1837                        stack.push(("Ifindex", last_off));
1838                        break;
1839                    }
1840                }
1841                Napi::Id(val) => {
1842                    if last_off == offset {
1843                        stack.push(("Id", last_off));
1844                        break;
1845                    }
1846                }
1847                Napi::Irq(val) => {
1848                    if last_off == offset {
1849                        stack.push(("Irq", last_off));
1850                        break;
1851                    }
1852                }
1853                Napi::Pid(val) => {
1854                    if last_off == offset {
1855                        stack.push(("Pid", last_off));
1856                        break;
1857                    }
1858                }
1859                Napi::DeferHardIrqs(val) => {
1860                    if last_off == offset {
1861                        stack.push(("DeferHardIrqs", last_off));
1862                        break;
1863                    }
1864                }
1865                Napi::GroFlushTimeout(val) => {
1866                    if last_off == offset {
1867                        stack.push(("GroFlushTimeout", last_off));
1868                        break;
1869                    }
1870                }
1871                Napi::IrqSuspendTimeout(val) => {
1872                    if last_off == offset {
1873                        stack.push(("IrqSuspendTimeout", last_off));
1874                        break;
1875                    }
1876                }
1877                Napi::Threaded(val) => {
1878                    if last_off == offset {
1879                        stack.push(("Threaded", last_off));
1880                        break;
1881                    }
1882                }
1883                _ => {}
1884            };
1885            last_off = cur + attrs.pos;
1886        }
1887        if !stack.is_empty() {
1888            stack.push(("Napi", cur));
1889        }
1890        (stack, None)
1891    }
1892}
1893#[derive(Clone)]
1894pub enum XskInfo {}
1895impl<'a> IterableXskInfo<'a> {}
1896impl XskInfo {
1897    pub fn new<'a>(buf: &'a [u8]) -> IterableXskInfo<'a> {
1898        IterableXskInfo::with_loc(buf, buf.as_ptr() as usize)
1899    }
1900    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1901        None
1902    }
1903}
1904#[derive(Clone, Copy, Default)]
1905pub struct IterableXskInfo<'a> {
1906    buf: &'a [u8],
1907    pos: usize,
1908    orig_loc: usize,
1909}
1910impl<'a> IterableXskInfo<'a> {
1911    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1912        Self {
1913            buf,
1914            pos: 0,
1915            orig_loc,
1916        }
1917    }
1918    pub fn get_buf(&self) -> &'a [u8] {
1919        self.buf
1920    }
1921}
1922impl<'a> Iterator for IterableXskInfo<'a> {
1923    type Item = Result<XskInfo, ErrorContext>;
1924    fn next(&mut self) -> Option<Self::Item> {
1925        let pos = self.pos;
1926        let mut r#type;
1927        loop {
1928            r#type = None;
1929            if self.buf.len() == self.pos {
1930                return None;
1931            }
1932            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1933                break;
1934            };
1935            r#type = Some(header.r#type);
1936            let res = match header.r#type {
1937                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1938                n => continue,
1939            };
1940            return Some(Ok(res));
1941        }
1942        Some(Err(ErrorContext::new(
1943            "XskInfo",
1944            r#type.and_then(|t| XskInfo::attr_from_type(t)),
1945            self.orig_loc,
1946            self.buf.as_ptr().wrapping_add(pos) as usize,
1947        )))
1948    }
1949}
1950impl std::fmt::Debug for IterableXskInfo<'_> {
1951    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1952        let mut fmt = f.debug_struct("XskInfo");
1953        for attr in self.clone() {
1954            let attr = match attr {
1955                Ok(a) => a,
1956                Err(err) => {
1957                    fmt.finish()?;
1958                    f.write_str("Err(")?;
1959                    err.fmt(f)?;
1960                    return f.write_str(")");
1961                }
1962            };
1963            match attr {};
1964        }
1965        fmt.finish()
1966    }
1967}
1968impl IterableXskInfo<'_> {
1969    pub fn lookup_attr(
1970        &self,
1971        offset: usize,
1972        missing_type: Option<u16>,
1973    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1974        let mut stack = Vec::new();
1975        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1976        if cur == offset {
1977            stack.push(("XskInfo", offset));
1978            return (stack, missing_type.and_then(|t| XskInfo::attr_from_type(t)));
1979        }
1980        (stack, None)
1981    }
1982}
1983#[derive(Clone)]
1984pub enum Queue<'a> {
1985    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
1986    Id(u32),
1987    #[doc = "ifindex of the netdevice to which the queue belongs."]
1988    Ifindex(u32),
1989    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
1990    Type(u32),
1991    #[doc = "ID of the NAPI instance which services this queue."]
1992    NapiId(u32),
1993    #[doc = "ID of the dmabuf attached to this queue, if any."]
1994    Dmabuf(u32),
1995    #[doc = "io_uring memory provider information."]
1996    IoUring(IterableIoUringProviderInfo<'a>),
1997    #[doc = "XSK information for this queue, if any."]
1998    Xsk(IterableXskInfo<'a>),
1999}
2000impl<'a> IterableQueue<'a> {
2001    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
2002    pub fn get_id(&self) -> Result<u32, ErrorContext> {
2003        let mut iter = self.clone();
2004        iter.pos = 0;
2005        for attr in iter {
2006            if let Queue::Id(val) = attr? {
2007                return Ok(val);
2008            }
2009        }
2010        Err(ErrorContext::new_missing(
2011            "Queue",
2012            "Id",
2013            self.orig_loc,
2014            self.buf.as_ptr() as usize,
2015        ))
2016    }
2017    #[doc = "ifindex of the netdevice to which the queue belongs."]
2018    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2019        let mut iter = self.clone();
2020        iter.pos = 0;
2021        for attr in iter {
2022            if let Queue::Ifindex(val) = attr? {
2023                return Ok(val);
2024            }
2025        }
2026        Err(ErrorContext::new_missing(
2027            "Queue",
2028            "Ifindex",
2029            self.orig_loc,
2030            self.buf.as_ptr() as usize,
2031        ))
2032    }
2033    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
2034    pub fn get_type(&self) -> Result<u32, ErrorContext> {
2035        let mut iter = self.clone();
2036        iter.pos = 0;
2037        for attr in iter {
2038            if let Queue::Type(val) = attr? {
2039                return Ok(val);
2040            }
2041        }
2042        Err(ErrorContext::new_missing(
2043            "Queue",
2044            "Type",
2045            self.orig_loc,
2046            self.buf.as_ptr() as usize,
2047        ))
2048    }
2049    #[doc = "ID of the NAPI instance which services this queue."]
2050    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
2051        let mut iter = self.clone();
2052        iter.pos = 0;
2053        for attr in iter {
2054            if let Queue::NapiId(val) = attr? {
2055                return Ok(val);
2056            }
2057        }
2058        Err(ErrorContext::new_missing(
2059            "Queue",
2060            "NapiId",
2061            self.orig_loc,
2062            self.buf.as_ptr() as usize,
2063        ))
2064    }
2065    #[doc = "ID of the dmabuf attached to this queue, if any."]
2066    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
2067        let mut iter = self.clone();
2068        iter.pos = 0;
2069        for attr in iter {
2070            if let Queue::Dmabuf(val) = attr? {
2071                return Ok(val);
2072            }
2073        }
2074        Err(ErrorContext::new_missing(
2075            "Queue",
2076            "Dmabuf",
2077            self.orig_loc,
2078            self.buf.as_ptr() as usize,
2079        ))
2080    }
2081    #[doc = "io_uring memory provider information."]
2082    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
2083        let mut iter = self.clone();
2084        iter.pos = 0;
2085        for attr in iter {
2086            if let Queue::IoUring(val) = attr? {
2087                return Ok(val);
2088            }
2089        }
2090        Err(ErrorContext::new_missing(
2091            "Queue",
2092            "IoUring",
2093            self.orig_loc,
2094            self.buf.as_ptr() as usize,
2095        ))
2096    }
2097    #[doc = "XSK information for this queue, if any."]
2098    pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
2099        let mut iter = self.clone();
2100        iter.pos = 0;
2101        for attr in iter {
2102            if let Queue::Xsk(val) = attr? {
2103                return Ok(val);
2104            }
2105        }
2106        Err(ErrorContext::new_missing(
2107            "Queue",
2108            "Xsk",
2109            self.orig_loc,
2110            self.buf.as_ptr() as usize,
2111        ))
2112    }
2113}
2114impl Queue<'_> {
2115    pub fn new<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
2116        IterableQueue::with_loc(buf, buf.as_ptr() as usize)
2117    }
2118    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2119        let res = match r#type {
2120            1u16 => "Id",
2121            2u16 => "Ifindex",
2122            3u16 => "Type",
2123            4u16 => "NapiId",
2124            5u16 => "Dmabuf",
2125            6u16 => "IoUring",
2126            7u16 => "Xsk",
2127            _ => return None,
2128        };
2129        Some(res)
2130    }
2131}
2132#[derive(Clone, Copy, Default)]
2133pub struct IterableQueue<'a> {
2134    buf: &'a [u8],
2135    pos: usize,
2136    orig_loc: usize,
2137}
2138impl<'a> IterableQueue<'a> {
2139    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2140        Self {
2141            buf,
2142            pos: 0,
2143            orig_loc,
2144        }
2145    }
2146    pub fn get_buf(&self) -> &'a [u8] {
2147        self.buf
2148    }
2149}
2150impl<'a> Iterator for IterableQueue<'a> {
2151    type Item = Result<Queue<'a>, ErrorContext>;
2152    fn next(&mut self) -> Option<Self::Item> {
2153        let pos = self.pos;
2154        let mut r#type;
2155        loop {
2156            r#type = None;
2157            if self.buf.len() == self.pos {
2158                return None;
2159            }
2160            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2161                break;
2162            };
2163            r#type = Some(header.r#type);
2164            let res = match header.r#type {
2165                1u16 => Queue::Id({
2166                    let res = parse_u32(next);
2167                    let Some(val) = res else { break };
2168                    val
2169                }),
2170                2u16 => Queue::Ifindex({
2171                    let res = parse_u32(next);
2172                    let Some(val) = res else { break };
2173                    val
2174                }),
2175                3u16 => Queue::Type({
2176                    let res = parse_u32(next);
2177                    let Some(val) = res else { break };
2178                    val
2179                }),
2180                4u16 => Queue::NapiId({
2181                    let res = parse_u32(next);
2182                    let Some(val) = res else { break };
2183                    val
2184                }),
2185                5u16 => Queue::Dmabuf({
2186                    let res = parse_u32(next);
2187                    let Some(val) = res else { break };
2188                    val
2189                }),
2190                6u16 => Queue::IoUring({
2191                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
2192                    let Some(val) = res else { break };
2193                    val
2194                }),
2195                7u16 => Queue::Xsk({
2196                    let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
2197                    let Some(val) = res else { break };
2198                    val
2199                }),
2200                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2201                n => continue,
2202            };
2203            return Some(Ok(res));
2204        }
2205        Some(Err(ErrorContext::new(
2206            "Queue",
2207            r#type.and_then(|t| Queue::attr_from_type(t)),
2208            self.orig_loc,
2209            self.buf.as_ptr().wrapping_add(pos) as usize,
2210        )))
2211    }
2212}
2213impl<'a> std::fmt::Debug for IterableQueue<'_> {
2214    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2215        let mut fmt = f.debug_struct("Queue");
2216        for attr in self.clone() {
2217            let attr = match attr {
2218                Ok(a) => a,
2219                Err(err) => {
2220                    fmt.finish()?;
2221                    f.write_str("Err(")?;
2222                    err.fmt(f)?;
2223                    return f.write_str(")");
2224                }
2225            };
2226            match attr {
2227                Queue::Id(val) => fmt.field("Id", &val),
2228                Queue::Ifindex(val) => fmt.field("Ifindex", &val),
2229                Queue::Type(val) => {
2230                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
2231                }
2232                Queue::NapiId(val) => fmt.field("NapiId", &val),
2233                Queue::Dmabuf(val) => fmt.field("Dmabuf", &val),
2234                Queue::IoUring(val) => fmt.field("IoUring", &val),
2235                Queue::Xsk(val) => fmt.field("Xsk", &val),
2236            };
2237        }
2238        fmt.finish()
2239    }
2240}
2241impl IterableQueue<'_> {
2242    pub fn lookup_attr(
2243        &self,
2244        offset: usize,
2245        missing_type: Option<u16>,
2246    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2247        let mut stack = Vec::new();
2248        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2249        if cur == offset {
2250            stack.push(("Queue", offset));
2251            return (stack, missing_type.and_then(|t| Queue::attr_from_type(t)));
2252        }
2253        if cur > offset || cur + self.buf.len() < offset {
2254            return (stack, None);
2255        }
2256        let mut attrs = self.clone();
2257        let mut last_off = cur + attrs.pos;
2258        let mut missing = None;
2259        while let Some(attr) = attrs.next() {
2260            let Ok(attr) = attr else { break };
2261            match attr {
2262                Queue::Id(val) => {
2263                    if last_off == offset {
2264                        stack.push(("Id", last_off));
2265                        break;
2266                    }
2267                }
2268                Queue::Ifindex(val) => {
2269                    if last_off == offset {
2270                        stack.push(("Ifindex", last_off));
2271                        break;
2272                    }
2273                }
2274                Queue::Type(val) => {
2275                    if last_off == offset {
2276                        stack.push(("Type", last_off));
2277                        break;
2278                    }
2279                }
2280                Queue::NapiId(val) => {
2281                    if last_off == offset {
2282                        stack.push(("NapiId", last_off));
2283                        break;
2284                    }
2285                }
2286                Queue::Dmabuf(val) => {
2287                    if last_off == offset {
2288                        stack.push(("Dmabuf", last_off));
2289                        break;
2290                    }
2291                }
2292                Queue::IoUring(val) => {
2293                    (stack, missing) = val.lookup_attr(offset, missing_type);
2294                    if !stack.is_empty() {
2295                        break;
2296                    }
2297                }
2298                Queue::Xsk(val) => {
2299                    (stack, missing) = val.lookup_attr(offset, missing_type);
2300                    if !stack.is_empty() {
2301                        break;
2302                    }
2303                }
2304                _ => {}
2305            };
2306            last_off = cur + attrs.pos;
2307        }
2308        if !stack.is_empty() {
2309            stack.push(("Queue", cur));
2310        }
2311        (stack, missing)
2312    }
2313}
2314#[derive(Clone)]
2315pub enum Qstats {
2316    #[doc = "ifindex of the netdevice to which stats belong."]
2317    Ifindex(u32),
2318    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2319    QueueType(u32),
2320    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2321    QueueId(u32),
2322    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2323    Scope(u32),
2324    #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
2325    RxPackets(u32),
2326    #[doc = "Successfully received bytes, see `rx-packets`."]
2327    RxBytes(u32),
2328    #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
2329    TxPackets(u32),
2330    #[doc = "Successfully sent bytes, see `tx-packets`."]
2331    TxBytes(u32),
2332    #[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\non driver implementation and whether system recovers quickly.\n"]
2333    RxAllocFail(u32),
2334    #[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"]
2335    RxHwDrops(u32),
2336    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2337    RxHwDropOverruns(u32),
2338    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2339    RxCsumComplete(u32),
2340    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2341    RxCsumUnnecessary(u32),
2342    #[doc = "Number of packets that were not checksummed by device."]
2343    RxCsumNone(u32),
2344    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2345    RxCsumBad(u32),
2346    #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
2347    RxHwGroPackets(u32),
2348    #[doc = "See `rx-hw-gro-packets`."]
2349    RxHwGroBytes(u32),
2350    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2351    RxHwGroWirePackets(u32),
2352    #[doc = "See `rx-hw-gro-wire-packets`."]
2353    RxHwGroWireBytes(u32),
2354    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2355    RxHwDropRatelimits(u32),
2356    #[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"]
2357    TxHwDrops(u32),
2358    #[doc = "Number of packets dropped because they were invalid or malformed."]
2359    TxHwDropErrors(u32),
2360    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2361    TxCsumNone(u32),
2362    #[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"]
2363    TxNeedsCsum(u32),
2364    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2365    TxHwGsoPackets(u32),
2366    #[doc = "See `tx-hw-gso-packets`."]
2367    TxHwGsoBytes(u32),
2368    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2369    TxHwGsoWirePackets(u32),
2370    #[doc = "See `tx-hw-gso-wire-packets`."]
2371    TxHwGsoWireBytes(u32),
2372    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2373    TxHwDropRatelimits(u32),
2374    #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
2375    TxStop(u32),
2376    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2377    TxWake(u32),
2378}
2379impl<'a> IterableQstats<'a> {
2380    #[doc = "ifindex of the netdevice to which stats belong."]
2381    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2382        let mut iter = self.clone();
2383        iter.pos = 0;
2384        for attr in iter {
2385            if let Qstats::Ifindex(val) = attr? {
2386                return Ok(val);
2387            }
2388        }
2389        Err(ErrorContext::new_missing(
2390            "Qstats",
2391            "Ifindex",
2392            self.orig_loc,
2393            self.buf.as_ptr() as usize,
2394        ))
2395    }
2396    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2397    pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
2398        let mut iter = self.clone();
2399        iter.pos = 0;
2400        for attr in iter {
2401            if let Qstats::QueueType(val) = attr? {
2402                return Ok(val);
2403            }
2404        }
2405        Err(ErrorContext::new_missing(
2406            "Qstats",
2407            "QueueType",
2408            self.orig_loc,
2409            self.buf.as_ptr() as usize,
2410        ))
2411    }
2412    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2413    pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
2414        let mut iter = self.clone();
2415        iter.pos = 0;
2416        for attr in iter {
2417            if let Qstats::QueueId(val) = attr? {
2418                return Ok(val);
2419            }
2420        }
2421        Err(ErrorContext::new_missing(
2422            "Qstats",
2423            "QueueId",
2424            self.orig_loc,
2425            self.buf.as_ptr() as usize,
2426        ))
2427    }
2428    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2429    pub fn get_scope(&self) -> Result<u32, ErrorContext> {
2430        let mut iter = self.clone();
2431        iter.pos = 0;
2432        for attr in iter {
2433            if let Qstats::Scope(val) = attr? {
2434                return Ok(val);
2435            }
2436        }
2437        Err(ErrorContext::new_missing(
2438            "Qstats",
2439            "Scope",
2440            self.orig_loc,
2441            self.buf.as_ptr() as usize,
2442        ))
2443    }
2444    #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
2445    pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
2446        let mut iter = self.clone();
2447        iter.pos = 0;
2448        for attr in iter {
2449            if let Qstats::RxPackets(val) = attr? {
2450                return Ok(val);
2451            }
2452        }
2453        Err(ErrorContext::new_missing(
2454            "Qstats",
2455            "RxPackets",
2456            self.orig_loc,
2457            self.buf.as_ptr() as usize,
2458        ))
2459    }
2460    #[doc = "Successfully received bytes, see `rx-packets`."]
2461    pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
2462        let mut iter = self.clone();
2463        iter.pos = 0;
2464        for attr in iter {
2465            if let Qstats::RxBytes(val) = attr? {
2466                return Ok(val);
2467            }
2468        }
2469        Err(ErrorContext::new_missing(
2470            "Qstats",
2471            "RxBytes",
2472            self.orig_loc,
2473            self.buf.as_ptr() as usize,
2474        ))
2475    }
2476    #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
2477    pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
2478        let mut iter = self.clone();
2479        iter.pos = 0;
2480        for attr in iter {
2481            if let Qstats::TxPackets(val) = attr? {
2482                return Ok(val);
2483            }
2484        }
2485        Err(ErrorContext::new_missing(
2486            "Qstats",
2487            "TxPackets",
2488            self.orig_loc,
2489            self.buf.as_ptr() as usize,
2490        ))
2491    }
2492    #[doc = "Successfully sent bytes, see `tx-packets`."]
2493    pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
2494        let mut iter = self.clone();
2495        iter.pos = 0;
2496        for attr in iter {
2497            if let Qstats::TxBytes(val) = attr? {
2498                return Ok(val);
2499            }
2500        }
2501        Err(ErrorContext::new_missing(
2502            "Qstats",
2503            "TxBytes",
2504            self.orig_loc,
2505            self.buf.as_ptr() as usize,
2506        ))
2507    }
2508    #[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\non driver implementation and whether system recovers quickly.\n"]
2509    pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
2510        let mut iter = self.clone();
2511        iter.pos = 0;
2512        for attr in iter {
2513            if let Qstats::RxAllocFail(val) = attr? {
2514                return Ok(val);
2515            }
2516        }
2517        Err(ErrorContext::new_missing(
2518            "Qstats",
2519            "RxAllocFail",
2520            self.orig_loc,
2521            self.buf.as_ptr() as usize,
2522        ))
2523    }
2524    #[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"]
2525    pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
2526        let mut iter = self.clone();
2527        iter.pos = 0;
2528        for attr in iter {
2529            if let Qstats::RxHwDrops(val) = attr? {
2530                return Ok(val);
2531            }
2532        }
2533        Err(ErrorContext::new_missing(
2534            "Qstats",
2535            "RxHwDrops",
2536            self.orig_loc,
2537            self.buf.as_ptr() as usize,
2538        ))
2539    }
2540    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2541    pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
2542        let mut iter = self.clone();
2543        iter.pos = 0;
2544        for attr in iter {
2545            if let Qstats::RxHwDropOverruns(val) = attr? {
2546                return Ok(val);
2547            }
2548        }
2549        Err(ErrorContext::new_missing(
2550            "Qstats",
2551            "RxHwDropOverruns",
2552            self.orig_loc,
2553            self.buf.as_ptr() as usize,
2554        ))
2555    }
2556    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2557    pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
2558        let mut iter = self.clone();
2559        iter.pos = 0;
2560        for attr in iter {
2561            if let Qstats::RxCsumComplete(val) = attr? {
2562                return Ok(val);
2563            }
2564        }
2565        Err(ErrorContext::new_missing(
2566            "Qstats",
2567            "RxCsumComplete",
2568            self.orig_loc,
2569            self.buf.as_ptr() as usize,
2570        ))
2571    }
2572    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2573    pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
2574        let mut iter = self.clone();
2575        iter.pos = 0;
2576        for attr in iter {
2577            if let Qstats::RxCsumUnnecessary(val) = attr? {
2578                return Ok(val);
2579            }
2580        }
2581        Err(ErrorContext::new_missing(
2582            "Qstats",
2583            "RxCsumUnnecessary",
2584            self.orig_loc,
2585            self.buf.as_ptr() as usize,
2586        ))
2587    }
2588    #[doc = "Number of packets that were not checksummed by device."]
2589    pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
2590        let mut iter = self.clone();
2591        iter.pos = 0;
2592        for attr in iter {
2593            if let Qstats::RxCsumNone(val) = attr? {
2594                return Ok(val);
2595            }
2596        }
2597        Err(ErrorContext::new_missing(
2598            "Qstats",
2599            "RxCsumNone",
2600            self.orig_loc,
2601            self.buf.as_ptr() as usize,
2602        ))
2603    }
2604    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2605    pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
2606        let mut iter = self.clone();
2607        iter.pos = 0;
2608        for attr in iter {
2609            if let Qstats::RxCsumBad(val) = attr? {
2610                return Ok(val);
2611            }
2612        }
2613        Err(ErrorContext::new_missing(
2614            "Qstats",
2615            "RxCsumBad",
2616            self.orig_loc,
2617            self.buf.as_ptr() as usize,
2618        ))
2619    }
2620    #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
2621    pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
2622        let mut iter = self.clone();
2623        iter.pos = 0;
2624        for attr in iter {
2625            if let Qstats::RxHwGroPackets(val) = attr? {
2626                return Ok(val);
2627            }
2628        }
2629        Err(ErrorContext::new_missing(
2630            "Qstats",
2631            "RxHwGroPackets",
2632            self.orig_loc,
2633            self.buf.as_ptr() as usize,
2634        ))
2635    }
2636    #[doc = "See `rx-hw-gro-packets`."]
2637    pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
2638        let mut iter = self.clone();
2639        iter.pos = 0;
2640        for attr in iter {
2641            if let Qstats::RxHwGroBytes(val) = attr? {
2642                return Ok(val);
2643            }
2644        }
2645        Err(ErrorContext::new_missing(
2646            "Qstats",
2647            "RxHwGroBytes",
2648            self.orig_loc,
2649            self.buf.as_ptr() as usize,
2650        ))
2651    }
2652    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2653    pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
2654        let mut iter = self.clone();
2655        iter.pos = 0;
2656        for attr in iter {
2657            if let Qstats::RxHwGroWirePackets(val) = attr? {
2658                return Ok(val);
2659            }
2660        }
2661        Err(ErrorContext::new_missing(
2662            "Qstats",
2663            "RxHwGroWirePackets",
2664            self.orig_loc,
2665            self.buf.as_ptr() as usize,
2666        ))
2667    }
2668    #[doc = "See `rx-hw-gro-wire-packets`."]
2669    pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
2670        let mut iter = self.clone();
2671        iter.pos = 0;
2672        for attr in iter {
2673            if let Qstats::RxHwGroWireBytes(val) = attr? {
2674                return Ok(val);
2675            }
2676        }
2677        Err(ErrorContext::new_missing(
2678            "Qstats",
2679            "RxHwGroWireBytes",
2680            self.orig_loc,
2681            self.buf.as_ptr() as usize,
2682        ))
2683    }
2684    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2685    pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2686        let mut iter = self.clone();
2687        iter.pos = 0;
2688        for attr in iter {
2689            if let Qstats::RxHwDropRatelimits(val) = attr? {
2690                return Ok(val);
2691            }
2692        }
2693        Err(ErrorContext::new_missing(
2694            "Qstats",
2695            "RxHwDropRatelimits",
2696            self.orig_loc,
2697            self.buf.as_ptr() as usize,
2698        ))
2699    }
2700    #[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"]
2701    pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
2702        let mut iter = self.clone();
2703        iter.pos = 0;
2704        for attr in iter {
2705            if let Qstats::TxHwDrops(val) = attr? {
2706                return Ok(val);
2707            }
2708        }
2709        Err(ErrorContext::new_missing(
2710            "Qstats",
2711            "TxHwDrops",
2712            self.orig_loc,
2713            self.buf.as_ptr() as usize,
2714        ))
2715    }
2716    #[doc = "Number of packets dropped because they were invalid or malformed."]
2717    pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
2718        let mut iter = self.clone();
2719        iter.pos = 0;
2720        for attr in iter {
2721            if let Qstats::TxHwDropErrors(val) = attr? {
2722                return Ok(val);
2723            }
2724        }
2725        Err(ErrorContext::new_missing(
2726            "Qstats",
2727            "TxHwDropErrors",
2728            self.orig_loc,
2729            self.buf.as_ptr() as usize,
2730        ))
2731    }
2732    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2733    pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
2734        let mut iter = self.clone();
2735        iter.pos = 0;
2736        for attr in iter {
2737            if let Qstats::TxCsumNone(val) = attr? {
2738                return Ok(val);
2739            }
2740        }
2741        Err(ErrorContext::new_missing(
2742            "Qstats",
2743            "TxCsumNone",
2744            self.orig_loc,
2745            self.buf.as_ptr() as usize,
2746        ))
2747    }
2748    #[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"]
2749    pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
2750        let mut iter = self.clone();
2751        iter.pos = 0;
2752        for attr in iter {
2753            if let Qstats::TxNeedsCsum(val) = attr? {
2754                return Ok(val);
2755            }
2756        }
2757        Err(ErrorContext::new_missing(
2758            "Qstats",
2759            "TxNeedsCsum",
2760            self.orig_loc,
2761            self.buf.as_ptr() as usize,
2762        ))
2763    }
2764    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2765    pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
2766        let mut iter = self.clone();
2767        iter.pos = 0;
2768        for attr in iter {
2769            if let Qstats::TxHwGsoPackets(val) = attr? {
2770                return Ok(val);
2771            }
2772        }
2773        Err(ErrorContext::new_missing(
2774            "Qstats",
2775            "TxHwGsoPackets",
2776            self.orig_loc,
2777            self.buf.as_ptr() as usize,
2778        ))
2779    }
2780    #[doc = "See `tx-hw-gso-packets`."]
2781    pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
2782        let mut iter = self.clone();
2783        iter.pos = 0;
2784        for attr in iter {
2785            if let Qstats::TxHwGsoBytes(val) = attr? {
2786                return Ok(val);
2787            }
2788        }
2789        Err(ErrorContext::new_missing(
2790            "Qstats",
2791            "TxHwGsoBytes",
2792            self.orig_loc,
2793            self.buf.as_ptr() as usize,
2794        ))
2795    }
2796    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2797    pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
2798        let mut iter = self.clone();
2799        iter.pos = 0;
2800        for attr in iter {
2801            if let Qstats::TxHwGsoWirePackets(val) = attr? {
2802                return Ok(val);
2803            }
2804        }
2805        Err(ErrorContext::new_missing(
2806            "Qstats",
2807            "TxHwGsoWirePackets",
2808            self.orig_loc,
2809            self.buf.as_ptr() as usize,
2810        ))
2811    }
2812    #[doc = "See `tx-hw-gso-wire-packets`."]
2813    pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
2814        let mut iter = self.clone();
2815        iter.pos = 0;
2816        for attr in iter {
2817            if let Qstats::TxHwGsoWireBytes(val) = attr? {
2818                return Ok(val);
2819            }
2820        }
2821        Err(ErrorContext::new_missing(
2822            "Qstats",
2823            "TxHwGsoWireBytes",
2824            self.orig_loc,
2825            self.buf.as_ptr() as usize,
2826        ))
2827    }
2828    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2829    pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2830        let mut iter = self.clone();
2831        iter.pos = 0;
2832        for attr in iter {
2833            if let Qstats::TxHwDropRatelimits(val) = attr? {
2834                return Ok(val);
2835            }
2836        }
2837        Err(ErrorContext::new_missing(
2838            "Qstats",
2839            "TxHwDropRatelimits",
2840            self.orig_loc,
2841            self.buf.as_ptr() as usize,
2842        ))
2843    }
2844    #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
2845    pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
2846        let mut iter = self.clone();
2847        iter.pos = 0;
2848        for attr in iter {
2849            if let Qstats::TxStop(val) = attr? {
2850                return Ok(val);
2851            }
2852        }
2853        Err(ErrorContext::new_missing(
2854            "Qstats",
2855            "TxStop",
2856            self.orig_loc,
2857            self.buf.as_ptr() as usize,
2858        ))
2859    }
2860    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2861    pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
2862        let mut iter = self.clone();
2863        iter.pos = 0;
2864        for attr in iter {
2865            if let Qstats::TxWake(val) = attr? {
2866                return Ok(val);
2867            }
2868        }
2869        Err(ErrorContext::new_missing(
2870            "Qstats",
2871            "TxWake",
2872            self.orig_loc,
2873            self.buf.as_ptr() as usize,
2874        ))
2875    }
2876}
2877impl Qstats {
2878    pub fn new<'a>(buf: &'a [u8]) -> IterableQstats<'a> {
2879        IterableQstats::with_loc(buf, buf.as_ptr() as usize)
2880    }
2881    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2882        let res = match r#type {
2883            1u16 => "Ifindex",
2884            2u16 => "QueueType",
2885            3u16 => "QueueId",
2886            4u16 => "Scope",
2887            8u16 => "RxPackets",
2888            9u16 => "RxBytes",
2889            10u16 => "TxPackets",
2890            11u16 => "TxBytes",
2891            12u16 => "RxAllocFail",
2892            13u16 => "RxHwDrops",
2893            14u16 => "RxHwDropOverruns",
2894            15u16 => "RxCsumComplete",
2895            16u16 => "RxCsumUnnecessary",
2896            17u16 => "RxCsumNone",
2897            18u16 => "RxCsumBad",
2898            19u16 => "RxHwGroPackets",
2899            20u16 => "RxHwGroBytes",
2900            21u16 => "RxHwGroWirePackets",
2901            22u16 => "RxHwGroWireBytes",
2902            23u16 => "RxHwDropRatelimits",
2903            24u16 => "TxHwDrops",
2904            25u16 => "TxHwDropErrors",
2905            26u16 => "TxCsumNone",
2906            27u16 => "TxNeedsCsum",
2907            28u16 => "TxHwGsoPackets",
2908            29u16 => "TxHwGsoBytes",
2909            30u16 => "TxHwGsoWirePackets",
2910            31u16 => "TxHwGsoWireBytes",
2911            32u16 => "TxHwDropRatelimits",
2912            33u16 => "TxStop",
2913            34u16 => "TxWake",
2914            _ => return None,
2915        };
2916        Some(res)
2917    }
2918}
2919#[derive(Clone, Copy, Default)]
2920pub struct IterableQstats<'a> {
2921    buf: &'a [u8],
2922    pos: usize,
2923    orig_loc: usize,
2924}
2925impl<'a> IterableQstats<'a> {
2926    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2927        Self {
2928            buf,
2929            pos: 0,
2930            orig_loc,
2931        }
2932    }
2933    pub fn get_buf(&self) -> &'a [u8] {
2934        self.buf
2935    }
2936}
2937impl<'a> Iterator for IterableQstats<'a> {
2938    type Item = Result<Qstats, ErrorContext>;
2939    fn next(&mut self) -> Option<Self::Item> {
2940        let pos = self.pos;
2941        let mut r#type;
2942        loop {
2943            r#type = None;
2944            if self.buf.len() == self.pos {
2945                return None;
2946            }
2947            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2948                break;
2949            };
2950            r#type = Some(header.r#type);
2951            let res = match header.r#type {
2952                1u16 => Qstats::Ifindex({
2953                    let res = parse_u32(next);
2954                    let Some(val) = res else { break };
2955                    val
2956                }),
2957                2u16 => Qstats::QueueType({
2958                    let res = parse_u32(next);
2959                    let Some(val) = res else { break };
2960                    val
2961                }),
2962                3u16 => Qstats::QueueId({
2963                    let res = parse_u32(next);
2964                    let Some(val) = res else { break };
2965                    val
2966                }),
2967                4u16 => Qstats::Scope({
2968                    let res = parse_u32(next);
2969                    let Some(val) = res else { break };
2970                    val
2971                }),
2972                8u16 => Qstats::RxPackets({
2973                    let res = parse_u32(next);
2974                    let Some(val) = res else { break };
2975                    val
2976                }),
2977                9u16 => Qstats::RxBytes({
2978                    let res = parse_u32(next);
2979                    let Some(val) = res else { break };
2980                    val
2981                }),
2982                10u16 => Qstats::TxPackets({
2983                    let res = parse_u32(next);
2984                    let Some(val) = res else { break };
2985                    val
2986                }),
2987                11u16 => Qstats::TxBytes({
2988                    let res = parse_u32(next);
2989                    let Some(val) = res else { break };
2990                    val
2991                }),
2992                12u16 => Qstats::RxAllocFail({
2993                    let res = parse_u32(next);
2994                    let Some(val) = res else { break };
2995                    val
2996                }),
2997                13u16 => Qstats::RxHwDrops({
2998                    let res = parse_u32(next);
2999                    let Some(val) = res else { break };
3000                    val
3001                }),
3002                14u16 => Qstats::RxHwDropOverruns({
3003                    let res = parse_u32(next);
3004                    let Some(val) = res else { break };
3005                    val
3006                }),
3007                15u16 => Qstats::RxCsumComplete({
3008                    let res = parse_u32(next);
3009                    let Some(val) = res else { break };
3010                    val
3011                }),
3012                16u16 => Qstats::RxCsumUnnecessary({
3013                    let res = parse_u32(next);
3014                    let Some(val) = res else { break };
3015                    val
3016                }),
3017                17u16 => Qstats::RxCsumNone({
3018                    let res = parse_u32(next);
3019                    let Some(val) = res else { break };
3020                    val
3021                }),
3022                18u16 => Qstats::RxCsumBad({
3023                    let res = parse_u32(next);
3024                    let Some(val) = res else { break };
3025                    val
3026                }),
3027                19u16 => Qstats::RxHwGroPackets({
3028                    let res = parse_u32(next);
3029                    let Some(val) = res else { break };
3030                    val
3031                }),
3032                20u16 => Qstats::RxHwGroBytes({
3033                    let res = parse_u32(next);
3034                    let Some(val) = res else { break };
3035                    val
3036                }),
3037                21u16 => Qstats::RxHwGroWirePackets({
3038                    let res = parse_u32(next);
3039                    let Some(val) = res else { break };
3040                    val
3041                }),
3042                22u16 => Qstats::RxHwGroWireBytes({
3043                    let res = parse_u32(next);
3044                    let Some(val) = res else { break };
3045                    val
3046                }),
3047                23u16 => Qstats::RxHwDropRatelimits({
3048                    let res = parse_u32(next);
3049                    let Some(val) = res else { break };
3050                    val
3051                }),
3052                24u16 => Qstats::TxHwDrops({
3053                    let res = parse_u32(next);
3054                    let Some(val) = res else { break };
3055                    val
3056                }),
3057                25u16 => Qstats::TxHwDropErrors({
3058                    let res = parse_u32(next);
3059                    let Some(val) = res else { break };
3060                    val
3061                }),
3062                26u16 => Qstats::TxCsumNone({
3063                    let res = parse_u32(next);
3064                    let Some(val) = res else { break };
3065                    val
3066                }),
3067                27u16 => Qstats::TxNeedsCsum({
3068                    let res = parse_u32(next);
3069                    let Some(val) = res else { break };
3070                    val
3071                }),
3072                28u16 => Qstats::TxHwGsoPackets({
3073                    let res = parse_u32(next);
3074                    let Some(val) = res else { break };
3075                    val
3076                }),
3077                29u16 => Qstats::TxHwGsoBytes({
3078                    let res = parse_u32(next);
3079                    let Some(val) = res else { break };
3080                    val
3081                }),
3082                30u16 => Qstats::TxHwGsoWirePackets({
3083                    let res = parse_u32(next);
3084                    let Some(val) = res else { break };
3085                    val
3086                }),
3087                31u16 => Qstats::TxHwGsoWireBytes({
3088                    let res = parse_u32(next);
3089                    let Some(val) = res else { break };
3090                    val
3091                }),
3092                32u16 => Qstats::TxHwDropRatelimits({
3093                    let res = parse_u32(next);
3094                    let Some(val) = res else { break };
3095                    val
3096                }),
3097                33u16 => Qstats::TxStop({
3098                    let res = parse_u32(next);
3099                    let Some(val) = res else { break };
3100                    val
3101                }),
3102                34u16 => Qstats::TxWake({
3103                    let res = parse_u32(next);
3104                    let Some(val) = res else { break };
3105                    val
3106                }),
3107                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3108                n => continue,
3109            };
3110            return Some(Ok(res));
3111        }
3112        Some(Err(ErrorContext::new(
3113            "Qstats",
3114            r#type.and_then(|t| Qstats::attr_from_type(t)),
3115            self.orig_loc,
3116            self.buf.as_ptr().wrapping_add(pos) as usize,
3117        )))
3118    }
3119}
3120impl std::fmt::Debug for IterableQstats<'_> {
3121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3122        let mut fmt = f.debug_struct("Qstats");
3123        for attr in self.clone() {
3124            let attr = match attr {
3125                Ok(a) => a,
3126                Err(err) => {
3127                    fmt.finish()?;
3128                    f.write_str("Err(")?;
3129                    err.fmt(f)?;
3130                    return f.write_str(")");
3131                }
3132            };
3133            match attr {
3134                Qstats::Ifindex(val) => fmt.field("Ifindex", &val),
3135                Qstats::QueueType(val) => {
3136                    fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
3137                }
3138                Qstats::QueueId(val) => fmt.field("QueueId", &val),
3139                Qstats::Scope(val) => {
3140                    fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
3141                }
3142                Qstats::RxPackets(val) => fmt.field("RxPackets", &val),
3143                Qstats::RxBytes(val) => fmt.field("RxBytes", &val),
3144                Qstats::TxPackets(val) => fmt.field("TxPackets", &val),
3145                Qstats::TxBytes(val) => fmt.field("TxBytes", &val),
3146                Qstats::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
3147                Qstats::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
3148                Qstats::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
3149                Qstats::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
3150                Qstats::RxCsumUnnecessary(val) => fmt.field("RxCsumUnnecessary", &val),
3151                Qstats::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
3152                Qstats::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
3153                Qstats::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
3154                Qstats::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
3155                Qstats::RxHwGroWirePackets(val) => fmt.field("RxHwGroWirePackets", &val),
3156                Qstats::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
3157                Qstats::RxHwDropRatelimits(val) => fmt.field("RxHwDropRatelimits", &val),
3158                Qstats::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
3159                Qstats::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
3160                Qstats::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
3161                Qstats::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
3162                Qstats::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
3163                Qstats::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
3164                Qstats::TxHwGsoWirePackets(val) => fmt.field("TxHwGsoWirePackets", &val),
3165                Qstats::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
3166                Qstats::TxHwDropRatelimits(val) => fmt.field("TxHwDropRatelimits", &val),
3167                Qstats::TxStop(val) => fmt.field("TxStop", &val),
3168                Qstats::TxWake(val) => fmt.field("TxWake", &val),
3169            };
3170        }
3171        fmt.finish()
3172    }
3173}
3174impl IterableQstats<'_> {
3175    pub fn lookup_attr(
3176        &self,
3177        offset: usize,
3178        missing_type: Option<u16>,
3179    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3180        let mut stack = Vec::new();
3181        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3182        if cur == offset {
3183            stack.push(("Qstats", offset));
3184            return (stack, missing_type.and_then(|t| Qstats::attr_from_type(t)));
3185        }
3186        if cur > offset || cur + self.buf.len() < offset {
3187            return (stack, None);
3188        }
3189        let mut attrs = self.clone();
3190        let mut last_off = cur + attrs.pos;
3191        while let Some(attr) = attrs.next() {
3192            let Ok(attr) = attr else { break };
3193            match attr {
3194                Qstats::Ifindex(val) => {
3195                    if last_off == offset {
3196                        stack.push(("Ifindex", last_off));
3197                        break;
3198                    }
3199                }
3200                Qstats::QueueType(val) => {
3201                    if last_off == offset {
3202                        stack.push(("QueueType", last_off));
3203                        break;
3204                    }
3205                }
3206                Qstats::QueueId(val) => {
3207                    if last_off == offset {
3208                        stack.push(("QueueId", last_off));
3209                        break;
3210                    }
3211                }
3212                Qstats::Scope(val) => {
3213                    if last_off == offset {
3214                        stack.push(("Scope", last_off));
3215                        break;
3216                    }
3217                }
3218                Qstats::RxPackets(val) => {
3219                    if last_off == offset {
3220                        stack.push(("RxPackets", last_off));
3221                        break;
3222                    }
3223                }
3224                Qstats::RxBytes(val) => {
3225                    if last_off == offset {
3226                        stack.push(("RxBytes", last_off));
3227                        break;
3228                    }
3229                }
3230                Qstats::TxPackets(val) => {
3231                    if last_off == offset {
3232                        stack.push(("TxPackets", last_off));
3233                        break;
3234                    }
3235                }
3236                Qstats::TxBytes(val) => {
3237                    if last_off == offset {
3238                        stack.push(("TxBytes", last_off));
3239                        break;
3240                    }
3241                }
3242                Qstats::RxAllocFail(val) => {
3243                    if last_off == offset {
3244                        stack.push(("RxAllocFail", last_off));
3245                        break;
3246                    }
3247                }
3248                Qstats::RxHwDrops(val) => {
3249                    if last_off == offset {
3250                        stack.push(("RxHwDrops", last_off));
3251                        break;
3252                    }
3253                }
3254                Qstats::RxHwDropOverruns(val) => {
3255                    if last_off == offset {
3256                        stack.push(("RxHwDropOverruns", last_off));
3257                        break;
3258                    }
3259                }
3260                Qstats::RxCsumComplete(val) => {
3261                    if last_off == offset {
3262                        stack.push(("RxCsumComplete", last_off));
3263                        break;
3264                    }
3265                }
3266                Qstats::RxCsumUnnecessary(val) => {
3267                    if last_off == offset {
3268                        stack.push(("RxCsumUnnecessary", last_off));
3269                        break;
3270                    }
3271                }
3272                Qstats::RxCsumNone(val) => {
3273                    if last_off == offset {
3274                        stack.push(("RxCsumNone", last_off));
3275                        break;
3276                    }
3277                }
3278                Qstats::RxCsumBad(val) => {
3279                    if last_off == offset {
3280                        stack.push(("RxCsumBad", last_off));
3281                        break;
3282                    }
3283                }
3284                Qstats::RxHwGroPackets(val) => {
3285                    if last_off == offset {
3286                        stack.push(("RxHwGroPackets", last_off));
3287                        break;
3288                    }
3289                }
3290                Qstats::RxHwGroBytes(val) => {
3291                    if last_off == offset {
3292                        stack.push(("RxHwGroBytes", last_off));
3293                        break;
3294                    }
3295                }
3296                Qstats::RxHwGroWirePackets(val) => {
3297                    if last_off == offset {
3298                        stack.push(("RxHwGroWirePackets", last_off));
3299                        break;
3300                    }
3301                }
3302                Qstats::RxHwGroWireBytes(val) => {
3303                    if last_off == offset {
3304                        stack.push(("RxHwGroWireBytes", last_off));
3305                        break;
3306                    }
3307                }
3308                Qstats::RxHwDropRatelimits(val) => {
3309                    if last_off == offset {
3310                        stack.push(("RxHwDropRatelimits", last_off));
3311                        break;
3312                    }
3313                }
3314                Qstats::TxHwDrops(val) => {
3315                    if last_off == offset {
3316                        stack.push(("TxHwDrops", last_off));
3317                        break;
3318                    }
3319                }
3320                Qstats::TxHwDropErrors(val) => {
3321                    if last_off == offset {
3322                        stack.push(("TxHwDropErrors", last_off));
3323                        break;
3324                    }
3325                }
3326                Qstats::TxCsumNone(val) => {
3327                    if last_off == offset {
3328                        stack.push(("TxCsumNone", last_off));
3329                        break;
3330                    }
3331                }
3332                Qstats::TxNeedsCsum(val) => {
3333                    if last_off == offset {
3334                        stack.push(("TxNeedsCsum", last_off));
3335                        break;
3336                    }
3337                }
3338                Qstats::TxHwGsoPackets(val) => {
3339                    if last_off == offset {
3340                        stack.push(("TxHwGsoPackets", last_off));
3341                        break;
3342                    }
3343                }
3344                Qstats::TxHwGsoBytes(val) => {
3345                    if last_off == offset {
3346                        stack.push(("TxHwGsoBytes", last_off));
3347                        break;
3348                    }
3349                }
3350                Qstats::TxHwGsoWirePackets(val) => {
3351                    if last_off == offset {
3352                        stack.push(("TxHwGsoWirePackets", last_off));
3353                        break;
3354                    }
3355                }
3356                Qstats::TxHwGsoWireBytes(val) => {
3357                    if last_off == offset {
3358                        stack.push(("TxHwGsoWireBytes", last_off));
3359                        break;
3360                    }
3361                }
3362                Qstats::TxHwDropRatelimits(val) => {
3363                    if last_off == offset {
3364                        stack.push(("TxHwDropRatelimits", last_off));
3365                        break;
3366                    }
3367                }
3368                Qstats::TxStop(val) => {
3369                    if last_off == offset {
3370                        stack.push(("TxStop", last_off));
3371                        break;
3372                    }
3373                }
3374                Qstats::TxWake(val) => {
3375                    if last_off == offset {
3376                        stack.push(("TxWake", last_off));
3377                        break;
3378                    }
3379                }
3380                _ => {}
3381            };
3382            last_off = cur + attrs.pos;
3383        }
3384        if !stack.is_empty() {
3385            stack.push(("Qstats", cur));
3386        }
3387        (stack, None)
3388    }
3389}
3390#[derive(Clone)]
3391pub enum QueueId {
3392    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
3393    Id(u32),
3394    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
3395    Type(u32),
3396}
3397impl<'a> IterableQueueId<'a> {
3398    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
3399    pub fn get_id(&self) -> Result<u32, ErrorContext> {
3400        let mut iter = self.clone();
3401        iter.pos = 0;
3402        for attr in iter {
3403            if let QueueId::Id(val) = attr? {
3404                return Ok(val);
3405            }
3406        }
3407        Err(ErrorContext::new_missing(
3408            "QueueId",
3409            "Id",
3410            self.orig_loc,
3411            self.buf.as_ptr() as usize,
3412        ))
3413    }
3414    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
3415    pub fn get_type(&self) -> Result<u32, ErrorContext> {
3416        let mut iter = self.clone();
3417        iter.pos = 0;
3418        for attr in iter {
3419            if let QueueId::Type(val) = attr? {
3420                return Ok(val);
3421            }
3422        }
3423        Err(ErrorContext::new_missing(
3424            "QueueId",
3425            "Type",
3426            self.orig_loc,
3427            self.buf.as_ptr() as usize,
3428        ))
3429    }
3430}
3431impl QueueId {
3432    pub fn new<'a>(buf: &'a [u8]) -> IterableQueueId<'a> {
3433        IterableQueueId::with_loc(buf, buf.as_ptr() as usize)
3434    }
3435    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3436        Queue::attr_from_type(r#type)
3437    }
3438}
3439#[derive(Clone, Copy, Default)]
3440pub struct IterableQueueId<'a> {
3441    buf: &'a [u8],
3442    pos: usize,
3443    orig_loc: usize,
3444}
3445impl<'a> IterableQueueId<'a> {
3446    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3447        Self {
3448            buf,
3449            pos: 0,
3450            orig_loc,
3451        }
3452    }
3453    pub fn get_buf(&self) -> &'a [u8] {
3454        self.buf
3455    }
3456}
3457impl<'a> Iterator for IterableQueueId<'a> {
3458    type Item = Result<QueueId, ErrorContext>;
3459    fn next(&mut self) -> Option<Self::Item> {
3460        let pos = self.pos;
3461        let mut r#type;
3462        loop {
3463            r#type = None;
3464            if self.buf.len() == self.pos {
3465                return None;
3466            }
3467            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3468                break;
3469            };
3470            r#type = Some(header.r#type);
3471            let res = match header.r#type {
3472                1u16 => QueueId::Id({
3473                    let res = parse_u32(next);
3474                    let Some(val) = res else { break };
3475                    val
3476                }),
3477                3u16 => QueueId::Type({
3478                    let res = parse_u32(next);
3479                    let Some(val) = res else { break };
3480                    val
3481                }),
3482                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3483                n => continue,
3484            };
3485            return Some(Ok(res));
3486        }
3487        Some(Err(ErrorContext::new(
3488            "QueueId",
3489            r#type.and_then(|t| QueueId::attr_from_type(t)),
3490            self.orig_loc,
3491            self.buf.as_ptr().wrapping_add(pos) as usize,
3492        )))
3493    }
3494}
3495impl std::fmt::Debug for IterableQueueId<'_> {
3496    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3497        let mut fmt = f.debug_struct("QueueId");
3498        for attr in self.clone() {
3499            let attr = match attr {
3500                Ok(a) => a,
3501                Err(err) => {
3502                    fmt.finish()?;
3503                    f.write_str("Err(")?;
3504                    err.fmt(f)?;
3505                    return f.write_str(")");
3506                }
3507            };
3508            match attr {
3509                QueueId::Id(val) => fmt.field("Id", &val),
3510                QueueId::Type(val) => {
3511                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
3512                }
3513            };
3514        }
3515        fmt.finish()
3516    }
3517}
3518impl IterableQueueId<'_> {
3519    pub fn lookup_attr(
3520        &self,
3521        offset: usize,
3522        missing_type: Option<u16>,
3523    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3524        let mut stack = Vec::new();
3525        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3526        if cur == offset {
3527            stack.push(("QueueId", offset));
3528            return (stack, missing_type.and_then(|t| QueueId::attr_from_type(t)));
3529        }
3530        if cur > offset || cur + self.buf.len() < offset {
3531            return (stack, None);
3532        }
3533        let mut attrs = self.clone();
3534        let mut last_off = cur + attrs.pos;
3535        while let Some(attr) = attrs.next() {
3536            let Ok(attr) = attr else { break };
3537            match attr {
3538                QueueId::Id(val) => {
3539                    if last_off == offset {
3540                        stack.push(("Id", last_off));
3541                        break;
3542                    }
3543                }
3544                QueueId::Type(val) => {
3545                    if last_off == offset {
3546                        stack.push(("Type", last_off));
3547                        break;
3548                    }
3549                }
3550                _ => {}
3551            };
3552            last_off = cur + attrs.pos;
3553        }
3554        if !stack.is_empty() {
3555            stack.push(("QueueId", cur));
3556        }
3557        (stack, None)
3558    }
3559}
3560#[derive(Clone)]
3561pub enum Dmabuf<'a> {
3562    #[doc = "netdev ifindex to bind the dmabuf to."]
3563    Ifindex(u32),
3564    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3565    Queues(IterableQueueId<'a>),
3566    #[doc = "dmabuf file descriptor to bind."]
3567    Fd(u32),
3568    #[doc = "id of the dmabuf binding"]
3569    Id(u32),
3570}
3571impl<'a> IterableDmabuf<'a> {
3572    #[doc = "netdev ifindex to bind the dmabuf to."]
3573    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
3574        let mut iter = self.clone();
3575        iter.pos = 0;
3576        for attr in iter {
3577            if let Dmabuf::Ifindex(val) = attr? {
3578                return Ok(val);
3579            }
3580        }
3581        Err(ErrorContext::new_missing(
3582            "Dmabuf",
3583            "Ifindex",
3584            self.orig_loc,
3585            self.buf.as_ptr() as usize,
3586        ))
3587    }
3588    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3589    pub fn get_queues(&self) -> MultiAttrIterable<Self, Dmabuf<'a>, IterableQueueId<'a>> {
3590        MultiAttrIterable::new(self.clone(), |variant| {
3591            if let Dmabuf::Queues(val) = variant {
3592                Some(val)
3593            } else {
3594                None
3595            }
3596        })
3597    }
3598    #[doc = "dmabuf file descriptor to bind."]
3599    pub fn get_fd(&self) -> Result<u32, ErrorContext> {
3600        let mut iter = self.clone();
3601        iter.pos = 0;
3602        for attr in iter {
3603            if let Dmabuf::Fd(val) = attr? {
3604                return Ok(val);
3605            }
3606        }
3607        Err(ErrorContext::new_missing(
3608            "Dmabuf",
3609            "Fd",
3610            self.orig_loc,
3611            self.buf.as_ptr() as usize,
3612        ))
3613    }
3614    #[doc = "id of the dmabuf binding"]
3615    pub fn get_id(&self) -> Result<u32, ErrorContext> {
3616        let mut iter = self.clone();
3617        iter.pos = 0;
3618        for attr in iter {
3619            if let Dmabuf::Id(val) = attr? {
3620                return Ok(val);
3621            }
3622        }
3623        Err(ErrorContext::new_missing(
3624            "Dmabuf",
3625            "Id",
3626            self.orig_loc,
3627            self.buf.as_ptr() as usize,
3628        ))
3629    }
3630}
3631impl Dmabuf<'_> {
3632    pub fn new<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
3633        IterableDmabuf::with_loc(buf, buf.as_ptr() as usize)
3634    }
3635    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3636        let res = match r#type {
3637            1u16 => "Ifindex",
3638            2u16 => "Queues",
3639            3u16 => "Fd",
3640            4u16 => "Id",
3641            _ => return None,
3642        };
3643        Some(res)
3644    }
3645}
3646#[derive(Clone, Copy, Default)]
3647pub struct IterableDmabuf<'a> {
3648    buf: &'a [u8],
3649    pos: usize,
3650    orig_loc: usize,
3651}
3652impl<'a> IterableDmabuf<'a> {
3653    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3654        Self {
3655            buf,
3656            pos: 0,
3657            orig_loc,
3658        }
3659    }
3660    pub fn get_buf(&self) -> &'a [u8] {
3661        self.buf
3662    }
3663}
3664impl<'a> Iterator for IterableDmabuf<'a> {
3665    type Item = Result<Dmabuf<'a>, ErrorContext>;
3666    fn next(&mut self) -> Option<Self::Item> {
3667        let pos = self.pos;
3668        let mut r#type;
3669        loop {
3670            r#type = None;
3671            if self.buf.len() == self.pos {
3672                return None;
3673            }
3674            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3675                break;
3676            };
3677            r#type = Some(header.r#type);
3678            let res = match header.r#type {
3679                1u16 => Dmabuf::Ifindex({
3680                    let res = parse_u32(next);
3681                    let Some(val) = res else { break };
3682                    val
3683                }),
3684                2u16 => Dmabuf::Queues({
3685                    let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
3686                    let Some(val) = res else { break };
3687                    val
3688                }),
3689                3u16 => Dmabuf::Fd({
3690                    let res = parse_u32(next);
3691                    let Some(val) = res else { break };
3692                    val
3693                }),
3694                4u16 => Dmabuf::Id({
3695                    let res = parse_u32(next);
3696                    let Some(val) = res else { break };
3697                    val
3698                }),
3699                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3700                n => continue,
3701            };
3702            return Some(Ok(res));
3703        }
3704        Some(Err(ErrorContext::new(
3705            "Dmabuf",
3706            r#type.and_then(|t| Dmabuf::attr_from_type(t)),
3707            self.orig_loc,
3708            self.buf.as_ptr().wrapping_add(pos) as usize,
3709        )))
3710    }
3711}
3712impl<'a> std::fmt::Debug for IterableDmabuf<'_> {
3713    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3714        let mut fmt = f.debug_struct("Dmabuf");
3715        for attr in self.clone() {
3716            let attr = match attr {
3717                Ok(a) => a,
3718                Err(err) => {
3719                    fmt.finish()?;
3720                    f.write_str("Err(")?;
3721                    err.fmt(f)?;
3722                    return f.write_str(")");
3723                }
3724            };
3725            match attr {
3726                Dmabuf::Ifindex(val) => fmt.field("Ifindex", &val),
3727                Dmabuf::Queues(val) => fmt.field("Queues", &val),
3728                Dmabuf::Fd(val) => fmt.field("Fd", &val),
3729                Dmabuf::Id(val) => fmt.field("Id", &val),
3730            };
3731        }
3732        fmt.finish()
3733    }
3734}
3735impl IterableDmabuf<'_> {
3736    pub fn lookup_attr(
3737        &self,
3738        offset: usize,
3739        missing_type: Option<u16>,
3740    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3741        let mut stack = Vec::new();
3742        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3743        if cur == offset {
3744            stack.push(("Dmabuf", offset));
3745            return (stack, missing_type.and_then(|t| Dmabuf::attr_from_type(t)));
3746        }
3747        if cur > offset || cur + self.buf.len() < offset {
3748            return (stack, None);
3749        }
3750        let mut attrs = self.clone();
3751        let mut last_off = cur + attrs.pos;
3752        let mut missing = None;
3753        while let Some(attr) = attrs.next() {
3754            let Ok(attr) = attr else { break };
3755            match attr {
3756                Dmabuf::Ifindex(val) => {
3757                    if last_off == offset {
3758                        stack.push(("Ifindex", last_off));
3759                        break;
3760                    }
3761                }
3762                Dmabuf::Queues(val) => {
3763                    (stack, missing) = val.lookup_attr(offset, missing_type);
3764                    if !stack.is_empty() {
3765                        break;
3766                    }
3767                }
3768                Dmabuf::Fd(val) => {
3769                    if last_off == offset {
3770                        stack.push(("Fd", last_off));
3771                        break;
3772                    }
3773                }
3774                Dmabuf::Id(val) => {
3775                    if last_off == offset {
3776                        stack.push(("Id", last_off));
3777                        break;
3778                    }
3779                }
3780                _ => {}
3781            };
3782            last_off = cur + attrs.pos;
3783        }
3784        if !stack.is_empty() {
3785            stack.push(("Dmabuf", cur));
3786        }
3787        (stack, missing)
3788    }
3789}
3790pub struct PushDev<Prev: Rec> {
3791    pub(crate) prev: Option<Prev>,
3792    pub(crate) header_offset: Option<usize>,
3793}
3794impl<Prev: Rec> Rec for PushDev<Prev> {
3795    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3796        self.prev.as_mut().unwrap().as_rec_mut()
3797    }
3798    fn as_rec(&self) -> &Vec<u8> {
3799        self.prev.as_ref().unwrap().as_rec()
3800    }
3801}
3802impl<Prev: Rec> PushDev<Prev> {
3803    pub fn new(prev: Prev) -> Self {
3804        Self {
3805            prev: Some(prev),
3806            header_offset: None,
3807        }
3808    }
3809    pub fn end_nested(mut self) -> Prev {
3810        let mut prev = self.prev.take().unwrap();
3811        if let Some(header_offset) = &self.header_offset {
3812            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3813        }
3814        prev
3815    }
3816    #[doc = "netdev ifindex"]
3817    pub fn push_ifindex(mut self, value: u32) -> Self {
3818        push_header(self.as_rec_mut(), 1u16, 4 as u16);
3819        self.as_rec_mut().extend(value.to_ne_bytes());
3820        self
3821    }
3822    pub fn push_pad(mut self, value: &[u8]) -> Self {
3823        push_header(self.as_rec_mut(), 2u16, value.len() as u16);
3824        self.as_rec_mut().extend(value);
3825        self
3826    }
3827    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
3828    pub fn push_xdp_features(mut self, value: u64) -> Self {
3829        push_header(self.as_rec_mut(), 3u16, 8 as u16);
3830        self.as_rec_mut().extend(value.to_ne_bytes());
3831        self
3832    }
3833    #[doc = "max fragment count supported by ZC driver"]
3834    pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
3835        push_header(self.as_rec_mut(), 4u16, 4 as u16);
3836        self.as_rec_mut().extend(value.to_ne_bytes());
3837        self
3838    }
3839    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
3840    pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
3841        push_header(self.as_rec_mut(), 5u16, 8 as u16);
3842        self.as_rec_mut().extend(value.to_ne_bytes());
3843        self
3844    }
3845    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
3846    pub fn push_xsk_features(mut self, value: u64) -> Self {
3847        push_header(self.as_rec_mut(), 6u16, 8 as u16);
3848        self.as_rec_mut().extend(value.to_ne_bytes());
3849        self
3850    }
3851}
3852impl<Prev: Rec> Drop for PushDev<Prev> {
3853    fn drop(&mut self) {
3854        if let Some(prev) = &mut self.prev {
3855            if let Some(header_offset) = &self.header_offset {
3856                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3857            }
3858        }
3859    }
3860}
3861pub struct PushIoUringProviderInfo<Prev: Rec> {
3862    pub(crate) prev: Option<Prev>,
3863    pub(crate) header_offset: Option<usize>,
3864}
3865impl<Prev: Rec> Rec for PushIoUringProviderInfo<Prev> {
3866    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3867        self.prev.as_mut().unwrap().as_rec_mut()
3868    }
3869    fn as_rec(&self) -> &Vec<u8> {
3870        self.prev.as_ref().unwrap().as_rec()
3871    }
3872}
3873impl<Prev: Rec> PushIoUringProviderInfo<Prev> {
3874    pub fn new(prev: Prev) -> Self {
3875        Self {
3876            prev: Some(prev),
3877            header_offset: None,
3878        }
3879    }
3880    pub fn end_nested(mut self) -> Prev {
3881        let mut prev = self.prev.take().unwrap();
3882        if let Some(header_offset) = &self.header_offset {
3883            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3884        }
3885        prev
3886    }
3887}
3888impl<Prev: Rec> Drop for PushIoUringProviderInfo<Prev> {
3889    fn drop(&mut self) {
3890        if let Some(prev) = &mut self.prev {
3891            if let Some(header_offset) = &self.header_offset {
3892                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3893            }
3894        }
3895    }
3896}
3897pub struct PushPagePool<Prev: Rec> {
3898    pub(crate) prev: Option<Prev>,
3899    pub(crate) header_offset: Option<usize>,
3900}
3901impl<Prev: Rec> Rec for PushPagePool<Prev> {
3902    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3903        self.prev.as_mut().unwrap().as_rec_mut()
3904    }
3905    fn as_rec(&self) -> &Vec<u8> {
3906        self.prev.as_ref().unwrap().as_rec()
3907    }
3908}
3909impl<Prev: Rec> PushPagePool<Prev> {
3910    pub fn new(prev: Prev) -> Self {
3911        Self {
3912            prev: Some(prev),
3913            header_offset: None,
3914        }
3915    }
3916    pub fn end_nested(mut self) -> Prev {
3917        let mut prev = self.prev.take().unwrap();
3918        if let Some(header_offset) = &self.header_offset {
3919            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3920        }
3921        prev
3922    }
3923    #[doc = "Unique ID of a Page Pool instance."]
3924    pub fn push_id(mut self, value: u32) -> Self {
3925        push_header(self.as_rec_mut(), 1u16, 4 as u16);
3926        self.as_rec_mut().extend(value.to_ne_bytes());
3927        self
3928    }
3929    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
3930    pub fn push_ifindex(mut self, value: u32) -> Self {
3931        push_header(self.as_rec_mut(), 2u16, 4 as u16);
3932        self.as_rec_mut().extend(value.to_ne_bytes());
3933        self
3934    }
3935    #[doc = "Id of NAPI using this Page Pool instance."]
3936    pub fn push_napi_id(mut self, value: u32) -> Self {
3937        push_header(self.as_rec_mut(), 3u16, 4 as u16);
3938        self.as_rec_mut().extend(value.to_ne_bytes());
3939        self
3940    }
3941    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
3942    pub fn push_inflight(mut self, value: u32) -> Self {
3943        push_header(self.as_rec_mut(), 4u16, 4 as u16);
3944        self.as_rec_mut().extend(value.to_ne_bytes());
3945        self
3946    }
3947    #[doc = "Amount of memory held by inflight pages.\n"]
3948    pub fn push_inflight_mem(mut self, value: u32) -> Self {
3949        push_header(self.as_rec_mut(), 5u16, 4 as u16);
3950        self.as_rec_mut().extend(value.to_ne_bytes());
3951        self
3952    }
3953    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
3954    pub fn push_detach_time(mut self, value: u32) -> Self {
3955        push_header(self.as_rec_mut(), 6u16, 4 as u16);
3956        self.as_rec_mut().extend(value.to_ne_bytes());
3957        self
3958    }
3959    #[doc = "ID of the dmabuf this page-pool is attached to."]
3960    pub fn push_dmabuf(mut self, value: u32) -> Self {
3961        push_header(self.as_rec_mut(), 7u16, 4 as u16);
3962        self.as_rec_mut().extend(value.to_ne_bytes());
3963        self
3964    }
3965    #[doc = "io-uring memory provider information."]
3966    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
3967        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
3968        PushIoUringProviderInfo {
3969            prev: Some(self),
3970            header_offset: Some(header_offset),
3971        }
3972    }
3973}
3974impl<Prev: Rec> Drop for PushPagePool<Prev> {
3975    fn drop(&mut self) {
3976        if let Some(prev) = &mut self.prev {
3977            if let Some(header_offset) = &self.header_offset {
3978                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3979            }
3980        }
3981    }
3982}
3983pub struct PushPagePoolInfo<Prev: Rec> {
3984    pub(crate) prev: Option<Prev>,
3985    pub(crate) header_offset: Option<usize>,
3986}
3987impl<Prev: Rec> Rec for PushPagePoolInfo<Prev> {
3988    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3989        self.prev.as_mut().unwrap().as_rec_mut()
3990    }
3991    fn as_rec(&self) -> &Vec<u8> {
3992        self.prev.as_ref().unwrap().as_rec()
3993    }
3994}
3995impl<Prev: Rec> PushPagePoolInfo<Prev> {
3996    pub fn new(prev: Prev) -> Self {
3997        Self {
3998            prev: Some(prev),
3999            header_offset: None,
4000        }
4001    }
4002    pub fn end_nested(mut self) -> Prev {
4003        let mut prev = self.prev.take().unwrap();
4004        if let Some(header_offset) = &self.header_offset {
4005            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4006        }
4007        prev
4008    }
4009    #[doc = "Unique ID of a Page Pool instance."]
4010    pub fn push_id(mut self, value: u32) -> Self {
4011        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4012        self.as_rec_mut().extend(value.to_ne_bytes());
4013        self
4014    }
4015    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
4016    pub fn push_ifindex(mut self, value: u32) -> Self {
4017        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4018        self.as_rec_mut().extend(value.to_ne_bytes());
4019        self
4020    }
4021}
4022impl<Prev: Rec> Drop for PushPagePoolInfo<Prev> {
4023    fn drop(&mut self) {
4024        if let Some(prev) = &mut self.prev {
4025            if let Some(header_offset) = &self.header_offset {
4026                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4027            }
4028        }
4029    }
4030}
4031pub struct PushPagePoolStats<Prev: Rec> {
4032    pub(crate) prev: Option<Prev>,
4033    pub(crate) header_offset: Option<usize>,
4034}
4035impl<Prev: Rec> Rec for PushPagePoolStats<Prev> {
4036    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4037        self.prev.as_mut().unwrap().as_rec_mut()
4038    }
4039    fn as_rec(&self) -> &Vec<u8> {
4040        self.prev.as_ref().unwrap().as_rec()
4041    }
4042}
4043impl<Prev: Rec> PushPagePoolStats<Prev> {
4044    pub fn new(prev: Prev) -> Self {
4045        Self {
4046            prev: Some(prev),
4047            header_offset: None,
4048        }
4049    }
4050    pub fn end_nested(mut self) -> Prev {
4051        let mut prev = self.prev.take().unwrap();
4052        if let Some(header_offset) = &self.header_offset {
4053            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4054        }
4055        prev
4056    }
4057    #[doc = "Page pool identifying information."]
4058    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
4059        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4060        PushPagePoolInfo {
4061            prev: Some(self),
4062            header_offset: Some(header_offset),
4063        }
4064    }
4065    pub fn push_alloc_fast(mut self, value: u32) -> Self {
4066        push_header(self.as_rec_mut(), 8u16, 4 as u16);
4067        self.as_rec_mut().extend(value.to_ne_bytes());
4068        self
4069    }
4070    pub fn push_alloc_slow(mut self, value: u32) -> Self {
4071        push_header(self.as_rec_mut(), 9u16, 4 as u16);
4072        self.as_rec_mut().extend(value.to_ne_bytes());
4073        self
4074    }
4075    pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
4076        push_header(self.as_rec_mut(), 10u16, 4 as u16);
4077        self.as_rec_mut().extend(value.to_ne_bytes());
4078        self
4079    }
4080    pub fn push_alloc_empty(mut self, value: u32) -> Self {
4081        push_header(self.as_rec_mut(), 11u16, 4 as u16);
4082        self.as_rec_mut().extend(value.to_ne_bytes());
4083        self
4084    }
4085    pub fn push_alloc_refill(mut self, value: u32) -> Self {
4086        push_header(self.as_rec_mut(), 12u16, 4 as u16);
4087        self.as_rec_mut().extend(value.to_ne_bytes());
4088        self
4089    }
4090    pub fn push_alloc_waive(mut self, value: u32) -> Self {
4091        push_header(self.as_rec_mut(), 13u16, 4 as u16);
4092        self.as_rec_mut().extend(value.to_ne_bytes());
4093        self
4094    }
4095    pub fn push_recycle_cached(mut self, value: u32) -> Self {
4096        push_header(self.as_rec_mut(), 14u16, 4 as u16);
4097        self.as_rec_mut().extend(value.to_ne_bytes());
4098        self
4099    }
4100    pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
4101        push_header(self.as_rec_mut(), 15u16, 4 as u16);
4102        self.as_rec_mut().extend(value.to_ne_bytes());
4103        self
4104    }
4105    pub fn push_recycle_ring(mut self, value: u32) -> Self {
4106        push_header(self.as_rec_mut(), 16u16, 4 as u16);
4107        self.as_rec_mut().extend(value.to_ne_bytes());
4108        self
4109    }
4110    pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
4111        push_header(self.as_rec_mut(), 17u16, 4 as u16);
4112        self.as_rec_mut().extend(value.to_ne_bytes());
4113        self
4114    }
4115    pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
4116        push_header(self.as_rec_mut(), 18u16, 4 as u16);
4117        self.as_rec_mut().extend(value.to_ne_bytes());
4118        self
4119    }
4120}
4121impl<Prev: Rec> Drop for PushPagePoolStats<Prev> {
4122    fn drop(&mut self) {
4123        if let Some(prev) = &mut self.prev {
4124            if let Some(header_offset) = &self.header_offset {
4125                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4126            }
4127        }
4128    }
4129}
4130pub struct PushNapi<Prev: Rec> {
4131    pub(crate) prev: Option<Prev>,
4132    pub(crate) header_offset: Option<usize>,
4133}
4134impl<Prev: Rec> Rec for PushNapi<Prev> {
4135    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4136        self.prev.as_mut().unwrap().as_rec_mut()
4137    }
4138    fn as_rec(&self) -> &Vec<u8> {
4139        self.prev.as_ref().unwrap().as_rec()
4140    }
4141}
4142impl<Prev: Rec> PushNapi<Prev> {
4143    pub fn new(prev: Prev) -> Self {
4144        Self {
4145            prev: Some(prev),
4146            header_offset: None,
4147        }
4148    }
4149    pub fn end_nested(mut self) -> Prev {
4150        let mut prev = self.prev.take().unwrap();
4151        if let Some(header_offset) = &self.header_offset {
4152            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4153        }
4154        prev
4155    }
4156    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
4157    pub fn push_ifindex(mut self, value: u32) -> Self {
4158        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4159        self.as_rec_mut().extend(value.to_ne_bytes());
4160        self
4161    }
4162    #[doc = "ID of the NAPI instance."]
4163    pub fn push_id(mut self, value: u32) -> Self {
4164        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4165        self.as_rec_mut().extend(value.to_ne_bytes());
4166        self
4167    }
4168    #[doc = "The associated interrupt vector number for the napi"]
4169    pub fn push_irq(mut self, value: u32) -> Self {
4170        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4171        self.as_rec_mut().extend(value.to_ne_bytes());
4172        self
4173    }
4174    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
4175    pub fn push_pid(mut self, value: u32) -> Self {
4176        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4177        self.as_rec_mut().extend(value.to_ne_bytes());
4178        self
4179    }
4180    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
4181    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
4182        push_header(self.as_rec_mut(), 5u16, 4 as u16);
4183        self.as_rec_mut().extend(value.to_ne_bytes());
4184        self
4185    }
4186    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
4187    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
4188        push_header(self.as_rec_mut(), 6u16, 4 as u16);
4189        self.as_rec_mut().extend(value.to_ne_bytes());
4190        self
4191    }
4192    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
4193    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
4194        push_header(self.as_rec_mut(), 7u16, 4 as u16);
4195        self.as_rec_mut().extend(value.to_ne_bytes());
4196        self
4197    }
4198    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
4199    pub fn push_threaded(mut self, value: u32) -> Self {
4200        push_header(self.as_rec_mut(), 8u16, 4 as u16);
4201        self.as_rec_mut().extend(value.to_ne_bytes());
4202        self
4203    }
4204}
4205impl<Prev: Rec> Drop for PushNapi<Prev> {
4206    fn drop(&mut self) {
4207        if let Some(prev) = &mut self.prev {
4208            if let Some(header_offset) = &self.header_offset {
4209                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4210            }
4211        }
4212    }
4213}
4214pub struct PushXskInfo<Prev: Rec> {
4215    pub(crate) prev: Option<Prev>,
4216    pub(crate) header_offset: Option<usize>,
4217}
4218impl<Prev: Rec> Rec for PushXskInfo<Prev> {
4219    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4220        self.prev.as_mut().unwrap().as_rec_mut()
4221    }
4222    fn as_rec(&self) -> &Vec<u8> {
4223        self.prev.as_ref().unwrap().as_rec()
4224    }
4225}
4226impl<Prev: Rec> PushXskInfo<Prev> {
4227    pub fn new(prev: Prev) -> Self {
4228        Self {
4229            prev: Some(prev),
4230            header_offset: None,
4231        }
4232    }
4233    pub fn end_nested(mut self) -> Prev {
4234        let mut prev = self.prev.take().unwrap();
4235        if let Some(header_offset) = &self.header_offset {
4236            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4237        }
4238        prev
4239    }
4240}
4241impl<Prev: Rec> Drop for PushXskInfo<Prev> {
4242    fn drop(&mut self) {
4243        if let Some(prev) = &mut self.prev {
4244            if let Some(header_offset) = &self.header_offset {
4245                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4246            }
4247        }
4248    }
4249}
4250pub struct PushQueue<Prev: Rec> {
4251    pub(crate) prev: Option<Prev>,
4252    pub(crate) header_offset: Option<usize>,
4253}
4254impl<Prev: Rec> Rec for PushQueue<Prev> {
4255    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4256        self.prev.as_mut().unwrap().as_rec_mut()
4257    }
4258    fn as_rec(&self) -> &Vec<u8> {
4259        self.prev.as_ref().unwrap().as_rec()
4260    }
4261}
4262impl<Prev: Rec> PushQueue<Prev> {
4263    pub fn new(prev: Prev) -> Self {
4264        Self {
4265            prev: Some(prev),
4266            header_offset: None,
4267        }
4268    }
4269    pub fn end_nested(mut self) -> Prev {
4270        let mut prev = self.prev.take().unwrap();
4271        if let Some(header_offset) = &self.header_offset {
4272            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4273        }
4274        prev
4275    }
4276    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
4277    pub fn push_id(mut self, value: u32) -> Self {
4278        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4279        self.as_rec_mut().extend(value.to_ne_bytes());
4280        self
4281    }
4282    #[doc = "ifindex of the netdevice to which the queue belongs."]
4283    pub fn push_ifindex(mut self, value: u32) -> Self {
4284        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4285        self.as_rec_mut().extend(value.to_ne_bytes());
4286        self
4287    }
4288    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
4289    pub fn push_type(mut self, value: u32) -> Self {
4290        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4291        self.as_rec_mut().extend(value.to_ne_bytes());
4292        self
4293    }
4294    #[doc = "ID of the NAPI instance which services this queue."]
4295    pub fn push_napi_id(mut self, value: u32) -> Self {
4296        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4297        self.as_rec_mut().extend(value.to_ne_bytes());
4298        self
4299    }
4300    #[doc = "ID of the dmabuf attached to this queue, if any."]
4301    pub fn push_dmabuf(mut self, value: u32) -> Self {
4302        push_header(self.as_rec_mut(), 5u16, 4 as u16);
4303        self.as_rec_mut().extend(value.to_ne_bytes());
4304        self
4305    }
4306    #[doc = "io_uring memory provider information."]
4307    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
4308        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
4309        PushIoUringProviderInfo {
4310            prev: Some(self),
4311            header_offset: Some(header_offset),
4312        }
4313    }
4314    #[doc = "XSK information for this queue, if any."]
4315    pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
4316        let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
4317        PushXskInfo {
4318            prev: Some(self),
4319            header_offset: Some(header_offset),
4320        }
4321    }
4322}
4323impl<Prev: Rec> Drop for PushQueue<Prev> {
4324    fn drop(&mut self) {
4325        if let Some(prev) = &mut self.prev {
4326            if let Some(header_offset) = &self.header_offset {
4327                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4328            }
4329        }
4330    }
4331}
4332pub struct PushQstats<Prev: Rec> {
4333    pub(crate) prev: Option<Prev>,
4334    pub(crate) header_offset: Option<usize>,
4335}
4336impl<Prev: Rec> Rec for PushQstats<Prev> {
4337    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4338        self.prev.as_mut().unwrap().as_rec_mut()
4339    }
4340    fn as_rec(&self) -> &Vec<u8> {
4341        self.prev.as_ref().unwrap().as_rec()
4342    }
4343}
4344impl<Prev: Rec> PushQstats<Prev> {
4345    pub fn new(prev: Prev) -> Self {
4346        Self {
4347            prev: Some(prev),
4348            header_offset: None,
4349        }
4350    }
4351    pub fn end_nested(mut self) -> Prev {
4352        let mut prev = self.prev.take().unwrap();
4353        if let Some(header_offset) = &self.header_offset {
4354            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4355        }
4356        prev
4357    }
4358    #[doc = "ifindex of the netdevice to which stats belong."]
4359    pub fn push_ifindex(mut self, value: u32) -> Self {
4360        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4361        self.as_rec_mut().extend(value.to_ne_bytes());
4362        self
4363    }
4364    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
4365    pub fn push_queue_type(mut self, value: u32) -> Self {
4366        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4367        self.as_rec_mut().extend(value.to_ne_bytes());
4368        self
4369    }
4370    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
4371    pub fn push_queue_id(mut self, value: u32) -> Self {
4372        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4373        self.as_rec_mut().extend(value.to_ne_bytes());
4374        self
4375    }
4376    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
4377    pub fn push_scope(mut self, value: u32) -> Self {
4378        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4379        self.as_rec_mut().extend(value.to_ne_bytes());
4380        self
4381    }
4382    #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
4383    pub fn push_rx_packets(mut self, value: u32) -> Self {
4384        push_header(self.as_rec_mut(), 8u16, 4 as u16);
4385        self.as_rec_mut().extend(value.to_ne_bytes());
4386        self
4387    }
4388    #[doc = "Successfully received bytes, see `rx-packets`."]
4389    pub fn push_rx_bytes(mut self, value: u32) -> Self {
4390        push_header(self.as_rec_mut(), 9u16, 4 as u16);
4391        self.as_rec_mut().extend(value.to_ne_bytes());
4392        self
4393    }
4394    #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
4395    pub fn push_tx_packets(mut self, value: u32) -> Self {
4396        push_header(self.as_rec_mut(), 10u16, 4 as u16);
4397        self.as_rec_mut().extend(value.to_ne_bytes());
4398        self
4399    }
4400    #[doc = "Successfully sent bytes, see `tx-packets`."]
4401    pub fn push_tx_bytes(mut self, value: u32) -> Self {
4402        push_header(self.as_rec_mut(), 11u16, 4 as u16);
4403        self.as_rec_mut().extend(value.to_ne_bytes());
4404        self
4405    }
4406    #[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\non driver implementation and whether system recovers quickly.\n"]
4407    pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
4408        push_header(self.as_rec_mut(), 12u16, 4 as u16);
4409        self.as_rec_mut().extend(value.to_ne_bytes());
4410        self
4411    }
4412    #[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"]
4413    pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
4414        push_header(self.as_rec_mut(), 13u16, 4 as u16);
4415        self.as_rec_mut().extend(value.to_ne_bytes());
4416        self
4417    }
4418    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
4419    pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
4420        push_header(self.as_rec_mut(), 14u16, 4 as u16);
4421        self.as_rec_mut().extend(value.to_ne_bytes());
4422        self
4423    }
4424    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
4425    pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
4426        push_header(self.as_rec_mut(), 15u16, 4 as u16);
4427        self.as_rec_mut().extend(value.to_ne_bytes());
4428        self
4429    }
4430    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
4431    pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
4432        push_header(self.as_rec_mut(), 16u16, 4 as u16);
4433        self.as_rec_mut().extend(value.to_ne_bytes());
4434        self
4435    }
4436    #[doc = "Number of packets that were not checksummed by device."]
4437    pub fn push_rx_csum_none(mut self, value: u32) -> Self {
4438        push_header(self.as_rec_mut(), 17u16, 4 as u16);
4439        self.as_rec_mut().extend(value.to_ne_bytes());
4440        self
4441    }
4442    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
4443    pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
4444        push_header(self.as_rec_mut(), 18u16, 4 as u16);
4445        self.as_rec_mut().extend(value.to_ne_bytes());
4446        self
4447    }
4448    #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
4449    pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
4450        push_header(self.as_rec_mut(), 19u16, 4 as u16);
4451        self.as_rec_mut().extend(value.to_ne_bytes());
4452        self
4453    }
4454    #[doc = "See `rx-hw-gro-packets`."]
4455    pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
4456        push_header(self.as_rec_mut(), 20u16, 4 as u16);
4457        self.as_rec_mut().extend(value.to_ne_bytes());
4458        self
4459    }
4460    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
4461    pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
4462        push_header(self.as_rec_mut(), 21u16, 4 as u16);
4463        self.as_rec_mut().extend(value.to_ne_bytes());
4464        self
4465    }
4466    #[doc = "See `rx-hw-gro-wire-packets`."]
4467    pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
4468        push_header(self.as_rec_mut(), 22u16, 4 as u16);
4469        self.as_rec_mut().extend(value.to_ne_bytes());
4470        self
4471    }
4472    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
4473    pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4474        push_header(self.as_rec_mut(), 23u16, 4 as u16);
4475        self.as_rec_mut().extend(value.to_ne_bytes());
4476        self
4477    }
4478    #[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"]
4479    pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
4480        push_header(self.as_rec_mut(), 24u16, 4 as u16);
4481        self.as_rec_mut().extend(value.to_ne_bytes());
4482        self
4483    }
4484    #[doc = "Number of packets dropped because they were invalid or malformed."]
4485    pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
4486        push_header(self.as_rec_mut(), 25u16, 4 as u16);
4487        self.as_rec_mut().extend(value.to_ne_bytes());
4488        self
4489    }
4490    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
4491    pub fn push_tx_csum_none(mut self, value: u32) -> Self {
4492        push_header(self.as_rec_mut(), 26u16, 4 as u16);
4493        self.as_rec_mut().extend(value.to_ne_bytes());
4494        self
4495    }
4496    #[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"]
4497    pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
4498        push_header(self.as_rec_mut(), 27u16, 4 as u16);
4499        self.as_rec_mut().extend(value.to_ne_bytes());
4500        self
4501    }
4502    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
4503    pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
4504        push_header(self.as_rec_mut(), 28u16, 4 as u16);
4505        self.as_rec_mut().extend(value.to_ne_bytes());
4506        self
4507    }
4508    #[doc = "See `tx-hw-gso-packets`."]
4509    pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
4510        push_header(self.as_rec_mut(), 29u16, 4 as u16);
4511        self.as_rec_mut().extend(value.to_ne_bytes());
4512        self
4513    }
4514    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
4515    pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
4516        push_header(self.as_rec_mut(), 30u16, 4 as u16);
4517        self.as_rec_mut().extend(value.to_ne_bytes());
4518        self
4519    }
4520    #[doc = "See `tx-hw-gso-wire-packets`."]
4521    pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
4522        push_header(self.as_rec_mut(), 31u16, 4 as u16);
4523        self.as_rec_mut().extend(value.to_ne_bytes());
4524        self
4525    }
4526    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
4527    pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4528        push_header(self.as_rec_mut(), 32u16, 4 as u16);
4529        self.as_rec_mut().extend(value.to_ne_bytes());
4530        self
4531    }
4532    #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
4533    pub fn push_tx_stop(mut self, value: u32) -> Self {
4534        push_header(self.as_rec_mut(), 33u16, 4 as u16);
4535        self.as_rec_mut().extend(value.to_ne_bytes());
4536        self
4537    }
4538    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
4539    pub fn push_tx_wake(mut self, value: u32) -> Self {
4540        push_header(self.as_rec_mut(), 34u16, 4 as u16);
4541        self.as_rec_mut().extend(value.to_ne_bytes());
4542        self
4543    }
4544}
4545impl<Prev: Rec> Drop for PushQstats<Prev> {
4546    fn drop(&mut self) {
4547        if let Some(prev) = &mut self.prev {
4548            if let Some(header_offset) = &self.header_offset {
4549                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4550            }
4551        }
4552    }
4553}
4554pub struct PushQueueId<Prev: Rec> {
4555    pub(crate) prev: Option<Prev>,
4556    pub(crate) header_offset: Option<usize>,
4557}
4558impl<Prev: Rec> Rec for PushQueueId<Prev> {
4559    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4560        self.prev.as_mut().unwrap().as_rec_mut()
4561    }
4562    fn as_rec(&self) -> &Vec<u8> {
4563        self.prev.as_ref().unwrap().as_rec()
4564    }
4565}
4566impl<Prev: Rec> PushQueueId<Prev> {
4567    pub fn new(prev: Prev) -> Self {
4568        Self {
4569            prev: Some(prev),
4570            header_offset: None,
4571        }
4572    }
4573    pub fn end_nested(mut self) -> Prev {
4574        let mut prev = self.prev.take().unwrap();
4575        if let Some(header_offset) = &self.header_offset {
4576            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4577        }
4578        prev
4579    }
4580    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
4581    pub fn push_id(mut self, value: u32) -> Self {
4582        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4583        self.as_rec_mut().extend(value.to_ne_bytes());
4584        self
4585    }
4586    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
4587    pub fn push_type(mut self, value: u32) -> Self {
4588        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4589        self.as_rec_mut().extend(value.to_ne_bytes());
4590        self
4591    }
4592}
4593impl<Prev: Rec> Drop for PushQueueId<Prev> {
4594    fn drop(&mut self) {
4595        if let Some(prev) = &mut self.prev {
4596            if let Some(header_offset) = &self.header_offset {
4597                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4598            }
4599        }
4600    }
4601}
4602pub struct PushDmabuf<Prev: Rec> {
4603    pub(crate) prev: Option<Prev>,
4604    pub(crate) header_offset: Option<usize>,
4605}
4606impl<Prev: Rec> Rec for PushDmabuf<Prev> {
4607    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4608        self.prev.as_mut().unwrap().as_rec_mut()
4609    }
4610    fn as_rec(&self) -> &Vec<u8> {
4611        self.prev.as_ref().unwrap().as_rec()
4612    }
4613}
4614impl<Prev: Rec> PushDmabuf<Prev> {
4615    pub fn new(prev: Prev) -> Self {
4616        Self {
4617            prev: Some(prev),
4618            header_offset: None,
4619        }
4620    }
4621    pub fn end_nested(mut self) -> Prev {
4622        let mut prev = self.prev.take().unwrap();
4623        if let Some(header_offset) = &self.header_offset {
4624            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4625        }
4626        prev
4627    }
4628    #[doc = "netdev ifindex to bind the dmabuf to."]
4629    pub fn push_ifindex(mut self, value: u32) -> Self {
4630        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4631        self.as_rec_mut().extend(value.to_ne_bytes());
4632        self
4633    }
4634    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
4635    pub fn nested_queues(mut self) -> PushQueueId<Self> {
4636        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
4637        PushQueueId {
4638            prev: Some(self),
4639            header_offset: Some(header_offset),
4640        }
4641    }
4642    #[doc = "dmabuf file descriptor to bind."]
4643    pub fn push_fd(mut self, value: u32) -> Self {
4644        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4645        self.as_rec_mut().extend(value.to_ne_bytes());
4646        self
4647    }
4648    #[doc = "id of the dmabuf binding"]
4649    pub fn push_id(mut self, value: u32) -> Self {
4650        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4651        self.as_rec_mut().extend(value.to_ne_bytes());
4652        self
4653    }
4654}
4655impl<Prev: Rec> Drop for PushDmabuf<Prev> {
4656    fn drop(&mut self) {
4657        if let Some(prev) = &mut self.prev {
4658            if let Some(header_offset) = &self.header_offset {
4659                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4660            }
4661        }
4662    }
4663}
4664#[doc = "Get / dump information about a netdev."]
4665pub struct PushOpDevGetDumpRequest<Prev: Rec> {
4666    pub(crate) prev: Option<Prev>,
4667    pub(crate) header_offset: Option<usize>,
4668}
4669impl<Prev: Rec> Rec for PushOpDevGetDumpRequest<Prev> {
4670    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4671        self.prev.as_mut().unwrap().as_rec_mut()
4672    }
4673    fn as_rec(&self) -> &Vec<u8> {
4674        self.prev.as_ref().unwrap().as_rec()
4675    }
4676}
4677impl<Prev: Rec> PushOpDevGetDumpRequest<Prev> {
4678    pub fn new(mut prev: Prev) -> Self {
4679        Self::write_header(&mut prev);
4680        Self::new_without_header(prev)
4681    }
4682    fn new_without_header(prev: Prev) -> Self {
4683        Self {
4684            prev: Some(prev),
4685            header_offset: None,
4686        }
4687    }
4688    fn write_header(prev: &mut Prev) {
4689        let mut header = PushBuiltinNfgenmsg::new();
4690        header.set_cmd(1u8);
4691        header.set_version(1u8);
4692        prev.as_rec_mut().extend(header.as_slice());
4693    }
4694    pub fn end_nested(mut self) -> Prev {
4695        let mut prev = self.prev.take().unwrap();
4696        if let Some(header_offset) = &self.header_offset {
4697            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4698        }
4699        prev
4700    }
4701}
4702impl<Prev: Rec> Drop for PushOpDevGetDumpRequest<Prev> {
4703    fn drop(&mut self) {
4704        if let Some(prev) = &mut self.prev {
4705            if let Some(header_offset) = &self.header_offset {
4706                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4707            }
4708        }
4709    }
4710}
4711#[doc = "Get / dump information about a netdev."]
4712#[derive(Clone)]
4713pub enum OpDevGetDumpRequest {}
4714impl<'a> IterableOpDevGetDumpRequest<'a> {}
4715impl OpDevGetDumpRequest {
4716    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpRequest<'a> {
4717        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4718        IterableOpDevGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
4719    }
4720    fn attr_from_type(r#type: u16) -> Option<&'static str> {
4721        Dev::attr_from_type(r#type)
4722    }
4723}
4724#[derive(Clone, Copy, Default)]
4725pub struct IterableOpDevGetDumpRequest<'a> {
4726    buf: &'a [u8],
4727    pos: usize,
4728    orig_loc: usize,
4729}
4730impl<'a> IterableOpDevGetDumpRequest<'a> {
4731    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4732        Self {
4733            buf,
4734            pos: 0,
4735            orig_loc,
4736        }
4737    }
4738    pub fn get_buf(&self) -> &'a [u8] {
4739        self.buf
4740    }
4741}
4742impl<'a> Iterator for IterableOpDevGetDumpRequest<'a> {
4743    type Item = Result<OpDevGetDumpRequest, ErrorContext>;
4744    fn next(&mut self) -> Option<Self::Item> {
4745        let pos = self.pos;
4746        let mut r#type;
4747        loop {
4748            r#type = None;
4749            if self.buf.len() == self.pos {
4750                return None;
4751            }
4752            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
4753                break;
4754            };
4755            r#type = Some(header.r#type);
4756            let res = match header.r#type {
4757                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4758                n => continue,
4759            };
4760            return Some(Ok(res));
4761        }
4762        Some(Err(ErrorContext::new(
4763            "OpDevGetDumpRequest",
4764            r#type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4765            self.orig_loc,
4766            self.buf.as_ptr().wrapping_add(pos) as usize,
4767        )))
4768    }
4769}
4770impl std::fmt::Debug for IterableOpDevGetDumpRequest<'_> {
4771    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4772        let mut fmt = f.debug_struct("OpDevGetDumpRequest");
4773        for attr in self.clone() {
4774            let attr = match attr {
4775                Ok(a) => a,
4776                Err(err) => {
4777                    fmt.finish()?;
4778                    f.write_str("Err(")?;
4779                    err.fmt(f)?;
4780                    return f.write_str(")");
4781                }
4782            };
4783            match attr {};
4784        }
4785        fmt.finish()
4786    }
4787}
4788impl IterableOpDevGetDumpRequest<'_> {
4789    pub fn lookup_attr(
4790        &self,
4791        offset: usize,
4792        missing_type: Option<u16>,
4793    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4794        let mut stack = Vec::new();
4795        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4796        if cur == offset + PushBuiltinNfgenmsg::len() {
4797            stack.push(("OpDevGetDumpRequest", offset));
4798            return (
4799                stack,
4800                missing_type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4801            );
4802        }
4803        (stack, None)
4804    }
4805}
4806#[doc = "Get / dump information about a netdev."]
4807pub struct PushOpDevGetDumpReply<Prev: Rec> {
4808    pub(crate) prev: Option<Prev>,
4809    pub(crate) header_offset: Option<usize>,
4810}
4811impl<Prev: Rec> Rec for PushOpDevGetDumpReply<Prev> {
4812    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4813        self.prev.as_mut().unwrap().as_rec_mut()
4814    }
4815    fn as_rec(&self) -> &Vec<u8> {
4816        self.prev.as_ref().unwrap().as_rec()
4817    }
4818}
4819impl<Prev: Rec> PushOpDevGetDumpReply<Prev> {
4820    pub fn new(mut prev: Prev) -> Self {
4821        Self::write_header(&mut prev);
4822        Self::new_without_header(prev)
4823    }
4824    fn new_without_header(prev: Prev) -> Self {
4825        Self {
4826            prev: Some(prev),
4827            header_offset: None,
4828        }
4829    }
4830    fn write_header(prev: &mut Prev) {
4831        let mut header = PushBuiltinNfgenmsg::new();
4832        header.set_cmd(1u8);
4833        header.set_version(1u8);
4834        prev.as_rec_mut().extend(header.as_slice());
4835    }
4836    pub fn end_nested(mut self) -> Prev {
4837        let mut prev = self.prev.take().unwrap();
4838        if let Some(header_offset) = &self.header_offset {
4839            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4840        }
4841        prev
4842    }
4843    #[doc = "netdev ifindex"]
4844    pub fn push_ifindex(mut self, value: u32) -> Self {
4845        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4846        self.as_rec_mut().extend(value.to_ne_bytes());
4847        self
4848    }
4849    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4850    pub fn push_xdp_features(mut self, value: u64) -> Self {
4851        push_header(self.as_rec_mut(), 3u16, 8 as u16);
4852        self.as_rec_mut().extend(value.to_ne_bytes());
4853        self
4854    }
4855    #[doc = "max fragment count supported by ZC driver"]
4856    pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
4857        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4858        self.as_rec_mut().extend(value.to_ne_bytes());
4859        self
4860    }
4861    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4862    pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
4863        push_header(self.as_rec_mut(), 5u16, 8 as u16);
4864        self.as_rec_mut().extend(value.to_ne_bytes());
4865        self
4866    }
4867    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4868    pub fn push_xsk_features(mut self, value: u64) -> Self {
4869        push_header(self.as_rec_mut(), 6u16, 8 as u16);
4870        self.as_rec_mut().extend(value.to_ne_bytes());
4871        self
4872    }
4873}
4874impl<Prev: Rec> Drop for PushOpDevGetDumpReply<Prev> {
4875    fn drop(&mut self) {
4876        if let Some(prev) = &mut self.prev {
4877            if let Some(header_offset) = &self.header_offset {
4878                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4879            }
4880        }
4881    }
4882}
4883#[doc = "Get / dump information about a netdev."]
4884#[derive(Clone)]
4885pub enum OpDevGetDumpReply {
4886    #[doc = "netdev ifindex"]
4887    Ifindex(u32),
4888    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4889    XdpFeatures(u64),
4890    #[doc = "max fragment count supported by ZC driver"]
4891    XdpZcMaxSegs(u32),
4892    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4893    XdpRxMetadataFeatures(u64),
4894    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4895    XskFeatures(u64),
4896}
4897impl<'a> IterableOpDevGetDumpReply<'a> {
4898    #[doc = "netdev ifindex"]
4899    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
4900        let mut iter = self.clone();
4901        iter.pos = 0;
4902        for attr in iter {
4903            if let OpDevGetDumpReply::Ifindex(val) = attr? {
4904                return Ok(val);
4905            }
4906        }
4907        Err(ErrorContext::new_missing(
4908            "OpDevGetDumpReply",
4909            "Ifindex",
4910            self.orig_loc,
4911            self.buf.as_ptr() as usize,
4912        ))
4913    }
4914    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4915    pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
4916        let mut iter = self.clone();
4917        iter.pos = 0;
4918        for attr in iter {
4919            if let OpDevGetDumpReply::XdpFeatures(val) = attr? {
4920                return Ok(val);
4921            }
4922        }
4923        Err(ErrorContext::new_missing(
4924            "OpDevGetDumpReply",
4925            "XdpFeatures",
4926            self.orig_loc,
4927            self.buf.as_ptr() as usize,
4928        ))
4929    }
4930    #[doc = "max fragment count supported by ZC driver"]
4931    pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
4932        let mut iter = self.clone();
4933        iter.pos = 0;
4934        for attr in iter {
4935            if let OpDevGetDumpReply::XdpZcMaxSegs(val) = attr? {
4936                return Ok(val);
4937            }
4938        }
4939        Err(ErrorContext::new_missing(
4940            "OpDevGetDumpReply",
4941            "XdpZcMaxSegs",
4942            self.orig_loc,
4943            self.buf.as_ptr() as usize,
4944        ))
4945    }
4946    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4947    pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
4948        let mut iter = self.clone();
4949        iter.pos = 0;
4950        for attr in iter {
4951            if let OpDevGetDumpReply::XdpRxMetadataFeatures(val) = attr? {
4952                return Ok(val);
4953            }
4954        }
4955        Err(ErrorContext::new_missing(
4956            "OpDevGetDumpReply",
4957            "XdpRxMetadataFeatures",
4958            self.orig_loc,
4959            self.buf.as_ptr() as usize,
4960        ))
4961    }
4962    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4963    pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
4964        let mut iter = self.clone();
4965        iter.pos = 0;
4966        for attr in iter {
4967            if let OpDevGetDumpReply::XskFeatures(val) = attr? {
4968                return Ok(val);
4969            }
4970        }
4971        Err(ErrorContext::new_missing(
4972            "OpDevGetDumpReply",
4973            "XskFeatures",
4974            self.orig_loc,
4975            self.buf.as_ptr() as usize,
4976        ))
4977    }
4978}
4979impl OpDevGetDumpReply {
4980    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpReply<'a> {
4981        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4982        IterableOpDevGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
4983    }
4984    fn attr_from_type(r#type: u16) -> Option<&'static str> {
4985        Dev::attr_from_type(r#type)
4986    }
4987}
4988#[derive(Clone, Copy, Default)]
4989pub struct IterableOpDevGetDumpReply<'a> {
4990    buf: &'a [u8],
4991    pos: usize,
4992    orig_loc: usize,
4993}
4994impl<'a> IterableOpDevGetDumpReply<'a> {
4995    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4996        Self {
4997            buf,
4998            pos: 0,
4999            orig_loc,
5000        }
5001    }
5002    pub fn get_buf(&self) -> &'a [u8] {
5003        self.buf
5004    }
5005}
5006impl<'a> Iterator for IterableOpDevGetDumpReply<'a> {
5007    type Item = Result<OpDevGetDumpReply, ErrorContext>;
5008    fn next(&mut self) -> Option<Self::Item> {
5009        let pos = self.pos;
5010        let mut r#type;
5011        loop {
5012            r#type = None;
5013            if self.buf.len() == self.pos {
5014                return None;
5015            }
5016            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5017                break;
5018            };
5019            r#type = Some(header.r#type);
5020            let res = match header.r#type {
5021                1u16 => OpDevGetDumpReply::Ifindex({
5022                    let res = parse_u32(next);
5023                    let Some(val) = res else { break };
5024                    val
5025                }),
5026                3u16 => OpDevGetDumpReply::XdpFeatures({
5027                    let res = parse_u64(next);
5028                    let Some(val) = res else { break };
5029                    val
5030                }),
5031                4u16 => OpDevGetDumpReply::XdpZcMaxSegs({
5032                    let res = parse_u32(next);
5033                    let Some(val) = res else { break };
5034                    val
5035                }),
5036                5u16 => OpDevGetDumpReply::XdpRxMetadataFeatures({
5037                    let res = parse_u64(next);
5038                    let Some(val) = res else { break };
5039                    val
5040                }),
5041                6u16 => OpDevGetDumpReply::XskFeatures({
5042                    let res = parse_u64(next);
5043                    let Some(val) = res else { break };
5044                    val
5045                }),
5046                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5047                n => continue,
5048            };
5049            return Some(Ok(res));
5050        }
5051        Some(Err(ErrorContext::new(
5052            "OpDevGetDumpReply",
5053            r#type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5054            self.orig_loc,
5055            self.buf.as_ptr().wrapping_add(pos) as usize,
5056        )))
5057    }
5058}
5059impl std::fmt::Debug for IterableOpDevGetDumpReply<'_> {
5060    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5061        let mut fmt = f.debug_struct("OpDevGetDumpReply");
5062        for attr in self.clone() {
5063            let attr = match attr {
5064                Ok(a) => a,
5065                Err(err) => {
5066                    fmt.finish()?;
5067                    f.write_str("Err(")?;
5068                    err.fmt(f)?;
5069                    return f.write_str(")");
5070                }
5071            };
5072            match attr {
5073                OpDevGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
5074                OpDevGetDumpReply::XdpFeatures(val) => {
5075                    fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5076                }
5077                OpDevGetDumpReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5078                OpDevGetDumpReply::XdpRxMetadataFeatures(val) => fmt.field(
5079                    "XdpRxMetadataFeatures",
5080                    &FormatFlags(val.into(), XdpRxMetadata::from_value),
5081                ),
5082                OpDevGetDumpReply::XskFeatures(val) => fmt.field(
5083                    "XskFeatures",
5084                    &FormatFlags(val.into(), XskFlags::from_value),
5085                ),
5086            };
5087        }
5088        fmt.finish()
5089    }
5090}
5091impl IterableOpDevGetDumpReply<'_> {
5092    pub fn lookup_attr(
5093        &self,
5094        offset: usize,
5095        missing_type: Option<u16>,
5096    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5097        let mut stack = Vec::new();
5098        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5099        if cur == offset + PushBuiltinNfgenmsg::len() {
5100            stack.push(("OpDevGetDumpReply", offset));
5101            return (
5102                stack,
5103                missing_type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5104            );
5105        }
5106        if cur > offset || cur + self.buf.len() < offset {
5107            return (stack, None);
5108        }
5109        let mut attrs = self.clone();
5110        let mut last_off = cur + attrs.pos;
5111        while let Some(attr) = attrs.next() {
5112            let Ok(attr) = attr else { break };
5113            match attr {
5114                OpDevGetDumpReply::Ifindex(val) => {
5115                    if last_off == offset {
5116                        stack.push(("Ifindex", last_off));
5117                        break;
5118                    }
5119                }
5120                OpDevGetDumpReply::XdpFeatures(val) => {
5121                    if last_off == offset {
5122                        stack.push(("XdpFeatures", last_off));
5123                        break;
5124                    }
5125                }
5126                OpDevGetDumpReply::XdpZcMaxSegs(val) => {
5127                    if last_off == offset {
5128                        stack.push(("XdpZcMaxSegs", last_off));
5129                        break;
5130                    }
5131                }
5132                OpDevGetDumpReply::XdpRxMetadataFeatures(val) => {
5133                    if last_off == offset {
5134                        stack.push(("XdpRxMetadataFeatures", last_off));
5135                        break;
5136                    }
5137                }
5138                OpDevGetDumpReply::XskFeatures(val) => {
5139                    if last_off == offset {
5140                        stack.push(("XskFeatures", last_off));
5141                        break;
5142                    }
5143                }
5144                _ => {}
5145            };
5146            last_off = cur + attrs.pos;
5147        }
5148        if !stack.is_empty() {
5149            stack.push(("OpDevGetDumpReply", cur));
5150        }
5151        (stack, None)
5152    }
5153}
5154#[derive(Debug)]
5155pub struct RequestOpDevGetDumpRequest<'r> {
5156    request: Request<'r>,
5157}
5158impl<'r> RequestOpDevGetDumpRequest<'r> {
5159    pub fn new(mut request: Request<'r>) -> Self {
5160        PushOpDevGetDumpRequest::write_header(&mut request.buf_mut());
5161        Self {
5162            request: request.set_dump(),
5163        }
5164    }
5165    pub fn encode(&mut self) -> PushOpDevGetDumpRequest<&mut Vec<u8>> {
5166        PushOpDevGetDumpRequest::new_without_header(self.request.buf_mut())
5167    }
5168    pub fn into_encoder(self) -> PushOpDevGetDumpRequest<RequestBuf<'r>> {
5169        PushOpDevGetDumpRequest::new_without_header(self.request.buf)
5170    }
5171    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpDevGetDumpRequest<'buf> {
5172        OpDevGetDumpRequest::new(buf)
5173    }
5174}
5175impl NetlinkRequest for RequestOpDevGetDumpRequest<'_> {
5176    fn protocol(&self) -> Protocol {
5177        Protocol::Generic("netdev".as_bytes())
5178    }
5179    fn flags(&self) -> u16 {
5180        self.request.flags
5181    }
5182    fn payload(&self) -> &[u8] {
5183        self.request.buf()
5184    }
5185    type ReplyType<'buf> = IterableOpDevGetDumpReply<'buf>;
5186    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5187        OpDevGetDumpReply::new(buf)
5188    }
5189    fn lookup(
5190        buf: &[u8],
5191        offset: usize,
5192        missing_type: Option<u16>,
5193    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5194        OpDevGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
5195    }
5196}
5197#[doc = "Get / dump information about a netdev."]
5198pub struct PushOpDevGetDoRequest<Prev: Rec> {
5199    pub(crate) prev: Option<Prev>,
5200    pub(crate) header_offset: Option<usize>,
5201}
5202impl<Prev: Rec> Rec for PushOpDevGetDoRequest<Prev> {
5203    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5204        self.prev.as_mut().unwrap().as_rec_mut()
5205    }
5206    fn as_rec(&self) -> &Vec<u8> {
5207        self.prev.as_ref().unwrap().as_rec()
5208    }
5209}
5210impl<Prev: Rec> PushOpDevGetDoRequest<Prev> {
5211    pub fn new(mut prev: Prev) -> Self {
5212        Self::write_header(&mut prev);
5213        Self::new_without_header(prev)
5214    }
5215    fn new_without_header(prev: Prev) -> Self {
5216        Self {
5217            prev: Some(prev),
5218            header_offset: None,
5219        }
5220    }
5221    fn write_header(prev: &mut Prev) {
5222        let mut header = PushBuiltinNfgenmsg::new();
5223        header.set_cmd(1u8);
5224        header.set_version(1u8);
5225        prev.as_rec_mut().extend(header.as_slice());
5226    }
5227    pub fn end_nested(mut self) -> Prev {
5228        let mut prev = self.prev.take().unwrap();
5229        if let Some(header_offset) = &self.header_offset {
5230            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5231        }
5232        prev
5233    }
5234    #[doc = "netdev ifindex"]
5235    pub fn push_ifindex(mut self, value: u32) -> Self {
5236        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5237        self.as_rec_mut().extend(value.to_ne_bytes());
5238        self
5239    }
5240}
5241impl<Prev: Rec> Drop for PushOpDevGetDoRequest<Prev> {
5242    fn drop(&mut self) {
5243        if let Some(prev) = &mut self.prev {
5244            if let Some(header_offset) = &self.header_offset {
5245                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5246            }
5247        }
5248    }
5249}
5250#[doc = "Get / dump information about a netdev."]
5251#[derive(Clone)]
5252pub enum OpDevGetDoRequest {
5253    #[doc = "netdev ifindex"]
5254    Ifindex(u32),
5255}
5256impl<'a> IterableOpDevGetDoRequest<'a> {
5257    #[doc = "netdev ifindex"]
5258    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5259        let mut iter = self.clone();
5260        iter.pos = 0;
5261        for attr in iter {
5262            if let OpDevGetDoRequest::Ifindex(val) = attr? {
5263                return Ok(val);
5264            }
5265        }
5266        Err(ErrorContext::new_missing(
5267            "OpDevGetDoRequest",
5268            "Ifindex",
5269            self.orig_loc,
5270            self.buf.as_ptr() as usize,
5271        ))
5272    }
5273}
5274impl OpDevGetDoRequest {
5275    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoRequest<'a> {
5276        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5277        IterableOpDevGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
5278    }
5279    fn attr_from_type(r#type: u16) -> Option<&'static str> {
5280        Dev::attr_from_type(r#type)
5281    }
5282}
5283#[derive(Clone, Copy, Default)]
5284pub struct IterableOpDevGetDoRequest<'a> {
5285    buf: &'a [u8],
5286    pos: usize,
5287    orig_loc: usize,
5288}
5289impl<'a> IterableOpDevGetDoRequest<'a> {
5290    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5291        Self {
5292            buf,
5293            pos: 0,
5294            orig_loc,
5295        }
5296    }
5297    pub fn get_buf(&self) -> &'a [u8] {
5298        self.buf
5299    }
5300}
5301impl<'a> Iterator for IterableOpDevGetDoRequest<'a> {
5302    type Item = Result<OpDevGetDoRequest, ErrorContext>;
5303    fn next(&mut self) -> Option<Self::Item> {
5304        let pos = self.pos;
5305        let mut r#type;
5306        loop {
5307            r#type = None;
5308            if self.buf.len() == self.pos {
5309                return None;
5310            }
5311            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5312                break;
5313            };
5314            r#type = Some(header.r#type);
5315            let res = match header.r#type {
5316                1u16 => OpDevGetDoRequest::Ifindex({
5317                    let res = parse_u32(next);
5318                    let Some(val) = res else { break };
5319                    val
5320                }),
5321                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5322                n => continue,
5323            };
5324            return Some(Ok(res));
5325        }
5326        Some(Err(ErrorContext::new(
5327            "OpDevGetDoRequest",
5328            r#type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5329            self.orig_loc,
5330            self.buf.as_ptr().wrapping_add(pos) as usize,
5331        )))
5332    }
5333}
5334impl std::fmt::Debug for IterableOpDevGetDoRequest<'_> {
5335    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5336        let mut fmt = f.debug_struct("OpDevGetDoRequest");
5337        for attr in self.clone() {
5338            let attr = match attr {
5339                Ok(a) => a,
5340                Err(err) => {
5341                    fmt.finish()?;
5342                    f.write_str("Err(")?;
5343                    err.fmt(f)?;
5344                    return f.write_str(")");
5345                }
5346            };
5347            match attr {
5348                OpDevGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
5349            };
5350        }
5351        fmt.finish()
5352    }
5353}
5354impl IterableOpDevGetDoRequest<'_> {
5355    pub fn lookup_attr(
5356        &self,
5357        offset: usize,
5358        missing_type: Option<u16>,
5359    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5360        let mut stack = Vec::new();
5361        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5362        if cur == offset + PushBuiltinNfgenmsg::len() {
5363            stack.push(("OpDevGetDoRequest", offset));
5364            return (
5365                stack,
5366                missing_type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5367            );
5368        }
5369        if cur > offset || cur + self.buf.len() < offset {
5370            return (stack, None);
5371        }
5372        let mut attrs = self.clone();
5373        let mut last_off = cur + attrs.pos;
5374        while let Some(attr) = attrs.next() {
5375            let Ok(attr) = attr else { break };
5376            match attr {
5377                OpDevGetDoRequest::Ifindex(val) => {
5378                    if last_off == offset {
5379                        stack.push(("Ifindex", last_off));
5380                        break;
5381                    }
5382                }
5383                _ => {}
5384            };
5385            last_off = cur + attrs.pos;
5386        }
5387        if !stack.is_empty() {
5388            stack.push(("OpDevGetDoRequest", cur));
5389        }
5390        (stack, None)
5391    }
5392}
5393#[doc = "Get / dump information about a netdev."]
5394pub struct PushOpDevGetDoReply<Prev: Rec> {
5395    pub(crate) prev: Option<Prev>,
5396    pub(crate) header_offset: Option<usize>,
5397}
5398impl<Prev: Rec> Rec for PushOpDevGetDoReply<Prev> {
5399    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5400        self.prev.as_mut().unwrap().as_rec_mut()
5401    }
5402    fn as_rec(&self) -> &Vec<u8> {
5403        self.prev.as_ref().unwrap().as_rec()
5404    }
5405}
5406impl<Prev: Rec> PushOpDevGetDoReply<Prev> {
5407    pub fn new(mut prev: Prev) -> Self {
5408        Self::write_header(&mut prev);
5409        Self::new_without_header(prev)
5410    }
5411    fn new_without_header(prev: Prev) -> Self {
5412        Self {
5413            prev: Some(prev),
5414            header_offset: None,
5415        }
5416    }
5417    fn write_header(prev: &mut Prev) {
5418        let mut header = PushBuiltinNfgenmsg::new();
5419        header.set_cmd(1u8);
5420        header.set_version(1u8);
5421        prev.as_rec_mut().extend(header.as_slice());
5422    }
5423    pub fn end_nested(mut self) -> Prev {
5424        let mut prev = self.prev.take().unwrap();
5425        if let Some(header_offset) = &self.header_offset {
5426            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5427        }
5428        prev
5429    }
5430    #[doc = "netdev ifindex"]
5431    pub fn push_ifindex(mut self, value: u32) -> Self {
5432        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5433        self.as_rec_mut().extend(value.to_ne_bytes());
5434        self
5435    }
5436    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5437    pub fn push_xdp_features(mut self, value: u64) -> Self {
5438        push_header(self.as_rec_mut(), 3u16, 8 as u16);
5439        self.as_rec_mut().extend(value.to_ne_bytes());
5440        self
5441    }
5442    #[doc = "max fragment count supported by ZC driver"]
5443    pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
5444        push_header(self.as_rec_mut(), 4u16, 4 as u16);
5445        self.as_rec_mut().extend(value.to_ne_bytes());
5446        self
5447    }
5448    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5449    pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
5450        push_header(self.as_rec_mut(), 5u16, 8 as u16);
5451        self.as_rec_mut().extend(value.to_ne_bytes());
5452        self
5453    }
5454    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5455    pub fn push_xsk_features(mut self, value: u64) -> Self {
5456        push_header(self.as_rec_mut(), 6u16, 8 as u16);
5457        self.as_rec_mut().extend(value.to_ne_bytes());
5458        self
5459    }
5460}
5461impl<Prev: Rec> Drop for PushOpDevGetDoReply<Prev> {
5462    fn drop(&mut self) {
5463        if let Some(prev) = &mut self.prev {
5464            if let Some(header_offset) = &self.header_offset {
5465                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5466            }
5467        }
5468    }
5469}
5470#[doc = "Get / dump information about a netdev."]
5471#[derive(Clone)]
5472pub enum OpDevGetDoReply {
5473    #[doc = "netdev ifindex"]
5474    Ifindex(u32),
5475    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5476    XdpFeatures(u64),
5477    #[doc = "max fragment count supported by ZC driver"]
5478    XdpZcMaxSegs(u32),
5479    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5480    XdpRxMetadataFeatures(u64),
5481    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5482    XskFeatures(u64),
5483}
5484impl<'a> IterableOpDevGetDoReply<'a> {
5485    #[doc = "netdev ifindex"]
5486    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5487        let mut iter = self.clone();
5488        iter.pos = 0;
5489        for attr in iter {
5490            if let OpDevGetDoReply::Ifindex(val) = attr? {
5491                return Ok(val);
5492            }
5493        }
5494        Err(ErrorContext::new_missing(
5495            "OpDevGetDoReply",
5496            "Ifindex",
5497            self.orig_loc,
5498            self.buf.as_ptr() as usize,
5499        ))
5500    }
5501    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5502    pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
5503        let mut iter = self.clone();
5504        iter.pos = 0;
5505        for attr in iter {
5506            if let OpDevGetDoReply::XdpFeatures(val) = attr? {
5507                return Ok(val);
5508            }
5509        }
5510        Err(ErrorContext::new_missing(
5511            "OpDevGetDoReply",
5512            "XdpFeatures",
5513            self.orig_loc,
5514            self.buf.as_ptr() as usize,
5515        ))
5516    }
5517    #[doc = "max fragment count supported by ZC driver"]
5518    pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
5519        let mut iter = self.clone();
5520        iter.pos = 0;
5521        for attr in iter {
5522            if let OpDevGetDoReply::XdpZcMaxSegs(val) = attr? {
5523                return Ok(val);
5524            }
5525        }
5526        Err(ErrorContext::new_missing(
5527            "OpDevGetDoReply",
5528            "XdpZcMaxSegs",
5529            self.orig_loc,
5530            self.buf.as_ptr() as usize,
5531        ))
5532    }
5533    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5534    pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
5535        let mut iter = self.clone();
5536        iter.pos = 0;
5537        for attr in iter {
5538            if let OpDevGetDoReply::XdpRxMetadataFeatures(val) = attr? {
5539                return Ok(val);
5540            }
5541        }
5542        Err(ErrorContext::new_missing(
5543            "OpDevGetDoReply",
5544            "XdpRxMetadataFeatures",
5545            self.orig_loc,
5546            self.buf.as_ptr() as usize,
5547        ))
5548    }
5549    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5550    pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
5551        let mut iter = self.clone();
5552        iter.pos = 0;
5553        for attr in iter {
5554            if let OpDevGetDoReply::XskFeatures(val) = attr? {
5555                return Ok(val);
5556            }
5557        }
5558        Err(ErrorContext::new_missing(
5559            "OpDevGetDoReply",
5560            "XskFeatures",
5561            self.orig_loc,
5562            self.buf.as_ptr() as usize,
5563        ))
5564    }
5565}
5566impl OpDevGetDoReply {
5567    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoReply<'a> {
5568        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5569        IterableOpDevGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
5570    }
5571    fn attr_from_type(r#type: u16) -> Option<&'static str> {
5572        Dev::attr_from_type(r#type)
5573    }
5574}
5575#[derive(Clone, Copy, Default)]
5576pub struct IterableOpDevGetDoReply<'a> {
5577    buf: &'a [u8],
5578    pos: usize,
5579    orig_loc: usize,
5580}
5581impl<'a> IterableOpDevGetDoReply<'a> {
5582    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5583        Self {
5584            buf,
5585            pos: 0,
5586            orig_loc,
5587        }
5588    }
5589    pub fn get_buf(&self) -> &'a [u8] {
5590        self.buf
5591    }
5592}
5593impl<'a> Iterator for IterableOpDevGetDoReply<'a> {
5594    type Item = Result<OpDevGetDoReply, ErrorContext>;
5595    fn next(&mut self) -> Option<Self::Item> {
5596        let pos = self.pos;
5597        let mut r#type;
5598        loop {
5599            r#type = None;
5600            if self.buf.len() == self.pos {
5601                return None;
5602            }
5603            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5604                break;
5605            };
5606            r#type = Some(header.r#type);
5607            let res = match header.r#type {
5608                1u16 => OpDevGetDoReply::Ifindex({
5609                    let res = parse_u32(next);
5610                    let Some(val) = res else { break };
5611                    val
5612                }),
5613                3u16 => OpDevGetDoReply::XdpFeatures({
5614                    let res = parse_u64(next);
5615                    let Some(val) = res else { break };
5616                    val
5617                }),
5618                4u16 => OpDevGetDoReply::XdpZcMaxSegs({
5619                    let res = parse_u32(next);
5620                    let Some(val) = res else { break };
5621                    val
5622                }),
5623                5u16 => OpDevGetDoReply::XdpRxMetadataFeatures({
5624                    let res = parse_u64(next);
5625                    let Some(val) = res else { break };
5626                    val
5627                }),
5628                6u16 => OpDevGetDoReply::XskFeatures({
5629                    let res = parse_u64(next);
5630                    let Some(val) = res else { break };
5631                    val
5632                }),
5633                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5634                n => continue,
5635            };
5636            return Some(Ok(res));
5637        }
5638        Some(Err(ErrorContext::new(
5639            "OpDevGetDoReply",
5640            r#type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5641            self.orig_loc,
5642            self.buf.as_ptr().wrapping_add(pos) as usize,
5643        )))
5644    }
5645}
5646impl std::fmt::Debug for IterableOpDevGetDoReply<'_> {
5647    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5648        let mut fmt = f.debug_struct("OpDevGetDoReply");
5649        for attr in self.clone() {
5650            let attr = match attr {
5651                Ok(a) => a,
5652                Err(err) => {
5653                    fmt.finish()?;
5654                    f.write_str("Err(")?;
5655                    err.fmt(f)?;
5656                    return f.write_str(")");
5657                }
5658            };
5659            match attr {
5660                OpDevGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
5661                OpDevGetDoReply::XdpFeatures(val) => {
5662                    fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5663                }
5664                OpDevGetDoReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5665                OpDevGetDoReply::XdpRxMetadataFeatures(val) => fmt.field(
5666                    "XdpRxMetadataFeatures",
5667                    &FormatFlags(val.into(), XdpRxMetadata::from_value),
5668                ),
5669                OpDevGetDoReply::XskFeatures(val) => fmt.field(
5670                    "XskFeatures",
5671                    &FormatFlags(val.into(), XskFlags::from_value),
5672                ),
5673            };
5674        }
5675        fmt.finish()
5676    }
5677}
5678impl IterableOpDevGetDoReply<'_> {
5679    pub fn lookup_attr(
5680        &self,
5681        offset: usize,
5682        missing_type: Option<u16>,
5683    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5684        let mut stack = Vec::new();
5685        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5686        if cur == offset + PushBuiltinNfgenmsg::len() {
5687            stack.push(("OpDevGetDoReply", offset));
5688            return (
5689                stack,
5690                missing_type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5691            );
5692        }
5693        if cur > offset || cur + self.buf.len() < offset {
5694            return (stack, None);
5695        }
5696        let mut attrs = self.clone();
5697        let mut last_off = cur + attrs.pos;
5698        while let Some(attr) = attrs.next() {
5699            let Ok(attr) = attr else { break };
5700            match attr {
5701                OpDevGetDoReply::Ifindex(val) => {
5702                    if last_off == offset {
5703                        stack.push(("Ifindex", last_off));
5704                        break;
5705                    }
5706                }
5707                OpDevGetDoReply::XdpFeatures(val) => {
5708                    if last_off == offset {
5709                        stack.push(("XdpFeatures", last_off));
5710                        break;
5711                    }
5712                }
5713                OpDevGetDoReply::XdpZcMaxSegs(val) => {
5714                    if last_off == offset {
5715                        stack.push(("XdpZcMaxSegs", last_off));
5716                        break;
5717                    }
5718                }
5719                OpDevGetDoReply::XdpRxMetadataFeatures(val) => {
5720                    if last_off == offset {
5721                        stack.push(("XdpRxMetadataFeatures", last_off));
5722                        break;
5723                    }
5724                }
5725                OpDevGetDoReply::XskFeatures(val) => {
5726                    if last_off == offset {
5727                        stack.push(("XskFeatures", last_off));
5728                        break;
5729                    }
5730                }
5731                _ => {}
5732            };
5733            last_off = cur + attrs.pos;
5734        }
5735        if !stack.is_empty() {
5736            stack.push(("OpDevGetDoReply", cur));
5737        }
5738        (stack, None)
5739    }
5740}
5741#[derive(Debug)]
5742pub struct RequestOpDevGetDoRequest<'r> {
5743    request: Request<'r>,
5744}
5745impl<'r> RequestOpDevGetDoRequest<'r> {
5746    pub fn new(mut request: Request<'r>) -> Self {
5747        PushOpDevGetDoRequest::write_header(&mut request.buf_mut());
5748        Self { request: request }
5749    }
5750    pub fn encode(&mut self) -> PushOpDevGetDoRequest<&mut Vec<u8>> {
5751        PushOpDevGetDoRequest::new_without_header(self.request.buf_mut())
5752    }
5753    pub fn into_encoder(self) -> PushOpDevGetDoRequest<RequestBuf<'r>> {
5754        PushOpDevGetDoRequest::new_without_header(self.request.buf)
5755    }
5756    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpDevGetDoRequest<'buf> {
5757        OpDevGetDoRequest::new(buf)
5758    }
5759}
5760impl NetlinkRequest for RequestOpDevGetDoRequest<'_> {
5761    fn protocol(&self) -> Protocol {
5762        Protocol::Generic("netdev".as_bytes())
5763    }
5764    fn flags(&self) -> u16 {
5765        self.request.flags
5766    }
5767    fn payload(&self) -> &[u8] {
5768        self.request.buf()
5769    }
5770    type ReplyType<'buf> = IterableOpDevGetDoReply<'buf>;
5771    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5772        OpDevGetDoReply::new(buf)
5773    }
5774    fn lookup(
5775        buf: &[u8],
5776        offset: usize,
5777        missing_type: Option<u16>,
5778    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5779        OpDevGetDoRequest::new(buf).lookup_attr(offset, missing_type)
5780    }
5781}
5782#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5783pub struct PushOpPagePoolGetDumpRequest<Prev: Rec> {
5784    pub(crate) prev: Option<Prev>,
5785    pub(crate) header_offset: Option<usize>,
5786}
5787impl<Prev: Rec> Rec for PushOpPagePoolGetDumpRequest<Prev> {
5788    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5789        self.prev.as_mut().unwrap().as_rec_mut()
5790    }
5791    fn as_rec(&self) -> &Vec<u8> {
5792        self.prev.as_ref().unwrap().as_rec()
5793    }
5794}
5795impl<Prev: Rec> PushOpPagePoolGetDumpRequest<Prev> {
5796    pub fn new(mut prev: Prev) -> Self {
5797        Self::write_header(&mut prev);
5798        Self::new_without_header(prev)
5799    }
5800    fn new_without_header(prev: Prev) -> Self {
5801        Self {
5802            prev: Some(prev),
5803            header_offset: None,
5804        }
5805    }
5806    fn write_header(prev: &mut Prev) {
5807        let mut header = PushBuiltinNfgenmsg::new();
5808        header.set_cmd(5u8);
5809        header.set_version(1u8);
5810        prev.as_rec_mut().extend(header.as_slice());
5811    }
5812    pub fn end_nested(mut self) -> Prev {
5813        let mut prev = self.prev.take().unwrap();
5814        if let Some(header_offset) = &self.header_offset {
5815            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5816        }
5817        prev
5818    }
5819}
5820impl<Prev: Rec> Drop for PushOpPagePoolGetDumpRequest<Prev> {
5821    fn drop(&mut self) {
5822        if let Some(prev) = &mut self.prev {
5823            if let Some(header_offset) = &self.header_offset {
5824                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5825            }
5826        }
5827    }
5828}
5829#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5830#[derive(Clone)]
5831pub enum OpPagePoolGetDumpRequest {}
5832impl<'a> IterableOpPagePoolGetDumpRequest<'a> {}
5833impl OpPagePoolGetDumpRequest {
5834    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpRequest<'a> {
5835        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5836        IterableOpPagePoolGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
5837    }
5838    fn attr_from_type(r#type: u16) -> Option<&'static str> {
5839        PagePool::attr_from_type(r#type)
5840    }
5841}
5842#[derive(Clone, Copy, Default)]
5843pub struct IterableOpPagePoolGetDumpRequest<'a> {
5844    buf: &'a [u8],
5845    pos: usize,
5846    orig_loc: usize,
5847}
5848impl<'a> IterableOpPagePoolGetDumpRequest<'a> {
5849    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5850        Self {
5851            buf,
5852            pos: 0,
5853            orig_loc,
5854        }
5855    }
5856    pub fn get_buf(&self) -> &'a [u8] {
5857        self.buf
5858    }
5859}
5860impl<'a> Iterator for IterableOpPagePoolGetDumpRequest<'a> {
5861    type Item = Result<OpPagePoolGetDumpRequest, ErrorContext>;
5862    fn next(&mut self) -> Option<Self::Item> {
5863        let pos = self.pos;
5864        let mut r#type;
5865        loop {
5866            r#type = None;
5867            if self.buf.len() == self.pos {
5868                return None;
5869            }
5870            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5871                break;
5872            };
5873            r#type = Some(header.r#type);
5874            let res = match header.r#type {
5875                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5876                n => continue,
5877            };
5878            return Some(Ok(res));
5879        }
5880        Some(Err(ErrorContext::new(
5881            "OpPagePoolGetDumpRequest",
5882            r#type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5883            self.orig_loc,
5884            self.buf.as_ptr().wrapping_add(pos) as usize,
5885        )))
5886    }
5887}
5888impl std::fmt::Debug for IterableOpPagePoolGetDumpRequest<'_> {
5889    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5890        let mut fmt = f.debug_struct("OpPagePoolGetDumpRequest");
5891        for attr in self.clone() {
5892            let attr = match attr {
5893                Ok(a) => a,
5894                Err(err) => {
5895                    fmt.finish()?;
5896                    f.write_str("Err(")?;
5897                    err.fmt(f)?;
5898                    return f.write_str(")");
5899                }
5900            };
5901            match attr {};
5902        }
5903        fmt.finish()
5904    }
5905}
5906impl IterableOpPagePoolGetDumpRequest<'_> {
5907    pub fn lookup_attr(
5908        &self,
5909        offset: usize,
5910        missing_type: Option<u16>,
5911    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5912        let mut stack = Vec::new();
5913        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5914        if cur == offset + PushBuiltinNfgenmsg::len() {
5915            stack.push(("OpPagePoolGetDumpRequest", offset));
5916            return (
5917                stack,
5918                missing_type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5919            );
5920        }
5921        (stack, None)
5922    }
5923}
5924#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5925pub struct PushOpPagePoolGetDumpReply<Prev: Rec> {
5926    pub(crate) prev: Option<Prev>,
5927    pub(crate) header_offset: Option<usize>,
5928}
5929impl<Prev: Rec> Rec for PushOpPagePoolGetDumpReply<Prev> {
5930    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5931        self.prev.as_mut().unwrap().as_rec_mut()
5932    }
5933    fn as_rec(&self) -> &Vec<u8> {
5934        self.prev.as_ref().unwrap().as_rec()
5935    }
5936}
5937impl<Prev: Rec> PushOpPagePoolGetDumpReply<Prev> {
5938    pub fn new(mut prev: Prev) -> Self {
5939        Self::write_header(&mut prev);
5940        Self::new_without_header(prev)
5941    }
5942    fn new_without_header(prev: Prev) -> Self {
5943        Self {
5944            prev: Some(prev),
5945            header_offset: None,
5946        }
5947    }
5948    fn write_header(prev: &mut Prev) {
5949        let mut header = PushBuiltinNfgenmsg::new();
5950        header.set_cmd(5u8);
5951        header.set_version(1u8);
5952        prev.as_rec_mut().extend(header.as_slice());
5953    }
5954    pub fn end_nested(mut self) -> Prev {
5955        let mut prev = self.prev.take().unwrap();
5956        if let Some(header_offset) = &self.header_offset {
5957            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5958        }
5959        prev
5960    }
5961    #[doc = "Unique ID of a Page Pool instance."]
5962    pub fn push_id(mut self, value: u32) -> Self {
5963        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5964        self.as_rec_mut().extend(value.to_ne_bytes());
5965        self
5966    }
5967    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
5968    pub fn push_ifindex(mut self, value: u32) -> Self {
5969        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5970        self.as_rec_mut().extend(value.to_ne_bytes());
5971        self
5972    }
5973    #[doc = "Id of NAPI using this Page Pool instance."]
5974    pub fn push_napi_id(mut self, value: u32) -> Self {
5975        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5976        self.as_rec_mut().extend(value.to_ne_bytes());
5977        self
5978    }
5979    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
5980    pub fn push_inflight(mut self, value: u32) -> Self {
5981        push_header(self.as_rec_mut(), 4u16, 4 as u16);
5982        self.as_rec_mut().extend(value.to_ne_bytes());
5983        self
5984    }
5985    #[doc = "Amount of memory held by inflight pages.\n"]
5986    pub fn push_inflight_mem(mut self, value: u32) -> Self {
5987        push_header(self.as_rec_mut(), 5u16, 4 as u16);
5988        self.as_rec_mut().extend(value.to_ne_bytes());
5989        self
5990    }
5991    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
5992    pub fn push_detach_time(mut self, value: u32) -> Self {
5993        push_header(self.as_rec_mut(), 6u16, 4 as u16);
5994        self.as_rec_mut().extend(value.to_ne_bytes());
5995        self
5996    }
5997    #[doc = "ID of the dmabuf this page-pool is attached to."]
5998    pub fn push_dmabuf(mut self, value: u32) -> Self {
5999        push_header(self.as_rec_mut(), 7u16, 4 as u16);
6000        self.as_rec_mut().extend(value.to_ne_bytes());
6001        self
6002    }
6003    #[doc = "io-uring memory provider information."]
6004    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
6005        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
6006        PushIoUringProviderInfo {
6007            prev: Some(self),
6008            header_offset: Some(header_offset),
6009        }
6010    }
6011}
6012impl<Prev: Rec> Drop for PushOpPagePoolGetDumpReply<Prev> {
6013    fn drop(&mut self) {
6014        if let Some(prev) = &mut self.prev {
6015            if let Some(header_offset) = &self.header_offset {
6016                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6017            }
6018        }
6019    }
6020}
6021#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6022#[derive(Clone)]
6023pub enum OpPagePoolGetDumpReply<'a> {
6024    #[doc = "Unique ID of a Page Pool instance."]
6025    Id(u32),
6026    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6027    Ifindex(u32),
6028    #[doc = "Id of NAPI using this Page Pool instance."]
6029    NapiId(u32),
6030    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6031    Inflight(u32),
6032    #[doc = "Amount of memory held by inflight pages.\n"]
6033    InflightMem(u32),
6034    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6035    DetachTime(u32),
6036    #[doc = "ID of the dmabuf this page-pool is attached to."]
6037    Dmabuf(u32),
6038    #[doc = "io-uring memory provider information."]
6039    IoUring(IterableIoUringProviderInfo<'a>),
6040}
6041impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6042    #[doc = "Unique ID of a Page Pool instance."]
6043    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6044        let mut iter = self.clone();
6045        iter.pos = 0;
6046        for attr in iter {
6047            if let OpPagePoolGetDumpReply::Id(val) = attr? {
6048                return Ok(val);
6049            }
6050        }
6051        Err(ErrorContext::new_missing(
6052            "OpPagePoolGetDumpReply",
6053            "Id",
6054            self.orig_loc,
6055            self.buf.as_ptr() as usize,
6056        ))
6057    }
6058    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6059    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6060        let mut iter = self.clone();
6061        iter.pos = 0;
6062        for attr in iter {
6063            if let OpPagePoolGetDumpReply::Ifindex(val) = attr? {
6064                return Ok(val);
6065            }
6066        }
6067        Err(ErrorContext::new_missing(
6068            "OpPagePoolGetDumpReply",
6069            "Ifindex",
6070            self.orig_loc,
6071            self.buf.as_ptr() as usize,
6072        ))
6073    }
6074    #[doc = "Id of NAPI using this Page Pool instance."]
6075    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6076        let mut iter = self.clone();
6077        iter.pos = 0;
6078        for attr in iter {
6079            if let OpPagePoolGetDumpReply::NapiId(val) = attr? {
6080                return Ok(val);
6081            }
6082        }
6083        Err(ErrorContext::new_missing(
6084            "OpPagePoolGetDumpReply",
6085            "NapiId",
6086            self.orig_loc,
6087            self.buf.as_ptr() as usize,
6088        ))
6089    }
6090    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6091    pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6092        let mut iter = self.clone();
6093        iter.pos = 0;
6094        for attr in iter {
6095            if let OpPagePoolGetDumpReply::Inflight(val) = attr? {
6096                return Ok(val);
6097            }
6098        }
6099        Err(ErrorContext::new_missing(
6100            "OpPagePoolGetDumpReply",
6101            "Inflight",
6102            self.orig_loc,
6103            self.buf.as_ptr() as usize,
6104        ))
6105    }
6106    #[doc = "Amount of memory held by inflight pages.\n"]
6107    pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6108        let mut iter = self.clone();
6109        iter.pos = 0;
6110        for attr in iter {
6111            if let OpPagePoolGetDumpReply::InflightMem(val) = attr? {
6112                return Ok(val);
6113            }
6114        }
6115        Err(ErrorContext::new_missing(
6116            "OpPagePoolGetDumpReply",
6117            "InflightMem",
6118            self.orig_loc,
6119            self.buf.as_ptr() as usize,
6120        ))
6121    }
6122    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6123    pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6124        let mut iter = self.clone();
6125        iter.pos = 0;
6126        for attr in iter {
6127            if let OpPagePoolGetDumpReply::DetachTime(val) = attr? {
6128                return Ok(val);
6129            }
6130        }
6131        Err(ErrorContext::new_missing(
6132            "OpPagePoolGetDumpReply",
6133            "DetachTime",
6134            self.orig_loc,
6135            self.buf.as_ptr() as usize,
6136        ))
6137    }
6138    #[doc = "ID of the dmabuf this page-pool is attached to."]
6139    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6140        let mut iter = self.clone();
6141        iter.pos = 0;
6142        for attr in iter {
6143            if let OpPagePoolGetDumpReply::Dmabuf(val) = attr? {
6144                return Ok(val);
6145            }
6146        }
6147        Err(ErrorContext::new_missing(
6148            "OpPagePoolGetDumpReply",
6149            "Dmabuf",
6150            self.orig_loc,
6151            self.buf.as_ptr() as usize,
6152        ))
6153    }
6154    #[doc = "io-uring memory provider information."]
6155    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6156        let mut iter = self.clone();
6157        iter.pos = 0;
6158        for attr in iter {
6159            if let OpPagePoolGetDumpReply::IoUring(val) = attr? {
6160                return Ok(val);
6161            }
6162        }
6163        Err(ErrorContext::new_missing(
6164            "OpPagePoolGetDumpReply",
6165            "IoUring",
6166            self.orig_loc,
6167            self.buf.as_ptr() as usize,
6168        ))
6169    }
6170}
6171impl OpPagePoolGetDumpReply<'_> {
6172    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpReply<'a> {
6173        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6174        IterableOpPagePoolGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
6175    }
6176    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6177        PagePool::attr_from_type(r#type)
6178    }
6179}
6180#[derive(Clone, Copy, Default)]
6181pub struct IterableOpPagePoolGetDumpReply<'a> {
6182    buf: &'a [u8],
6183    pos: usize,
6184    orig_loc: usize,
6185}
6186impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6187    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6188        Self {
6189            buf,
6190            pos: 0,
6191            orig_loc,
6192        }
6193    }
6194    pub fn get_buf(&self) -> &'a [u8] {
6195        self.buf
6196    }
6197}
6198impl<'a> Iterator for IterableOpPagePoolGetDumpReply<'a> {
6199    type Item = Result<OpPagePoolGetDumpReply<'a>, ErrorContext>;
6200    fn next(&mut self) -> Option<Self::Item> {
6201        let pos = self.pos;
6202        let mut r#type;
6203        loop {
6204            r#type = None;
6205            if self.buf.len() == self.pos {
6206                return None;
6207            }
6208            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6209                break;
6210            };
6211            r#type = Some(header.r#type);
6212            let res = match header.r#type {
6213                1u16 => OpPagePoolGetDumpReply::Id({
6214                    let res = parse_u32(next);
6215                    let Some(val) = res else { break };
6216                    val
6217                }),
6218                2u16 => OpPagePoolGetDumpReply::Ifindex({
6219                    let res = parse_u32(next);
6220                    let Some(val) = res else { break };
6221                    val
6222                }),
6223                3u16 => OpPagePoolGetDumpReply::NapiId({
6224                    let res = parse_u32(next);
6225                    let Some(val) = res else { break };
6226                    val
6227                }),
6228                4u16 => OpPagePoolGetDumpReply::Inflight({
6229                    let res = parse_u32(next);
6230                    let Some(val) = res else { break };
6231                    val
6232                }),
6233                5u16 => OpPagePoolGetDumpReply::InflightMem({
6234                    let res = parse_u32(next);
6235                    let Some(val) = res else { break };
6236                    val
6237                }),
6238                6u16 => OpPagePoolGetDumpReply::DetachTime({
6239                    let res = parse_u32(next);
6240                    let Some(val) = res else { break };
6241                    val
6242                }),
6243                7u16 => OpPagePoolGetDumpReply::Dmabuf({
6244                    let res = parse_u32(next);
6245                    let Some(val) = res else { break };
6246                    val
6247                }),
6248                8u16 => OpPagePoolGetDumpReply::IoUring({
6249                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6250                    let Some(val) = res else { break };
6251                    val
6252                }),
6253                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6254                n => continue,
6255            };
6256            return Some(Ok(res));
6257        }
6258        Some(Err(ErrorContext::new(
6259            "OpPagePoolGetDumpReply",
6260            r#type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6261            self.orig_loc,
6262            self.buf.as_ptr().wrapping_add(pos) as usize,
6263        )))
6264    }
6265}
6266impl<'a> std::fmt::Debug for IterableOpPagePoolGetDumpReply<'_> {
6267    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6268        let mut fmt = f.debug_struct("OpPagePoolGetDumpReply");
6269        for attr in self.clone() {
6270            let attr = match attr {
6271                Ok(a) => a,
6272                Err(err) => {
6273                    fmt.finish()?;
6274                    f.write_str("Err(")?;
6275                    err.fmt(f)?;
6276                    return f.write_str(")");
6277                }
6278            };
6279            match attr {
6280                OpPagePoolGetDumpReply::Id(val) => fmt.field("Id", &val),
6281                OpPagePoolGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
6282                OpPagePoolGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
6283                OpPagePoolGetDumpReply::Inflight(val) => fmt.field("Inflight", &val),
6284                OpPagePoolGetDumpReply::InflightMem(val) => fmt.field("InflightMem", &val),
6285                OpPagePoolGetDumpReply::DetachTime(val) => fmt.field("DetachTime", &val),
6286                OpPagePoolGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6287                OpPagePoolGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
6288            };
6289        }
6290        fmt.finish()
6291    }
6292}
6293impl IterableOpPagePoolGetDumpReply<'_> {
6294    pub fn lookup_attr(
6295        &self,
6296        offset: usize,
6297        missing_type: Option<u16>,
6298    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6299        let mut stack = Vec::new();
6300        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6301        if cur == offset + PushBuiltinNfgenmsg::len() {
6302            stack.push(("OpPagePoolGetDumpReply", offset));
6303            return (
6304                stack,
6305                missing_type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6306            );
6307        }
6308        if cur > offset || cur + self.buf.len() < offset {
6309            return (stack, None);
6310        }
6311        let mut attrs = self.clone();
6312        let mut last_off = cur + attrs.pos;
6313        let mut missing = None;
6314        while let Some(attr) = attrs.next() {
6315            let Ok(attr) = attr else { break };
6316            match attr {
6317                OpPagePoolGetDumpReply::Id(val) => {
6318                    if last_off == offset {
6319                        stack.push(("Id", last_off));
6320                        break;
6321                    }
6322                }
6323                OpPagePoolGetDumpReply::Ifindex(val) => {
6324                    if last_off == offset {
6325                        stack.push(("Ifindex", last_off));
6326                        break;
6327                    }
6328                }
6329                OpPagePoolGetDumpReply::NapiId(val) => {
6330                    if last_off == offset {
6331                        stack.push(("NapiId", last_off));
6332                        break;
6333                    }
6334                }
6335                OpPagePoolGetDumpReply::Inflight(val) => {
6336                    if last_off == offset {
6337                        stack.push(("Inflight", last_off));
6338                        break;
6339                    }
6340                }
6341                OpPagePoolGetDumpReply::InflightMem(val) => {
6342                    if last_off == offset {
6343                        stack.push(("InflightMem", last_off));
6344                        break;
6345                    }
6346                }
6347                OpPagePoolGetDumpReply::DetachTime(val) => {
6348                    if last_off == offset {
6349                        stack.push(("DetachTime", last_off));
6350                        break;
6351                    }
6352                }
6353                OpPagePoolGetDumpReply::Dmabuf(val) => {
6354                    if last_off == offset {
6355                        stack.push(("Dmabuf", last_off));
6356                        break;
6357                    }
6358                }
6359                OpPagePoolGetDumpReply::IoUring(val) => {
6360                    (stack, missing) = val.lookup_attr(offset, missing_type);
6361                    if !stack.is_empty() {
6362                        break;
6363                    }
6364                }
6365                _ => {}
6366            };
6367            last_off = cur + attrs.pos;
6368        }
6369        if !stack.is_empty() {
6370            stack.push(("OpPagePoolGetDumpReply", cur));
6371        }
6372        (stack, missing)
6373    }
6374}
6375#[derive(Debug)]
6376pub struct RequestOpPagePoolGetDumpRequest<'r> {
6377    request: Request<'r>,
6378}
6379impl<'r> RequestOpPagePoolGetDumpRequest<'r> {
6380    pub fn new(mut request: Request<'r>) -> Self {
6381        PushOpPagePoolGetDumpRequest::write_header(&mut request.buf_mut());
6382        Self {
6383            request: request.set_dump(),
6384        }
6385    }
6386    pub fn encode(&mut self) -> PushOpPagePoolGetDumpRequest<&mut Vec<u8>> {
6387        PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf_mut())
6388    }
6389    pub fn into_encoder(self) -> PushOpPagePoolGetDumpRequest<RequestBuf<'r>> {
6390        PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf)
6391    }
6392    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolGetDumpRequest<'buf> {
6393        OpPagePoolGetDumpRequest::new(buf)
6394    }
6395}
6396impl NetlinkRequest for RequestOpPagePoolGetDumpRequest<'_> {
6397    fn protocol(&self) -> Protocol {
6398        Protocol::Generic("netdev".as_bytes())
6399    }
6400    fn flags(&self) -> u16 {
6401        self.request.flags
6402    }
6403    fn payload(&self) -> &[u8] {
6404        self.request.buf()
6405    }
6406    type ReplyType<'buf> = IterableOpPagePoolGetDumpReply<'buf>;
6407    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6408        OpPagePoolGetDumpReply::new(buf)
6409    }
6410    fn lookup(
6411        buf: &[u8],
6412        offset: usize,
6413        missing_type: Option<u16>,
6414    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6415        OpPagePoolGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
6416    }
6417}
6418#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6419pub struct PushOpPagePoolGetDoRequest<Prev: Rec> {
6420    pub(crate) prev: Option<Prev>,
6421    pub(crate) header_offset: Option<usize>,
6422}
6423impl<Prev: Rec> Rec for PushOpPagePoolGetDoRequest<Prev> {
6424    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6425        self.prev.as_mut().unwrap().as_rec_mut()
6426    }
6427    fn as_rec(&self) -> &Vec<u8> {
6428        self.prev.as_ref().unwrap().as_rec()
6429    }
6430}
6431impl<Prev: Rec> PushOpPagePoolGetDoRequest<Prev> {
6432    pub fn new(mut prev: Prev) -> Self {
6433        Self::write_header(&mut prev);
6434        Self::new_without_header(prev)
6435    }
6436    fn new_without_header(prev: Prev) -> Self {
6437        Self {
6438            prev: Some(prev),
6439            header_offset: None,
6440        }
6441    }
6442    fn write_header(prev: &mut Prev) {
6443        let mut header = PushBuiltinNfgenmsg::new();
6444        header.set_cmd(5u8);
6445        header.set_version(1u8);
6446        prev.as_rec_mut().extend(header.as_slice());
6447    }
6448    pub fn end_nested(mut self) -> Prev {
6449        let mut prev = self.prev.take().unwrap();
6450        if let Some(header_offset) = &self.header_offset {
6451            finalize_nested_header(prev.as_rec_mut(), *header_offset);
6452        }
6453        prev
6454    }
6455    #[doc = "Unique ID of a Page Pool instance."]
6456    pub fn push_id(mut self, value: u32) -> Self {
6457        push_header(self.as_rec_mut(), 1u16, 4 as u16);
6458        self.as_rec_mut().extend(value.to_ne_bytes());
6459        self
6460    }
6461}
6462impl<Prev: Rec> Drop for PushOpPagePoolGetDoRequest<Prev> {
6463    fn drop(&mut self) {
6464        if let Some(prev) = &mut self.prev {
6465            if let Some(header_offset) = &self.header_offset {
6466                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6467            }
6468        }
6469    }
6470}
6471#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6472#[derive(Clone)]
6473pub enum OpPagePoolGetDoRequest {
6474    #[doc = "Unique ID of a Page Pool instance."]
6475    Id(u32),
6476}
6477impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6478    #[doc = "Unique ID of a Page Pool instance."]
6479    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6480        let mut iter = self.clone();
6481        iter.pos = 0;
6482        for attr in iter {
6483            if let OpPagePoolGetDoRequest::Id(val) = attr? {
6484                return Ok(val);
6485            }
6486        }
6487        Err(ErrorContext::new_missing(
6488            "OpPagePoolGetDoRequest",
6489            "Id",
6490            self.orig_loc,
6491            self.buf.as_ptr() as usize,
6492        ))
6493    }
6494}
6495impl OpPagePoolGetDoRequest {
6496    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoRequest<'a> {
6497        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6498        IterableOpPagePoolGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
6499    }
6500    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6501        PagePool::attr_from_type(r#type)
6502    }
6503}
6504#[derive(Clone, Copy, Default)]
6505pub struct IterableOpPagePoolGetDoRequest<'a> {
6506    buf: &'a [u8],
6507    pos: usize,
6508    orig_loc: usize,
6509}
6510impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6511    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6512        Self {
6513            buf,
6514            pos: 0,
6515            orig_loc,
6516        }
6517    }
6518    pub fn get_buf(&self) -> &'a [u8] {
6519        self.buf
6520    }
6521}
6522impl<'a> Iterator for IterableOpPagePoolGetDoRequest<'a> {
6523    type Item = Result<OpPagePoolGetDoRequest, ErrorContext>;
6524    fn next(&mut self) -> Option<Self::Item> {
6525        let pos = self.pos;
6526        let mut r#type;
6527        loop {
6528            r#type = None;
6529            if self.buf.len() == self.pos {
6530                return None;
6531            }
6532            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6533                break;
6534            };
6535            r#type = Some(header.r#type);
6536            let res = match header.r#type {
6537                1u16 => OpPagePoolGetDoRequest::Id({
6538                    let res = parse_u32(next);
6539                    let Some(val) = res else { break };
6540                    val
6541                }),
6542                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6543                n => continue,
6544            };
6545            return Some(Ok(res));
6546        }
6547        Some(Err(ErrorContext::new(
6548            "OpPagePoolGetDoRequest",
6549            r#type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6550            self.orig_loc,
6551            self.buf.as_ptr().wrapping_add(pos) as usize,
6552        )))
6553    }
6554}
6555impl std::fmt::Debug for IterableOpPagePoolGetDoRequest<'_> {
6556    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6557        let mut fmt = f.debug_struct("OpPagePoolGetDoRequest");
6558        for attr in self.clone() {
6559            let attr = match attr {
6560                Ok(a) => a,
6561                Err(err) => {
6562                    fmt.finish()?;
6563                    f.write_str("Err(")?;
6564                    err.fmt(f)?;
6565                    return f.write_str(")");
6566                }
6567            };
6568            match attr {
6569                OpPagePoolGetDoRequest::Id(val) => fmt.field("Id", &val),
6570            };
6571        }
6572        fmt.finish()
6573    }
6574}
6575impl IterableOpPagePoolGetDoRequest<'_> {
6576    pub fn lookup_attr(
6577        &self,
6578        offset: usize,
6579        missing_type: Option<u16>,
6580    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6581        let mut stack = Vec::new();
6582        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6583        if cur == offset + PushBuiltinNfgenmsg::len() {
6584            stack.push(("OpPagePoolGetDoRequest", offset));
6585            return (
6586                stack,
6587                missing_type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6588            );
6589        }
6590        if cur > offset || cur + self.buf.len() < offset {
6591            return (stack, None);
6592        }
6593        let mut attrs = self.clone();
6594        let mut last_off = cur + attrs.pos;
6595        while let Some(attr) = attrs.next() {
6596            let Ok(attr) = attr else { break };
6597            match attr {
6598                OpPagePoolGetDoRequest::Id(val) => {
6599                    if last_off == offset {
6600                        stack.push(("Id", last_off));
6601                        break;
6602                    }
6603                }
6604                _ => {}
6605            };
6606            last_off = cur + attrs.pos;
6607        }
6608        if !stack.is_empty() {
6609            stack.push(("OpPagePoolGetDoRequest", cur));
6610        }
6611        (stack, None)
6612    }
6613}
6614#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6615pub struct PushOpPagePoolGetDoReply<Prev: Rec> {
6616    pub(crate) prev: Option<Prev>,
6617    pub(crate) header_offset: Option<usize>,
6618}
6619impl<Prev: Rec> Rec for PushOpPagePoolGetDoReply<Prev> {
6620    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6621        self.prev.as_mut().unwrap().as_rec_mut()
6622    }
6623    fn as_rec(&self) -> &Vec<u8> {
6624        self.prev.as_ref().unwrap().as_rec()
6625    }
6626}
6627impl<Prev: Rec> PushOpPagePoolGetDoReply<Prev> {
6628    pub fn new(mut prev: Prev) -> Self {
6629        Self::write_header(&mut prev);
6630        Self::new_without_header(prev)
6631    }
6632    fn new_without_header(prev: Prev) -> Self {
6633        Self {
6634            prev: Some(prev),
6635            header_offset: None,
6636        }
6637    }
6638    fn write_header(prev: &mut Prev) {
6639        let mut header = PushBuiltinNfgenmsg::new();
6640        header.set_cmd(5u8);
6641        header.set_version(1u8);
6642        prev.as_rec_mut().extend(header.as_slice());
6643    }
6644    pub fn end_nested(mut self) -> Prev {
6645        let mut prev = self.prev.take().unwrap();
6646        if let Some(header_offset) = &self.header_offset {
6647            finalize_nested_header(prev.as_rec_mut(), *header_offset);
6648        }
6649        prev
6650    }
6651    #[doc = "Unique ID of a Page Pool instance."]
6652    pub fn push_id(mut self, value: u32) -> Self {
6653        push_header(self.as_rec_mut(), 1u16, 4 as u16);
6654        self.as_rec_mut().extend(value.to_ne_bytes());
6655        self
6656    }
6657    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6658    pub fn push_ifindex(mut self, value: u32) -> Self {
6659        push_header(self.as_rec_mut(), 2u16, 4 as u16);
6660        self.as_rec_mut().extend(value.to_ne_bytes());
6661        self
6662    }
6663    #[doc = "Id of NAPI using this Page Pool instance."]
6664    pub fn push_napi_id(mut self, value: u32) -> Self {
6665        push_header(self.as_rec_mut(), 3u16, 4 as u16);
6666        self.as_rec_mut().extend(value.to_ne_bytes());
6667        self
6668    }
6669    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6670    pub fn push_inflight(mut self, value: u32) -> Self {
6671        push_header(self.as_rec_mut(), 4u16, 4 as u16);
6672        self.as_rec_mut().extend(value.to_ne_bytes());
6673        self
6674    }
6675    #[doc = "Amount of memory held by inflight pages.\n"]
6676    pub fn push_inflight_mem(mut self, value: u32) -> Self {
6677        push_header(self.as_rec_mut(), 5u16, 4 as u16);
6678        self.as_rec_mut().extend(value.to_ne_bytes());
6679        self
6680    }
6681    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6682    pub fn push_detach_time(mut self, value: u32) -> Self {
6683        push_header(self.as_rec_mut(), 6u16, 4 as u16);
6684        self.as_rec_mut().extend(value.to_ne_bytes());
6685        self
6686    }
6687    #[doc = "ID of the dmabuf this page-pool is attached to."]
6688    pub fn push_dmabuf(mut self, value: u32) -> Self {
6689        push_header(self.as_rec_mut(), 7u16, 4 as u16);
6690        self.as_rec_mut().extend(value.to_ne_bytes());
6691        self
6692    }
6693    #[doc = "io-uring memory provider information."]
6694    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
6695        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
6696        PushIoUringProviderInfo {
6697            prev: Some(self),
6698            header_offset: Some(header_offset),
6699        }
6700    }
6701}
6702impl<Prev: Rec> Drop for PushOpPagePoolGetDoReply<Prev> {
6703    fn drop(&mut self) {
6704        if let Some(prev) = &mut self.prev {
6705            if let Some(header_offset) = &self.header_offset {
6706                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6707            }
6708        }
6709    }
6710}
6711#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6712#[derive(Clone)]
6713pub enum OpPagePoolGetDoReply<'a> {
6714    #[doc = "Unique ID of a Page Pool instance."]
6715    Id(u32),
6716    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6717    Ifindex(u32),
6718    #[doc = "Id of NAPI using this Page Pool instance."]
6719    NapiId(u32),
6720    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6721    Inflight(u32),
6722    #[doc = "Amount of memory held by inflight pages.\n"]
6723    InflightMem(u32),
6724    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6725    DetachTime(u32),
6726    #[doc = "ID of the dmabuf this page-pool is attached to."]
6727    Dmabuf(u32),
6728    #[doc = "io-uring memory provider information."]
6729    IoUring(IterableIoUringProviderInfo<'a>),
6730}
6731impl<'a> IterableOpPagePoolGetDoReply<'a> {
6732    #[doc = "Unique ID of a Page Pool instance."]
6733    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6734        let mut iter = self.clone();
6735        iter.pos = 0;
6736        for attr in iter {
6737            if let OpPagePoolGetDoReply::Id(val) = attr? {
6738                return Ok(val);
6739            }
6740        }
6741        Err(ErrorContext::new_missing(
6742            "OpPagePoolGetDoReply",
6743            "Id",
6744            self.orig_loc,
6745            self.buf.as_ptr() as usize,
6746        ))
6747    }
6748    #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6749    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6750        let mut iter = self.clone();
6751        iter.pos = 0;
6752        for attr in iter {
6753            if let OpPagePoolGetDoReply::Ifindex(val) = attr? {
6754                return Ok(val);
6755            }
6756        }
6757        Err(ErrorContext::new_missing(
6758            "OpPagePoolGetDoReply",
6759            "Ifindex",
6760            self.orig_loc,
6761            self.buf.as_ptr() as usize,
6762        ))
6763    }
6764    #[doc = "Id of NAPI using this Page Pool instance."]
6765    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6766        let mut iter = self.clone();
6767        iter.pos = 0;
6768        for attr in iter {
6769            if let OpPagePoolGetDoReply::NapiId(val) = attr? {
6770                return Ok(val);
6771            }
6772        }
6773        Err(ErrorContext::new_missing(
6774            "OpPagePoolGetDoReply",
6775            "NapiId",
6776            self.orig_loc,
6777            self.buf.as_ptr() as usize,
6778        ))
6779    }
6780    #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6781    pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6782        let mut iter = self.clone();
6783        iter.pos = 0;
6784        for attr in iter {
6785            if let OpPagePoolGetDoReply::Inflight(val) = attr? {
6786                return Ok(val);
6787            }
6788        }
6789        Err(ErrorContext::new_missing(
6790            "OpPagePoolGetDoReply",
6791            "Inflight",
6792            self.orig_loc,
6793            self.buf.as_ptr() as usize,
6794        ))
6795    }
6796    #[doc = "Amount of memory held by inflight pages.\n"]
6797    pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6798        let mut iter = self.clone();
6799        iter.pos = 0;
6800        for attr in iter {
6801            if let OpPagePoolGetDoReply::InflightMem(val) = attr? {
6802                return Ok(val);
6803            }
6804        }
6805        Err(ErrorContext::new_missing(
6806            "OpPagePoolGetDoReply",
6807            "InflightMem",
6808            self.orig_loc,
6809            self.buf.as_ptr() as usize,
6810        ))
6811    }
6812    #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6813    pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6814        let mut iter = self.clone();
6815        iter.pos = 0;
6816        for attr in iter {
6817            if let OpPagePoolGetDoReply::DetachTime(val) = attr? {
6818                return Ok(val);
6819            }
6820        }
6821        Err(ErrorContext::new_missing(
6822            "OpPagePoolGetDoReply",
6823            "DetachTime",
6824            self.orig_loc,
6825            self.buf.as_ptr() as usize,
6826        ))
6827    }
6828    #[doc = "ID of the dmabuf this page-pool is attached to."]
6829    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6830        let mut iter = self.clone();
6831        iter.pos = 0;
6832        for attr in iter {
6833            if let OpPagePoolGetDoReply::Dmabuf(val) = attr? {
6834                return Ok(val);
6835            }
6836        }
6837        Err(ErrorContext::new_missing(
6838            "OpPagePoolGetDoReply",
6839            "Dmabuf",
6840            self.orig_loc,
6841            self.buf.as_ptr() as usize,
6842        ))
6843    }
6844    #[doc = "io-uring memory provider information."]
6845    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6846        let mut iter = self.clone();
6847        iter.pos = 0;
6848        for attr in iter {
6849            if let OpPagePoolGetDoReply::IoUring(val) = attr? {
6850                return Ok(val);
6851            }
6852        }
6853        Err(ErrorContext::new_missing(
6854            "OpPagePoolGetDoReply",
6855            "IoUring",
6856            self.orig_loc,
6857            self.buf.as_ptr() as usize,
6858        ))
6859    }
6860}
6861impl OpPagePoolGetDoReply<'_> {
6862    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoReply<'a> {
6863        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6864        IterableOpPagePoolGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
6865    }
6866    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6867        PagePool::attr_from_type(r#type)
6868    }
6869}
6870#[derive(Clone, Copy, Default)]
6871pub struct IterableOpPagePoolGetDoReply<'a> {
6872    buf: &'a [u8],
6873    pos: usize,
6874    orig_loc: usize,
6875}
6876impl<'a> IterableOpPagePoolGetDoReply<'a> {
6877    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6878        Self {
6879            buf,
6880            pos: 0,
6881            orig_loc,
6882        }
6883    }
6884    pub fn get_buf(&self) -> &'a [u8] {
6885        self.buf
6886    }
6887}
6888impl<'a> Iterator for IterableOpPagePoolGetDoReply<'a> {
6889    type Item = Result<OpPagePoolGetDoReply<'a>, ErrorContext>;
6890    fn next(&mut self) -> Option<Self::Item> {
6891        let pos = self.pos;
6892        let mut r#type;
6893        loop {
6894            r#type = None;
6895            if self.buf.len() == self.pos {
6896                return None;
6897            }
6898            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6899                break;
6900            };
6901            r#type = Some(header.r#type);
6902            let res = match header.r#type {
6903                1u16 => OpPagePoolGetDoReply::Id({
6904                    let res = parse_u32(next);
6905                    let Some(val) = res else { break };
6906                    val
6907                }),
6908                2u16 => OpPagePoolGetDoReply::Ifindex({
6909                    let res = parse_u32(next);
6910                    let Some(val) = res else { break };
6911                    val
6912                }),
6913                3u16 => OpPagePoolGetDoReply::NapiId({
6914                    let res = parse_u32(next);
6915                    let Some(val) = res else { break };
6916                    val
6917                }),
6918                4u16 => OpPagePoolGetDoReply::Inflight({
6919                    let res = parse_u32(next);
6920                    let Some(val) = res else { break };
6921                    val
6922                }),
6923                5u16 => OpPagePoolGetDoReply::InflightMem({
6924                    let res = parse_u32(next);
6925                    let Some(val) = res else { break };
6926                    val
6927                }),
6928                6u16 => OpPagePoolGetDoReply::DetachTime({
6929                    let res = parse_u32(next);
6930                    let Some(val) = res else { break };
6931                    val
6932                }),
6933                7u16 => OpPagePoolGetDoReply::Dmabuf({
6934                    let res = parse_u32(next);
6935                    let Some(val) = res else { break };
6936                    val
6937                }),
6938                8u16 => OpPagePoolGetDoReply::IoUring({
6939                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6940                    let Some(val) = res else { break };
6941                    val
6942                }),
6943                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6944                n => continue,
6945            };
6946            return Some(Ok(res));
6947        }
6948        Some(Err(ErrorContext::new(
6949            "OpPagePoolGetDoReply",
6950            r#type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6951            self.orig_loc,
6952            self.buf.as_ptr().wrapping_add(pos) as usize,
6953        )))
6954    }
6955}
6956impl<'a> std::fmt::Debug for IterableOpPagePoolGetDoReply<'_> {
6957    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6958        let mut fmt = f.debug_struct("OpPagePoolGetDoReply");
6959        for attr in self.clone() {
6960            let attr = match attr {
6961                Ok(a) => a,
6962                Err(err) => {
6963                    fmt.finish()?;
6964                    f.write_str("Err(")?;
6965                    err.fmt(f)?;
6966                    return f.write_str(")");
6967                }
6968            };
6969            match attr {
6970                OpPagePoolGetDoReply::Id(val) => fmt.field("Id", &val),
6971                OpPagePoolGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
6972                OpPagePoolGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
6973                OpPagePoolGetDoReply::Inflight(val) => fmt.field("Inflight", &val),
6974                OpPagePoolGetDoReply::InflightMem(val) => fmt.field("InflightMem", &val),
6975                OpPagePoolGetDoReply::DetachTime(val) => fmt.field("DetachTime", &val),
6976                OpPagePoolGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6977                OpPagePoolGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
6978            };
6979        }
6980        fmt.finish()
6981    }
6982}
6983impl IterableOpPagePoolGetDoReply<'_> {
6984    pub fn lookup_attr(
6985        &self,
6986        offset: usize,
6987        missing_type: Option<u16>,
6988    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6989        let mut stack = Vec::new();
6990        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6991        if cur == offset + PushBuiltinNfgenmsg::len() {
6992            stack.push(("OpPagePoolGetDoReply", offset));
6993            return (
6994                stack,
6995                missing_type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6996            );
6997        }
6998        if cur > offset || cur + self.buf.len() < offset {
6999            return (stack, None);
7000        }
7001        let mut attrs = self.clone();
7002        let mut last_off = cur + attrs.pos;
7003        let mut missing = None;
7004        while let Some(attr) = attrs.next() {
7005            let Ok(attr) = attr else { break };
7006            match attr {
7007                OpPagePoolGetDoReply::Id(val) => {
7008                    if last_off == offset {
7009                        stack.push(("Id", last_off));
7010                        break;
7011                    }
7012                }
7013                OpPagePoolGetDoReply::Ifindex(val) => {
7014                    if last_off == offset {
7015                        stack.push(("Ifindex", last_off));
7016                        break;
7017                    }
7018                }
7019                OpPagePoolGetDoReply::NapiId(val) => {
7020                    if last_off == offset {
7021                        stack.push(("NapiId", last_off));
7022                        break;
7023                    }
7024                }
7025                OpPagePoolGetDoReply::Inflight(val) => {
7026                    if last_off == offset {
7027                        stack.push(("Inflight", last_off));
7028                        break;
7029                    }
7030                }
7031                OpPagePoolGetDoReply::InflightMem(val) => {
7032                    if last_off == offset {
7033                        stack.push(("InflightMem", last_off));
7034                        break;
7035                    }
7036                }
7037                OpPagePoolGetDoReply::DetachTime(val) => {
7038                    if last_off == offset {
7039                        stack.push(("DetachTime", last_off));
7040                        break;
7041                    }
7042                }
7043                OpPagePoolGetDoReply::Dmabuf(val) => {
7044                    if last_off == offset {
7045                        stack.push(("Dmabuf", last_off));
7046                        break;
7047                    }
7048                }
7049                OpPagePoolGetDoReply::IoUring(val) => {
7050                    (stack, missing) = val.lookup_attr(offset, missing_type);
7051                    if !stack.is_empty() {
7052                        break;
7053                    }
7054                }
7055                _ => {}
7056            };
7057            last_off = cur + attrs.pos;
7058        }
7059        if !stack.is_empty() {
7060            stack.push(("OpPagePoolGetDoReply", cur));
7061        }
7062        (stack, missing)
7063    }
7064}
7065#[derive(Debug)]
7066pub struct RequestOpPagePoolGetDoRequest<'r> {
7067    request: Request<'r>,
7068}
7069impl<'r> RequestOpPagePoolGetDoRequest<'r> {
7070    pub fn new(mut request: Request<'r>) -> Self {
7071        PushOpPagePoolGetDoRequest::write_header(&mut request.buf_mut());
7072        Self { request: request }
7073    }
7074    pub fn encode(&mut self) -> PushOpPagePoolGetDoRequest<&mut Vec<u8>> {
7075        PushOpPagePoolGetDoRequest::new_without_header(self.request.buf_mut())
7076    }
7077    pub fn into_encoder(self) -> PushOpPagePoolGetDoRequest<RequestBuf<'r>> {
7078        PushOpPagePoolGetDoRequest::new_without_header(self.request.buf)
7079    }
7080    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolGetDoRequest<'buf> {
7081        OpPagePoolGetDoRequest::new(buf)
7082    }
7083}
7084impl NetlinkRequest for RequestOpPagePoolGetDoRequest<'_> {
7085    fn protocol(&self) -> Protocol {
7086        Protocol::Generic("netdev".as_bytes())
7087    }
7088    fn flags(&self) -> u16 {
7089        self.request.flags
7090    }
7091    fn payload(&self) -> &[u8] {
7092        self.request.buf()
7093    }
7094    type ReplyType<'buf> = IterableOpPagePoolGetDoReply<'buf>;
7095    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7096        OpPagePoolGetDoReply::new(buf)
7097    }
7098    fn lookup(
7099        buf: &[u8],
7100        offset: usize,
7101        missing_type: Option<u16>,
7102    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7103        OpPagePoolGetDoRequest::new(buf).lookup_attr(offset, missing_type)
7104    }
7105}
7106#[doc = "Get page pool statistics."]
7107pub struct PushOpPagePoolStatsGetDumpRequest<Prev: Rec> {
7108    pub(crate) prev: Option<Prev>,
7109    pub(crate) header_offset: Option<usize>,
7110}
7111impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpRequest<Prev> {
7112    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7113        self.prev.as_mut().unwrap().as_rec_mut()
7114    }
7115    fn as_rec(&self) -> &Vec<u8> {
7116        self.prev.as_ref().unwrap().as_rec()
7117    }
7118}
7119impl<Prev: Rec> PushOpPagePoolStatsGetDumpRequest<Prev> {
7120    pub fn new(mut prev: Prev) -> Self {
7121        Self::write_header(&mut prev);
7122        Self::new_without_header(prev)
7123    }
7124    fn new_without_header(prev: Prev) -> Self {
7125        Self {
7126            prev: Some(prev),
7127            header_offset: None,
7128        }
7129    }
7130    fn write_header(prev: &mut Prev) {
7131        let mut header = PushBuiltinNfgenmsg::new();
7132        header.set_cmd(9u8);
7133        header.set_version(1u8);
7134        prev.as_rec_mut().extend(header.as_slice());
7135    }
7136    pub fn end_nested(mut self) -> Prev {
7137        let mut prev = self.prev.take().unwrap();
7138        if let Some(header_offset) = &self.header_offset {
7139            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7140        }
7141        prev
7142    }
7143}
7144impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpRequest<Prev> {
7145    fn drop(&mut self) {
7146        if let Some(prev) = &mut self.prev {
7147            if let Some(header_offset) = &self.header_offset {
7148                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7149            }
7150        }
7151    }
7152}
7153#[doc = "Get page pool statistics."]
7154#[derive(Clone)]
7155pub enum OpPagePoolStatsGetDumpRequest {}
7156impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {}
7157impl OpPagePoolStatsGetDumpRequest {
7158    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpRequest<'a> {
7159        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7160        IterableOpPagePoolStatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
7161    }
7162    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7163        PagePoolStats::attr_from_type(r#type)
7164    }
7165}
7166#[derive(Clone, Copy, Default)]
7167pub struct IterableOpPagePoolStatsGetDumpRequest<'a> {
7168    buf: &'a [u8],
7169    pos: usize,
7170    orig_loc: usize,
7171}
7172impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {
7173    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7174        Self {
7175            buf,
7176            pos: 0,
7177            orig_loc,
7178        }
7179    }
7180    pub fn get_buf(&self) -> &'a [u8] {
7181        self.buf
7182    }
7183}
7184impl<'a> Iterator for IterableOpPagePoolStatsGetDumpRequest<'a> {
7185    type Item = Result<OpPagePoolStatsGetDumpRequest, ErrorContext>;
7186    fn next(&mut self) -> Option<Self::Item> {
7187        let pos = self.pos;
7188        let mut r#type;
7189        loop {
7190            r#type = None;
7191            if self.buf.len() == self.pos {
7192                return None;
7193            }
7194            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7195                break;
7196            };
7197            r#type = Some(header.r#type);
7198            let res = match header.r#type {
7199                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7200                n => continue,
7201            };
7202            return Some(Ok(res));
7203        }
7204        Some(Err(ErrorContext::new(
7205            "OpPagePoolStatsGetDumpRequest",
7206            r#type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7207            self.orig_loc,
7208            self.buf.as_ptr().wrapping_add(pos) as usize,
7209        )))
7210    }
7211}
7212impl std::fmt::Debug for IterableOpPagePoolStatsGetDumpRequest<'_> {
7213    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7214        let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpRequest");
7215        for attr in self.clone() {
7216            let attr = match attr {
7217                Ok(a) => a,
7218                Err(err) => {
7219                    fmt.finish()?;
7220                    f.write_str("Err(")?;
7221                    err.fmt(f)?;
7222                    return f.write_str(")");
7223                }
7224            };
7225            match attr {};
7226        }
7227        fmt.finish()
7228    }
7229}
7230impl IterableOpPagePoolStatsGetDumpRequest<'_> {
7231    pub fn lookup_attr(
7232        &self,
7233        offset: usize,
7234        missing_type: Option<u16>,
7235    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7236        let mut stack = Vec::new();
7237        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7238        if cur == offset + PushBuiltinNfgenmsg::len() {
7239            stack.push(("OpPagePoolStatsGetDumpRequest", offset));
7240            return (
7241                stack,
7242                missing_type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7243            );
7244        }
7245        (stack, None)
7246    }
7247}
7248#[doc = "Get page pool statistics."]
7249pub struct PushOpPagePoolStatsGetDumpReply<Prev: Rec> {
7250    pub(crate) prev: Option<Prev>,
7251    pub(crate) header_offset: Option<usize>,
7252}
7253impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpReply<Prev> {
7254    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7255        self.prev.as_mut().unwrap().as_rec_mut()
7256    }
7257    fn as_rec(&self) -> &Vec<u8> {
7258        self.prev.as_ref().unwrap().as_rec()
7259    }
7260}
7261impl<Prev: Rec> PushOpPagePoolStatsGetDumpReply<Prev> {
7262    pub fn new(mut prev: Prev) -> Self {
7263        Self::write_header(&mut prev);
7264        Self::new_without_header(prev)
7265    }
7266    fn new_without_header(prev: Prev) -> Self {
7267        Self {
7268            prev: Some(prev),
7269            header_offset: None,
7270        }
7271    }
7272    fn write_header(prev: &mut Prev) {
7273        let mut header = PushBuiltinNfgenmsg::new();
7274        header.set_cmd(9u8);
7275        header.set_version(1u8);
7276        prev.as_rec_mut().extend(header.as_slice());
7277    }
7278    pub fn end_nested(mut self) -> Prev {
7279        let mut prev = self.prev.take().unwrap();
7280        if let Some(header_offset) = &self.header_offset {
7281            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7282        }
7283        prev
7284    }
7285    #[doc = "Page pool identifying information."]
7286    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7287        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7288        PushPagePoolInfo {
7289            prev: Some(self),
7290            header_offset: Some(header_offset),
7291        }
7292    }
7293    pub fn push_alloc_fast(mut self, value: u32) -> Self {
7294        push_header(self.as_rec_mut(), 8u16, 4 as u16);
7295        self.as_rec_mut().extend(value.to_ne_bytes());
7296        self
7297    }
7298    pub fn push_alloc_slow(mut self, value: u32) -> Self {
7299        push_header(self.as_rec_mut(), 9u16, 4 as u16);
7300        self.as_rec_mut().extend(value.to_ne_bytes());
7301        self
7302    }
7303    pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
7304        push_header(self.as_rec_mut(), 10u16, 4 as u16);
7305        self.as_rec_mut().extend(value.to_ne_bytes());
7306        self
7307    }
7308    pub fn push_alloc_empty(mut self, value: u32) -> Self {
7309        push_header(self.as_rec_mut(), 11u16, 4 as u16);
7310        self.as_rec_mut().extend(value.to_ne_bytes());
7311        self
7312    }
7313    pub fn push_alloc_refill(mut self, value: u32) -> Self {
7314        push_header(self.as_rec_mut(), 12u16, 4 as u16);
7315        self.as_rec_mut().extend(value.to_ne_bytes());
7316        self
7317    }
7318    pub fn push_alloc_waive(mut self, value: u32) -> Self {
7319        push_header(self.as_rec_mut(), 13u16, 4 as u16);
7320        self.as_rec_mut().extend(value.to_ne_bytes());
7321        self
7322    }
7323    pub fn push_recycle_cached(mut self, value: u32) -> Self {
7324        push_header(self.as_rec_mut(), 14u16, 4 as u16);
7325        self.as_rec_mut().extend(value.to_ne_bytes());
7326        self
7327    }
7328    pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
7329        push_header(self.as_rec_mut(), 15u16, 4 as u16);
7330        self.as_rec_mut().extend(value.to_ne_bytes());
7331        self
7332    }
7333    pub fn push_recycle_ring(mut self, value: u32) -> Self {
7334        push_header(self.as_rec_mut(), 16u16, 4 as u16);
7335        self.as_rec_mut().extend(value.to_ne_bytes());
7336        self
7337    }
7338    pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
7339        push_header(self.as_rec_mut(), 17u16, 4 as u16);
7340        self.as_rec_mut().extend(value.to_ne_bytes());
7341        self
7342    }
7343    pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
7344        push_header(self.as_rec_mut(), 18u16, 4 as u16);
7345        self.as_rec_mut().extend(value.to_ne_bytes());
7346        self
7347    }
7348}
7349impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpReply<Prev> {
7350    fn drop(&mut self) {
7351        if let Some(prev) = &mut self.prev {
7352            if let Some(header_offset) = &self.header_offset {
7353                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7354            }
7355        }
7356    }
7357}
7358#[doc = "Get page pool statistics."]
7359#[derive(Clone)]
7360pub enum OpPagePoolStatsGetDumpReply<'a> {
7361    #[doc = "Page pool identifying information."]
7362    Info(IterablePagePoolInfo<'a>),
7363    AllocFast(u32),
7364    AllocSlow(u32),
7365    AllocSlowHighOrder(u32),
7366    AllocEmpty(u32),
7367    AllocRefill(u32),
7368    AllocWaive(u32),
7369    RecycleCached(u32),
7370    RecycleCacheFull(u32),
7371    RecycleRing(u32),
7372    RecycleRingFull(u32),
7373    RecycleReleasedRefcnt(u32),
7374}
7375impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7376    #[doc = "Page pool identifying information."]
7377    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7378        let mut iter = self.clone();
7379        iter.pos = 0;
7380        for attr in iter {
7381            if let OpPagePoolStatsGetDumpReply::Info(val) = attr? {
7382                return Ok(val);
7383            }
7384        }
7385        Err(ErrorContext::new_missing(
7386            "OpPagePoolStatsGetDumpReply",
7387            "Info",
7388            self.orig_loc,
7389            self.buf.as_ptr() as usize,
7390        ))
7391    }
7392    pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
7393        let mut iter = self.clone();
7394        iter.pos = 0;
7395        for attr in iter {
7396            if let OpPagePoolStatsGetDumpReply::AllocFast(val) = attr? {
7397                return Ok(val);
7398            }
7399        }
7400        Err(ErrorContext::new_missing(
7401            "OpPagePoolStatsGetDumpReply",
7402            "AllocFast",
7403            self.orig_loc,
7404            self.buf.as_ptr() as usize,
7405        ))
7406    }
7407    pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
7408        let mut iter = self.clone();
7409        iter.pos = 0;
7410        for attr in iter {
7411            if let OpPagePoolStatsGetDumpReply::AllocSlow(val) = attr? {
7412                return Ok(val);
7413            }
7414        }
7415        Err(ErrorContext::new_missing(
7416            "OpPagePoolStatsGetDumpReply",
7417            "AllocSlow",
7418            self.orig_loc,
7419            self.buf.as_ptr() as usize,
7420        ))
7421    }
7422    pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
7423        let mut iter = self.clone();
7424        iter.pos = 0;
7425        for attr in iter {
7426            if let OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) = attr? {
7427                return Ok(val);
7428            }
7429        }
7430        Err(ErrorContext::new_missing(
7431            "OpPagePoolStatsGetDumpReply",
7432            "AllocSlowHighOrder",
7433            self.orig_loc,
7434            self.buf.as_ptr() as usize,
7435        ))
7436    }
7437    pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
7438        let mut iter = self.clone();
7439        iter.pos = 0;
7440        for attr in iter {
7441            if let OpPagePoolStatsGetDumpReply::AllocEmpty(val) = attr? {
7442                return Ok(val);
7443            }
7444        }
7445        Err(ErrorContext::new_missing(
7446            "OpPagePoolStatsGetDumpReply",
7447            "AllocEmpty",
7448            self.orig_loc,
7449            self.buf.as_ptr() as usize,
7450        ))
7451    }
7452    pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
7453        let mut iter = self.clone();
7454        iter.pos = 0;
7455        for attr in iter {
7456            if let OpPagePoolStatsGetDumpReply::AllocRefill(val) = attr? {
7457                return Ok(val);
7458            }
7459        }
7460        Err(ErrorContext::new_missing(
7461            "OpPagePoolStatsGetDumpReply",
7462            "AllocRefill",
7463            self.orig_loc,
7464            self.buf.as_ptr() as usize,
7465        ))
7466    }
7467    pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
7468        let mut iter = self.clone();
7469        iter.pos = 0;
7470        for attr in iter {
7471            if let OpPagePoolStatsGetDumpReply::AllocWaive(val) = attr? {
7472                return Ok(val);
7473            }
7474        }
7475        Err(ErrorContext::new_missing(
7476            "OpPagePoolStatsGetDumpReply",
7477            "AllocWaive",
7478            self.orig_loc,
7479            self.buf.as_ptr() as usize,
7480        ))
7481    }
7482    pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
7483        let mut iter = self.clone();
7484        iter.pos = 0;
7485        for attr in iter {
7486            if let OpPagePoolStatsGetDumpReply::RecycleCached(val) = attr? {
7487                return Ok(val);
7488            }
7489        }
7490        Err(ErrorContext::new_missing(
7491            "OpPagePoolStatsGetDumpReply",
7492            "RecycleCached",
7493            self.orig_loc,
7494            self.buf.as_ptr() as usize,
7495        ))
7496    }
7497    pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
7498        let mut iter = self.clone();
7499        iter.pos = 0;
7500        for attr in iter {
7501            if let OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) = attr? {
7502                return Ok(val);
7503            }
7504        }
7505        Err(ErrorContext::new_missing(
7506            "OpPagePoolStatsGetDumpReply",
7507            "RecycleCacheFull",
7508            self.orig_loc,
7509            self.buf.as_ptr() as usize,
7510        ))
7511    }
7512    pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
7513        let mut iter = self.clone();
7514        iter.pos = 0;
7515        for attr in iter {
7516            if let OpPagePoolStatsGetDumpReply::RecycleRing(val) = attr? {
7517                return Ok(val);
7518            }
7519        }
7520        Err(ErrorContext::new_missing(
7521            "OpPagePoolStatsGetDumpReply",
7522            "RecycleRing",
7523            self.orig_loc,
7524            self.buf.as_ptr() as usize,
7525        ))
7526    }
7527    pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
7528        let mut iter = self.clone();
7529        iter.pos = 0;
7530        for attr in iter {
7531            if let OpPagePoolStatsGetDumpReply::RecycleRingFull(val) = attr? {
7532                return Ok(val);
7533            }
7534        }
7535        Err(ErrorContext::new_missing(
7536            "OpPagePoolStatsGetDumpReply",
7537            "RecycleRingFull",
7538            self.orig_loc,
7539            self.buf.as_ptr() as usize,
7540        ))
7541    }
7542    pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
7543        let mut iter = self.clone();
7544        iter.pos = 0;
7545        for attr in iter {
7546            if let OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) = attr? {
7547                return Ok(val);
7548            }
7549        }
7550        Err(ErrorContext::new_missing(
7551            "OpPagePoolStatsGetDumpReply",
7552            "RecycleReleasedRefcnt",
7553            self.orig_loc,
7554            self.buf.as_ptr() as usize,
7555        ))
7556    }
7557}
7558impl OpPagePoolStatsGetDumpReply<'_> {
7559    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpReply<'a> {
7560        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7561        IterableOpPagePoolStatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
7562    }
7563    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7564        PagePoolStats::attr_from_type(r#type)
7565    }
7566}
7567#[derive(Clone, Copy, Default)]
7568pub struct IterableOpPagePoolStatsGetDumpReply<'a> {
7569    buf: &'a [u8],
7570    pos: usize,
7571    orig_loc: usize,
7572}
7573impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7574    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7575        Self {
7576            buf,
7577            pos: 0,
7578            orig_loc,
7579        }
7580    }
7581    pub fn get_buf(&self) -> &'a [u8] {
7582        self.buf
7583    }
7584}
7585impl<'a> Iterator for IterableOpPagePoolStatsGetDumpReply<'a> {
7586    type Item = Result<OpPagePoolStatsGetDumpReply<'a>, ErrorContext>;
7587    fn next(&mut self) -> Option<Self::Item> {
7588        let pos = self.pos;
7589        let mut r#type;
7590        loop {
7591            r#type = None;
7592            if self.buf.len() == self.pos {
7593                return None;
7594            }
7595            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7596                break;
7597            };
7598            r#type = Some(header.r#type);
7599            let res = match header.r#type {
7600                1u16 => OpPagePoolStatsGetDumpReply::Info({
7601                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7602                    let Some(val) = res else { break };
7603                    val
7604                }),
7605                8u16 => OpPagePoolStatsGetDumpReply::AllocFast({
7606                    let res = parse_u32(next);
7607                    let Some(val) = res else { break };
7608                    val
7609                }),
7610                9u16 => OpPagePoolStatsGetDumpReply::AllocSlow({
7611                    let res = parse_u32(next);
7612                    let Some(val) = res else { break };
7613                    val
7614                }),
7615                10u16 => OpPagePoolStatsGetDumpReply::AllocSlowHighOrder({
7616                    let res = parse_u32(next);
7617                    let Some(val) = res else { break };
7618                    val
7619                }),
7620                11u16 => OpPagePoolStatsGetDumpReply::AllocEmpty({
7621                    let res = parse_u32(next);
7622                    let Some(val) = res else { break };
7623                    val
7624                }),
7625                12u16 => OpPagePoolStatsGetDumpReply::AllocRefill({
7626                    let res = parse_u32(next);
7627                    let Some(val) = res else { break };
7628                    val
7629                }),
7630                13u16 => OpPagePoolStatsGetDumpReply::AllocWaive({
7631                    let res = parse_u32(next);
7632                    let Some(val) = res else { break };
7633                    val
7634                }),
7635                14u16 => OpPagePoolStatsGetDumpReply::RecycleCached({
7636                    let res = parse_u32(next);
7637                    let Some(val) = res else { break };
7638                    val
7639                }),
7640                15u16 => OpPagePoolStatsGetDumpReply::RecycleCacheFull({
7641                    let res = parse_u32(next);
7642                    let Some(val) = res else { break };
7643                    val
7644                }),
7645                16u16 => OpPagePoolStatsGetDumpReply::RecycleRing({
7646                    let res = parse_u32(next);
7647                    let Some(val) = res else { break };
7648                    val
7649                }),
7650                17u16 => OpPagePoolStatsGetDumpReply::RecycleRingFull({
7651                    let res = parse_u32(next);
7652                    let Some(val) = res else { break };
7653                    val
7654                }),
7655                18u16 => OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt({
7656                    let res = parse_u32(next);
7657                    let Some(val) = res else { break };
7658                    val
7659                }),
7660                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7661                n => continue,
7662            };
7663            return Some(Ok(res));
7664        }
7665        Some(Err(ErrorContext::new(
7666            "OpPagePoolStatsGetDumpReply",
7667            r#type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7668            self.orig_loc,
7669            self.buf.as_ptr().wrapping_add(pos) as usize,
7670        )))
7671    }
7672}
7673impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDumpReply<'_> {
7674    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7675        let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpReply");
7676        for attr in self.clone() {
7677            let attr = match attr {
7678                Ok(a) => a,
7679                Err(err) => {
7680                    fmt.finish()?;
7681                    f.write_str("Err(")?;
7682                    err.fmt(f)?;
7683                    return f.write_str(")");
7684                }
7685            };
7686            match attr {
7687                OpPagePoolStatsGetDumpReply::Info(val) => fmt.field("Info", &val),
7688                OpPagePoolStatsGetDumpReply::AllocFast(val) => fmt.field("AllocFast", &val),
7689                OpPagePoolStatsGetDumpReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
7690                OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7691                    fmt.field("AllocSlowHighOrder", &val)
7692                }
7693                OpPagePoolStatsGetDumpReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
7694                OpPagePoolStatsGetDumpReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
7695                OpPagePoolStatsGetDumpReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
7696                OpPagePoolStatsGetDumpReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
7697                OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7698                    fmt.field("RecycleCacheFull", &val)
7699                }
7700                OpPagePoolStatsGetDumpReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
7701                OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7702                    fmt.field("RecycleRingFull", &val)
7703                }
7704                OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7705                    fmt.field("RecycleReleasedRefcnt", &val)
7706                }
7707            };
7708        }
7709        fmt.finish()
7710    }
7711}
7712impl IterableOpPagePoolStatsGetDumpReply<'_> {
7713    pub fn lookup_attr(
7714        &self,
7715        offset: usize,
7716        missing_type: Option<u16>,
7717    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7718        let mut stack = Vec::new();
7719        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7720        if cur == offset + PushBuiltinNfgenmsg::len() {
7721            stack.push(("OpPagePoolStatsGetDumpReply", offset));
7722            return (
7723                stack,
7724                missing_type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7725            );
7726        }
7727        if cur > offset || cur + self.buf.len() < offset {
7728            return (stack, None);
7729        }
7730        let mut attrs = self.clone();
7731        let mut last_off = cur + attrs.pos;
7732        let mut missing = None;
7733        while let Some(attr) = attrs.next() {
7734            let Ok(attr) = attr else { break };
7735            match attr {
7736                OpPagePoolStatsGetDumpReply::Info(val) => {
7737                    (stack, missing) = val.lookup_attr(offset, missing_type);
7738                    if !stack.is_empty() {
7739                        break;
7740                    }
7741                }
7742                OpPagePoolStatsGetDumpReply::AllocFast(val) => {
7743                    if last_off == offset {
7744                        stack.push(("AllocFast", last_off));
7745                        break;
7746                    }
7747                }
7748                OpPagePoolStatsGetDumpReply::AllocSlow(val) => {
7749                    if last_off == offset {
7750                        stack.push(("AllocSlow", last_off));
7751                        break;
7752                    }
7753                }
7754                OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7755                    if last_off == offset {
7756                        stack.push(("AllocSlowHighOrder", last_off));
7757                        break;
7758                    }
7759                }
7760                OpPagePoolStatsGetDumpReply::AllocEmpty(val) => {
7761                    if last_off == offset {
7762                        stack.push(("AllocEmpty", last_off));
7763                        break;
7764                    }
7765                }
7766                OpPagePoolStatsGetDumpReply::AllocRefill(val) => {
7767                    if last_off == offset {
7768                        stack.push(("AllocRefill", last_off));
7769                        break;
7770                    }
7771                }
7772                OpPagePoolStatsGetDumpReply::AllocWaive(val) => {
7773                    if last_off == offset {
7774                        stack.push(("AllocWaive", last_off));
7775                        break;
7776                    }
7777                }
7778                OpPagePoolStatsGetDumpReply::RecycleCached(val) => {
7779                    if last_off == offset {
7780                        stack.push(("RecycleCached", last_off));
7781                        break;
7782                    }
7783                }
7784                OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7785                    if last_off == offset {
7786                        stack.push(("RecycleCacheFull", last_off));
7787                        break;
7788                    }
7789                }
7790                OpPagePoolStatsGetDumpReply::RecycleRing(val) => {
7791                    if last_off == offset {
7792                        stack.push(("RecycleRing", last_off));
7793                        break;
7794                    }
7795                }
7796                OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7797                    if last_off == offset {
7798                        stack.push(("RecycleRingFull", last_off));
7799                        break;
7800                    }
7801                }
7802                OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7803                    if last_off == offset {
7804                        stack.push(("RecycleReleasedRefcnt", last_off));
7805                        break;
7806                    }
7807                }
7808                _ => {}
7809            };
7810            last_off = cur + attrs.pos;
7811        }
7812        if !stack.is_empty() {
7813            stack.push(("OpPagePoolStatsGetDumpReply", cur));
7814        }
7815        (stack, missing)
7816    }
7817}
7818#[derive(Debug)]
7819pub struct RequestOpPagePoolStatsGetDumpRequest<'r> {
7820    request: Request<'r>,
7821}
7822impl<'r> RequestOpPagePoolStatsGetDumpRequest<'r> {
7823    pub fn new(mut request: Request<'r>) -> Self {
7824        PushOpPagePoolStatsGetDumpRequest::write_header(&mut request.buf_mut());
7825        Self {
7826            request: request.set_dump(),
7827        }
7828    }
7829    pub fn encode(&mut self) -> PushOpPagePoolStatsGetDumpRequest<&mut Vec<u8>> {
7830        PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf_mut())
7831    }
7832    pub fn into_encoder(self) -> PushOpPagePoolStatsGetDumpRequest<RequestBuf<'r>> {
7833        PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf)
7834    }
7835    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolStatsGetDumpRequest<'buf> {
7836        OpPagePoolStatsGetDumpRequest::new(buf)
7837    }
7838}
7839impl NetlinkRequest for RequestOpPagePoolStatsGetDumpRequest<'_> {
7840    fn protocol(&self) -> Protocol {
7841        Protocol::Generic("netdev".as_bytes())
7842    }
7843    fn flags(&self) -> u16 {
7844        self.request.flags
7845    }
7846    fn payload(&self) -> &[u8] {
7847        self.request.buf()
7848    }
7849    type ReplyType<'buf> = IterableOpPagePoolStatsGetDumpReply<'buf>;
7850    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7851        OpPagePoolStatsGetDumpReply::new(buf)
7852    }
7853    fn lookup(
7854        buf: &[u8],
7855        offset: usize,
7856        missing_type: Option<u16>,
7857    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7858        OpPagePoolStatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
7859    }
7860}
7861#[doc = "Get page pool statistics."]
7862pub struct PushOpPagePoolStatsGetDoRequest<Prev: Rec> {
7863    pub(crate) prev: Option<Prev>,
7864    pub(crate) header_offset: Option<usize>,
7865}
7866impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoRequest<Prev> {
7867    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7868        self.prev.as_mut().unwrap().as_rec_mut()
7869    }
7870    fn as_rec(&self) -> &Vec<u8> {
7871        self.prev.as_ref().unwrap().as_rec()
7872    }
7873}
7874impl<Prev: Rec> PushOpPagePoolStatsGetDoRequest<Prev> {
7875    pub fn new(mut prev: Prev) -> Self {
7876        Self::write_header(&mut prev);
7877        Self::new_without_header(prev)
7878    }
7879    fn new_without_header(prev: Prev) -> Self {
7880        Self {
7881            prev: Some(prev),
7882            header_offset: None,
7883        }
7884    }
7885    fn write_header(prev: &mut Prev) {
7886        let mut header = PushBuiltinNfgenmsg::new();
7887        header.set_cmd(9u8);
7888        header.set_version(1u8);
7889        prev.as_rec_mut().extend(header.as_slice());
7890    }
7891    pub fn end_nested(mut self) -> Prev {
7892        let mut prev = self.prev.take().unwrap();
7893        if let Some(header_offset) = &self.header_offset {
7894            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7895        }
7896        prev
7897    }
7898    #[doc = "Page pool identifying information."]
7899    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7900        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7901        PushPagePoolInfo {
7902            prev: Some(self),
7903            header_offset: Some(header_offset),
7904        }
7905    }
7906}
7907impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoRequest<Prev> {
7908    fn drop(&mut self) {
7909        if let Some(prev) = &mut self.prev {
7910            if let Some(header_offset) = &self.header_offset {
7911                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7912            }
7913        }
7914    }
7915}
7916#[doc = "Get page pool statistics."]
7917#[derive(Clone)]
7918pub enum OpPagePoolStatsGetDoRequest<'a> {
7919    #[doc = "Page pool identifying information."]
7920    Info(IterablePagePoolInfo<'a>),
7921}
7922impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7923    #[doc = "Page pool identifying information."]
7924    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7925        let mut iter = self.clone();
7926        iter.pos = 0;
7927        for attr in iter {
7928            if let OpPagePoolStatsGetDoRequest::Info(val) = attr? {
7929                return Ok(val);
7930            }
7931        }
7932        Err(ErrorContext::new_missing(
7933            "OpPagePoolStatsGetDoRequest",
7934            "Info",
7935            self.orig_loc,
7936            self.buf.as_ptr() as usize,
7937        ))
7938    }
7939}
7940impl OpPagePoolStatsGetDoRequest<'_> {
7941    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoRequest<'a> {
7942        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7943        IterableOpPagePoolStatsGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
7944    }
7945    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7946        PagePoolStats::attr_from_type(r#type)
7947    }
7948}
7949#[derive(Clone, Copy, Default)]
7950pub struct IterableOpPagePoolStatsGetDoRequest<'a> {
7951    buf: &'a [u8],
7952    pos: usize,
7953    orig_loc: usize,
7954}
7955impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7956    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7957        Self {
7958            buf,
7959            pos: 0,
7960            orig_loc,
7961        }
7962    }
7963    pub fn get_buf(&self) -> &'a [u8] {
7964        self.buf
7965    }
7966}
7967impl<'a> Iterator for IterableOpPagePoolStatsGetDoRequest<'a> {
7968    type Item = Result<OpPagePoolStatsGetDoRequest<'a>, ErrorContext>;
7969    fn next(&mut self) -> Option<Self::Item> {
7970        let pos = self.pos;
7971        let mut r#type;
7972        loop {
7973            r#type = None;
7974            if self.buf.len() == self.pos {
7975                return None;
7976            }
7977            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7978                break;
7979            };
7980            r#type = Some(header.r#type);
7981            let res = match header.r#type {
7982                1u16 => OpPagePoolStatsGetDoRequest::Info({
7983                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7984                    let Some(val) = res else { break };
7985                    val
7986                }),
7987                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7988                n => continue,
7989            };
7990            return Some(Ok(res));
7991        }
7992        Some(Err(ErrorContext::new(
7993            "OpPagePoolStatsGetDoRequest",
7994            r#type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
7995            self.orig_loc,
7996            self.buf.as_ptr().wrapping_add(pos) as usize,
7997        )))
7998    }
7999}
8000impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoRequest<'_> {
8001    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8002        let mut fmt = f.debug_struct("OpPagePoolStatsGetDoRequest");
8003        for attr in self.clone() {
8004            let attr = match attr {
8005                Ok(a) => a,
8006                Err(err) => {
8007                    fmt.finish()?;
8008                    f.write_str("Err(")?;
8009                    err.fmt(f)?;
8010                    return f.write_str(")");
8011                }
8012            };
8013            match attr {
8014                OpPagePoolStatsGetDoRequest::Info(val) => fmt.field("Info", &val),
8015            };
8016        }
8017        fmt.finish()
8018    }
8019}
8020impl IterableOpPagePoolStatsGetDoRequest<'_> {
8021    pub fn lookup_attr(
8022        &self,
8023        offset: usize,
8024        missing_type: Option<u16>,
8025    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8026        let mut stack = Vec::new();
8027        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8028        if cur == offset + PushBuiltinNfgenmsg::len() {
8029            stack.push(("OpPagePoolStatsGetDoRequest", offset));
8030            return (
8031                stack,
8032                missing_type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
8033            );
8034        }
8035        if cur > offset || cur + self.buf.len() < offset {
8036            return (stack, None);
8037        }
8038        let mut attrs = self.clone();
8039        let mut last_off = cur + attrs.pos;
8040        let mut missing = None;
8041        while let Some(attr) = attrs.next() {
8042            let Ok(attr) = attr else { break };
8043            match attr {
8044                OpPagePoolStatsGetDoRequest::Info(val) => {
8045                    (stack, missing) = val.lookup_attr(offset, missing_type);
8046                    if !stack.is_empty() {
8047                        break;
8048                    }
8049                }
8050                _ => {}
8051            };
8052            last_off = cur + attrs.pos;
8053        }
8054        if !stack.is_empty() {
8055            stack.push(("OpPagePoolStatsGetDoRequest", cur));
8056        }
8057        (stack, missing)
8058    }
8059}
8060#[doc = "Get page pool statistics."]
8061pub struct PushOpPagePoolStatsGetDoReply<Prev: Rec> {
8062    pub(crate) prev: Option<Prev>,
8063    pub(crate) header_offset: Option<usize>,
8064}
8065impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoReply<Prev> {
8066    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8067        self.prev.as_mut().unwrap().as_rec_mut()
8068    }
8069    fn as_rec(&self) -> &Vec<u8> {
8070        self.prev.as_ref().unwrap().as_rec()
8071    }
8072}
8073impl<Prev: Rec> PushOpPagePoolStatsGetDoReply<Prev> {
8074    pub fn new(mut prev: Prev) -> Self {
8075        Self::write_header(&mut prev);
8076        Self::new_without_header(prev)
8077    }
8078    fn new_without_header(prev: Prev) -> Self {
8079        Self {
8080            prev: Some(prev),
8081            header_offset: None,
8082        }
8083    }
8084    fn write_header(prev: &mut Prev) {
8085        let mut header = PushBuiltinNfgenmsg::new();
8086        header.set_cmd(9u8);
8087        header.set_version(1u8);
8088        prev.as_rec_mut().extend(header.as_slice());
8089    }
8090    pub fn end_nested(mut self) -> Prev {
8091        let mut prev = self.prev.take().unwrap();
8092        if let Some(header_offset) = &self.header_offset {
8093            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8094        }
8095        prev
8096    }
8097    #[doc = "Page pool identifying information."]
8098    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
8099        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
8100        PushPagePoolInfo {
8101            prev: Some(self),
8102            header_offset: Some(header_offset),
8103        }
8104    }
8105    pub fn push_alloc_fast(mut self, value: u32) -> Self {
8106        push_header(self.as_rec_mut(), 8u16, 4 as u16);
8107        self.as_rec_mut().extend(value.to_ne_bytes());
8108        self
8109    }
8110    pub fn push_alloc_slow(mut self, value: u32) -> Self {
8111        push_header(self.as_rec_mut(), 9u16, 4 as u16);
8112        self.as_rec_mut().extend(value.to_ne_bytes());
8113        self
8114    }
8115    pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
8116        push_header(self.as_rec_mut(), 10u16, 4 as u16);
8117        self.as_rec_mut().extend(value.to_ne_bytes());
8118        self
8119    }
8120    pub fn push_alloc_empty(mut self, value: u32) -> Self {
8121        push_header(self.as_rec_mut(), 11u16, 4 as u16);
8122        self.as_rec_mut().extend(value.to_ne_bytes());
8123        self
8124    }
8125    pub fn push_alloc_refill(mut self, value: u32) -> Self {
8126        push_header(self.as_rec_mut(), 12u16, 4 as u16);
8127        self.as_rec_mut().extend(value.to_ne_bytes());
8128        self
8129    }
8130    pub fn push_alloc_waive(mut self, value: u32) -> Self {
8131        push_header(self.as_rec_mut(), 13u16, 4 as u16);
8132        self.as_rec_mut().extend(value.to_ne_bytes());
8133        self
8134    }
8135    pub fn push_recycle_cached(mut self, value: u32) -> Self {
8136        push_header(self.as_rec_mut(), 14u16, 4 as u16);
8137        self.as_rec_mut().extend(value.to_ne_bytes());
8138        self
8139    }
8140    pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
8141        push_header(self.as_rec_mut(), 15u16, 4 as u16);
8142        self.as_rec_mut().extend(value.to_ne_bytes());
8143        self
8144    }
8145    pub fn push_recycle_ring(mut self, value: u32) -> Self {
8146        push_header(self.as_rec_mut(), 16u16, 4 as u16);
8147        self.as_rec_mut().extend(value.to_ne_bytes());
8148        self
8149    }
8150    pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
8151        push_header(self.as_rec_mut(), 17u16, 4 as u16);
8152        self.as_rec_mut().extend(value.to_ne_bytes());
8153        self
8154    }
8155    pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
8156        push_header(self.as_rec_mut(), 18u16, 4 as u16);
8157        self.as_rec_mut().extend(value.to_ne_bytes());
8158        self
8159    }
8160}
8161impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoReply<Prev> {
8162    fn drop(&mut self) {
8163        if let Some(prev) = &mut self.prev {
8164            if let Some(header_offset) = &self.header_offset {
8165                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8166            }
8167        }
8168    }
8169}
8170#[doc = "Get page pool statistics."]
8171#[derive(Clone)]
8172pub enum OpPagePoolStatsGetDoReply<'a> {
8173    #[doc = "Page pool identifying information."]
8174    Info(IterablePagePoolInfo<'a>),
8175    AllocFast(u32),
8176    AllocSlow(u32),
8177    AllocSlowHighOrder(u32),
8178    AllocEmpty(u32),
8179    AllocRefill(u32),
8180    AllocWaive(u32),
8181    RecycleCached(u32),
8182    RecycleCacheFull(u32),
8183    RecycleRing(u32),
8184    RecycleRingFull(u32),
8185    RecycleReleasedRefcnt(u32),
8186}
8187impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8188    #[doc = "Page pool identifying information."]
8189    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
8190        let mut iter = self.clone();
8191        iter.pos = 0;
8192        for attr in iter {
8193            if let OpPagePoolStatsGetDoReply::Info(val) = attr? {
8194                return Ok(val);
8195            }
8196        }
8197        Err(ErrorContext::new_missing(
8198            "OpPagePoolStatsGetDoReply",
8199            "Info",
8200            self.orig_loc,
8201            self.buf.as_ptr() as usize,
8202        ))
8203    }
8204    pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
8205        let mut iter = self.clone();
8206        iter.pos = 0;
8207        for attr in iter {
8208            if let OpPagePoolStatsGetDoReply::AllocFast(val) = attr? {
8209                return Ok(val);
8210            }
8211        }
8212        Err(ErrorContext::new_missing(
8213            "OpPagePoolStatsGetDoReply",
8214            "AllocFast",
8215            self.orig_loc,
8216            self.buf.as_ptr() as usize,
8217        ))
8218    }
8219    pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
8220        let mut iter = self.clone();
8221        iter.pos = 0;
8222        for attr in iter {
8223            if let OpPagePoolStatsGetDoReply::AllocSlow(val) = attr? {
8224                return Ok(val);
8225            }
8226        }
8227        Err(ErrorContext::new_missing(
8228            "OpPagePoolStatsGetDoReply",
8229            "AllocSlow",
8230            self.orig_loc,
8231            self.buf.as_ptr() as usize,
8232        ))
8233    }
8234    pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
8235        let mut iter = self.clone();
8236        iter.pos = 0;
8237        for attr in iter {
8238            if let OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) = attr? {
8239                return Ok(val);
8240            }
8241        }
8242        Err(ErrorContext::new_missing(
8243            "OpPagePoolStatsGetDoReply",
8244            "AllocSlowHighOrder",
8245            self.orig_loc,
8246            self.buf.as_ptr() as usize,
8247        ))
8248    }
8249    pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
8250        let mut iter = self.clone();
8251        iter.pos = 0;
8252        for attr in iter {
8253            if let OpPagePoolStatsGetDoReply::AllocEmpty(val) = attr? {
8254                return Ok(val);
8255            }
8256        }
8257        Err(ErrorContext::new_missing(
8258            "OpPagePoolStatsGetDoReply",
8259            "AllocEmpty",
8260            self.orig_loc,
8261            self.buf.as_ptr() as usize,
8262        ))
8263    }
8264    pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
8265        let mut iter = self.clone();
8266        iter.pos = 0;
8267        for attr in iter {
8268            if let OpPagePoolStatsGetDoReply::AllocRefill(val) = attr? {
8269                return Ok(val);
8270            }
8271        }
8272        Err(ErrorContext::new_missing(
8273            "OpPagePoolStatsGetDoReply",
8274            "AllocRefill",
8275            self.orig_loc,
8276            self.buf.as_ptr() as usize,
8277        ))
8278    }
8279    pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
8280        let mut iter = self.clone();
8281        iter.pos = 0;
8282        for attr in iter {
8283            if let OpPagePoolStatsGetDoReply::AllocWaive(val) = attr? {
8284                return Ok(val);
8285            }
8286        }
8287        Err(ErrorContext::new_missing(
8288            "OpPagePoolStatsGetDoReply",
8289            "AllocWaive",
8290            self.orig_loc,
8291            self.buf.as_ptr() as usize,
8292        ))
8293    }
8294    pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
8295        let mut iter = self.clone();
8296        iter.pos = 0;
8297        for attr in iter {
8298            if let OpPagePoolStatsGetDoReply::RecycleCached(val) = attr? {
8299                return Ok(val);
8300            }
8301        }
8302        Err(ErrorContext::new_missing(
8303            "OpPagePoolStatsGetDoReply",
8304            "RecycleCached",
8305            self.orig_loc,
8306            self.buf.as_ptr() as usize,
8307        ))
8308    }
8309    pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
8310        let mut iter = self.clone();
8311        iter.pos = 0;
8312        for attr in iter {
8313            if let OpPagePoolStatsGetDoReply::RecycleCacheFull(val) = attr? {
8314                return Ok(val);
8315            }
8316        }
8317        Err(ErrorContext::new_missing(
8318            "OpPagePoolStatsGetDoReply",
8319            "RecycleCacheFull",
8320            self.orig_loc,
8321            self.buf.as_ptr() as usize,
8322        ))
8323    }
8324    pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
8325        let mut iter = self.clone();
8326        iter.pos = 0;
8327        for attr in iter {
8328            if let OpPagePoolStatsGetDoReply::RecycleRing(val) = attr? {
8329                return Ok(val);
8330            }
8331        }
8332        Err(ErrorContext::new_missing(
8333            "OpPagePoolStatsGetDoReply",
8334            "RecycleRing",
8335            self.orig_loc,
8336            self.buf.as_ptr() as usize,
8337        ))
8338    }
8339    pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
8340        let mut iter = self.clone();
8341        iter.pos = 0;
8342        for attr in iter {
8343            if let OpPagePoolStatsGetDoReply::RecycleRingFull(val) = attr? {
8344                return Ok(val);
8345            }
8346        }
8347        Err(ErrorContext::new_missing(
8348            "OpPagePoolStatsGetDoReply",
8349            "RecycleRingFull",
8350            self.orig_loc,
8351            self.buf.as_ptr() as usize,
8352        ))
8353    }
8354    pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
8355        let mut iter = self.clone();
8356        iter.pos = 0;
8357        for attr in iter {
8358            if let OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) = attr? {
8359                return Ok(val);
8360            }
8361        }
8362        Err(ErrorContext::new_missing(
8363            "OpPagePoolStatsGetDoReply",
8364            "RecycleReleasedRefcnt",
8365            self.orig_loc,
8366            self.buf.as_ptr() as usize,
8367        ))
8368    }
8369}
8370impl OpPagePoolStatsGetDoReply<'_> {
8371    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoReply<'a> {
8372        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8373        IterableOpPagePoolStatsGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
8374    }
8375    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8376        PagePoolStats::attr_from_type(r#type)
8377    }
8378}
8379#[derive(Clone, Copy, Default)]
8380pub struct IterableOpPagePoolStatsGetDoReply<'a> {
8381    buf: &'a [u8],
8382    pos: usize,
8383    orig_loc: usize,
8384}
8385impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8386    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8387        Self {
8388            buf,
8389            pos: 0,
8390            orig_loc,
8391        }
8392    }
8393    pub fn get_buf(&self) -> &'a [u8] {
8394        self.buf
8395    }
8396}
8397impl<'a> Iterator for IterableOpPagePoolStatsGetDoReply<'a> {
8398    type Item = Result<OpPagePoolStatsGetDoReply<'a>, ErrorContext>;
8399    fn next(&mut self) -> Option<Self::Item> {
8400        let pos = self.pos;
8401        let mut r#type;
8402        loop {
8403            r#type = None;
8404            if self.buf.len() == self.pos {
8405                return None;
8406            }
8407            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8408                break;
8409            };
8410            r#type = Some(header.r#type);
8411            let res = match header.r#type {
8412                1u16 => OpPagePoolStatsGetDoReply::Info({
8413                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
8414                    let Some(val) = res else { break };
8415                    val
8416                }),
8417                8u16 => OpPagePoolStatsGetDoReply::AllocFast({
8418                    let res = parse_u32(next);
8419                    let Some(val) = res else { break };
8420                    val
8421                }),
8422                9u16 => OpPagePoolStatsGetDoReply::AllocSlow({
8423                    let res = parse_u32(next);
8424                    let Some(val) = res else { break };
8425                    val
8426                }),
8427                10u16 => OpPagePoolStatsGetDoReply::AllocSlowHighOrder({
8428                    let res = parse_u32(next);
8429                    let Some(val) = res else { break };
8430                    val
8431                }),
8432                11u16 => OpPagePoolStatsGetDoReply::AllocEmpty({
8433                    let res = parse_u32(next);
8434                    let Some(val) = res else { break };
8435                    val
8436                }),
8437                12u16 => OpPagePoolStatsGetDoReply::AllocRefill({
8438                    let res = parse_u32(next);
8439                    let Some(val) = res else { break };
8440                    val
8441                }),
8442                13u16 => OpPagePoolStatsGetDoReply::AllocWaive({
8443                    let res = parse_u32(next);
8444                    let Some(val) = res else { break };
8445                    val
8446                }),
8447                14u16 => OpPagePoolStatsGetDoReply::RecycleCached({
8448                    let res = parse_u32(next);
8449                    let Some(val) = res else { break };
8450                    val
8451                }),
8452                15u16 => OpPagePoolStatsGetDoReply::RecycleCacheFull({
8453                    let res = parse_u32(next);
8454                    let Some(val) = res else { break };
8455                    val
8456                }),
8457                16u16 => OpPagePoolStatsGetDoReply::RecycleRing({
8458                    let res = parse_u32(next);
8459                    let Some(val) = res else { break };
8460                    val
8461                }),
8462                17u16 => OpPagePoolStatsGetDoReply::RecycleRingFull({
8463                    let res = parse_u32(next);
8464                    let Some(val) = res else { break };
8465                    val
8466                }),
8467                18u16 => OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt({
8468                    let res = parse_u32(next);
8469                    let Some(val) = res else { break };
8470                    val
8471                }),
8472                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8473                n => continue,
8474            };
8475            return Some(Ok(res));
8476        }
8477        Some(Err(ErrorContext::new(
8478            "OpPagePoolStatsGetDoReply",
8479            r#type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8480            self.orig_loc,
8481            self.buf.as_ptr().wrapping_add(pos) as usize,
8482        )))
8483    }
8484}
8485impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoReply<'_> {
8486    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8487        let mut fmt = f.debug_struct("OpPagePoolStatsGetDoReply");
8488        for attr in self.clone() {
8489            let attr = match attr {
8490                Ok(a) => a,
8491                Err(err) => {
8492                    fmt.finish()?;
8493                    f.write_str("Err(")?;
8494                    err.fmt(f)?;
8495                    return f.write_str(")");
8496                }
8497            };
8498            match attr {
8499                OpPagePoolStatsGetDoReply::Info(val) => fmt.field("Info", &val),
8500                OpPagePoolStatsGetDoReply::AllocFast(val) => fmt.field("AllocFast", &val),
8501                OpPagePoolStatsGetDoReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
8502                OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8503                    fmt.field("AllocSlowHighOrder", &val)
8504                }
8505                OpPagePoolStatsGetDoReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
8506                OpPagePoolStatsGetDoReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
8507                OpPagePoolStatsGetDoReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
8508                OpPagePoolStatsGetDoReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
8509                OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8510                    fmt.field("RecycleCacheFull", &val)
8511                }
8512                OpPagePoolStatsGetDoReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
8513                OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8514                    fmt.field("RecycleRingFull", &val)
8515                }
8516                OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8517                    fmt.field("RecycleReleasedRefcnt", &val)
8518                }
8519            };
8520        }
8521        fmt.finish()
8522    }
8523}
8524impl IterableOpPagePoolStatsGetDoReply<'_> {
8525    pub fn lookup_attr(
8526        &self,
8527        offset: usize,
8528        missing_type: Option<u16>,
8529    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8530        let mut stack = Vec::new();
8531        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8532        if cur == offset + PushBuiltinNfgenmsg::len() {
8533            stack.push(("OpPagePoolStatsGetDoReply", offset));
8534            return (
8535                stack,
8536                missing_type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8537            );
8538        }
8539        if cur > offset || cur + self.buf.len() < offset {
8540            return (stack, None);
8541        }
8542        let mut attrs = self.clone();
8543        let mut last_off = cur + attrs.pos;
8544        let mut missing = None;
8545        while let Some(attr) = attrs.next() {
8546            let Ok(attr) = attr else { break };
8547            match attr {
8548                OpPagePoolStatsGetDoReply::Info(val) => {
8549                    (stack, missing) = val.lookup_attr(offset, missing_type);
8550                    if !stack.is_empty() {
8551                        break;
8552                    }
8553                }
8554                OpPagePoolStatsGetDoReply::AllocFast(val) => {
8555                    if last_off == offset {
8556                        stack.push(("AllocFast", last_off));
8557                        break;
8558                    }
8559                }
8560                OpPagePoolStatsGetDoReply::AllocSlow(val) => {
8561                    if last_off == offset {
8562                        stack.push(("AllocSlow", last_off));
8563                        break;
8564                    }
8565                }
8566                OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8567                    if last_off == offset {
8568                        stack.push(("AllocSlowHighOrder", last_off));
8569                        break;
8570                    }
8571                }
8572                OpPagePoolStatsGetDoReply::AllocEmpty(val) => {
8573                    if last_off == offset {
8574                        stack.push(("AllocEmpty", last_off));
8575                        break;
8576                    }
8577                }
8578                OpPagePoolStatsGetDoReply::AllocRefill(val) => {
8579                    if last_off == offset {
8580                        stack.push(("AllocRefill", last_off));
8581                        break;
8582                    }
8583                }
8584                OpPagePoolStatsGetDoReply::AllocWaive(val) => {
8585                    if last_off == offset {
8586                        stack.push(("AllocWaive", last_off));
8587                        break;
8588                    }
8589                }
8590                OpPagePoolStatsGetDoReply::RecycleCached(val) => {
8591                    if last_off == offset {
8592                        stack.push(("RecycleCached", last_off));
8593                        break;
8594                    }
8595                }
8596                OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8597                    if last_off == offset {
8598                        stack.push(("RecycleCacheFull", last_off));
8599                        break;
8600                    }
8601                }
8602                OpPagePoolStatsGetDoReply::RecycleRing(val) => {
8603                    if last_off == offset {
8604                        stack.push(("RecycleRing", last_off));
8605                        break;
8606                    }
8607                }
8608                OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8609                    if last_off == offset {
8610                        stack.push(("RecycleRingFull", last_off));
8611                        break;
8612                    }
8613                }
8614                OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8615                    if last_off == offset {
8616                        stack.push(("RecycleReleasedRefcnt", last_off));
8617                        break;
8618                    }
8619                }
8620                _ => {}
8621            };
8622            last_off = cur + attrs.pos;
8623        }
8624        if !stack.is_empty() {
8625            stack.push(("OpPagePoolStatsGetDoReply", cur));
8626        }
8627        (stack, missing)
8628    }
8629}
8630#[derive(Debug)]
8631pub struct RequestOpPagePoolStatsGetDoRequest<'r> {
8632    request: Request<'r>,
8633}
8634impl<'r> RequestOpPagePoolStatsGetDoRequest<'r> {
8635    pub fn new(mut request: Request<'r>) -> Self {
8636        PushOpPagePoolStatsGetDoRequest::write_header(&mut request.buf_mut());
8637        Self { request: request }
8638    }
8639    pub fn encode(&mut self) -> PushOpPagePoolStatsGetDoRequest<&mut Vec<u8>> {
8640        PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf_mut())
8641    }
8642    pub fn into_encoder(self) -> PushOpPagePoolStatsGetDoRequest<RequestBuf<'r>> {
8643        PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf)
8644    }
8645    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolStatsGetDoRequest<'buf> {
8646        OpPagePoolStatsGetDoRequest::new(buf)
8647    }
8648}
8649impl NetlinkRequest for RequestOpPagePoolStatsGetDoRequest<'_> {
8650    fn protocol(&self) -> Protocol {
8651        Protocol::Generic("netdev".as_bytes())
8652    }
8653    fn flags(&self) -> u16 {
8654        self.request.flags
8655    }
8656    fn payload(&self) -> &[u8] {
8657        self.request.buf()
8658    }
8659    type ReplyType<'buf> = IterableOpPagePoolStatsGetDoReply<'buf>;
8660    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
8661        OpPagePoolStatsGetDoReply::new(buf)
8662    }
8663    fn lookup(
8664        buf: &[u8],
8665        offset: usize,
8666        missing_type: Option<u16>,
8667    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8668        OpPagePoolStatsGetDoRequest::new(buf).lookup_attr(offset, missing_type)
8669    }
8670}
8671#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8672pub struct PushOpQueueGetDumpRequest<Prev: Rec> {
8673    pub(crate) prev: Option<Prev>,
8674    pub(crate) header_offset: Option<usize>,
8675}
8676impl<Prev: Rec> Rec for PushOpQueueGetDumpRequest<Prev> {
8677    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8678        self.prev.as_mut().unwrap().as_rec_mut()
8679    }
8680    fn as_rec(&self) -> &Vec<u8> {
8681        self.prev.as_ref().unwrap().as_rec()
8682    }
8683}
8684impl<Prev: Rec> PushOpQueueGetDumpRequest<Prev> {
8685    pub fn new(mut prev: Prev) -> Self {
8686        Self::write_header(&mut prev);
8687        Self::new_without_header(prev)
8688    }
8689    fn new_without_header(prev: Prev) -> Self {
8690        Self {
8691            prev: Some(prev),
8692            header_offset: None,
8693        }
8694    }
8695    fn write_header(prev: &mut Prev) {
8696        let mut header = PushBuiltinNfgenmsg::new();
8697        header.set_cmd(10u8);
8698        header.set_version(1u8);
8699        prev.as_rec_mut().extend(header.as_slice());
8700    }
8701    pub fn end_nested(mut self) -> Prev {
8702        let mut prev = self.prev.take().unwrap();
8703        if let Some(header_offset) = &self.header_offset {
8704            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8705        }
8706        prev
8707    }
8708    #[doc = "ifindex of the netdevice to which the queue belongs."]
8709    pub fn push_ifindex(mut self, value: u32) -> Self {
8710        push_header(self.as_rec_mut(), 2u16, 4 as u16);
8711        self.as_rec_mut().extend(value.to_ne_bytes());
8712        self
8713    }
8714}
8715impl<Prev: Rec> Drop for PushOpQueueGetDumpRequest<Prev> {
8716    fn drop(&mut self) {
8717        if let Some(prev) = &mut self.prev {
8718            if let Some(header_offset) = &self.header_offset {
8719                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8720            }
8721        }
8722    }
8723}
8724#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8725#[derive(Clone)]
8726pub enum OpQueueGetDumpRequest {
8727    #[doc = "ifindex of the netdevice to which the queue belongs."]
8728    Ifindex(u32),
8729}
8730impl<'a> IterableOpQueueGetDumpRequest<'a> {
8731    #[doc = "ifindex of the netdevice to which the queue belongs."]
8732    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8733        let mut iter = self.clone();
8734        iter.pos = 0;
8735        for attr in iter {
8736            if let OpQueueGetDumpRequest::Ifindex(val) = attr? {
8737                return Ok(val);
8738            }
8739        }
8740        Err(ErrorContext::new_missing(
8741            "OpQueueGetDumpRequest",
8742            "Ifindex",
8743            self.orig_loc,
8744            self.buf.as_ptr() as usize,
8745        ))
8746    }
8747}
8748impl OpQueueGetDumpRequest {
8749    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpRequest<'a> {
8750        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8751        IterableOpQueueGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
8752    }
8753    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8754        Queue::attr_from_type(r#type)
8755    }
8756}
8757#[derive(Clone, Copy, Default)]
8758pub struct IterableOpQueueGetDumpRequest<'a> {
8759    buf: &'a [u8],
8760    pos: usize,
8761    orig_loc: usize,
8762}
8763impl<'a> IterableOpQueueGetDumpRequest<'a> {
8764    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8765        Self {
8766            buf,
8767            pos: 0,
8768            orig_loc,
8769        }
8770    }
8771    pub fn get_buf(&self) -> &'a [u8] {
8772        self.buf
8773    }
8774}
8775impl<'a> Iterator for IterableOpQueueGetDumpRequest<'a> {
8776    type Item = Result<OpQueueGetDumpRequest, ErrorContext>;
8777    fn next(&mut self) -> Option<Self::Item> {
8778        let pos = self.pos;
8779        let mut r#type;
8780        loop {
8781            r#type = None;
8782            if self.buf.len() == self.pos {
8783                return None;
8784            }
8785            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8786                break;
8787            };
8788            r#type = Some(header.r#type);
8789            let res = match header.r#type {
8790                2u16 => OpQueueGetDumpRequest::Ifindex({
8791                    let res = parse_u32(next);
8792                    let Some(val) = res else { break };
8793                    val
8794                }),
8795                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8796                n => continue,
8797            };
8798            return Some(Ok(res));
8799        }
8800        Some(Err(ErrorContext::new(
8801            "OpQueueGetDumpRequest",
8802            r#type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8803            self.orig_loc,
8804            self.buf.as_ptr().wrapping_add(pos) as usize,
8805        )))
8806    }
8807}
8808impl std::fmt::Debug for IterableOpQueueGetDumpRequest<'_> {
8809    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8810        let mut fmt = f.debug_struct("OpQueueGetDumpRequest");
8811        for attr in self.clone() {
8812            let attr = match attr {
8813                Ok(a) => a,
8814                Err(err) => {
8815                    fmt.finish()?;
8816                    f.write_str("Err(")?;
8817                    err.fmt(f)?;
8818                    return f.write_str(")");
8819                }
8820            };
8821            match attr {
8822                OpQueueGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
8823            };
8824        }
8825        fmt.finish()
8826    }
8827}
8828impl IterableOpQueueGetDumpRequest<'_> {
8829    pub fn lookup_attr(
8830        &self,
8831        offset: usize,
8832        missing_type: Option<u16>,
8833    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8834        let mut stack = Vec::new();
8835        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8836        if cur == offset + PushBuiltinNfgenmsg::len() {
8837            stack.push(("OpQueueGetDumpRequest", offset));
8838            return (
8839                stack,
8840                missing_type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8841            );
8842        }
8843        if cur > offset || cur + self.buf.len() < offset {
8844            return (stack, None);
8845        }
8846        let mut attrs = self.clone();
8847        let mut last_off = cur + attrs.pos;
8848        while let Some(attr) = attrs.next() {
8849            let Ok(attr) = attr else { break };
8850            match attr {
8851                OpQueueGetDumpRequest::Ifindex(val) => {
8852                    if last_off == offset {
8853                        stack.push(("Ifindex", last_off));
8854                        break;
8855                    }
8856                }
8857                _ => {}
8858            };
8859            last_off = cur + attrs.pos;
8860        }
8861        if !stack.is_empty() {
8862            stack.push(("OpQueueGetDumpRequest", cur));
8863        }
8864        (stack, None)
8865    }
8866}
8867#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8868pub struct PushOpQueueGetDumpReply<Prev: Rec> {
8869    pub(crate) prev: Option<Prev>,
8870    pub(crate) header_offset: Option<usize>,
8871}
8872impl<Prev: Rec> Rec for PushOpQueueGetDumpReply<Prev> {
8873    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8874        self.prev.as_mut().unwrap().as_rec_mut()
8875    }
8876    fn as_rec(&self) -> &Vec<u8> {
8877        self.prev.as_ref().unwrap().as_rec()
8878    }
8879}
8880impl<Prev: Rec> PushOpQueueGetDumpReply<Prev> {
8881    pub fn new(mut prev: Prev) -> Self {
8882        Self::write_header(&mut prev);
8883        Self::new_without_header(prev)
8884    }
8885    fn new_without_header(prev: Prev) -> Self {
8886        Self {
8887            prev: Some(prev),
8888            header_offset: None,
8889        }
8890    }
8891    fn write_header(prev: &mut Prev) {
8892        let mut header = PushBuiltinNfgenmsg::new();
8893        header.set_cmd(10u8);
8894        header.set_version(1u8);
8895        prev.as_rec_mut().extend(header.as_slice());
8896    }
8897    pub fn end_nested(mut self) -> Prev {
8898        let mut prev = self.prev.take().unwrap();
8899        if let Some(header_offset) = &self.header_offset {
8900            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8901        }
8902        prev
8903    }
8904    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
8905    pub fn push_id(mut self, value: u32) -> Self {
8906        push_header(self.as_rec_mut(), 1u16, 4 as u16);
8907        self.as_rec_mut().extend(value.to_ne_bytes());
8908        self
8909    }
8910    #[doc = "ifindex of the netdevice to which the queue belongs."]
8911    pub fn push_ifindex(mut self, value: u32) -> Self {
8912        push_header(self.as_rec_mut(), 2u16, 4 as u16);
8913        self.as_rec_mut().extend(value.to_ne_bytes());
8914        self
8915    }
8916    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
8917    pub fn push_type(mut self, value: u32) -> Self {
8918        push_header(self.as_rec_mut(), 3u16, 4 as u16);
8919        self.as_rec_mut().extend(value.to_ne_bytes());
8920        self
8921    }
8922    #[doc = "ID of the NAPI instance which services this queue."]
8923    pub fn push_napi_id(mut self, value: u32) -> Self {
8924        push_header(self.as_rec_mut(), 4u16, 4 as u16);
8925        self.as_rec_mut().extend(value.to_ne_bytes());
8926        self
8927    }
8928    #[doc = "ID of the dmabuf attached to this queue, if any."]
8929    pub fn push_dmabuf(mut self, value: u32) -> Self {
8930        push_header(self.as_rec_mut(), 5u16, 4 as u16);
8931        self.as_rec_mut().extend(value.to_ne_bytes());
8932        self
8933    }
8934    #[doc = "io_uring memory provider information."]
8935    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
8936        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
8937        PushIoUringProviderInfo {
8938            prev: Some(self),
8939            header_offset: Some(header_offset),
8940        }
8941    }
8942    #[doc = "XSK information for this queue, if any."]
8943    pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
8944        let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
8945        PushXskInfo {
8946            prev: Some(self),
8947            header_offset: Some(header_offset),
8948        }
8949    }
8950}
8951impl<Prev: Rec> Drop for PushOpQueueGetDumpReply<Prev> {
8952    fn drop(&mut self) {
8953        if let Some(prev) = &mut self.prev {
8954            if let Some(header_offset) = &self.header_offset {
8955                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8956            }
8957        }
8958    }
8959}
8960#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8961#[derive(Clone)]
8962pub enum OpQueueGetDumpReply<'a> {
8963    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
8964    Id(u32),
8965    #[doc = "ifindex of the netdevice to which the queue belongs."]
8966    Ifindex(u32),
8967    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
8968    Type(u32),
8969    #[doc = "ID of the NAPI instance which services this queue."]
8970    NapiId(u32),
8971    #[doc = "ID of the dmabuf attached to this queue, if any."]
8972    Dmabuf(u32),
8973    #[doc = "io_uring memory provider information."]
8974    IoUring(IterableIoUringProviderInfo<'a>),
8975    #[doc = "XSK information for this queue, if any."]
8976    Xsk(IterableXskInfo<'a>),
8977}
8978impl<'a> IterableOpQueueGetDumpReply<'a> {
8979    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
8980    pub fn get_id(&self) -> Result<u32, ErrorContext> {
8981        let mut iter = self.clone();
8982        iter.pos = 0;
8983        for attr in iter {
8984            if let OpQueueGetDumpReply::Id(val) = attr? {
8985                return Ok(val);
8986            }
8987        }
8988        Err(ErrorContext::new_missing(
8989            "OpQueueGetDumpReply",
8990            "Id",
8991            self.orig_loc,
8992            self.buf.as_ptr() as usize,
8993        ))
8994    }
8995    #[doc = "ifindex of the netdevice to which the queue belongs."]
8996    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8997        let mut iter = self.clone();
8998        iter.pos = 0;
8999        for attr in iter {
9000            if let OpQueueGetDumpReply::Ifindex(val) = attr? {
9001                return Ok(val);
9002            }
9003        }
9004        Err(ErrorContext::new_missing(
9005            "OpQueueGetDumpReply",
9006            "Ifindex",
9007            self.orig_loc,
9008            self.buf.as_ptr() as usize,
9009        ))
9010    }
9011    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9012    pub fn get_type(&self) -> Result<u32, ErrorContext> {
9013        let mut iter = self.clone();
9014        iter.pos = 0;
9015        for attr in iter {
9016            if let OpQueueGetDumpReply::Type(val) = attr? {
9017                return Ok(val);
9018            }
9019        }
9020        Err(ErrorContext::new_missing(
9021            "OpQueueGetDumpReply",
9022            "Type",
9023            self.orig_loc,
9024            self.buf.as_ptr() as usize,
9025        ))
9026    }
9027    #[doc = "ID of the NAPI instance which services this queue."]
9028    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
9029        let mut iter = self.clone();
9030        iter.pos = 0;
9031        for attr in iter {
9032            if let OpQueueGetDumpReply::NapiId(val) = attr? {
9033                return Ok(val);
9034            }
9035        }
9036        Err(ErrorContext::new_missing(
9037            "OpQueueGetDumpReply",
9038            "NapiId",
9039            self.orig_loc,
9040            self.buf.as_ptr() as usize,
9041        ))
9042    }
9043    #[doc = "ID of the dmabuf attached to this queue, if any."]
9044    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
9045        let mut iter = self.clone();
9046        iter.pos = 0;
9047        for attr in iter {
9048            if let OpQueueGetDumpReply::Dmabuf(val) = attr? {
9049                return Ok(val);
9050            }
9051        }
9052        Err(ErrorContext::new_missing(
9053            "OpQueueGetDumpReply",
9054            "Dmabuf",
9055            self.orig_loc,
9056            self.buf.as_ptr() as usize,
9057        ))
9058    }
9059    #[doc = "io_uring memory provider information."]
9060    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
9061        let mut iter = self.clone();
9062        iter.pos = 0;
9063        for attr in iter {
9064            if let OpQueueGetDumpReply::IoUring(val) = attr? {
9065                return Ok(val);
9066            }
9067        }
9068        Err(ErrorContext::new_missing(
9069            "OpQueueGetDumpReply",
9070            "IoUring",
9071            self.orig_loc,
9072            self.buf.as_ptr() as usize,
9073        ))
9074    }
9075    #[doc = "XSK information for this queue, if any."]
9076    pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9077        let mut iter = self.clone();
9078        iter.pos = 0;
9079        for attr in iter {
9080            if let OpQueueGetDumpReply::Xsk(val) = attr? {
9081                return Ok(val);
9082            }
9083        }
9084        Err(ErrorContext::new_missing(
9085            "OpQueueGetDumpReply",
9086            "Xsk",
9087            self.orig_loc,
9088            self.buf.as_ptr() as usize,
9089        ))
9090    }
9091}
9092impl OpQueueGetDumpReply<'_> {
9093    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpReply<'a> {
9094        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9095        IterableOpQueueGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
9096    }
9097    fn attr_from_type(r#type: u16) -> Option<&'static str> {
9098        Queue::attr_from_type(r#type)
9099    }
9100}
9101#[derive(Clone, Copy, Default)]
9102pub struct IterableOpQueueGetDumpReply<'a> {
9103    buf: &'a [u8],
9104    pos: usize,
9105    orig_loc: usize,
9106}
9107impl<'a> IterableOpQueueGetDumpReply<'a> {
9108    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9109        Self {
9110            buf,
9111            pos: 0,
9112            orig_loc,
9113        }
9114    }
9115    pub fn get_buf(&self) -> &'a [u8] {
9116        self.buf
9117    }
9118}
9119impl<'a> Iterator for IterableOpQueueGetDumpReply<'a> {
9120    type Item = Result<OpQueueGetDumpReply<'a>, ErrorContext>;
9121    fn next(&mut self) -> Option<Self::Item> {
9122        let pos = self.pos;
9123        let mut r#type;
9124        loop {
9125            r#type = None;
9126            if self.buf.len() == self.pos {
9127                return None;
9128            }
9129            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
9130                break;
9131            };
9132            r#type = Some(header.r#type);
9133            let res = match header.r#type {
9134                1u16 => OpQueueGetDumpReply::Id({
9135                    let res = parse_u32(next);
9136                    let Some(val) = res else { break };
9137                    val
9138                }),
9139                2u16 => OpQueueGetDumpReply::Ifindex({
9140                    let res = parse_u32(next);
9141                    let Some(val) = res else { break };
9142                    val
9143                }),
9144                3u16 => OpQueueGetDumpReply::Type({
9145                    let res = parse_u32(next);
9146                    let Some(val) = res else { break };
9147                    val
9148                }),
9149                4u16 => OpQueueGetDumpReply::NapiId({
9150                    let res = parse_u32(next);
9151                    let Some(val) = res else { break };
9152                    val
9153                }),
9154                5u16 => OpQueueGetDumpReply::Dmabuf({
9155                    let res = parse_u32(next);
9156                    let Some(val) = res else { break };
9157                    val
9158                }),
9159                6u16 => OpQueueGetDumpReply::IoUring({
9160                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9161                    let Some(val) = res else { break };
9162                    val
9163                }),
9164                7u16 => OpQueueGetDumpReply::Xsk({
9165                    let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9166                    let Some(val) = res else { break };
9167                    val
9168                }),
9169                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
9170                n => continue,
9171            };
9172            return Some(Ok(res));
9173        }
9174        Some(Err(ErrorContext::new(
9175            "OpQueueGetDumpReply",
9176            r#type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9177            self.orig_loc,
9178            self.buf.as_ptr().wrapping_add(pos) as usize,
9179        )))
9180    }
9181}
9182impl<'a> std::fmt::Debug for IterableOpQueueGetDumpReply<'_> {
9183    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9184        let mut fmt = f.debug_struct("OpQueueGetDumpReply");
9185        for attr in self.clone() {
9186            let attr = match attr {
9187                Ok(a) => a,
9188                Err(err) => {
9189                    fmt.finish()?;
9190                    f.write_str("Err(")?;
9191                    err.fmt(f)?;
9192                    return f.write_str(")");
9193                }
9194            };
9195            match attr {
9196                OpQueueGetDumpReply::Id(val) => fmt.field("Id", &val),
9197                OpQueueGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
9198                OpQueueGetDumpReply::Type(val) => {
9199                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9200                }
9201                OpQueueGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
9202                OpQueueGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9203                OpQueueGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
9204                OpQueueGetDumpReply::Xsk(val) => fmt.field("Xsk", &val),
9205            };
9206        }
9207        fmt.finish()
9208    }
9209}
9210impl IterableOpQueueGetDumpReply<'_> {
9211    pub fn lookup_attr(
9212        &self,
9213        offset: usize,
9214        missing_type: Option<u16>,
9215    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9216        let mut stack = Vec::new();
9217        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9218        if cur == offset + PushBuiltinNfgenmsg::len() {
9219            stack.push(("OpQueueGetDumpReply", offset));
9220            return (
9221                stack,
9222                missing_type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9223            );
9224        }
9225        if cur > offset || cur + self.buf.len() < offset {
9226            return (stack, None);
9227        }
9228        let mut attrs = self.clone();
9229        let mut last_off = cur + attrs.pos;
9230        let mut missing = None;
9231        while let Some(attr) = attrs.next() {
9232            let Ok(attr) = attr else { break };
9233            match attr {
9234                OpQueueGetDumpReply::Id(val) => {
9235                    if last_off == offset {
9236                        stack.push(("Id", last_off));
9237                        break;
9238                    }
9239                }
9240                OpQueueGetDumpReply::Ifindex(val) => {
9241                    if last_off == offset {
9242                        stack.push(("Ifindex", last_off));
9243                        break;
9244                    }
9245                }
9246                OpQueueGetDumpReply::Type(val) => {
9247                    if last_off == offset {
9248                        stack.push(("Type", last_off));
9249                        break;
9250                    }
9251                }
9252                OpQueueGetDumpReply::NapiId(val) => {
9253                    if last_off == offset {
9254                        stack.push(("NapiId", last_off));
9255                        break;
9256                    }
9257                }
9258                OpQueueGetDumpReply::Dmabuf(val) => {
9259                    if last_off == offset {
9260                        stack.push(("Dmabuf", last_off));
9261                        break;
9262                    }
9263                }
9264                OpQueueGetDumpReply::IoUring(val) => {
9265                    (stack, missing) = val.lookup_attr(offset, missing_type);
9266                    if !stack.is_empty() {
9267                        break;
9268                    }
9269                }
9270                OpQueueGetDumpReply::Xsk(val) => {
9271                    (stack, missing) = val.lookup_attr(offset, missing_type);
9272                    if !stack.is_empty() {
9273                        break;
9274                    }
9275                }
9276                _ => {}
9277            };
9278            last_off = cur + attrs.pos;
9279        }
9280        if !stack.is_empty() {
9281            stack.push(("OpQueueGetDumpReply", cur));
9282        }
9283        (stack, missing)
9284    }
9285}
9286#[derive(Debug)]
9287pub struct RequestOpQueueGetDumpRequest<'r> {
9288    request: Request<'r>,
9289}
9290impl<'r> RequestOpQueueGetDumpRequest<'r> {
9291    pub fn new(mut request: Request<'r>) -> Self {
9292        PushOpQueueGetDumpRequest::write_header(&mut request.buf_mut());
9293        Self {
9294            request: request.set_dump(),
9295        }
9296    }
9297    pub fn encode(&mut self) -> PushOpQueueGetDumpRequest<&mut Vec<u8>> {
9298        PushOpQueueGetDumpRequest::new_without_header(self.request.buf_mut())
9299    }
9300    pub fn into_encoder(self) -> PushOpQueueGetDumpRequest<RequestBuf<'r>> {
9301        PushOpQueueGetDumpRequest::new_without_header(self.request.buf)
9302    }
9303    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpQueueGetDumpRequest<'buf> {
9304        OpQueueGetDumpRequest::new(buf)
9305    }
9306}
9307impl NetlinkRequest for RequestOpQueueGetDumpRequest<'_> {
9308    fn protocol(&self) -> Protocol {
9309        Protocol::Generic("netdev".as_bytes())
9310    }
9311    fn flags(&self) -> u16 {
9312        self.request.flags
9313    }
9314    fn payload(&self) -> &[u8] {
9315        self.request.buf()
9316    }
9317    type ReplyType<'buf> = IterableOpQueueGetDumpReply<'buf>;
9318    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9319        OpQueueGetDumpReply::new(buf)
9320    }
9321    fn lookup(
9322        buf: &[u8],
9323        offset: usize,
9324        missing_type: Option<u16>,
9325    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9326        OpQueueGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
9327    }
9328}
9329#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9330pub struct PushOpQueueGetDoRequest<Prev: Rec> {
9331    pub(crate) prev: Option<Prev>,
9332    pub(crate) header_offset: Option<usize>,
9333}
9334impl<Prev: Rec> Rec for PushOpQueueGetDoRequest<Prev> {
9335    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9336        self.prev.as_mut().unwrap().as_rec_mut()
9337    }
9338    fn as_rec(&self) -> &Vec<u8> {
9339        self.prev.as_ref().unwrap().as_rec()
9340    }
9341}
9342impl<Prev: Rec> PushOpQueueGetDoRequest<Prev> {
9343    pub fn new(mut prev: Prev) -> Self {
9344        Self::write_header(&mut prev);
9345        Self::new_without_header(prev)
9346    }
9347    fn new_without_header(prev: Prev) -> Self {
9348        Self {
9349            prev: Some(prev),
9350            header_offset: None,
9351        }
9352    }
9353    fn write_header(prev: &mut Prev) {
9354        let mut header = PushBuiltinNfgenmsg::new();
9355        header.set_cmd(10u8);
9356        header.set_version(1u8);
9357        prev.as_rec_mut().extend(header.as_slice());
9358    }
9359    pub fn end_nested(mut self) -> Prev {
9360        let mut prev = self.prev.take().unwrap();
9361        if let Some(header_offset) = &self.header_offset {
9362            finalize_nested_header(prev.as_rec_mut(), *header_offset);
9363        }
9364        prev
9365    }
9366    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9367    pub fn push_id(mut self, value: u32) -> Self {
9368        push_header(self.as_rec_mut(), 1u16, 4 as u16);
9369        self.as_rec_mut().extend(value.to_ne_bytes());
9370        self
9371    }
9372    #[doc = "ifindex of the netdevice to which the queue belongs."]
9373    pub fn push_ifindex(mut self, value: u32) -> Self {
9374        push_header(self.as_rec_mut(), 2u16, 4 as u16);
9375        self.as_rec_mut().extend(value.to_ne_bytes());
9376        self
9377    }
9378    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9379    pub fn push_type(mut self, value: u32) -> Self {
9380        push_header(self.as_rec_mut(), 3u16, 4 as u16);
9381        self.as_rec_mut().extend(value.to_ne_bytes());
9382        self
9383    }
9384}
9385impl<Prev: Rec> Drop for PushOpQueueGetDoRequest<Prev> {
9386    fn drop(&mut self) {
9387        if let Some(prev) = &mut self.prev {
9388            if let Some(header_offset) = &self.header_offset {
9389                finalize_nested_header(prev.as_rec_mut(), *header_offset);
9390            }
9391        }
9392    }
9393}
9394#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9395#[derive(Clone)]
9396pub enum OpQueueGetDoRequest {
9397    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9398    Id(u32),
9399    #[doc = "ifindex of the netdevice to which the queue belongs."]
9400    Ifindex(u32),
9401    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9402    Type(u32),
9403}
9404impl<'a> IterableOpQueueGetDoRequest<'a> {
9405    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9406    pub fn get_id(&self) -> Result<u32, ErrorContext> {
9407        let mut iter = self.clone();
9408        iter.pos = 0;
9409        for attr in iter {
9410            if let OpQueueGetDoRequest::Id(val) = attr? {
9411                return Ok(val);
9412            }
9413        }
9414        Err(ErrorContext::new_missing(
9415            "OpQueueGetDoRequest",
9416            "Id",
9417            self.orig_loc,
9418            self.buf.as_ptr() as usize,
9419        ))
9420    }
9421    #[doc = "ifindex of the netdevice to which the queue belongs."]
9422    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9423        let mut iter = self.clone();
9424        iter.pos = 0;
9425        for attr in iter {
9426            if let OpQueueGetDoRequest::Ifindex(val) = attr? {
9427                return Ok(val);
9428            }
9429        }
9430        Err(ErrorContext::new_missing(
9431            "OpQueueGetDoRequest",
9432            "Ifindex",
9433            self.orig_loc,
9434            self.buf.as_ptr() as usize,
9435        ))
9436    }
9437    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9438    pub fn get_type(&self) -> Result<u32, ErrorContext> {
9439        let mut iter = self.clone();
9440        iter.pos = 0;
9441        for attr in iter {
9442            if let OpQueueGetDoRequest::Type(val) = attr? {
9443                return Ok(val);
9444            }
9445        }
9446        Err(ErrorContext::new_missing(
9447            "OpQueueGetDoRequest",
9448            "Type",
9449            self.orig_loc,
9450            self.buf.as_ptr() as usize,
9451        ))
9452    }
9453}
9454impl OpQueueGetDoRequest {
9455    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoRequest<'a> {
9456        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9457        IterableOpQueueGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
9458    }
9459    fn attr_from_type(r#type: u16) -> Option<&'static str> {
9460        Queue::attr_from_type(r#type)
9461    }
9462}
9463#[derive(Clone, Copy, Default)]
9464pub struct IterableOpQueueGetDoRequest<'a> {
9465    buf: &'a [u8],
9466    pos: usize,
9467    orig_loc: usize,
9468}
9469impl<'a> IterableOpQueueGetDoRequest<'a> {
9470    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9471        Self {
9472            buf,
9473            pos: 0,
9474            orig_loc,
9475        }
9476    }
9477    pub fn get_buf(&self) -> &'a [u8] {
9478        self.buf
9479    }
9480}
9481impl<'a> Iterator for IterableOpQueueGetDoRequest<'a> {
9482    type Item = Result<OpQueueGetDoRequest, ErrorContext>;
9483    fn next(&mut self) -> Option<Self::Item> {
9484        let pos = self.pos;
9485        let mut r#type;
9486        loop {
9487            r#type = None;
9488            if self.buf.len() == self.pos {
9489                return None;
9490            }
9491            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
9492                break;
9493            };
9494            r#type = Some(header.r#type);
9495            let res = match header.r#type {
9496                1u16 => OpQueueGetDoRequest::Id({
9497                    let res = parse_u32(next);
9498                    let Some(val) = res else { break };
9499                    val
9500                }),
9501                2u16 => OpQueueGetDoRequest::Ifindex({
9502                    let res = parse_u32(next);
9503                    let Some(val) = res else { break };
9504                    val
9505                }),
9506                3u16 => OpQueueGetDoRequest::Type({
9507                    let res = parse_u32(next);
9508                    let Some(val) = res else { break };
9509                    val
9510                }),
9511                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
9512                n => continue,
9513            };
9514            return Some(Ok(res));
9515        }
9516        Some(Err(ErrorContext::new(
9517            "OpQueueGetDoRequest",
9518            r#type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9519            self.orig_loc,
9520            self.buf.as_ptr().wrapping_add(pos) as usize,
9521        )))
9522    }
9523}
9524impl std::fmt::Debug for IterableOpQueueGetDoRequest<'_> {
9525    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9526        let mut fmt = f.debug_struct("OpQueueGetDoRequest");
9527        for attr in self.clone() {
9528            let attr = match attr {
9529                Ok(a) => a,
9530                Err(err) => {
9531                    fmt.finish()?;
9532                    f.write_str("Err(")?;
9533                    err.fmt(f)?;
9534                    return f.write_str(")");
9535                }
9536            };
9537            match attr {
9538                OpQueueGetDoRequest::Id(val) => fmt.field("Id", &val),
9539                OpQueueGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
9540                OpQueueGetDoRequest::Type(val) => {
9541                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9542                }
9543            };
9544        }
9545        fmt.finish()
9546    }
9547}
9548impl IterableOpQueueGetDoRequest<'_> {
9549    pub fn lookup_attr(
9550        &self,
9551        offset: usize,
9552        missing_type: Option<u16>,
9553    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9554        let mut stack = Vec::new();
9555        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9556        if cur == offset + PushBuiltinNfgenmsg::len() {
9557            stack.push(("OpQueueGetDoRequest", offset));
9558            return (
9559                stack,
9560                missing_type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9561            );
9562        }
9563        if cur > offset || cur + self.buf.len() < offset {
9564            return (stack, None);
9565        }
9566        let mut attrs = self.clone();
9567        let mut last_off = cur + attrs.pos;
9568        while let Some(attr) = attrs.next() {
9569            let Ok(attr) = attr else { break };
9570            match attr {
9571                OpQueueGetDoRequest::Id(val) => {
9572                    if last_off == offset {
9573                        stack.push(("Id", last_off));
9574                        break;
9575                    }
9576                }
9577                OpQueueGetDoRequest::Ifindex(val) => {
9578                    if last_off == offset {
9579                        stack.push(("Ifindex", last_off));
9580                        break;
9581                    }
9582                }
9583                OpQueueGetDoRequest::Type(val) => {
9584                    if last_off == offset {
9585                        stack.push(("Type", last_off));
9586                        break;
9587                    }
9588                }
9589                _ => {}
9590            };
9591            last_off = cur + attrs.pos;
9592        }
9593        if !stack.is_empty() {
9594            stack.push(("OpQueueGetDoRequest", cur));
9595        }
9596        (stack, None)
9597    }
9598}
9599#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9600pub struct PushOpQueueGetDoReply<Prev: Rec> {
9601    pub(crate) prev: Option<Prev>,
9602    pub(crate) header_offset: Option<usize>,
9603}
9604impl<Prev: Rec> Rec for PushOpQueueGetDoReply<Prev> {
9605    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9606        self.prev.as_mut().unwrap().as_rec_mut()
9607    }
9608    fn as_rec(&self) -> &Vec<u8> {
9609        self.prev.as_ref().unwrap().as_rec()
9610    }
9611}
9612impl<Prev: Rec> PushOpQueueGetDoReply<Prev> {
9613    pub fn new(mut prev: Prev) -> Self {
9614        Self::write_header(&mut prev);
9615        Self::new_without_header(prev)
9616    }
9617    fn new_without_header(prev: Prev) -> Self {
9618        Self {
9619            prev: Some(prev),
9620            header_offset: None,
9621        }
9622    }
9623    fn write_header(prev: &mut Prev) {
9624        let mut header = PushBuiltinNfgenmsg::new();
9625        header.set_cmd(10u8);
9626        header.set_version(1u8);
9627        prev.as_rec_mut().extend(header.as_slice());
9628    }
9629    pub fn end_nested(mut self) -> Prev {
9630        let mut prev = self.prev.take().unwrap();
9631        if let Some(header_offset) = &self.header_offset {
9632            finalize_nested_header(prev.as_rec_mut(), *header_offset);
9633        }
9634        prev
9635    }
9636    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9637    pub fn push_id(mut self, value: u32) -> Self {
9638        push_header(self.as_rec_mut(), 1u16, 4 as u16);
9639        self.as_rec_mut().extend(value.to_ne_bytes());
9640        self
9641    }
9642    #[doc = "ifindex of the netdevice to which the queue belongs."]
9643    pub fn push_ifindex(mut self, value: u32) -> Self {
9644        push_header(self.as_rec_mut(), 2u16, 4 as u16);
9645        self.as_rec_mut().extend(value.to_ne_bytes());
9646        self
9647    }
9648    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9649    pub fn push_type(mut self, value: u32) -> Self {
9650        push_header(self.as_rec_mut(), 3u16, 4 as u16);
9651        self.as_rec_mut().extend(value.to_ne_bytes());
9652        self
9653    }
9654    #[doc = "ID of the NAPI instance which services this queue."]
9655    pub fn push_napi_id(mut self, value: u32) -> Self {
9656        push_header(self.as_rec_mut(), 4u16, 4 as u16);
9657        self.as_rec_mut().extend(value.to_ne_bytes());
9658        self
9659    }
9660    #[doc = "ID of the dmabuf attached to this queue, if any."]
9661    pub fn push_dmabuf(mut self, value: u32) -> Self {
9662        push_header(self.as_rec_mut(), 5u16, 4 as u16);
9663        self.as_rec_mut().extend(value.to_ne_bytes());
9664        self
9665    }
9666    #[doc = "io_uring memory provider information."]
9667    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
9668        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
9669        PushIoUringProviderInfo {
9670            prev: Some(self),
9671            header_offset: Some(header_offset),
9672        }
9673    }
9674    #[doc = "XSK information for this queue, if any."]
9675    pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
9676        let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
9677        PushXskInfo {
9678            prev: Some(self),
9679            header_offset: Some(header_offset),
9680        }
9681    }
9682}
9683impl<Prev: Rec> Drop for PushOpQueueGetDoReply<Prev> {
9684    fn drop(&mut self) {
9685        if let Some(prev) = &mut self.prev {
9686            if let Some(header_offset) = &self.header_offset {
9687                finalize_nested_header(prev.as_rec_mut(), *header_offset);
9688            }
9689        }
9690    }
9691}
9692#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9693#[derive(Clone)]
9694pub enum OpQueueGetDoReply<'a> {
9695    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9696    Id(u32),
9697    #[doc = "ifindex of the netdevice to which the queue belongs."]
9698    Ifindex(u32),
9699    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9700    Type(u32),
9701    #[doc = "ID of the NAPI instance which services this queue."]
9702    NapiId(u32),
9703    #[doc = "ID of the dmabuf attached to this queue, if any."]
9704    Dmabuf(u32),
9705    #[doc = "io_uring memory provider information."]
9706    IoUring(IterableIoUringProviderInfo<'a>),
9707    #[doc = "XSK information for this queue, if any."]
9708    Xsk(IterableXskInfo<'a>),
9709}
9710impl<'a> IterableOpQueueGetDoReply<'a> {
9711    #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9712    pub fn get_id(&self) -> Result<u32, ErrorContext> {
9713        let mut iter = self.clone();
9714        iter.pos = 0;
9715        for attr in iter {
9716            if let OpQueueGetDoReply::Id(val) = attr? {
9717                return Ok(val);
9718            }
9719        }
9720        Err(ErrorContext::new_missing(
9721            "OpQueueGetDoReply",
9722            "Id",
9723            self.orig_loc,
9724            self.buf.as_ptr() as usize,
9725        ))
9726    }
9727    #[doc = "ifindex of the netdevice to which the queue belongs."]
9728    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9729        let mut iter = self.clone();
9730        iter.pos = 0;
9731        for attr in iter {
9732            if let OpQueueGetDoReply::Ifindex(val) = attr? {
9733                return Ok(val);
9734            }
9735        }
9736        Err(ErrorContext::new_missing(
9737            "OpQueueGetDoReply",
9738            "Ifindex",
9739            self.orig_loc,
9740            self.buf.as_ptr() as usize,
9741        ))
9742    }
9743    #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9744    pub fn get_type(&self) -> Result<u32, ErrorContext> {
9745        let mut iter = self.clone();
9746        iter.pos = 0;
9747        for attr in iter {
9748            if let OpQueueGetDoReply::Type(val) = attr? {
9749                return Ok(val);
9750            }
9751        }
9752        Err(ErrorContext::new_missing(
9753            "OpQueueGetDoReply",
9754            "Type",
9755            self.orig_loc,
9756            self.buf.as_ptr() as usize,
9757        ))
9758    }
9759    #[doc = "ID of the NAPI instance which services this queue."]
9760    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
9761        let mut iter = self.clone();
9762        iter.pos = 0;
9763        for attr in iter {
9764            if let OpQueueGetDoReply::NapiId(val) = attr? {
9765                return Ok(val);
9766            }
9767        }
9768        Err(ErrorContext::new_missing(
9769            "OpQueueGetDoReply",
9770            "NapiId",
9771            self.orig_loc,
9772            self.buf.as_ptr() as usize,
9773        ))
9774    }
9775    #[doc = "ID of the dmabuf attached to this queue, if any."]
9776    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
9777        let mut iter = self.clone();
9778        iter.pos = 0;
9779        for attr in iter {
9780            if let OpQueueGetDoReply::Dmabuf(val) = attr? {
9781                return Ok(val);
9782            }
9783        }
9784        Err(ErrorContext::new_missing(
9785            "OpQueueGetDoReply",
9786            "Dmabuf",
9787            self.orig_loc,
9788            self.buf.as_ptr() as usize,
9789        ))
9790    }
9791    #[doc = "io_uring memory provider information."]
9792    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
9793        let mut iter = self.clone();
9794        iter.pos = 0;
9795        for attr in iter {
9796            if let OpQueueGetDoReply::IoUring(val) = attr? {
9797                return Ok(val);
9798            }
9799        }
9800        Err(ErrorContext::new_missing(
9801            "OpQueueGetDoReply",
9802            "IoUring",
9803            self.orig_loc,
9804            self.buf.as_ptr() as usize,
9805        ))
9806    }
9807    #[doc = "XSK information for this queue, if any."]
9808    pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9809        let mut iter = self.clone();
9810        iter.pos = 0;
9811        for attr in iter {
9812            if let OpQueueGetDoReply::Xsk(val) = attr? {
9813                return Ok(val);
9814            }
9815        }
9816        Err(ErrorContext::new_missing(
9817            "OpQueueGetDoReply",
9818            "Xsk",
9819            self.orig_loc,
9820            self.buf.as_ptr() as usize,
9821        ))
9822    }
9823}
9824impl OpQueueGetDoReply<'_> {
9825    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoReply<'a> {
9826        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9827        IterableOpQueueGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
9828    }
9829    fn attr_from_type(r#type: u16) -> Option<&'static str> {
9830        Queue::attr_from_type(r#type)
9831    }
9832}
9833#[derive(Clone, Copy, Default)]
9834pub struct IterableOpQueueGetDoReply<'a> {
9835    buf: &'a [u8],
9836    pos: usize,
9837    orig_loc: usize,
9838}
9839impl<'a> IterableOpQueueGetDoReply<'a> {
9840    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9841        Self {
9842            buf,
9843            pos: 0,
9844            orig_loc,
9845        }
9846    }
9847    pub fn get_buf(&self) -> &'a [u8] {
9848        self.buf
9849    }
9850}
9851impl<'a> Iterator for IterableOpQueueGetDoReply<'a> {
9852    type Item = Result<OpQueueGetDoReply<'a>, ErrorContext>;
9853    fn next(&mut self) -> Option<Self::Item> {
9854        let pos = self.pos;
9855        let mut r#type;
9856        loop {
9857            r#type = None;
9858            if self.buf.len() == self.pos {
9859                return None;
9860            }
9861            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
9862                break;
9863            };
9864            r#type = Some(header.r#type);
9865            let res = match header.r#type {
9866                1u16 => OpQueueGetDoReply::Id({
9867                    let res = parse_u32(next);
9868                    let Some(val) = res else { break };
9869                    val
9870                }),
9871                2u16 => OpQueueGetDoReply::Ifindex({
9872                    let res = parse_u32(next);
9873                    let Some(val) = res else { break };
9874                    val
9875                }),
9876                3u16 => OpQueueGetDoReply::Type({
9877                    let res = parse_u32(next);
9878                    let Some(val) = res else { break };
9879                    val
9880                }),
9881                4u16 => OpQueueGetDoReply::NapiId({
9882                    let res = parse_u32(next);
9883                    let Some(val) = res else { break };
9884                    val
9885                }),
9886                5u16 => OpQueueGetDoReply::Dmabuf({
9887                    let res = parse_u32(next);
9888                    let Some(val) = res else { break };
9889                    val
9890                }),
9891                6u16 => OpQueueGetDoReply::IoUring({
9892                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9893                    let Some(val) = res else { break };
9894                    val
9895                }),
9896                7u16 => OpQueueGetDoReply::Xsk({
9897                    let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9898                    let Some(val) = res else { break };
9899                    val
9900                }),
9901                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
9902                n => continue,
9903            };
9904            return Some(Ok(res));
9905        }
9906        Some(Err(ErrorContext::new(
9907            "OpQueueGetDoReply",
9908            r#type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9909            self.orig_loc,
9910            self.buf.as_ptr().wrapping_add(pos) as usize,
9911        )))
9912    }
9913}
9914impl<'a> std::fmt::Debug for IterableOpQueueGetDoReply<'_> {
9915    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9916        let mut fmt = f.debug_struct("OpQueueGetDoReply");
9917        for attr in self.clone() {
9918            let attr = match attr {
9919                Ok(a) => a,
9920                Err(err) => {
9921                    fmt.finish()?;
9922                    f.write_str("Err(")?;
9923                    err.fmt(f)?;
9924                    return f.write_str(")");
9925                }
9926            };
9927            match attr {
9928                OpQueueGetDoReply::Id(val) => fmt.field("Id", &val),
9929                OpQueueGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
9930                OpQueueGetDoReply::Type(val) => {
9931                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9932                }
9933                OpQueueGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
9934                OpQueueGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9935                OpQueueGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
9936                OpQueueGetDoReply::Xsk(val) => fmt.field("Xsk", &val),
9937            };
9938        }
9939        fmt.finish()
9940    }
9941}
9942impl IterableOpQueueGetDoReply<'_> {
9943    pub fn lookup_attr(
9944        &self,
9945        offset: usize,
9946        missing_type: Option<u16>,
9947    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9948        let mut stack = Vec::new();
9949        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9950        if cur == offset + PushBuiltinNfgenmsg::len() {
9951            stack.push(("OpQueueGetDoReply", offset));
9952            return (
9953                stack,
9954                missing_type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9955            );
9956        }
9957        if cur > offset || cur + self.buf.len() < offset {
9958            return (stack, None);
9959        }
9960        let mut attrs = self.clone();
9961        let mut last_off = cur + attrs.pos;
9962        let mut missing = None;
9963        while let Some(attr) = attrs.next() {
9964            let Ok(attr) = attr else { break };
9965            match attr {
9966                OpQueueGetDoReply::Id(val) => {
9967                    if last_off == offset {
9968                        stack.push(("Id", last_off));
9969                        break;
9970                    }
9971                }
9972                OpQueueGetDoReply::Ifindex(val) => {
9973                    if last_off == offset {
9974                        stack.push(("Ifindex", last_off));
9975                        break;
9976                    }
9977                }
9978                OpQueueGetDoReply::Type(val) => {
9979                    if last_off == offset {
9980                        stack.push(("Type", last_off));
9981                        break;
9982                    }
9983                }
9984                OpQueueGetDoReply::NapiId(val) => {
9985                    if last_off == offset {
9986                        stack.push(("NapiId", last_off));
9987                        break;
9988                    }
9989                }
9990                OpQueueGetDoReply::Dmabuf(val) => {
9991                    if last_off == offset {
9992                        stack.push(("Dmabuf", last_off));
9993                        break;
9994                    }
9995                }
9996                OpQueueGetDoReply::IoUring(val) => {
9997                    (stack, missing) = val.lookup_attr(offset, missing_type);
9998                    if !stack.is_empty() {
9999                        break;
10000                    }
10001                }
10002                OpQueueGetDoReply::Xsk(val) => {
10003                    (stack, missing) = val.lookup_attr(offset, missing_type);
10004                    if !stack.is_empty() {
10005                        break;
10006                    }
10007                }
10008                _ => {}
10009            };
10010            last_off = cur + attrs.pos;
10011        }
10012        if !stack.is_empty() {
10013            stack.push(("OpQueueGetDoReply", cur));
10014        }
10015        (stack, missing)
10016    }
10017}
10018#[derive(Debug)]
10019pub struct RequestOpQueueGetDoRequest<'r> {
10020    request: Request<'r>,
10021}
10022impl<'r> RequestOpQueueGetDoRequest<'r> {
10023    pub fn new(mut request: Request<'r>) -> Self {
10024        PushOpQueueGetDoRequest::write_header(&mut request.buf_mut());
10025        Self { request: request }
10026    }
10027    pub fn encode(&mut self) -> PushOpQueueGetDoRequest<&mut Vec<u8>> {
10028        PushOpQueueGetDoRequest::new_without_header(self.request.buf_mut())
10029    }
10030    pub fn into_encoder(self) -> PushOpQueueGetDoRequest<RequestBuf<'r>> {
10031        PushOpQueueGetDoRequest::new_without_header(self.request.buf)
10032    }
10033    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpQueueGetDoRequest<'buf> {
10034        OpQueueGetDoRequest::new(buf)
10035    }
10036}
10037impl NetlinkRequest for RequestOpQueueGetDoRequest<'_> {
10038    fn protocol(&self) -> Protocol {
10039        Protocol::Generic("netdev".as_bytes())
10040    }
10041    fn flags(&self) -> u16 {
10042        self.request.flags
10043    }
10044    fn payload(&self) -> &[u8] {
10045        self.request.buf()
10046    }
10047    type ReplyType<'buf> = IterableOpQueueGetDoReply<'buf>;
10048    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
10049        OpQueueGetDoReply::new(buf)
10050    }
10051    fn lookup(
10052        buf: &[u8],
10053        offset: usize,
10054        missing_type: Option<u16>,
10055    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10056        OpQueueGetDoRequest::new(buf).lookup_attr(offset, missing_type)
10057    }
10058}
10059#[doc = "Get information about NAPI instances configured on the system."]
10060pub struct PushOpNapiGetDumpRequest<Prev: Rec> {
10061    pub(crate) prev: Option<Prev>,
10062    pub(crate) header_offset: Option<usize>,
10063}
10064impl<Prev: Rec> Rec for PushOpNapiGetDumpRequest<Prev> {
10065    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10066        self.prev.as_mut().unwrap().as_rec_mut()
10067    }
10068    fn as_rec(&self) -> &Vec<u8> {
10069        self.prev.as_ref().unwrap().as_rec()
10070    }
10071}
10072impl<Prev: Rec> PushOpNapiGetDumpRequest<Prev> {
10073    pub fn new(mut prev: Prev) -> Self {
10074        Self::write_header(&mut prev);
10075        Self::new_without_header(prev)
10076    }
10077    fn new_without_header(prev: Prev) -> Self {
10078        Self {
10079            prev: Some(prev),
10080            header_offset: None,
10081        }
10082    }
10083    fn write_header(prev: &mut Prev) {
10084        let mut header = PushBuiltinNfgenmsg::new();
10085        header.set_cmd(11u8);
10086        header.set_version(1u8);
10087        prev.as_rec_mut().extend(header.as_slice());
10088    }
10089    pub fn end_nested(mut self) -> Prev {
10090        let mut prev = self.prev.take().unwrap();
10091        if let Some(header_offset) = &self.header_offset {
10092            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10093        }
10094        prev
10095    }
10096    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10097    pub fn push_ifindex(mut self, value: u32) -> Self {
10098        push_header(self.as_rec_mut(), 1u16, 4 as u16);
10099        self.as_rec_mut().extend(value.to_ne_bytes());
10100        self
10101    }
10102}
10103impl<Prev: Rec> Drop for PushOpNapiGetDumpRequest<Prev> {
10104    fn drop(&mut self) {
10105        if let Some(prev) = &mut self.prev {
10106            if let Some(header_offset) = &self.header_offset {
10107                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10108            }
10109        }
10110    }
10111}
10112#[doc = "Get information about NAPI instances configured on the system."]
10113#[derive(Clone)]
10114pub enum OpNapiGetDumpRequest {
10115    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10116    Ifindex(u32),
10117}
10118impl<'a> IterableOpNapiGetDumpRequest<'a> {
10119    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10120    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10121        let mut iter = self.clone();
10122        iter.pos = 0;
10123        for attr in iter {
10124            if let OpNapiGetDumpRequest::Ifindex(val) = attr? {
10125                return Ok(val);
10126            }
10127        }
10128        Err(ErrorContext::new_missing(
10129            "OpNapiGetDumpRequest",
10130            "Ifindex",
10131            self.orig_loc,
10132            self.buf.as_ptr() as usize,
10133        ))
10134    }
10135}
10136impl OpNapiGetDumpRequest {
10137    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpRequest<'a> {
10138        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10139        IterableOpNapiGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
10140    }
10141    fn attr_from_type(r#type: u16) -> Option<&'static str> {
10142        Napi::attr_from_type(r#type)
10143    }
10144}
10145#[derive(Clone, Copy, Default)]
10146pub struct IterableOpNapiGetDumpRequest<'a> {
10147    buf: &'a [u8],
10148    pos: usize,
10149    orig_loc: usize,
10150}
10151impl<'a> IterableOpNapiGetDumpRequest<'a> {
10152    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10153        Self {
10154            buf,
10155            pos: 0,
10156            orig_loc,
10157        }
10158    }
10159    pub fn get_buf(&self) -> &'a [u8] {
10160        self.buf
10161    }
10162}
10163impl<'a> Iterator for IterableOpNapiGetDumpRequest<'a> {
10164    type Item = Result<OpNapiGetDumpRequest, ErrorContext>;
10165    fn next(&mut self) -> Option<Self::Item> {
10166        let pos = self.pos;
10167        let mut r#type;
10168        loop {
10169            r#type = None;
10170            if self.buf.len() == self.pos {
10171                return None;
10172            }
10173            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
10174                break;
10175            };
10176            r#type = Some(header.r#type);
10177            let res = match header.r#type {
10178                1u16 => OpNapiGetDumpRequest::Ifindex({
10179                    let res = parse_u32(next);
10180                    let Some(val) = res else { break };
10181                    val
10182                }),
10183                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
10184                n => continue,
10185            };
10186            return Some(Ok(res));
10187        }
10188        Some(Err(ErrorContext::new(
10189            "OpNapiGetDumpRequest",
10190            r#type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10191            self.orig_loc,
10192            self.buf.as_ptr().wrapping_add(pos) as usize,
10193        )))
10194    }
10195}
10196impl std::fmt::Debug for IterableOpNapiGetDumpRequest<'_> {
10197    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10198        let mut fmt = f.debug_struct("OpNapiGetDumpRequest");
10199        for attr in self.clone() {
10200            let attr = match attr {
10201                Ok(a) => a,
10202                Err(err) => {
10203                    fmt.finish()?;
10204                    f.write_str("Err(")?;
10205                    err.fmt(f)?;
10206                    return f.write_str(")");
10207                }
10208            };
10209            match attr {
10210                OpNapiGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
10211            };
10212        }
10213        fmt.finish()
10214    }
10215}
10216impl IterableOpNapiGetDumpRequest<'_> {
10217    pub fn lookup_attr(
10218        &self,
10219        offset: usize,
10220        missing_type: Option<u16>,
10221    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10222        let mut stack = Vec::new();
10223        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10224        if cur == offset + PushBuiltinNfgenmsg::len() {
10225            stack.push(("OpNapiGetDumpRequest", offset));
10226            return (
10227                stack,
10228                missing_type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10229            );
10230        }
10231        if cur > offset || cur + self.buf.len() < offset {
10232            return (stack, None);
10233        }
10234        let mut attrs = self.clone();
10235        let mut last_off = cur + attrs.pos;
10236        while let Some(attr) = attrs.next() {
10237            let Ok(attr) = attr else { break };
10238            match attr {
10239                OpNapiGetDumpRequest::Ifindex(val) => {
10240                    if last_off == offset {
10241                        stack.push(("Ifindex", last_off));
10242                        break;
10243                    }
10244                }
10245                _ => {}
10246            };
10247            last_off = cur + attrs.pos;
10248        }
10249        if !stack.is_empty() {
10250            stack.push(("OpNapiGetDumpRequest", cur));
10251        }
10252        (stack, None)
10253    }
10254}
10255#[doc = "Get information about NAPI instances configured on the system."]
10256pub struct PushOpNapiGetDumpReply<Prev: Rec> {
10257    pub(crate) prev: Option<Prev>,
10258    pub(crate) header_offset: Option<usize>,
10259}
10260impl<Prev: Rec> Rec for PushOpNapiGetDumpReply<Prev> {
10261    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10262        self.prev.as_mut().unwrap().as_rec_mut()
10263    }
10264    fn as_rec(&self) -> &Vec<u8> {
10265        self.prev.as_ref().unwrap().as_rec()
10266    }
10267}
10268impl<Prev: Rec> PushOpNapiGetDumpReply<Prev> {
10269    pub fn new(mut prev: Prev) -> Self {
10270        Self::write_header(&mut prev);
10271        Self::new_without_header(prev)
10272    }
10273    fn new_without_header(prev: Prev) -> Self {
10274        Self {
10275            prev: Some(prev),
10276            header_offset: None,
10277        }
10278    }
10279    fn write_header(prev: &mut Prev) {
10280        let mut header = PushBuiltinNfgenmsg::new();
10281        header.set_cmd(11u8);
10282        header.set_version(1u8);
10283        prev.as_rec_mut().extend(header.as_slice());
10284    }
10285    pub fn end_nested(mut self) -> Prev {
10286        let mut prev = self.prev.take().unwrap();
10287        if let Some(header_offset) = &self.header_offset {
10288            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10289        }
10290        prev
10291    }
10292    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10293    pub fn push_ifindex(mut self, value: u32) -> Self {
10294        push_header(self.as_rec_mut(), 1u16, 4 as u16);
10295        self.as_rec_mut().extend(value.to_ne_bytes());
10296        self
10297    }
10298    #[doc = "ID of the NAPI instance."]
10299    pub fn push_id(mut self, value: u32) -> Self {
10300        push_header(self.as_rec_mut(), 2u16, 4 as u16);
10301        self.as_rec_mut().extend(value.to_ne_bytes());
10302        self
10303    }
10304    #[doc = "The associated interrupt vector number for the napi"]
10305    pub fn push_irq(mut self, value: u32) -> Self {
10306        push_header(self.as_rec_mut(), 3u16, 4 as u16);
10307        self.as_rec_mut().extend(value.to_ne_bytes());
10308        self
10309    }
10310    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
10311    pub fn push_pid(mut self, value: u32) -> Self {
10312        push_header(self.as_rec_mut(), 4u16, 4 as u16);
10313        self.as_rec_mut().extend(value.to_ne_bytes());
10314        self
10315    }
10316    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10317    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
10318        push_header(self.as_rec_mut(), 5u16, 4 as u16);
10319        self.as_rec_mut().extend(value.to_ne_bytes());
10320        self
10321    }
10322    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
10323    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
10324        push_header(self.as_rec_mut(), 6u16, 4 as u16);
10325        self.as_rec_mut().extend(value.to_ne_bytes());
10326        self
10327    }
10328    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10329    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
10330        push_header(self.as_rec_mut(), 7u16, 4 as u16);
10331        self.as_rec_mut().extend(value.to_ne_bytes());
10332        self
10333    }
10334    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
10335    pub fn push_threaded(mut self, value: u32) -> Self {
10336        push_header(self.as_rec_mut(), 8u16, 4 as u16);
10337        self.as_rec_mut().extend(value.to_ne_bytes());
10338        self
10339    }
10340}
10341impl<Prev: Rec> Drop for PushOpNapiGetDumpReply<Prev> {
10342    fn drop(&mut self) {
10343        if let Some(prev) = &mut self.prev {
10344            if let Some(header_offset) = &self.header_offset {
10345                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10346            }
10347        }
10348    }
10349}
10350#[doc = "Get information about NAPI instances configured on the system."]
10351#[derive(Clone)]
10352pub enum OpNapiGetDumpReply {
10353    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10354    Ifindex(u32),
10355    #[doc = "ID of the NAPI instance."]
10356    Id(u32),
10357    #[doc = "The associated interrupt vector number for the napi"]
10358    Irq(u32),
10359    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
10360    Pid(u32),
10361    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10362    DeferHardIrqs(u32),
10363    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
10364    GroFlushTimeout(u32),
10365    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10366    IrqSuspendTimeout(u32),
10367    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
10368    Threaded(u32),
10369}
10370impl<'a> IterableOpNapiGetDumpReply<'a> {
10371    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10372    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10373        let mut iter = self.clone();
10374        iter.pos = 0;
10375        for attr in iter {
10376            if let OpNapiGetDumpReply::Ifindex(val) = attr? {
10377                return Ok(val);
10378            }
10379        }
10380        Err(ErrorContext::new_missing(
10381            "OpNapiGetDumpReply",
10382            "Ifindex",
10383            self.orig_loc,
10384            self.buf.as_ptr() as usize,
10385        ))
10386    }
10387    #[doc = "ID of the NAPI instance."]
10388    pub fn get_id(&self) -> Result<u32, ErrorContext> {
10389        let mut iter = self.clone();
10390        iter.pos = 0;
10391        for attr in iter {
10392            if let OpNapiGetDumpReply::Id(val) = attr? {
10393                return Ok(val);
10394            }
10395        }
10396        Err(ErrorContext::new_missing(
10397            "OpNapiGetDumpReply",
10398            "Id",
10399            self.orig_loc,
10400            self.buf.as_ptr() as usize,
10401        ))
10402    }
10403    #[doc = "The associated interrupt vector number for the napi"]
10404    pub fn get_irq(&self) -> Result<u32, ErrorContext> {
10405        let mut iter = self.clone();
10406        iter.pos = 0;
10407        for attr in iter {
10408            if let OpNapiGetDumpReply::Irq(val) = attr? {
10409                return Ok(val);
10410            }
10411        }
10412        Err(ErrorContext::new_missing(
10413            "OpNapiGetDumpReply",
10414            "Irq",
10415            self.orig_loc,
10416            self.buf.as_ptr() as usize,
10417        ))
10418    }
10419    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
10420    pub fn get_pid(&self) -> Result<u32, ErrorContext> {
10421        let mut iter = self.clone();
10422        iter.pos = 0;
10423        for attr in iter {
10424            if let OpNapiGetDumpReply::Pid(val) = attr? {
10425                return Ok(val);
10426            }
10427        }
10428        Err(ErrorContext::new_missing(
10429            "OpNapiGetDumpReply",
10430            "Pid",
10431            self.orig_loc,
10432            self.buf.as_ptr() as usize,
10433        ))
10434    }
10435    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10436    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
10437        let mut iter = self.clone();
10438        iter.pos = 0;
10439        for attr in iter {
10440            if let OpNapiGetDumpReply::DeferHardIrqs(val) = attr? {
10441                return Ok(val);
10442            }
10443        }
10444        Err(ErrorContext::new_missing(
10445            "OpNapiGetDumpReply",
10446            "DeferHardIrqs",
10447            self.orig_loc,
10448            self.buf.as_ptr() as usize,
10449        ))
10450    }
10451    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
10452    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
10453        let mut iter = self.clone();
10454        iter.pos = 0;
10455        for attr in iter {
10456            if let OpNapiGetDumpReply::GroFlushTimeout(val) = attr? {
10457                return Ok(val);
10458            }
10459        }
10460        Err(ErrorContext::new_missing(
10461            "OpNapiGetDumpReply",
10462            "GroFlushTimeout",
10463            self.orig_loc,
10464            self.buf.as_ptr() as usize,
10465        ))
10466    }
10467    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10468    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
10469        let mut iter = self.clone();
10470        iter.pos = 0;
10471        for attr in iter {
10472            if let OpNapiGetDumpReply::IrqSuspendTimeout(val) = attr? {
10473                return Ok(val);
10474            }
10475        }
10476        Err(ErrorContext::new_missing(
10477            "OpNapiGetDumpReply",
10478            "IrqSuspendTimeout",
10479            self.orig_loc,
10480            self.buf.as_ptr() as usize,
10481        ))
10482    }
10483    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
10484    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
10485        let mut iter = self.clone();
10486        iter.pos = 0;
10487        for attr in iter {
10488            if let OpNapiGetDumpReply::Threaded(val) = attr? {
10489                return Ok(val);
10490            }
10491        }
10492        Err(ErrorContext::new_missing(
10493            "OpNapiGetDumpReply",
10494            "Threaded",
10495            self.orig_loc,
10496            self.buf.as_ptr() as usize,
10497        ))
10498    }
10499}
10500impl OpNapiGetDumpReply {
10501    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpReply<'a> {
10502        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10503        IterableOpNapiGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
10504    }
10505    fn attr_from_type(r#type: u16) -> Option<&'static str> {
10506        Napi::attr_from_type(r#type)
10507    }
10508}
10509#[derive(Clone, Copy, Default)]
10510pub struct IterableOpNapiGetDumpReply<'a> {
10511    buf: &'a [u8],
10512    pos: usize,
10513    orig_loc: usize,
10514}
10515impl<'a> IterableOpNapiGetDumpReply<'a> {
10516    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10517        Self {
10518            buf,
10519            pos: 0,
10520            orig_loc,
10521        }
10522    }
10523    pub fn get_buf(&self) -> &'a [u8] {
10524        self.buf
10525    }
10526}
10527impl<'a> Iterator for IterableOpNapiGetDumpReply<'a> {
10528    type Item = Result<OpNapiGetDumpReply, ErrorContext>;
10529    fn next(&mut self) -> Option<Self::Item> {
10530        let pos = self.pos;
10531        let mut r#type;
10532        loop {
10533            r#type = None;
10534            if self.buf.len() == self.pos {
10535                return None;
10536            }
10537            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
10538                break;
10539            };
10540            r#type = Some(header.r#type);
10541            let res = match header.r#type {
10542                1u16 => OpNapiGetDumpReply::Ifindex({
10543                    let res = parse_u32(next);
10544                    let Some(val) = res else { break };
10545                    val
10546                }),
10547                2u16 => OpNapiGetDumpReply::Id({
10548                    let res = parse_u32(next);
10549                    let Some(val) = res else { break };
10550                    val
10551                }),
10552                3u16 => OpNapiGetDumpReply::Irq({
10553                    let res = parse_u32(next);
10554                    let Some(val) = res else { break };
10555                    val
10556                }),
10557                4u16 => OpNapiGetDumpReply::Pid({
10558                    let res = parse_u32(next);
10559                    let Some(val) = res else { break };
10560                    val
10561                }),
10562                5u16 => OpNapiGetDumpReply::DeferHardIrqs({
10563                    let res = parse_u32(next);
10564                    let Some(val) = res else { break };
10565                    val
10566                }),
10567                6u16 => OpNapiGetDumpReply::GroFlushTimeout({
10568                    let res = parse_u32(next);
10569                    let Some(val) = res else { break };
10570                    val
10571                }),
10572                7u16 => OpNapiGetDumpReply::IrqSuspendTimeout({
10573                    let res = parse_u32(next);
10574                    let Some(val) = res else { break };
10575                    val
10576                }),
10577                8u16 => OpNapiGetDumpReply::Threaded({
10578                    let res = parse_u32(next);
10579                    let Some(val) = res else { break };
10580                    val
10581                }),
10582                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
10583                n => continue,
10584            };
10585            return Some(Ok(res));
10586        }
10587        Some(Err(ErrorContext::new(
10588            "OpNapiGetDumpReply",
10589            r#type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10590            self.orig_loc,
10591            self.buf.as_ptr().wrapping_add(pos) as usize,
10592        )))
10593    }
10594}
10595impl std::fmt::Debug for IterableOpNapiGetDumpReply<'_> {
10596    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10597        let mut fmt = f.debug_struct("OpNapiGetDumpReply");
10598        for attr in self.clone() {
10599            let attr = match attr {
10600                Ok(a) => a,
10601                Err(err) => {
10602                    fmt.finish()?;
10603                    f.write_str("Err(")?;
10604                    err.fmt(f)?;
10605                    return f.write_str(")");
10606                }
10607            };
10608            match attr {
10609                OpNapiGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
10610                OpNapiGetDumpReply::Id(val) => fmt.field("Id", &val),
10611                OpNapiGetDumpReply::Irq(val) => fmt.field("Irq", &val),
10612                OpNapiGetDumpReply::Pid(val) => fmt.field("Pid", &val),
10613                OpNapiGetDumpReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
10614                OpNapiGetDumpReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
10615                OpNapiGetDumpReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
10616                OpNapiGetDumpReply::Threaded(val) => fmt.field(
10617                    "Threaded",
10618                    &FormatEnum(val.into(), NapiThreaded::from_value),
10619                ),
10620            };
10621        }
10622        fmt.finish()
10623    }
10624}
10625impl IterableOpNapiGetDumpReply<'_> {
10626    pub fn lookup_attr(
10627        &self,
10628        offset: usize,
10629        missing_type: Option<u16>,
10630    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10631        let mut stack = Vec::new();
10632        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10633        if cur == offset + PushBuiltinNfgenmsg::len() {
10634            stack.push(("OpNapiGetDumpReply", offset));
10635            return (
10636                stack,
10637                missing_type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10638            );
10639        }
10640        if cur > offset || cur + self.buf.len() < offset {
10641            return (stack, None);
10642        }
10643        let mut attrs = self.clone();
10644        let mut last_off = cur + attrs.pos;
10645        while let Some(attr) = attrs.next() {
10646            let Ok(attr) = attr else { break };
10647            match attr {
10648                OpNapiGetDumpReply::Ifindex(val) => {
10649                    if last_off == offset {
10650                        stack.push(("Ifindex", last_off));
10651                        break;
10652                    }
10653                }
10654                OpNapiGetDumpReply::Id(val) => {
10655                    if last_off == offset {
10656                        stack.push(("Id", last_off));
10657                        break;
10658                    }
10659                }
10660                OpNapiGetDumpReply::Irq(val) => {
10661                    if last_off == offset {
10662                        stack.push(("Irq", last_off));
10663                        break;
10664                    }
10665                }
10666                OpNapiGetDumpReply::Pid(val) => {
10667                    if last_off == offset {
10668                        stack.push(("Pid", last_off));
10669                        break;
10670                    }
10671                }
10672                OpNapiGetDumpReply::DeferHardIrqs(val) => {
10673                    if last_off == offset {
10674                        stack.push(("DeferHardIrqs", last_off));
10675                        break;
10676                    }
10677                }
10678                OpNapiGetDumpReply::GroFlushTimeout(val) => {
10679                    if last_off == offset {
10680                        stack.push(("GroFlushTimeout", last_off));
10681                        break;
10682                    }
10683                }
10684                OpNapiGetDumpReply::IrqSuspendTimeout(val) => {
10685                    if last_off == offset {
10686                        stack.push(("IrqSuspendTimeout", last_off));
10687                        break;
10688                    }
10689                }
10690                OpNapiGetDumpReply::Threaded(val) => {
10691                    if last_off == offset {
10692                        stack.push(("Threaded", last_off));
10693                        break;
10694                    }
10695                }
10696                _ => {}
10697            };
10698            last_off = cur + attrs.pos;
10699        }
10700        if !stack.is_empty() {
10701            stack.push(("OpNapiGetDumpReply", cur));
10702        }
10703        (stack, None)
10704    }
10705}
10706#[derive(Debug)]
10707pub struct RequestOpNapiGetDumpRequest<'r> {
10708    request: Request<'r>,
10709}
10710impl<'r> RequestOpNapiGetDumpRequest<'r> {
10711    pub fn new(mut request: Request<'r>) -> Self {
10712        PushOpNapiGetDumpRequest::write_header(&mut request.buf_mut());
10713        Self {
10714            request: request.set_dump(),
10715        }
10716    }
10717    pub fn encode(&mut self) -> PushOpNapiGetDumpRequest<&mut Vec<u8>> {
10718        PushOpNapiGetDumpRequest::new_without_header(self.request.buf_mut())
10719    }
10720    pub fn into_encoder(self) -> PushOpNapiGetDumpRequest<RequestBuf<'r>> {
10721        PushOpNapiGetDumpRequest::new_without_header(self.request.buf)
10722    }
10723    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpNapiGetDumpRequest<'buf> {
10724        OpNapiGetDumpRequest::new(buf)
10725    }
10726}
10727impl NetlinkRequest for RequestOpNapiGetDumpRequest<'_> {
10728    fn protocol(&self) -> Protocol {
10729        Protocol::Generic("netdev".as_bytes())
10730    }
10731    fn flags(&self) -> u16 {
10732        self.request.flags
10733    }
10734    fn payload(&self) -> &[u8] {
10735        self.request.buf()
10736    }
10737    type ReplyType<'buf> = IterableOpNapiGetDumpReply<'buf>;
10738    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
10739        OpNapiGetDumpReply::new(buf)
10740    }
10741    fn lookup(
10742        buf: &[u8],
10743        offset: usize,
10744        missing_type: Option<u16>,
10745    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10746        OpNapiGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
10747    }
10748}
10749#[doc = "Get information about NAPI instances configured on the system."]
10750pub struct PushOpNapiGetDoRequest<Prev: Rec> {
10751    pub(crate) prev: Option<Prev>,
10752    pub(crate) header_offset: Option<usize>,
10753}
10754impl<Prev: Rec> Rec for PushOpNapiGetDoRequest<Prev> {
10755    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10756        self.prev.as_mut().unwrap().as_rec_mut()
10757    }
10758    fn as_rec(&self) -> &Vec<u8> {
10759        self.prev.as_ref().unwrap().as_rec()
10760    }
10761}
10762impl<Prev: Rec> PushOpNapiGetDoRequest<Prev> {
10763    pub fn new(mut prev: Prev) -> Self {
10764        Self::write_header(&mut prev);
10765        Self::new_without_header(prev)
10766    }
10767    fn new_without_header(prev: Prev) -> Self {
10768        Self {
10769            prev: Some(prev),
10770            header_offset: None,
10771        }
10772    }
10773    fn write_header(prev: &mut Prev) {
10774        let mut header = PushBuiltinNfgenmsg::new();
10775        header.set_cmd(11u8);
10776        header.set_version(1u8);
10777        prev.as_rec_mut().extend(header.as_slice());
10778    }
10779    pub fn end_nested(mut self) -> Prev {
10780        let mut prev = self.prev.take().unwrap();
10781        if let Some(header_offset) = &self.header_offset {
10782            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10783        }
10784        prev
10785    }
10786    #[doc = "ID of the NAPI instance."]
10787    pub fn push_id(mut self, value: u32) -> Self {
10788        push_header(self.as_rec_mut(), 2u16, 4 as u16);
10789        self.as_rec_mut().extend(value.to_ne_bytes());
10790        self
10791    }
10792}
10793impl<Prev: Rec> Drop for PushOpNapiGetDoRequest<Prev> {
10794    fn drop(&mut self) {
10795        if let Some(prev) = &mut self.prev {
10796            if let Some(header_offset) = &self.header_offset {
10797                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10798            }
10799        }
10800    }
10801}
10802#[doc = "Get information about NAPI instances configured on the system."]
10803#[derive(Clone)]
10804pub enum OpNapiGetDoRequest {
10805    #[doc = "ID of the NAPI instance."]
10806    Id(u32),
10807}
10808impl<'a> IterableOpNapiGetDoRequest<'a> {
10809    #[doc = "ID of the NAPI instance."]
10810    pub fn get_id(&self) -> Result<u32, ErrorContext> {
10811        let mut iter = self.clone();
10812        iter.pos = 0;
10813        for attr in iter {
10814            if let OpNapiGetDoRequest::Id(val) = attr? {
10815                return Ok(val);
10816            }
10817        }
10818        Err(ErrorContext::new_missing(
10819            "OpNapiGetDoRequest",
10820            "Id",
10821            self.orig_loc,
10822            self.buf.as_ptr() as usize,
10823        ))
10824    }
10825}
10826impl OpNapiGetDoRequest {
10827    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoRequest<'a> {
10828        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10829        IterableOpNapiGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
10830    }
10831    fn attr_from_type(r#type: u16) -> Option<&'static str> {
10832        Napi::attr_from_type(r#type)
10833    }
10834}
10835#[derive(Clone, Copy, Default)]
10836pub struct IterableOpNapiGetDoRequest<'a> {
10837    buf: &'a [u8],
10838    pos: usize,
10839    orig_loc: usize,
10840}
10841impl<'a> IterableOpNapiGetDoRequest<'a> {
10842    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10843        Self {
10844            buf,
10845            pos: 0,
10846            orig_loc,
10847        }
10848    }
10849    pub fn get_buf(&self) -> &'a [u8] {
10850        self.buf
10851    }
10852}
10853impl<'a> Iterator for IterableOpNapiGetDoRequest<'a> {
10854    type Item = Result<OpNapiGetDoRequest, ErrorContext>;
10855    fn next(&mut self) -> Option<Self::Item> {
10856        let pos = self.pos;
10857        let mut r#type;
10858        loop {
10859            r#type = None;
10860            if self.buf.len() == self.pos {
10861                return None;
10862            }
10863            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
10864                break;
10865            };
10866            r#type = Some(header.r#type);
10867            let res = match header.r#type {
10868                2u16 => OpNapiGetDoRequest::Id({
10869                    let res = parse_u32(next);
10870                    let Some(val) = res else { break };
10871                    val
10872                }),
10873                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
10874                n => continue,
10875            };
10876            return Some(Ok(res));
10877        }
10878        Some(Err(ErrorContext::new(
10879            "OpNapiGetDoRequest",
10880            r#type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10881            self.orig_loc,
10882            self.buf.as_ptr().wrapping_add(pos) as usize,
10883        )))
10884    }
10885}
10886impl std::fmt::Debug for IterableOpNapiGetDoRequest<'_> {
10887    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10888        let mut fmt = f.debug_struct("OpNapiGetDoRequest");
10889        for attr in self.clone() {
10890            let attr = match attr {
10891                Ok(a) => a,
10892                Err(err) => {
10893                    fmt.finish()?;
10894                    f.write_str("Err(")?;
10895                    err.fmt(f)?;
10896                    return f.write_str(")");
10897                }
10898            };
10899            match attr {
10900                OpNapiGetDoRequest::Id(val) => fmt.field("Id", &val),
10901            };
10902        }
10903        fmt.finish()
10904    }
10905}
10906impl IterableOpNapiGetDoRequest<'_> {
10907    pub fn lookup_attr(
10908        &self,
10909        offset: usize,
10910        missing_type: Option<u16>,
10911    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10912        let mut stack = Vec::new();
10913        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10914        if cur == offset + PushBuiltinNfgenmsg::len() {
10915            stack.push(("OpNapiGetDoRequest", offset));
10916            return (
10917                stack,
10918                missing_type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10919            );
10920        }
10921        if cur > offset || cur + self.buf.len() < offset {
10922            return (stack, None);
10923        }
10924        let mut attrs = self.clone();
10925        let mut last_off = cur + attrs.pos;
10926        while let Some(attr) = attrs.next() {
10927            let Ok(attr) = attr else { break };
10928            match attr {
10929                OpNapiGetDoRequest::Id(val) => {
10930                    if last_off == offset {
10931                        stack.push(("Id", last_off));
10932                        break;
10933                    }
10934                }
10935                _ => {}
10936            };
10937            last_off = cur + attrs.pos;
10938        }
10939        if !stack.is_empty() {
10940            stack.push(("OpNapiGetDoRequest", cur));
10941        }
10942        (stack, None)
10943    }
10944}
10945#[doc = "Get information about NAPI instances configured on the system."]
10946pub struct PushOpNapiGetDoReply<Prev: Rec> {
10947    pub(crate) prev: Option<Prev>,
10948    pub(crate) header_offset: Option<usize>,
10949}
10950impl<Prev: Rec> Rec for PushOpNapiGetDoReply<Prev> {
10951    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10952        self.prev.as_mut().unwrap().as_rec_mut()
10953    }
10954    fn as_rec(&self) -> &Vec<u8> {
10955        self.prev.as_ref().unwrap().as_rec()
10956    }
10957}
10958impl<Prev: Rec> PushOpNapiGetDoReply<Prev> {
10959    pub fn new(mut prev: Prev) -> Self {
10960        Self::write_header(&mut prev);
10961        Self::new_without_header(prev)
10962    }
10963    fn new_without_header(prev: Prev) -> Self {
10964        Self {
10965            prev: Some(prev),
10966            header_offset: None,
10967        }
10968    }
10969    fn write_header(prev: &mut Prev) {
10970        let mut header = PushBuiltinNfgenmsg::new();
10971        header.set_cmd(11u8);
10972        header.set_version(1u8);
10973        prev.as_rec_mut().extend(header.as_slice());
10974    }
10975    pub fn end_nested(mut self) -> Prev {
10976        let mut prev = self.prev.take().unwrap();
10977        if let Some(header_offset) = &self.header_offset {
10978            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10979        }
10980        prev
10981    }
10982    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10983    pub fn push_ifindex(mut self, value: u32) -> Self {
10984        push_header(self.as_rec_mut(), 1u16, 4 as u16);
10985        self.as_rec_mut().extend(value.to_ne_bytes());
10986        self
10987    }
10988    #[doc = "ID of the NAPI instance."]
10989    pub fn push_id(mut self, value: u32) -> Self {
10990        push_header(self.as_rec_mut(), 2u16, 4 as u16);
10991        self.as_rec_mut().extend(value.to_ne_bytes());
10992        self
10993    }
10994    #[doc = "The associated interrupt vector number for the napi"]
10995    pub fn push_irq(mut self, value: u32) -> Self {
10996        push_header(self.as_rec_mut(), 3u16, 4 as u16);
10997        self.as_rec_mut().extend(value.to_ne_bytes());
10998        self
10999    }
11000    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
11001    pub fn push_pid(mut self, value: u32) -> Self {
11002        push_header(self.as_rec_mut(), 4u16, 4 as u16);
11003        self.as_rec_mut().extend(value.to_ne_bytes());
11004        self
11005    }
11006    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11007    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
11008        push_header(self.as_rec_mut(), 5u16, 4 as u16);
11009        self.as_rec_mut().extend(value.to_ne_bytes());
11010        self
11011    }
11012    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
11013    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
11014        push_header(self.as_rec_mut(), 6u16, 4 as u16);
11015        self.as_rec_mut().extend(value.to_ne_bytes());
11016        self
11017    }
11018    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11019    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
11020        push_header(self.as_rec_mut(), 7u16, 4 as u16);
11021        self.as_rec_mut().extend(value.to_ne_bytes());
11022        self
11023    }
11024    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
11025    pub fn push_threaded(mut self, value: u32) -> Self {
11026        push_header(self.as_rec_mut(), 8u16, 4 as u16);
11027        self.as_rec_mut().extend(value.to_ne_bytes());
11028        self
11029    }
11030}
11031impl<Prev: Rec> Drop for PushOpNapiGetDoReply<Prev> {
11032    fn drop(&mut self) {
11033        if let Some(prev) = &mut self.prev {
11034            if let Some(header_offset) = &self.header_offset {
11035                finalize_nested_header(prev.as_rec_mut(), *header_offset);
11036            }
11037        }
11038    }
11039}
11040#[doc = "Get information about NAPI instances configured on the system."]
11041#[derive(Clone)]
11042pub enum OpNapiGetDoReply {
11043    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
11044    Ifindex(u32),
11045    #[doc = "ID of the NAPI instance."]
11046    Id(u32),
11047    #[doc = "The associated interrupt vector number for the napi"]
11048    Irq(u32),
11049    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
11050    Pid(u32),
11051    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11052    DeferHardIrqs(u32),
11053    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
11054    GroFlushTimeout(u32),
11055    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11056    IrqSuspendTimeout(u32),
11057    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
11058    Threaded(u32),
11059}
11060impl<'a> IterableOpNapiGetDoReply<'a> {
11061    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
11062    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11063        let mut iter = self.clone();
11064        iter.pos = 0;
11065        for attr in iter {
11066            if let OpNapiGetDoReply::Ifindex(val) = attr? {
11067                return Ok(val);
11068            }
11069        }
11070        Err(ErrorContext::new_missing(
11071            "OpNapiGetDoReply",
11072            "Ifindex",
11073            self.orig_loc,
11074            self.buf.as_ptr() as usize,
11075        ))
11076    }
11077    #[doc = "ID of the NAPI instance."]
11078    pub fn get_id(&self) -> Result<u32, ErrorContext> {
11079        let mut iter = self.clone();
11080        iter.pos = 0;
11081        for attr in iter {
11082            if let OpNapiGetDoReply::Id(val) = attr? {
11083                return Ok(val);
11084            }
11085        }
11086        Err(ErrorContext::new_missing(
11087            "OpNapiGetDoReply",
11088            "Id",
11089            self.orig_loc,
11090            self.buf.as_ptr() as usize,
11091        ))
11092    }
11093    #[doc = "The associated interrupt vector number for the napi"]
11094    pub fn get_irq(&self) -> Result<u32, ErrorContext> {
11095        let mut iter = self.clone();
11096        iter.pos = 0;
11097        for attr in iter {
11098            if let OpNapiGetDoReply::Irq(val) = attr? {
11099                return Ok(val);
11100            }
11101        }
11102        Err(ErrorContext::new_missing(
11103            "OpNapiGetDoReply",
11104            "Irq",
11105            self.orig_loc,
11106            self.buf.as_ptr() as usize,
11107        ))
11108    }
11109    #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
11110    pub fn get_pid(&self) -> Result<u32, ErrorContext> {
11111        let mut iter = self.clone();
11112        iter.pos = 0;
11113        for attr in iter {
11114            if let OpNapiGetDoReply::Pid(val) = attr? {
11115                return Ok(val);
11116            }
11117        }
11118        Err(ErrorContext::new_missing(
11119            "OpNapiGetDoReply",
11120            "Pid",
11121            self.orig_loc,
11122            self.buf.as_ptr() as usize,
11123        ))
11124    }
11125    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11126    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
11127        let mut iter = self.clone();
11128        iter.pos = 0;
11129        for attr in iter {
11130            if let OpNapiGetDoReply::DeferHardIrqs(val) = attr? {
11131                return Ok(val);
11132            }
11133        }
11134        Err(ErrorContext::new_missing(
11135            "OpNapiGetDoReply",
11136            "DeferHardIrqs",
11137            self.orig_loc,
11138            self.buf.as_ptr() as usize,
11139        ))
11140    }
11141    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
11142    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
11143        let mut iter = self.clone();
11144        iter.pos = 0;
11145        for attr in iter {
11146            if let OpNapiGetDoReply::GroFlushTimeout(val) = attr? {
11147                return Ok(val);
11148            }
11149        }
11150        Err(ErrorContext::new_missing(
11151            "OpNapiGetDoReply",
11152            "GroFlushTimeout",
11153            self.orig_loc,
11154            self.buf.as_ptr() as usize,
11155        ))
11156    }
11157    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11158    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
11159        let mut iter = self.clone();
11160        iter.pos = 0;
11161        for attr in iter {
11162            if let OpNapiGetDoReply::IrqSuspendTimeout(val) = attr? {
11163                return Ok(val);
11164            }
11165        }
11166        Err(ErrorContext::new_missing(
11167            "OpNapiGetDoReply",
11168            "IrqSuspendTimeout",
11169            self.orig_loc,
11170            self.buf.as_ptr() as usize,
11171        ))
11172    }
11173    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
11174    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
11175        let mut iter = self.clone();
11176        iter.pos = 0;
11177        for attr in iter {
11178            if let OpNapiGetDoReply::Threaded(val) = attr? {
11179                return Ok(val);
11180            }
11181        }
11182        Err(ErrorContext::new_missing(
11183            "OpNapiGetDoReply",
11184            "Threaded",
11185            self.orig_loc,
11186            self.buf.as_ptr() as usize,
11187        ))
11188    }
11189}
11190impl OpNapiGetDoReply {
11191    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoReply<'a> {
11192        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11193        IterableOpNapiGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
11194    }
11195    fn attr_from_type(r#type: u16) -> Option<&'static str> {
11196        Napi::attr_from_type(r#type)
11197    }
11198}
11199#[derive(Clone, Copy, Default)]
11200pub struct IterableOpNapiGetDoReply<'a> {
11201    buf: &'a [u8],
11202    pos: usize,
11203    orig_loc: usize,
11204}
11205impl<'a> IterableOpNapiGetDoReply<'a> {
11206    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11207        Self {
11208            buf,
11209            pos: 0,
11210            orig_loc,
11211        }
11212    }
11213    pub fn get_buf(&self) -> &'a [u8] {
11214        self.buf
11215    }
11216}
11217impl<'a> Iterator for IterableOpNapiGetDoReply<'a> {
11218    type Item = Result<OpNapiGetDoReply, ErrorContext>;
11219    fn next(&mut self) -> Option<Self::Item> {
11220        let pos = self.pos;
11221        let mut r#type;
11222        loop {
11223            r#type = None;
11224            if self.buf.len() == self.pos {
11225                return None;
11226            }
11227            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
11228                break;
11229            };
11230            r#type = Some(header.r#type);
11231            let res = match header.r#type {
11232                1u16 => OpNapiGetDoReply::Ifindex({
11233                    let res = parse_u32(next);
11234                    let Some(val) = res else { break };
11235                    val
11236                }),
11237                2u16 => OpNapiGetDoReply::Id({
11238                    let res = parse_u32(next);
11239                    let Some(val) = res else { break };
11240                    val
11241                }),
11242                3u16 => OpNapiGetDoReply::Irq({
11243                    let res = parse_u32(next);
11244                    let Some(val) = res else { break };
11245                    val
11246                }),
11247                4u16 => OpNapiGetDoReply::Pid({
11248                    let res = parse_u32(next);
11249                    let Some(val) = res else { break };
11250                    val
11251                }),
11252                5u16 => OpNapiGetDoReply::DeferHardIrqs({
11253                    let res = parse_u32(next);
11254                    let Some(val) = res else { break };
11255                    val
11256                }),
11257                6u16 => OpNapiGetDoReply::GroFlushTimeout({
11258                    let res = parse_u32(next);
11259                    let Some(val) = res else { break };
11260                    val
11261                }),
11262                7u16 => OpNapiGetDoReply::IrqSuspendTimeout({
11263                    let res = parse_u32(next);
11264                    let Some(val) = res else { break };
11265                    val
11266                }),
11267                8u16 => OpNapiGetDoReply::Threaded({
11268                    let res = parse_u32(next);
11269                    let Some(val) = res else { break };
11270                    val
11271                }),
11272                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
11273                n => continue,
11274            };
11275            return Some(Ok(res));
11276        }
11277        Some(Err(ErrorContext::new(
11278            "OpNapiGetDoReply",
11279            r#type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11280            self.orig_loc,
11281            self.buf.as_ptr().wrapping_add(pos) as usize,
11282        )))
11283    }
11284}
11285impl std::fmt::Debug for IterableOpNapiGetDoReply<'_> {
11286    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11287        let mut fmt = f.debug_struct("OpNapiGetDoReply");
11288        for attr in self.clone() {
11289            let attr = match attr {
11290                Ok(a) => a,
11291                Err(err) => {
11292                    fmt.finish()?;
11293                    f.write_str("Err(")?;
11294                    err.fmt(f)?;
11295                    return f.write_str(")");
11296                }
11297            };
11298            match attr {
11299                OpNapiGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
11300                OpNapiGetDoReply::Id(val) => fmt.field("Id", &val),
11301                OpNapiGetDoReply::Irq(val) => fmt.field("Irq", &val),
11302                OpNapiGetDoReply::Pid(val) => fmt.field("Pid", &val),
11303                OpNapiGetDoReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
11304                OpNapiGetDoReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
11305                OpNapiGetDoReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
11306                OpNapiGetDoReply::Threaded(val) => fmt.field(
11307                    "Threaded",
11308                    &FormatEnum(val.into(), NapiThreaded::from_value),
11309                ),
11310            };
11311        }
11312        fmt.finish()
11313    }
11314}
11315impl IterableOpNapiGetDoReply<'_> {
11316    pub fn lookup_attr(
11317        &self,
11318        offset: usize,
11319        missing_type: Option<u16>,
11320    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11321        let mut stack = Vec::new();
11322        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11323        if cur == offset + PushBuiltinNfgenmsg::len() {
11324            stack.push(("OpNapiGetDoReply", offset));
11325            return (
11326                stack,
11327                missing_type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11328            );
11329        }
11330        if cur > offset || cur + self.buf.len() < offset {
11331            return (stack, None);
11332        }
11333        let mut attrs = self.clone();
11334        let mut last_off = cur + attrs.pos;
11335        while let Some(attr) = attrs.next() {
11336            let Ok(attr) = attr else { break };
11337            match attr {
11338                OpNapiGetDoReply::Ifindex(val) => {
11339                    if last_off == offset {
11340                        stack.push(("Ifindex", last_off));
11341                        break;
11342                    }
11343                }
11344                OpNapiGetDoReply::Id(val) => {
11345                    if last_off == offset {
11346                        stack.push(("Id", last_off));
11347                        break;
11348                    }
11349                }
11350                OpNapiGetDoReply::Irq(val) => {
11351                    if last_off == offset {
11352                        stack.push(("Irq", last_off));
11353                        break;
11354                    }
11355                }
11356                OpNapiGetDoReply::Pid(val) => {
11357                    if last_off == offset {
11358                        stack.push(("Pid", last_off));
11359                        break;
11360                    }
11361                }
11362                OpNapiGetDoReply::DeferHardIrqs(val) => {
11363                    if last_off == offset {
11364                        stack.push(("DeferHardIrqs", last_off));
11365                        break;
11366                    }
11367                }
11368                OpNapiGetDoReply::GroFlushTimeout(val) => {
11369                    if last_off == offset {
11370                        stack.push(("GroFlushTimeout", last_off));
11371                        break;
11372                    }
11373                }
11374                OpNapiGetDoReply::IrqSuspendTimeout(val) => {
11375                    if last_off == offset {
11376                        stack.push(("IrqSuspendTimeout", last_off));
11377                        break;
11378                    }
11379                }
11380                OpNapiGetDoReply::Threaded(val) => {
11381                    if last_off == offset {
11382                        stack.push(("Threaded", last_off));
11383                        break;
11384                    }
11385                }
11386                _ => {}
11387            };
11388            last_off = cur + attrs.pos;
11389        }
11390        if !stack.is_empty() {
11391            stack.push(("OpNapiGetDoReply", cur));
11392        }
11393        (stack, None)
11394    }
11395}
11396#[derive(Debug)]
11397pub struct RequestOpNapiGetDoRequest<'r> {
11398    request: Request<'r>,
11399}
11400impl<'r> RequestOpNapiGetDoRequest<'r> {
11401    pub fn new(mut request: Request<'r>) -> Self {
11402        PushOpNapiGetDoRequest::write_header(&mut request.buf_mut());
11403        Self { request: request }
11404    }
11405    pub fn encode(&mut self) -> PushOpNapiGetDoRequest<&mut Vec<u8>> {
11406        PushOpNapiGetDoRequest::new_without_header(self.request.buf_mut())
11407    }
11408    pub fn into_encoder(self) -> PushOpNapiGetDoRequest<RequestBuf<'r>> {
11409        PushOpNapiGetDoRequest::new_without_header(self.request.buf)
11410    }
11411    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpNapiGetDoRequest<'buf> {
11412        OpNapiGetDoRequest::new(buf)
11413    }
11414}
11415impl NetlinkRequest for RequestOpNapiGetDoRequest<'_> {
11416    fn protocol(&self) -> Protocol {
11417        Protocol::Generic("netdev".as_bytes())
11418    }
11419    fn flags(&self) -> u16 {
11420        self.request.flags
11421    }
11422    fn payload(&self) -> &[u8] {
11423        self.request.buf()
11424    }
11425    type ReplyType<'buf> = IterableOpNapiGetDoReply<'buf>;
11426    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
11427        OpNapiGetDoReply::new(buf)
11428    }
11429    fn lookup(
11430        buf: &[u8],
11431        offset: usize,
11432        missing_type: Option<u16>,
11433    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11434        OpNapiGetDoRequest::new(buf).lookup_attr(offset, missing_type)
11435    }
11436}
11437#[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"]
11438pub struct PushOpQstatsGetDumpRequest<Prev: Rec> {
11439    pub(crate) prev: Option<Prev>,
11440    pub(crate) header_offset: Option<usize>,
11441}
11442impl<Prev: Rec> Rec for PushOpQstatsGetDumpRequest<Prev> {
11443    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11444        self.prev.as_mut().unwrap().as_rec_mut()
11445    }
11446    fn as_rec(&self) -> &Vec<u8> {
11447        self.prev.as_ref().unwrap().as_rec()
11448    }
11449}
11450impl<Prev: Rec> PushOpQstatsGetDumpRequest<Prev> {
11451    pub fn new(mut prev: Prev) -> Self {
11452        Self::write_header(&mut prev);
11453        Self::new_without_header(prev)
11454    }
11455    fn new_without_header(prev: Prev) -> Self {
11456        Self {
11457            prev: Some(prev),
11458            header_offset: None,
11459        }
11460    }
11461    fn write_header(prev: &mut Prev) {
11462        let mut header = PushBuiltinNfgenmsg::new();
11463        header.set_cmd(12u8);
11464        header.set_version(1u8);
11465        prev.as_rec_mut().extend(header.as_slice());
11466    }
11467    pub fn end_nested(mut self) -> Prev {
11468        let mut prev = self.prev.take().unwrap();
11469        if let Some(header_offset) = &self.header_offset {
11470            finalize_nested_header(prev.as_rec_mut(), *header_offset);
11471        }
11472        prev
11473    }
11474    #[doc = "ifindex of the netdevice to which stats belong."]
11475    pub fn push_ifindex(mut self, value: u32) -> Self {
11476        push_header(self.as_rec_mut(), 1u16, 4 as u16);
11477        self.as_rec_mut().extend(value.to_ne_bytes());
11478        self
11479    }
11480    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11481    pub fn push_scope(mut self, value: u32) -> Self {
11482        push_header(self.as_rec_mut(), 4u16, 4 as u16);
11483        self.as_rec_mut().extend(value.to_ne_bytes());
11484        self
11485    }
11486}
11487impl<Prev: Rec> Drop for PushOpQstatsGetDumpRequest<Prev> {
11488    fn drop(&mut self) {
11489        if let Some(prev) = &mut self.prev {
11490            if let Some(header_offset) = &self.header_offset {
11491                finalize_nested_header(prev.as_rec_mut(), *header_offset);
11492            }
11493        }
11494    }
11495}
11496#[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"]
11497#[derive(Clone)]
11498pub enum OpQstatsGetDumpRequest {
11499    #[doc = "ifindex of the netdevice to which stats belong."]
11500    Ifindex(u32),
11501    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11502    Scope(u32),
11503}
11504impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11505    #[doc = "ifindex of the netdevice to which stats belong."]
11506    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11507        let mut iter = self.clone();
11508        iter.pos = 0;
11509        for attr in iter {
11510            if let OpQstatsGetDumpRequest::Ifindex(val) = attr? {
11511                return Ok(val);
11512            }
11513        }
11514        Err(ErrorContext::new_missing(
11515            "OpQstatsGetDumpRequest",
11516            "Ifindex",
11517            self.orig_loc,
11518            self.buf.as_ptr() as usize,
11519        ))
11520    }
11521    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11522    pub fn get_scope(&self) -> Result<u32, ErrorContext> {
11523        let mut iter = self.clone();
11524        iter.pos = 0;
11525        for attr in iter {
11526            if let OpQstatsGetDumpRequest::Scope(val) = attr? {
11527                return Ok(val);
11528            }
11529        }
11530        Err(ErrorContext::new_missing(
11531            "OpQstatsGetDumpRequest",
11532            "Scope",
11533            self.orig_loc,
11534            self.buf.as_ptr() as usize,
11535        ))
11536    }
11537}
11538impl OpQstatsGetDumpRequest {
11539    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpRequest<'a> {
11540        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11541        IterableOpQstatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
11542    }
11543    fn attr_from_type(r#type: u16) -> Option<&'static str> {
11544        Qstats::attr_from_type(r#type)
11545    }
11546}
11547#[derive(Clone, Copy, Default)]
11548pub struct IterableOpQstatsGetDumpRequest<'a> {
11549    buf: &'a [u8],
11550    pos: usize,
11551    orig_loc: usize,
11552}
11553impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11554    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11555        Self {
11556            buf,
11557            pos: 0,
11558            orig_loc,
11559        }
11560    }
11561    pub fn get_buf(&self) -> &'a [u8] {
11562        self.buf
11563    }
11564}
11565impl<'a> Iterator for IterableOpQstatsGetDumpRequest<'a> {
11566    type Item = Result<OpQstatsGetDumpRequest, ErrorContext>;
11567    fn next(&mut self) -> Option<Self::Item> {
11568        let pos = self.pos;
11569        let mut r#type;
11570        loop {
11571            r#type = None;
11572            if self.buf.len() == self.pos {
11573                return None;
11574            }
11575            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
11576                break;
11577            };
11578            r#type = Some(header.r#type);
11579            let res = match header.r#type {
11580                1u16 => OpQstatsGetDumpRequest::Ifindex({
11581                    let res = parse_u32(next);
11582                    let Some(val) = res else { break };
11583                    val
11584                }),
11585                4u16 => OpQstatsGetDumpRequest::Scope({
11586                    let res = parse_u32(next);
11587                    let Some(val) = res else { break };
11588                    val
11589                }),
11590                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
11591                n => continue,
11592            };
11593            return Some(Ok(res));
11594        }
11595        Some(Err(ErrorContext::new(
11596            "OpQstatsGetDumpRequest",
11597            r#type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11598            self.orig_loc,
11599            self.buf.as_ptr().wrapping_add(pos) as usize,
11600        )))
11601    }
11602}
11603impl std::fmt::Debug for IterableOpQstatsGetDumpRequest<'_> {
11604    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11605        let mut fmt = f.debug_struct("OpQstatsGetDumpRequest");
11606        for attr in self.clone() {
11607            let attr = match attr {
11608                Ok(a) => a,
11609                Err(err) => {
11610                    fmt.finish()?;
11611                    f.write_str("Err(")?;
11612                    err.fmt(f)?;
11613                    return f.write_str(")");
11614                }
11615            };
11616            match attr {
11617                OpQstatsGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
11618                OpQstatsGetDumpRequest::Scope(val) => {
11619                    fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
11620                }
11621            };
11622        }
11623        fmt.finish()
11624    }
11625}
11626impl IterableOpQstatsGetDumpRequest<'_> {
11627    pub fn lookup_attr(
11628        &self,
11629        offset: usize,
11630        missing_type: Option<u16>,
11631    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11632        let mut stack = Vec::new();
11633        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11634        if cur == offset + PushBuiltinNfgenmsg::len() {
11635            stack.push(("OpQstatsGetDumpRequest", offset));
11636            return (
11637                stack,
11638                missing_type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11639            );
11640        }
11641        if cur > offset || cur + self.buf.len() < offset {
11642            return (stack, None);
11643        }
11644        let mut attrs = self.clone();
11645        let mut last_off = cur + attrs.pos;
11646        while let Some(attr) = attrs.next() {
11647            let Ok(attr) = attr else { break };
11648            match attr {
11649                OpQstatsGetDumpRequest::Ifindex(val) => {
11650                    if last_off == offset {
11651                        stack.push(("Ifindex", last_off));
11652                        break;
11653                    }
11654                }
11655                OpQstatsGetDumpRequest::Scope(val) => {
11656                    if last_off == offset {
11657                        stack.push(("Scope", last_off));
11658                        break;
11659                    }
11660                }
11661                _ => {}
11662            };
11663            last_off = cur + attrs.pos;
11664        }
11665        if !stack.is_empty() {
11666            stack.push(("OpQstatsGetDumpRequest", cur));
11667        }
11668        (stack, None)
11669    }
11670}
11671#[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"]
11672pub struct PushOpQstatsGetDumpReply<Prev: Rec> {
11673    pub(crate) prev: Option<Prev>,
11674    pub(crate) header_offset: Option<usize>,
11675}
11676impl<Prev: Rec> Rec for PushOpQstatsGetDumpReply<Prev> {
11677    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11678        self.prev.as_mut().unwrap().as_rec_mut()
11679    }
11680    fn as_rec(&self) -> &Vec<u8> {
11681        self.prev.as_ref().unwrap().as_rec()
11682    }
11683}
11684impl<Prev: Rec> PushOpQstatsGetDumpReply<Prev> {
11685    pub fn new(mut prev: Prev) -> Self {
11686        Self::write_header(&mut prev);
11687        Self::new_without_header(prev)
11688    }
11689    fn new_without_header(prev: Prev) -> Self {
11690        Self {
11691            prev: Some(prev),
11692            header_offset: None,
11693        }
11694    }
11695    fn write_header(prev: &mut Prev) {
11696        let mut header = PushBuiltinNfgenmsg::new();
11697        header.set_cmd(12u8);
11698        header.set_version(1u8);
11699        prev.as_rec_mut().extend(header.as_slice());
11700    }
11701    pub fn end_nested(mut self) -> Prev {
11702        let mut prev = self.prev.take().unwrap();
11703        if let Some(header_offset) = &self.header_offset {
11704            finalize_nested_header(prev.as_rec_mut(), *header_offset);
11705        }
11706        prev
11707    }
11708    #[doc = "ifindex of the netdevice to which stats belong."]
11709    pub fn push_ifindex(mut self, value: u32) -> Self {
11710        push_header(self.as_rec_mut(), 1u16, 4 as u16);
11711        self.as_rec_mut().extend(value.to_ne_bytes());
11712        self
11713    }
11714    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11715    pub fn push_queue_type(mut self, value: u32) -> Self {
11716        push_header(self.as_rec_mut(), 2u16, 4 as u16);
11717        self.as_rec_mut().extend(value.to_ne_bytes());
11718        self
11719    }
11720    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11721    pub fn push_queue_id(mut self, value: u32) -> Self {
11722        push_header(self.as_rec_mut(), 3u16, 4 as u16);
11723        self.as_rec_mut().extend(value.to_ne_bytes());
11724        self
11725    }
11726    #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
11727    pub fn push_rx_packets(mut self, value: u32) -> Self {
11728        push_header(self.as_rec_mut(), 8u16, 4 as u16);
11729        self.as_rec_mut().extend(value.to_ne_bytes());
11730        self
11731    }
11732    #[doc = "Successfully received bytes, see `rx-packets`."]
11733    pub fn push_rx_bytes(mut self, value: u32) -> Self {
11734        push_header(self.as_rec_mut(), 9u16, 4 as u16);
11735        self.as_rec_mut().extend(value.to_ne_bytes());
11736        self
11737    }
11738    #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
11739    pub fn push_tx_packets(mut self, value: u32) -> Self {
11740        push_header(self.as_rec_mut(), 10u16, 4 as u16);
11741        self.as_rec_mut().extend(value.to_ne_bytes());
11742        self
11743    }
11744    #[doc = "Successfully sent bytes, see `tx-packets`."]
11745    pub fn push_tx_bytes(mut self, value: u32) -> Self {
11746        push_header(self.as_rec_mut(), 11u16, 4 as u16);
11747        self.as_rec_mut().extend(value.to_ne_bytes());
11748        self
11749    }
11750    #[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\non driver implementation and whether system recovers quickly.\n"]
11751    pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
11752        push_header(self.as_rec_mut(), 12u16, 4 as u16);
11753        self.as_rec_mut().extend(value.to_ne_bytes());
11754        self
11755    }
11756    #[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"]
11757    pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
11758        push_header(self.as_rec_mut(), 13u16, 4 as u16);
11759        self.as_rec_mut().extend(value.to_ne_bytes());
11760        self
11761    }
11762    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11763    pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
11764        push_header(self.as_rec_mut(), 14u16, 4 as u16);
11765        self.as_rec_mut().extend(value.to_ne_bytes());
11766        self
11767    }
11768    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11769    pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
11770        push_header(self.as_rec_mut(), 15u16, 4 as u16);
11771        self.as_rec_mut().extend(value.to_ne_bytes());
11772        self
11773    }
11774    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11775    pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
11776        push_header(self.as_rec_mut(), 16u16, 4 as u16);
11777        self.as_rec_mut().extend(value.to_ne_bytes());
11778        self
11779    }
11780    #[doc = "Number of packets that were not checksummed by device."]
11781    pub fn push_rx_csum_none(mut self, value: u32) -> Self {
11782        push_header(self.as_rec_mut(), 17u16, 4 as u16);
11783        self.as_rec_mut().extend(value.to_ne_bytes());
11784        self
11785    }
11786    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11787    pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
11788        push_header(self.as_rec_mut(), 18u16, 4 as u16);
11789        self.as_rec_mut().extend(value.to_ne_bytes());
11790        self
11791    }
11792    #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
11793    pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
11794        push_header(self.as_rec_mut(), 19u16, 4 as u16);
11795        self.as_rec_mut().extend(value.to_ne_bytes());
11796        self
11797    }
11798    #[doc = "See `rx-hw-gro-packets`."]
11799    pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
11800        push_header(self.as_rec_mut(), 20u16, 4 as u16);
11801        self.as_rec_mut().extend(value.to_ne_bytes());
11802        self
11803    }
11804    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11805    pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
11806        push_header(self.as_rec_mut(), 21u16, 4 as u16);
11807        self.as_rec_mut().extend(value.to_ne_bytes());
11808        self
11809    }
11810    #[doc = "See `rx-hw-gro-wire-packets`."]
11811    pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
11812        push_header(self.as_rec_mut(), 22u16, 4 as u16);
11813        self.as_rec_mut().extend(value.to_ne_bytes());
11814        self
11815    }
11816    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11817    pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11818        push_header(self.as_rec_mut(), 23u16, 4 as u16);
11819        self.as_rec_mut().extend(value.to_ne_bytes());
11820        self
11821    }
11822    #[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"]
11823    pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
11824        push_header(self.as_rec_mut(), 24u16, 4 as u16);
11825        self.as_rec_mut().extend(value.to_ne_bytes());
11826        self
11827    }
11828    #[doc = "Number of packets dropped because they were invalid or malformed."]
11829    pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
11830        push_header(self.as_rec_mut(), 25u16, 4 as u16);
11831        self.as_rec_mut().extend(value.to_ne_bytes());
11832        self
11833    }
11834    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11835    pub fn push_tx_csum_none(mut self, value: u32) -> Self {
11836        push_header(self.as_rec_mut(), 26u16, 4 as u16);
11837        self.as_rec_mut().extend(value.to_ne_bytes());
11838        self
11839    }
11840    #[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"]
11841    pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
11842        push_header(self.as_rec_mut(), 27u16, 4 as u16);
11843        self.as_rec_mut().extend(value.to_ne_bytes());
11844        self
11845    }
11846    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11847    pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
11848        push_header(self.as_rec_mut(), 28u16, 4 as u16);
11849        self.as_rec_mut().extend(value.to_ne_bytes());
11850        self
11851    }
11852    #[doc = "See `tx-hw-gso-packets`."]
11853    pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
11854        push_header(self.as_rec_mut(), 29u16, 4 as u16);
11855        self.as_rec_mut().extend(value.to_ne_bytes());
11856        self
11857    }
11858    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11859    pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
11860        push_header(self.as_rec_mut(), 30u16, 4 as u16);
11861        self.as_rec_mut().extend(value.to_ne_bytes());
11862        self
11863    }
11864    #[doc = "See `tx-hw-gso-wire-packets`."]
11865    pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
11866        push_header(self.as_rec_mut(), 31u16, 4 as u16);
11867        self.as_rec_mut().extend(value.to_ne_bytes());
11868        self
11869    }
11870    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11871    pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11872        push_header(self.as_rec_mut(), 32u16, 4 as u16);
11873        self.as_rec_mut().extend(value.to_ne_bytes());
11874        self
11875    }
11876    #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
11877    pub fn push_tx_stop(mut self, value: u32) -> Self {
11878        push_header(self.as_rec_mut(), 33u16, 4 as u16);
11879        self.as_rec_mut().extend(value.to_ne_bytes());
11880        self
11881    }
11882    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11883    pub fn push_tx_wake(mut self, value: u32) -> Self {
11884        push_header(self.as_rec_mut(), 34u16, 4 as u16);
11885        self.as_rec_mut().extend(value.to_ne_bytes());
11886        self
11887    }
11888}
11889impl<Prev: Rec> Drop for PushOpQstatsGetDumpReply<Prev> {
11890    fn drop(&mut self) {
11891        if let Some(prev) = &mut self.prev {
11892            if let Some(header_offset) = &self.header_offset {
11893                finalize_nested_header(prev.as_rec_mut(), *header_offset);
11894            }
11895        }
11896    }
11897}
11898#[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"]
11899#[derive(Clone)]
11900pub enum OpQstatsGetDumpReply {
11901    #[doc = "ifindex of the netdevice to which stats belong."]
11902    Ifindex(u32),
11903    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11904    QueueType(u32),
11905    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11906    QueueId(u32),
11907    #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
11908    RxPackets(u32),
11909    #[doc = "Successfully received bytes, see `rx-packets`."]
11910    RxBytes(u32),
11911    #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
11912    TxPackets(u32),
11913    #[doc = "Successfully sent bytes, see `tx-packets`."]
11914    TxBytes(u32),
11915    #[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\non driver implementation and whether system recovers quickly.\n"]
11916    RxAllocFail(u32),
11917    #[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"]
11918    RxHwDrops(u32),
11919    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11920    RxHwDropOverruns(u32),
11921    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11922    RxCsumComplete(u32),
11923    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11924    RxCsumUnnecessary(u32),
11925    #[doc = "Number of packets that were not checksummed by device."]
11926    RxCsumNone(u32),
11927    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11928    RxCsumBad(u32),
11929    #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
11930    RxHwGroPackets(u32),
11931    #[doc = "See `rx-hw-gro-packets`."]
11932    RxHwGroBytes(u32),
11933    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11934    RxHwGroWirePackets(u32),
11935    #[doc = "See `rx-hw-gro-wire-packets`."]
11936    RxHwGroWireBytes(u32),
11937    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11938    RxHwDropRatelimits(u32),
11939    #[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"]
11940    TxHwDrops(u32),
11941    #[doc = "Number of packets dropped because they were invalid or malformed."]
11942    TxHwDropErrors(u32),
11943    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11944    TxCsumNone(u32),
11945    #[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"]
11946    TxNeedsCsum(u32),
11947    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11948    TxHwGsoPackets(u32),
11949    #[doc = "See `tx-hw-gso-packets`."]
11950    TxHwGsoBytes(u32),
11951    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11952    TxHwGsoWirePackets(u32),
11953    #[doc = "See `tx-hw-gso-wire-packets`."]
11954    TxHwGsoWireBytes(u32),
11955    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11956    TxHwDropRatelimits(u32),
11957    #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
11958    TxStop(u32),
11959    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11960    TxWake(u32),
11961}
11962impl<'a> IterableOpQstatsGetDumpReply<'a> {
11963    #[doc = "ifindex of the netdevice to which stats belong."]
11964    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11965        let mut iter = self.clone();
11966        iter.pos = 0;
11967        for attr in iter {
11968            if let OpQstatsGetDumpReply::Ifindex(val) = attr? {
11969                return Ok(val);
11970            }
11971        }
11972        Err(ErrorContext::new_missing(
11973            "OpQstatsGetDumpReply",
11974            "Ifindex",
11975            self.orig_loc,
11976            self.buf.as_ptr() as usize,
11977        ))
11978    }
11979    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11980    pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
11981        let mut iter = self.clone();
11982        iter.pos = 0;
11983        for attr in iter {
11984            if let OpQstatsGetDumpReply::QueueType(val) = attr? {
11985                return Ok(val);
11986            }
11987        }
11988        Err(ErrorContext::new_missing(
11989            "OpQstatsGetDumpReply",
11990            "QueueType",
11991            self.orig_loc,
11992            self.buf.as_ptr() as usize,
11993        ))
11994    }
11995    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11996    pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
11997        let mut iter = self.clone();
11998        iter.pos = 0;
11999        for attr in iter {
12000            if let OpQstatsGetDumpReply::QueueId(val) = attr? {
12001                return Ok(val);
12002            }
12003        }
12004        Err(ErrorContext::new_missing(
12005            "OpQstatsGetDumpReply",
12006            "QueueId",
12007            self.orig_loc,
12008            self.buf.as_ptr() as usize,
12009        ))
12010    }
12011    #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
12012    pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
12013        let mut iter = self.clone();
12014        iter.pos = 0;
12015        for attr in iter {
12016            if let OpQstatsGetDumpReply::RxPackets(val) = attr? {
12017                return Ok(val);
12018            }
12019        }
12020        Err(ErrorContext::new_missing(
12021            "OpQstatsGetDumpReply",
12022            "RxPackets",
12023            self.orig_loc,
12024            self.buf.as_ptr() as usize,
12025        ))
12026    }
12027    #[doc = "Successfully received bytes, see `rx-packets`."]
12028    pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
12029        let mut iter = self.clone();
12030        iter.pos = 0;
12031        for attr in iter {
12032            if let OpQstatsGetDumpReply::RxBytes(val) = attr? {
12033                return Ok(val);
12034            }
12035        }
12036        Err(ErrorContext::new_missing(
12037            "OpQstatsGetDumpReply",
12038            "RxBytes",
12039            self.orig_loc,
12040            self.buf.as_ptr() as usize,
12041        ))
12042    }
12043    #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
12044    pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
12045        let mut iter = self.clone();
12046        iter.pos = 0;
12047        for attr in iter {
12048            if let OpQstatsGetDumpReply::TxPackets(val) = attr? {
12049                return Ok(val);
12050            }
12051        }
12052        Err(ErrorContext::new_missing(
12053            "OpQstatsGetDumpReply",
12054            "TxPackets",
12055            self.orig_loc,
12056            self.buf.as_ptr() as usize,
12057        ))
12058    }
12059    #[doc = "Successfully sent bytes, see `tx-packets`."]
12060    pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
12061        let mut iter = self.clone();
12062        iter.pos = 0;
12063        for attr in iter {
12064            if let OpQstatsGetDumpReply::TxBytes(val) = attr? {
12065                return Ok(val);
12066            }
12067        }
12068        Err(ErrorContext::new_missing(
12069            "OpQstatsGetDumpReply",
12070            "TxBytes",
12071            self.orig_loc,
12072            self.buf.as_ptr() as usize,
12073        ))
12074    }
12075    #[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\non driver implementation and whether system recovers quickly.\n"]
12076    pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
12077        let mut iter = self.clone();
12078        iter.pos = 0;
12079        for attr in iter {
12080            if let OpQstatsGetDumpReply::RxAllocFail(val) = attr? {
12081                return Ok(val);
12082            }
12083        }
12084        Err(ErrorContext::new_missing(
12085            "OpQstatsGetDumpReply",
12086            "RxAllocFail",
12087            self.orig_loc,
12088            self.buf.as_ptr() as usize,
12089        ))
12090    }
12091    #[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"]
12092    pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
12093        let mut iter = self.clone();
12094        iter.pos = 0;
12095        for attr in iter {
12096            if let OpQstatsGetDumpReply::RxHwDrops(val) = attr? {
12097                return Ok(val);
12098            }
12099        }
12100        Err(ErrorContext::new_missing(
12101            "OpQstatsGetDumpReply",
12102            "RxHwDrops",
12103            self.orig_loc,
12104            self.buf.as_ptr() as usize,
12105        ))
12106    }
12107    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
12108    pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
12109        let mut iter = self.clone();
12110        iter.pos = 0;
12111        for attr in iter {
12112            if let OpQstatsGetDumpReply::RxHwDropOverruns(val) = attr? {
12113                return Ok(val);
12114            }
12115        }
12116        Err(ErrorContext::new_missing(
12117            "OpQstatsGetDumpReply",
12118            "RxHwDropOverruns",
12119            self.orig_loc,
12120            self.buf.as_ptr() as usize,
12121        ))
12122    }
12123    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
12124    pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
12125        let mut iter = self.clone();
12126        iter.pos = 0;
12127        for attr in iter {
12128            if let OpQstatsGetDumpReply::RxCsumComplete(val) = attr? {
12129                return Ok(val);
12130            }
12131        }
12132        Err(ErrorContext::new_missing(
12133            "OpQstatsGetDumpReply",
12134            "RxCsumComplete",
12135            self.orig_loc,
12136            self.buf.as_ptr() as usize,
12137        ))
12138    }
12139    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
12140    pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
12141        let mut iter = self.clone();
12142        iter.pos = 0;
12143        for attr in iter {
12144            if let OpQstatsGetDumpReply::RxCsumUnnecessary(val) = attr? {
12145                return Ok(val);
12146            }
12147        }
12148        Err(ErrorContext::new_missing(
12149            "OpQstatsGetDumpReply",
12150            "RxCsumUnnecessary",
12151            self.orig_loc,
12152            self.buf.as_ptr() as usize,
12153        ))
12154    }
12155    #[doc = "Number of packets that were not checksummed by device."]
12156    pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
12157        let mut iter = self.clone();
12158        iter.pos = 0;
12159        for attr in iter {
12160            if let OpQstatsGetDumpReply::RxCsumNone(val) = attr? {
12161                return Ok(val);
12162            }
12163        }
12164        Err(ErrorContext::new_missing(
12165            "OpQstatsGetDumpReply",
12166            "RxCsumNone",
12167            self.orig_loc,
12168            self.buf.as_ptr() as usize,
12169        ))
12170    }
12171    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
12172    pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
12173        let mut iter = self.clone();
12174        iter.pos = 0;
12175        for attr in iter {
12176            if let OpQstatsGetDumpReply::RxCsumBad(val) = attr? {
12177                return Ok(val);
12178            }
12179        }
12180        Err(ErrorContext::new_missing(
12181            "OpQstatsGetDumpReply",
12182            "RxCsumBad",
12183            self.orig_loc,
12184            self.buf.as_ptr() as usize,
12185        ))
12186    }
12187    #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
12188    pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
12189        let mut iter = self.clone();
12190        iter.pos = 0;
12191        for attr in iter {
12192            if let OpQstatsGetDumpReply::RxHwGroPackets(val) = attr? {
12193                return Ok(val);
12194            }
12195        }
12196        Err(ErrorContext::new_missing(
12197            "OpQstatsGetDumpReply",
12198            "RxHwGroPackets",
12199            self.orig_loc,
12200            self.buf.as_ptr() as usize,
12201        ))
12202    }
12203    #[doc = "See `rx-hw-gro-packets`."]
12204    pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
12205        let mut iter = self.clone();
12206        iter.pos = 0;
12207        for attr in iter {
12208            if let OpQstatsGetDumpReply::RxHwGroBytes(val) = attr? {
12209                return Ok(val);
12210            }
12211        }
12212        Err(ErrorContext::new_missing(
12213            "OpQstatsGetDumpReply",
12214            "RxHwGroBytes",
12215            self.orig_loc,
12216            self.buf.as_ptr() as usize,
12217        ))
12218    }
12219    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
12220    pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
12221        let mut iter = self.clone();
12222        iter.pos = 0;
12223        for attr in iter {
12224            if let OpQstatsGetDumpReply::RxHwGroWirePackets(val) = attr? {
12225                return Ok(val);
12226            }
12227        }
12228        Err(ErrorContext::new_missing(
12229            "OpQstatsGetDumpReply",
12230            "RxHwGroWirePackets",
12231            self.orig_loc,
12232            self.buf.as_ptr() as usize,
12233        ))
12234    }
12235    #[doc = "See `rx-hw-gro-wire-packets`."]
12236    pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
12237        let mut iter = self.clone();
12238        iter.pos = 0;
12239        for attr in iter {
12240            if let OpQstatsGetDumpReply::RxHwGroWireBytes(val) = attr? {
12241                return Ok(val);
12242            }
12243        }
12244        Err(ErrorContext::new_missing(
12245            "OpQstatsGetDumpReply",
12246            "RxHwGroWireBytes",
12247            self.orig_loc,
12248            self.buf.as_ptr() as usize,
12249        ))
12250    }
12251    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
12252    pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12253        let mut iter = self.clone();
12254        iter.pos = 0;
12255        for attr in iter {
12256            if let OpQstatsGetDumpReply::RxHwDropRatelimits(val) = attr? {
12257                return Ok(val);
12258            }
12259        }
12260        Err(ErrorContext::new_missing(
12261            "OpQstatsGetDumpReply",
12262            "RxHwDropRatelimits",
12263            self.orig_loc,
12264            self.buf.as_ptr() as usize,
12265        ))
12266    }
12267    #[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"]
12268    pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
12269        let mut iter = self.clone();
12270        iter.pos = 0;
12271        for attr in iter {
12272            if let OpQstatsGetDumpReply::TxHwDrops(val) = attr? {
12273                return Ok(val);
12274            }
12275        }
12276        Err(ErrorContext::new_missing(
12277            "OpQstatsGetDumpReply",
12278            "TxHwDrops",
12279            self.orig_loc,
12280            self.buf.as_ptr() as usize,
12281        ))
12282    }
12283    #[doc = "Number of packets dropped because they were invalid or malformed."]
12284    pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
12285        let mut iter = self.clone();
12286        iter.pos = 0;
12287        for attr in iter {
12288            if let OpQstatsGetDumpReply::TxHwDropErrors(val) = attr? {
12289                return Ok(val);
12290            }
12291        }
12292        Err(ErrorContext::new_missing(
12293            "OpQstatsGetDumpReply",
12294            "TxHwDropErrors",
12295            self.orig_loc,
12296            self.buf.as_ptr() as usize,
12297        ))
12298    }
12299    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
12300    pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
12301        let mut iter = self.clone();
12302        iter.pos = 0;
12303        for attr in iter {
12304            if let OpQstatsGetDumpReply::TxCsumNone(val) = attr? {
12305                return Ok(val);
12306            }
12307        }
12308        Err(ErrorContext::new_missing(
12309            "OpQstatsGetDumpReply",
12310            "TxCsumNone",
12311            self.orig_loc,
12312            self.buf.as_ptr() as usize,
12313        ))
12314    }
12315    #[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"]
12316    pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
12317        let mut iter = self.clone();
12318        iter.pos = 0;
12319        for attr in iter {
12320            if let OpQstatsGetDumpReply::TxNeedsCsum(val) = attr? {
12321                return Ok(val);
12322            }
12323        }
12324        Err(ErrorContext::new_missing(
12325            "OpQstatsGetDumpReply",
12326            "TxNeedsCsum",
12327            self.orig_loc,
12328            self.buf.as_ptr() as usize,
12329        ))
12330    }
12331    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
12332    pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
12333        let mut iter = self.clone();
12334        iter.pos = 0;
12335        for attr in iter {
12336            if let OpQstatsGetDumpReply::TxHwGsoPackets(val) = attr? {
12337                return Ok(val);
12338            }
12339        }
12340        Err(ErrorContext::new_missing(
12341            "OpQstatsGetDumpReply",
12342            "TxHwGsoPackets",
12343            self.orig_loc,
12344            self.buf.as_ptr() as usize,
12345        ))
12346    }
12347    #[doc = "See `tx-hw-gso-packets`."]
12348    pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
12349        let mut iter = self.clone();
12350        iter.pos = 0;
12351        for attr in iter {
12352            if let OpQstatsGetDumpReply::TxHwGsoBytes(val) = attr? {
12353                return Ok(val);
12354            }
12355        }
12356        Err(ErrorContext::new_missing(
12357            "OpQstatsGetDumpReply",
12358            "TxHwGsoBytes",
12359            self.orig_loc,
12360            self.buf.as_ptr() as usize,
12361        ))
12362    }
12363    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
12364    pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
12365        let mut iter = self.clone();
12366        iter.pos = 0;
12367        for attr in iter {
12368            if let OpQstatsGetDumpReply::TxHwGsoWirePackets(val) = attr? {
12369                return Ok(val);
12370            }
12371        }
12372        Err(ErrorContext::new_missing(
12373            "OpQstatsGetDumpReply",
12374            "TxHwGsoWirePackets",
12375            self.orig_loc,
12376            self.buf.as_ptr() as usize,
12377        ))
12378    }
12379    #[doc = "See `tx-hw-gso-wire-packets`."]
12380    pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
12381        let mut iter = self.clone();
12382        iter.pos = 0;
12383        for attr in iter {
12384            if let OpQstatsGetDumpReply::TxHwGsoWireBytes(val) = attr? {
12385                return Ok(val);
12386            }
12387        }
12388        Err(ErrorContext::new_missing(
12389            "OpQstatsGetDumpReply",
12390            "TxHwGsoWireBytes",
12391            self.orig_loc,
12392            self.buf.as_ptr() as usize,
12393        ))
12394    }
12395    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
12396    pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12397        let mut iter = self.clone();
12398        iter.pos = 0;
12399        for attr in iter {
12400            if let OpQstatsGetDumpReply::TxHwDropRatelimits(val) = attr? {
12401                return Ok(val);
12402            }
12403        }
12404        Err(ErrorContext::new_missing(
12405            "OpQstatsGetDumpReply",
12406            "TxHwDropRatelimits",
12407            self.orig_loc,
12408            self.buf.as_ptr() as usize,
12409        ))
12410    }
12411    #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
12412    pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
12413        let mut iter = self.clone();
12414        iter.pos = 0;
12415        for attr in iter {
12416            if let OpQstatsGetDumpReply::TxStop(val) = attr? {
12417                return Ok(val);
12418            }
12419        }
12420        Err(ErrorContext::new_missing(
12421            "OpQstatsGetDumpReply",
12422            "TxStop",
12423            self.orig_loc,
12424            self.buf.as_ptr() as usize,
12425        ))
12426    }
12427    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
12428    pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
12429        let mut iter = self.clone();
12430        iter.pos = 0;
12431        for attr in iter {
12432            if let OpQstatsGetDumpReply::TxWake(val) = attr? {
12433                return Ok(val);
12434            }
12435        }
12436        Err(ErrorContext::new_missing(
12437            "OpQstatsGetDumpReply",
12438            "TxWake",
12439            self.orig_loc,
12440            self.buf.as_ptr() as usize,
12441        ))
12442    }
12443}
12444impl OpQstatsGetDumpReply {
12445    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpReply<'a> {
12446        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
12447        IterableOpQstatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
12448    }
12449    fn attr_from_type(r#type: u16) -> Option<&'static str> {
12450        Qstats::attr_from_type(r#type)
12451    }
12452}
12453#[derive(Clone, Copy, Default)]
12454pub struct IterableOpQstatsGetDumpReply<'a> {
12455    buf: &'a [u8],
12456    pos: usize,
12457    orig_loc: usize,
12458}
12459impl<'a> IterableOpQstatsGetDumpReply<'a> {
12460    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
12461        Self {
12462            buf,
12463            pos: 0,
12464            orig_loc,
12465        }
12466    }
12467    pub fn get_buf(&self) -> &'a [u8] {
12468        self.buf
12469    }
12470}
12471impl<'a> Iterator for IterableOpQstatsGetDumpReply<'a> {
12472    type Item = Result<OpQstatsGetDumpReply, ErrorContext>;
12473    fn next(&mut self) -> Option<Self::Item> {
12474        let pos = self.pos;
12475        let mut r#type;
12476        loop {
12477            r#type = None;
12478            if self.buf.len() == self.pos {
12479                return None;
12480            }
12481            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
12482                break;
12483            };
12484            r#type = Some(header.r#type);
12485            let res = match header.r#type {
12486                1u16 => OpQstatsGetDumpReply::Ifindex({
12487                    let res = parse_u32(next);
12488                    let Some(val) = res else { break };
12489                    val
12490                }),
12491                2u16 => OpQstatsGetDumpReply::QueueType({
12492                    let res = parse_u32(next);
12493                    let Some(val) = res else { break };
12494                    val
12495                }),
12496                3u16 => OpQstatsGetDumpReply::QueueId({
12497                    let res = parse_u32(next);
12498                    let Some(val) = res else { break };
12499                    val
12500                }),
12501                8u16 => OpQstatsGetDumpReply::RxPackets({
12502                    let res = parse_u32(next);
12503                    let Some(val) = res else { break };
12504                    val
12505                }),
12506                9u16 => OpQstatsGetDumpReply::RxBytes({
12507                    let res = parse_u32(next);
12508                    let Some(val) = res else { break };
12509                    val
12510                }),
12511                10u16 => OpQstatsGetDumpReply::TxPackets({
12512                    let res = parse_u32(next);
12513                    let Some(val) = res else { break };
12514                    val
12515                }),
12516                11u16 => OpQstatsGetDumpReply::TxBytes({
12517                    let res = parse_u32(next);
12518                    let Some(val) = res else { break };
12519                    val
12520                }),
12521                12u16 => OpQstatsGetDumpReply::RxAllocFail({
12522                    let res = parse_u32(next);
12523                    let Some(val) = res else { break };
12524                    val
12525                }),
12526                13u16 => OpQstatsGetDumpReply::RxHwDrops({
12527                    let res = parse_u32(next);
12528                    let Some(val) = res else { break };
12529                    val
12530                }),
12531                14u16 => OpQstatsGetDumpReply::RxHwDropOverruns({
12532                    let res = parse_u32(next);
12533                    let Some(val) = res else { break };
12534                    val
12535                }),
12536                15u16 => OpQstatsGetDumpReply::RxCsumComplete({
12537                    let res = parse_u32(next);
12538                    let Some(val) = res else { break };
12539                    val
12540                }),
12541                16u16 => OpQstatsGetDumpReply::RxCsumUnnecessary({
12542                    let res = parse_u32(next);
12543                    let Some(val) = res else { break };
12544                    val
12545                }),
12546                17u16 => OpQstatsGetDumpReply::RxCsumNone({
12547                    let res = parse_u32(next);
12548                    let Some(val) = res else { break };
12549                    val
12550                }),
12551                18u16 => OpQstatsGetDumpReply::RxCsumBad({
12552                    let res = parse_u32(next);
12553                    let Some(val) = res else { break };
12554                    val
12555                }),
12556                19u16 => OpQstatsGetDumpReply::RxHwGroPackets({
12557                    let res = parse_u32(next);
12558                    let Some(val) = res else { break };
12559                    val
12560                }),
12561                20u16 => OpQstatsGetDumpReply::RxHwGroBytes({
12562                    let res = parse_u32(next);
12563                    let Some(val) = res else { break };
12564                    val
12565                }),
12566                21u16 => OpQstatsGetDumpReply::RxHwGroWirePackets({
12567                    let res = parse_u32(next);
12568                    let Some(val) = res else { break };
12569                    val
12570                }),
12571                22u16 => OpQstatsGetDumpReply::RxHwGroWireBytes({
12572                    let res = parse_u32(next);
12573                    let Some(val) = res else { break };
12574                    val
12575                }),
12576                23u16 => OpQstatsGetDumpReply::RxHwDropRatelimits({
12577                    let res = parse_u32(next);
12578                    let Some(val) = res else { break };
12579                    val
12580                }),
12581                24u16 => OpQstatsGetDumpReply::TxHwDrops({
12582                    let res = parse_u32(next);
12583                    let Some(val) = res else { break };
12584                    val
12585                }),
12586                25u16 => OpQstatsGetDumpReply::TxHwDropErrors({
12587                    let res = parse_u32(next);
12588                    let Some(val) = res else { break };
12589                    val
12590                }),
12591                26u16 => OpQstatsGetDumpReply::TxCsumNone({
12592                    let res = parse_u32(next);
12593                    let Some(val) = res else { break };
12594                    val
12595                }),
12596                27u16 => OpQstatsGetDumpReply::TxNeedsCsum({
12597                    let res = parse_u32(next);
12598                    let Some(val) = res else { break };
12599                    val
12600                }),
12601                28u16 => OpQstatsGetDumpReply::TxHwGsoPackets({
12602                    let res = parse_u32(next);
12603                    let Some(val) = res else { break };
12604                    val
12605                }),
12606                29u16 => OpQstatsGetDumpReply::TxHwGsoBytes({
12607                    let res = parse_u32(next);
12608                    let Some(val) = res else { break };
12609                    val
12610                }),
12611                30u16 => OpQstatsGetDumpReply::TxHwGsoWirePackets({
12612                    let res = parse_u32(next);
12613                    let Some(val) = res else { break };
12614                    val
12615                }),
12616                31u16 => OpQstatsGetDumpReply::TxHwGsoWireBytes({
12617                    let res = parse_u32(next);
12618                    let Some(val) = res else { break };
12619                    val
12620                }),
12621                32u16 => OpQstatsGetDumpReply::TxHwDropRatelimits({
12622                    let res = parse_u32(next);
12623                    let Some(val) = res else { break };
12624                    val
12625                }),
12626                33u16 => OpQstatsGetDumpReply::TxStop({
12627                    let res = parse_u32(next);
12628                    let Some(val) = res else { break };
12629                    val
12630                }),
12631                34u16 => OpQstatsGetDumpReply::TxWake({
12632                    let res = parse_u32(next);
12633                    let Some(val) = res else { break };
12634                    val
12635                }),
12636                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
12637                n => continue,
12638            };
12639            return Some(Ok(res));
12640        }
12641        Some(Err(ErrorContext::new(
12642            "OpQstatsGetDumpReply",
12643            r#type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12644            self.orig_loc,
12645            self.buf.as_ptr().wrapping_add(pos) as usize,
12646        )))
12647    }
12648}
12649impl std::fmt::Debug for IterableOpQstatsGetDumpReply<'_> {
12650    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12651        let mut fmt = f.debug_struct("OpQstatsGetDumpReply");
12652        for attr in self.clone() {
12653            let attr = match attr {
12654                Ok(a) => a,
12655                Err(err) => {
12656                    fmt.finish()?;
12657                    f.write_str("Err(")?;
12658                    err.fmt(f)?;
12659                    return f.write_str(")");
12660                }
12661            };
12662            match attr {
12663                OpQstatsGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
12664                OpQstatsGetDumpReply::QueueType(val) => {
12665                    fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
12666                }
12667                OpQstatsGetDumpReply::QueueId(val) => fmt.field("QueueId", &val),
12668                OpQstatsGetDumpReply::RxPackets(val) => fmt.field("RxPackets", &val),
12669                OpQstatsGetDumpReply::RxBytes(val) => fmt.field("RxBytes", &val),
12670                OpQstatsGetDumpReply::TxPackets(val) => fmt.field("TxPackets", &val),
12671                OpQstatsGetDumpReply::TxBytes(val) => fmt.field("TxBytes", &val),
12672                OpQstatsGetDumpReply::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
12673                OpQstatsGetDumpReply::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
12674                OpQstatsGetDumpReply::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
12675                OpQstatsGetDumpReply::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
12676                OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12677                    fmt.field("RxCsumUnnecessary", &val)
12678                }
12679                OpQstatsGetDumpReply::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
12680                OpQstatsGetDumpReply::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
12681                OpQstatsGetDumpReply::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
12682                OpQstatsGetDumpReply::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
12683                OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12684                    fmt.field("RxHwGroWirePackets", &val)
12685                }
12686                OpQstatsGetDumpReply::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
12687                OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12688                    fmt.field("RxHwDropRatelimits", &val)
12689                }
12690                OpQstatsGetDumpReply::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
12691                OpQstatsGetDumpReply::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
12692                OpQstatsGetDumpReply::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
12693                OpQstatsGetDumpReply::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
12694                OpQstatsGetDumpReply::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
12695                OpQstatsGetDumpReply::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
12696                OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12697                    fmt.field("TxHwGsoWirePackets", &val)
12698                }
12699                OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
12700                OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12701                    fmt.field("TxHwDropRatelimits", &val)
12702                }
12703                OpQstatsGetDumpReply::TxStop(val) => fmt.field("TxStop", &val),
12704                OpQstatsGetDumpReply::TxWake(val) => fmt.field("TxWake", &val),
12705            };
12706        }
12707        fmt.finish()
12708    }
12709}
12710impl IterableOpQstatsGetDumpReply<'_> {
12711    pub fn lookup_attr(
12712        &self,
12713        offset: usize,
12714        missing_type: Option<u16>,
12715    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12716        let mut stack = Vec::new();
12717        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
12718        if cur == offset + PushBuiltinNfgenmsg::len() {
12719            stack.push(("OpQstatsGetDumpReply", offset));
12720            return (
12721                stack,
12722                missing_type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12723            );
12724        }
12725        if cur > offset || cur + self.buf.len() < offset {
12726            return (stack, None);
12727        }
12728        let mut attrs = self.clone();
12729        let mut last_off = cur + attrs.pos;
12730        while let Some(attr) = attrs.next() {
12731            let Ok(attr) = attr else { break };
12732            match attr {
12733                OpQstatsGetDumpReply::Ifindex(val) => {
12734                    if last_off == offset {
12735                        stack.push(("Ifindex", last_off));
12736                        break;
12737                    }
12738                }
12739                OpQstatsGetDumpReply::QueueType(val) => {
12740                    if last_off == offset {
12741                        stack.push(("QueueType", last_off));
12742                        break;
12743                    }
12744                }
12745                OpQstatsGetDumpReply::QueueId(val) => {
12746                    if last_off == offset {
12747                        stack.push(("QueueId", last_off));
12748                        break;
12749                    }
12750                }
12751                OpQstatsGetDumpReply::RxPackets(val) => {
12752                    if last_off == offset {
12753                        stack.push(("RxPackets", last_off));
12754                        break;
12755                    }
12756                }
12757                OpQstatsGetDumpReply::RxBytes(val) => {
12758                    if last_off == offset {
12759                        stack.push(("RxBytes", last_off));
12760                        break;
12761                    }
12762                }
12763                OpQstatsGetDumpReply::TxPackets(val) => {
12764                    if last_off == offset {
12765                        stack.push(("TxPackets", last_off));
12766                        break;
12767                    }
12768                }
12769                OpQstatsGetDumpReply::TxBytes(val) => {
12770                    if last_off == offset {
12771                        stack.push(("TxBytes", last_off));
12772                        break;
12773                    }
12774                }
12775                OpQstatsGetDumpReply::RxAllocFail(val) => {
12776                    if last_off == offset {
12777                        stack.push(("RxAllocFail", last_off));
12778                        break;
12779                    }
12780                }
12781                OpQstatsGetDumpReply::RxHwDrops(val) => {
12782                    if last_off == offset {
12783                        stack.push(("RxHwDrops", last_off));
12784                        break;
12785                    }
12786                }
12787                OpQstatsGetDumpReply::RxHwDropOverruns(val) => {
12788                    if last_off == offset {
12789                        stack.push(("RxHwDropOverruns", last_off));
12790                        break;
12791                    }
12792                }
12793                OpQstatsGetDumpReply::RxCsumComplete(val) => {
12794                    if last_off == offset {
12795                        stack.push(("RxCsumComplete", last_off));
12796                        break;
12797                    }
12798                }
12799                OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12800                    if last_off == offset {
12801                        stack.push(("RxCsumUnnecessary", last_off));
12802                        break;
12803                    }
12804                }
12805                OpQstatsGetDumpReply::RxCsumNone(val) => {
12806                    if last_off == offset {
12807                        stack.push(("RxCsumNone", last_off));
12808                        break;
12809                    }
12810                }
12811                OpQstatsGetDumpReply::RxCsumBad(val) => {
12812                    if last_off == offset {
12813                        stack.push(("RxCsumBad", last_off));
12814                        break;
12815                    }
12816                }
12817                OpQstatsGetDumpReply::RxHwGroPackets(val) => {
12818                    if last_off == offset {
12819                        stack.push(("RxHwGroPackets", last_off));
12820                        break;
12821                    }
12822                }
12823                OpQstatsGetDumpReply::RxHwGroBytes(val) => {
12824                    if last_off == offset {
12825                        stack.push(("RxHwGroBytes", last_off));
12826                        break;
12827                    }
12828                }
12829                OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12830                    if last_off == offset {
12831                        stack.push(("RxHwGroWirePackets", last_off));
12832                        break;
12833                    }
12834                }
12835                OpQstatsGetDumpReply::RxHwGroWireBytes(val) => {
12836                    if last_off == offset {
12837                        stack.push(("RxHwGroWireBytes", last_off));
12838                        break;
12839                    }
12840                }
12841                OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12842                    if last_off == offset {
12843                        stack.push(("RxHwDropRatelimits", last_off));
12844                        break;
12845                    }
12846                }
12847                OpQstatsGetDumpReply::TxHwDrops(val) => {
12848                    if last_off == offset {
12849                        stack.push(("TxHwDrops", last_off));
12850                        break;
12851                    }
12852                }
12853                OpQstatsGetDumpReply::TxHwDropErrors(val) => {
12854                    if last_off == offset {
12855                        stack.push(("TxHwDropErrors", last_off));
12856                        break;
12857                    }
12858                }
12859                OpQstatsGetDumpReply::TxCsumNone(val) => {
12860                    if last_off == offset {
12861                        stack.push(("TxCsumNone", last_off));
12862                        break;
12863                    }
12864                }
12865                OpQstatsGetDumpReply::TxNeedsCsum(val) => {
12866                    if last_off == offset {
12867                        stack.push(("TxNeedsCsum", last_off));
12868                        break;
12869                    }
12870                }
12871                OpQstatsGetDumpReply::TxHwGsoPackets(val) => {
12872                    if last_off == offset {
12873                        stack.push(("TxHwGsoPackets", last_off));
12874                        break;
12875                    }
12876                }
12877                OpQstatsGetDumpReply::TxHwGsoBytes(val) => {
12878                    if last_off == offset {
12879                        stack.push(("TxHwGsoBytes", last_off));
12880                        break;
12881                    }
12882                }
12883                OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12884                    if last_off == offset {
12885                        stack.push(("TxHwGsoWirePackets", last_off));
12886                        break;
12887                    }
12888                }
12889                OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => {
12890                    if last_off == offset {
12891                        stack.push(("TxHwGsoWireBytes", last_off));
12892                        break;
12893                    }
12894                }
12895                OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12896                    if last_off == offset {
12897                        stack.push(("TxHwDropRatelimits", last_off));
12898                        break;
12899                    }
12900                }
12901                OpQstatsGetDumpReply::TxStop(val) => {
12902                    if last_off == offset {
12903                        stack.push(("TxStop", last_off));
12904                        break;
12905                    }
12906                }
12907                OpQstatsGetDumpReply::TxWake(val) => {
12908                    if last_off == offset {
12909                        stack.push(("TxWake", last_off));
12910                        break;
12911                    }
12912                }
12913                _ => {}
12914            };
12915            last_off = cur + attrs.pos;
12916        }
12917        if !stack.is_empty() {
12918            stack.push(("OpQstatsGetDumpReply", cur));
12919        }
12920        (stack, None)
12921    }
12922}
12923#[derive(Debug)]
12924pub struct RequestOpQstatsGetDumpRequest<'r> {
12925    request: Request<'r>,
12926}
12927impl<'r> RequestOpQstatsGetDumpRequest<'r> {
12928    pub fn new(mut request: Request<'r>) -> Self {
12929        PushOpQstatsGetDumpRequest::write_header(&mut request.buf_mut());
12930        Self {
12931            request: request.set_dump(),
12932        }
12933    }
12934    pub fn encode(&mut self) -> PushOpQstatsGetDumpRequest<&mut Vec<u8>> {
12935        PushOpQstatsGetDumpRequest::new_without_header(self.request.buf_mut())
12936    }
12937    pub fn into_encoder(self) -> PushOpQstatsGetDumpRequest<RequestBuf<'r>> {
12938        PushOpQstatsGetDumpRequest::new_without_header(self.request.buf)
12939    }
12940    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpQstatsGetDumpRequest<'buf> {
12941        OpQstatsGetDumpRequest::new(buf)
12942    }
12943}
12944impl NetlinkRequest for RequestOpQstatsGetDumpRequest<'_> {
12945    fn protocol(&self) -> Protocol {
12946        Protocol::Generic("netdev".as_bytes())
12947    }
12948    fn flags(&self) -> u16 {
12949        self.request.flags
12950    }
12951    fn payload(&self) -> &[u8] {
12952        self.request.buf()
12953    }
12954    type ReplyType<'buf> = IterableOpQstatsGetDumpReply<'buf>;
12955    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
12956        OpQstatsGetDumpReply::new(buf)
12957    }
12958    fn lookup(
12959        buf: &[u8],
12960        offset: usize,
12961        missing_type: Option<u16>,
12962    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12963        OpQstatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
12964    }
12965}
12966#[doc = "Bind dmabuf to netdev"]
12967pub struct PushOpBindRxDoRequest<Prev: Rec> {
12968    pub(crate) prev: Option<Prev>,
12969    pub(crate) header_offset: Option<usize>,
12970}
12971impl<Prev: Rec> Rec for PushOpBindRxDoRequest<Prev> {
12972    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
12973        self.prev.as_mut().unwrap().as_rec_mut()
12974    }
12975    fn as_rec(&self) -> &Vec<u8> {
12976        self.prev.as_ref().unwrap().as_rec()
12977    }
12978}
12979impl<Prev: Rec> PushOpBindRxDoRequest<Prev> {
12980    pub fn new(mut prev: Prev) -> Self {
12981        Self::write_header(&mut prev);
12982        Self::new_without_header(prev)
12983    }
12984    fn new_without_header(prev: Prev) -> Self {
12985        Self {
12986            prev: Some(prev),
12987            header_offset: None,
12988        }
12989    }
12990    fn write_header(prev: &mut Prev) {
12991        let mut header = PushBuiltinNfgenmsg::new();
12992        header.set_cmd(13u8);
12993        header.set_version(1u8);
12994        prev.as_rec_mut().extend(header.as_slice());
12995    }
12996    pub fn end_nested(mut self) -> Prev {
12997        let mut prev = self.prev.take().unwrap();
12998        if let Some(header_offset) = &self.header_offset {
12999            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13000        }
13001        prev
13002    }
13003    #[doc = "netdev ifindex to bind the dmabuf to."]
13004    pub fn push_ifindex(mut self, value: u32) -> Self {
13005        push_header(self.as_rec_mut(), 1u16, 4 as u16);
13006        self.as_rec_mut().extend(value.to_ne_bytes());
13007        self
13008    }
13009    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
13010    pub fn nested_queues(mut self) -> PushQueueId<Self> {
13011        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
13012        PushQueueId {
13013            prev: Some(self),
13014            header_offset: Some(header_offset),
13015        }
13016    }
13017    #[doc = "dmabuf file descriptor to bind."]
13018    pub fn push_fd(mut self, value: u32) -> Self {
13019        push_header(self.as_rec_mut(), 3u16, 4 as u16);
13020        self.as_rec_mut().extend(value.to_ne_bytes());
13021        self
13022    }
13023}
13024impl<Prev: Rec> Drop for PushOpBindRxDoRequest<Prev> {
13025    fn drop(&mut self) {
13026        if let Some(prev) = &mut self.prev {
13027            if let Some(header_offset) = &self.header_offset {
13028                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13029            }
13030        }
13031    }
13032}
13033#[doc = "Bind dmabuf to netdev"]
13034#[derive(Clone)]
13035pub enum OpBindRxDoRequest<'a> {
13036    #[doc = "netdev ifindex to bind the dmabuf to."]
13037    Ifindex(u32),
13038    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
13039    Queues(IterableQueueId<'a>),
13040    #[doc = "dmabuf file descriptor to bind."]
13041    Fd(u32),
13042}
13043impl<'a> IterableOpBindRxDoRequest<'a> {
13044    #[doc = "netdev ifindex to bind the dmabuf to."]
13045    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
13046        let mut iter = self.clone();
13047        iter.pos = 0;
13048        for attr in iter {
13049            if let OpBindRxDoRequest::Ifindex(val) = attr? {
13050                return Ok(val);
13051            }
13052        }
13053        Err(ErrorContext::new_missing(
13054            "OpBindRxDoRequest",
13055            "Ifindex",
13056            self.orig_loc,
13057            self.buf.as_ptr() as usize,
13058        ))
13059    }
13060    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
13061    pub fn get_queues(
13062        &self,
13063    ) -> MultiAttrIterable<Self, OpBindRxDoRequest<'a>, IterableQueueId<'a>> {
13064        MultiAttrIterable::new(self.clone(), |variant| {
13065            if let OpBindRxDoRequest::Queues(val) = variant {
13066                Some(val)
13067            } else {
13068                None
13069            }
13070        })
13071    }
13072    #[doc = "dmabuf file descriptor to bind."]
13073    pub fn get_fd(&self) -> Result<u32, ErrorContext> {
13074        let mut iter = self.clone();
13075        iter.pos = 0;
13076        for attr in iter {
13077            if let OpBindRxDoRequest::Fd(val) = attr? {
13078                return Ok(val);
13079            }
13080        }
13081        Err(ErrorContext::new_missing(
13082            "OpBindRxDoRequest",
13083            "Fd",
13084            self.orig_loc,
13085            self.buf.as_ptr() as usize,
13086        ))
13087    }
13088}
13089impl OpBindRxDoRequest<'_> {
13090    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoRequest<'a> {
13091        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13092        IterableOpBindRxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13093    }
13094    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13095        Dmabuf::attr_from_type(r#type)
13096    }
13097}
13098#[derive(Clone, Copy, Default)]
13099pub struct IterableOpBindRxDoRequest<'a> {
13100    buf: &'a [u8],
13101    pos: usize,
13102    orig_loc: usize,
13103}
13104impl<'a> IterableOpBindRxDoRequest<'a> {
13105    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13106        Self {
13107            buf,
13108            pos: 0,
13109            orig_loc,
13110        }
13111    }
13112    pub fn get_buf(&self) -> &'a [u8] {
13113        self.buf
13114    }
13115}
13116impl<'a> Iterator for IterableOpBindRxDoRequest<'a> {
13117    type Item = Result<OpBindRxDoRequest<'a>, ErrorContext>;
13118    fn next(&mut self) -> Option<Self::Item> {
13119        let pos = self.pos;
13120        let mut r#type;
13121        loop {
13122            r#type = None;
13123            if self.buf.len() == self.pos {
13124                return None;
13125            }
13126            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13127                break;
13128            };
13129            r#type = Some(header.r#type);
13130            let res = match header.r#type {
13131                1u16 => OpBindRxDoRequest::Ifindex({
13132                    let res = parse_u32(next);
13133                    let Some(val) = res else { break };
13134                    val
13135                }),
13136                2u16 => OpBindRxDoRequest::Queues({
13137                    let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
13138                    let Some(val) = res else { break };
13139                    val
13140                }),
13141                3u16 => OpBindRxDoRequest::Fd({
13142                    let res = parse_u32(next);
13143                    let Some(val) = res else { break };
13144                    val
13145                }),
13146                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13147                n => continue,
13148            };
13149            return Some(Ok(res));
13150        }
13151        Some(Err(ErrorContext::new(
13152            "OpBindRxDoRequest",
13153            r#type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13154            self.orig_loc,
13155            self.buf.as_ptr().wrapping_add(pos) as usize,
13156        )))
13157    }
13158}
13159impl<'a> std::fmt::Debug for IterableOpBindRxDoRequest<'_> {
13160    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13161        let mut fmt = f.debug_struct("OpBindRxDoRequest");
13162        for attr in self.clone() {
13163            let attr = match attr {
13164                Ok(a) => a,
13165                Err(err) => {
13166                    fmt.finish()?;
13167                    f.write_str("Err(")?;
13168                    err.fmt(f)?;
13169                    return f.write_str(")");
13170                }
13171            };
13172            match attr {
13173                OpBindRxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
13174                OpBindRxDoRequest::Queues(val) => fmt.field("Queues", &val),
13175                OpBindRxDoRequest::Fd(val) => fmt.field("Fd", &val),
13176            };
13177        }
13178        fmt.finish()
13179    }
13180}
13181impl IterableOpBindRxDoRequest<'_> {
13182    pub fn lookup_attr(
13183        &self,
13184        offset: usize,
13185        missing_type: Option<u16>,
13186    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13187        let mut stack = Vec::new();
13188        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13189        if cur == offset + PushBuiltinNfgenmsg::len() {
13190            stack.push(("OpBindRxDoRequest", offset));
13191            return (
13192                stack,
13193                missing_type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13194            );
13195        }
13196        if cur > offset || cur + self.buf.len() < offset {
13197            return (stack, None);
13198        }
13199        let mut attrs = self.clone();
13200        let mut last_off = cur + attrs.pos;
13201        let mut missing = None;
13202        while let Some(attr) = attrs.next() {
13203            let Ok(attr) = attr else { break };
13204            match attr {
13205                OpBindRxDoRequest::Ifindex(val) => {
13206                    if last_off == offset {
13207                        stack.push(("Ifindex", last_off));
13208                        break;
13209                    }
13210                }
13211                OpBindRxDoRequest::Queues(val) => {
13212                    (stack, missing) = val.lookup_attr(offset, missing_type);
13213                    if !stack.is_empty() {
13214                        break;
13215                    }
13216                }
13217                OpBindRxDoRequest::Fd(val) => {
13218                    if last_off == offset {
13219                        stack.push(("Fd", last_off));
13220                        break;
13221                    }
13222                }
13223                _ => {}
13224            };
13225            last_off = cur + attrs.pos;
13226        }
13227        if !stack.is_empty() {
13228            stack.push(("OpBindRxDoRequest", cur));
13229        }
13230        (stack, missing)
13231    }
13232}
13233#[doc = "Bind dmabuf to netdev"]
13234pub struct PushOpBindRxDoReply<Prev: Rec> {
13235    pub(crate) prev: Option<Prev>,
13236    pub(crate) header_offset: Option<usize>,
13237}
13238impl<Prev: Rec> Rec for PushOpBindRxDoReply<Prev> {
13239    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13240        self.prev.as_mut().unwrap().as_rec_mut()
13241    }
13242    fn as_rec(&self) -> &Vec<u8> {
13243        self.prev.as_ref().unwrap().as_rec()
13244    }
13245}
13246impl<Prev: Rec> PushOpBindRxDoReply<Prev> {
13247    pub fn new(mut prev: Prev) -> Self {
13248        Self::write_header(&mut prev);
13249        Self::new_without_header(prev)
13250    }
13251    fn new_without_header(prev: Prev) -> Self {
13252        Self {
13253            prev: Some(prev),
13254            header_offset: None,
13255        }
13256    }
13257    fn write_header(prev: &mut Prev) {
13258        let mut header = PushBuiltinNfgenmsg::new();
13259        header.set_cmd(13u8);
13260        header.set_version(1u8);
13261        prev.as_rec_mut().extend(header.as_slice());
13262    }
13263    pub fn end_nested(mut self) -> Prev {
13264        let mut prev = self.prev.take().unwrap();
13265        if let Some(header_offset) = &self.header_offset {
13266            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13267        }
13268        prev
13269    }
13270    #[doc = "id of the dmabuf binding"]
13271    pub fn push_id(mut self, value: u32) -> Self {
13272        push_header(self.as_rec_mut(), 4u16, 4 as u16);
13273        self.as_rec_mut().extend(value.to_ne_bytes());
13274        self
13275    }
13276}
13277impl<Prev: Rec> Drop for PushOpBindRxDoReply<Prev> {
13278    fn drop(&mut self) {
13279        if let Some(prev) = &mut self.prev {
13280            if let Some(header_offset) = &self.header_offset {
13281                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13282            }
13283        }
13284    }
13285}
13286#[doc = "Bind dmabuf to netdev"]
13287#[derive(Clone)]
13288pub enum OpBindRxDoReply {
13289    #[doc = "id of the dmabuf binding"]
13290    Id(u32),
13291}
13292impl<'a> IterableOpBindRxDoReply<'a> {
13293    #[doc = "id of the dmabuf binding"]
13294    pub fn get_id(&self) -> Result<u32, ErrorContext> {
13295        let mut iter = self.clone();
13296        iter.pos = 0;
13297        for attr in iter {
13298            if let OpBindRxDoReply::Id(val) = attr? {
13299                return Ok(val);
13300            }
13301        }
13302        Err(ErrorContext::new_missing(
13303            "OpBindRxDoReply",
13304            "Id",
13305            self.orig_loc,
13306            self.buf.as_ptr() as usize,
13307        ))
13308    }
13309}
13310impl OpBindRxDoReply {
13311    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoReply<'a> {
13312        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13313        IterableOpBindRxDoReply::with_loc(attrs, buf.as_ptr() as usize)
13314    }
13315    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13316        Dmabuf::attr_from_type(r#type)
13317    }
13318}
13319#[derive(Clone, Copy, Default)]
13320pub struct IterableOpBindRxDoReply<'a> {
13321    buf: &'a [u8],
13322    pos: usize,
13323    orig_loc: usize,
13324}
13325impl<'a> IterableOpBindRxDoReply<'a> {
13326    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13327        Self {
13328            buf,
13329            pos: 0,
13330            orig_loc,
13331        }
13332    }
13333    pub fn get_buf(&self) -> &'a [u8] {
13334        self.buf
13335    }
13336}
13337impl<'a> Iterator for IterableOpBindRxDoReply<'a> {
13338    type Item = Result<OpBindRxDoReply, ErrorContext>;
13339    fn next(&mut self) -> Option<Self::Item> {
13340        let pos = self.pos;
13341        let mut r#type;
13342        loop {
13343            r#type = None;
13344            if self.buf.len() == self.pos {
13345                return None;
13346            }
13347            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13348                break;
13349            };
13350            r#type = Some(header.r#type);
13351            let res = match header.r#type {
13352                4u16 => OpBindRxDoReply::Id({
13353                    let res = parse_u32(next);
13354                    let Some(val) = res else { break };
13355                    val
13356                }),
13357                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13358                n => continue,
13359            };
13360            return Some(Ok(res));
13361        }
13362        Some(Err(ErrorContext::new(
13363            "OpBindRxDoReply",
13364            r#type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13365            self.orig_loc,
13366            self.buf.as_ptr().wrapping_add(pos) as usize,
13367        )))
13368    }
13369}
13370impl std::fmt::Debug for IterableOpBindRxDoReply<'_> {
13371    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13372        let mut fmt = f.debug_struct("OpBindRxDoReply");
13373        for attr in self.clone() {
13374            let attr = match attr {
13375                Ok(a) => a,
13376                Err(err) => {
13377                    fmt.finish()?;
13378                    f.write_str("Err(")?;
13379                    err.fmt(f)?;
13380                    return f.write_str(")");
13381                }
13382            };
13383            match attr {
13384                OpBindRxDoReply::Id(val) => fmt.field("Id", &val),
13385            };
13386        }
13387        fmt.finish()
13388    }
13389}
13390impl IterableOpBindRxDoReply<'_> {
13391    pub fn lookup_attr(
13392        &self,
13393        offset: usize,
13394        missing_type: Option<u16>,
13395    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13396        let mut stack = Vec::new();
13397        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13398        if cur == offset + PushBuiltinNfgenmsg::len() {
13399            stack.push(("OpBindRxDoReply", offset));
13400            return (
13401                stack,
13402                missing_type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13403            );
13404        }
13405        if cur > offset || cur + self.buf.len() < offset {
13406            return (stack, None);
13407        }
13408        let mut attrs = self.clone();
13409        let mut last_off = cur + attrs.pos;
13410        while let Some(attr) = attrs.next() {
13411            let Ok(attr) = attr else { break };
13412            match attr {
13413                OpBindRxDoReply::Id(val) => {
13414                    if last_off == offset {
13415                        stack.push(("Id", last_off));
13416                        break;
13417                    }
13418                }
13419                _ => {}
13420            };
13421            last_off = cur + attrs.pos;
13422        }
13423        if !stack.is_empty() {
13424            stack.push(("OpBindRxDoReply", cur));
13425        }
13426        (stack, None)
13427    }
13428}
13429#[derive(Debug)]
13430pub struct RequestOpBindRxDoRequest<'r> {
13431    request: Request<'r>,
13432}
13433impl<'r> RequestOpBindRxDoRequest<'r> {
13434    pub fn new(mut request: Request<'r>) -> Self {
13435        PushOpBindRxDoRequest::write_header(&mut request.buf_mut());
13436        Self { request: request }
13437    }
13438    pub fn encode(&mut self) -> PushOpBindRxDoRequest<&mut Vec<u8>> {
13439        PushOpBindRxDoRequest::new_without_header(self.request.buf_mut())
13440    }
13441    pub fn into_encoder(self) -> PushOpBindRxDoRequest<RequestBuf<'r>> {
13442        PushOpBindRxDoRequest::new_without_header(self.request.buf)
13443    }
13444    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpBindRxDoRequest<'buf> {
13445        OpBindRxDoRequest::new(buf)
13446    }
13447}
13448impl NetlinkRequest for RequestOpBindRxDoRequest<'_> {
13449    fn protocol(&self) -> Protocol {
13450        Protocol::Generic("netdev".as_bytes())
13451    }
13452    fn flags(&self) -> u16 {
13453        self.request.flags
13454    }
13455    fn payload(&self) -> &[u8] {
13456        self.request.buf()
13457    }
13458    type ReplyType<'buf> = IterableOpBindRxDoReply<'buf>;
13459    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13460        OpBindRxDoReply::new(buf)
13461    }
13462    fn lookup(
13463        buf: &[u8],
13464        offset: usize,
13465        missing_type: Option<u16>,
13466    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13467        OpBindRxDoRequest::new(buf).lookup_attr(offset, missing_type)
13468    }
13469}
13470#[doc = "Set configurable NAPI instance settings."]
13471pub struct PushOpNapiSetDoRequest<Prev: Rec> {
13472    pub(crate) prev: Option<Prev>,
13473    pub(crate) header_offset: Option<usize>,
13474}
13475impl<Prev: Rec> Rec for PushOpNapiSetDoRequest<Prev> {
13476    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13477        self.prev.as_mut().unwrap().as_rec_mut()
13478    }
13479    fn as_rec(&self) -> &Vec<u8> {
13480        self.prev.as_ref().unwrap().as_rec()
13481    }
13482}
13483impl<Prev: Rec> PushOpNapiSetDoRequest<Prev> {
13484    pub fn new(mut prev: Prev) -> Self {
13485        Self::write_header(&mut prev);
13486        Self::new_without_header(prev)
13487    }
13488    fn new_without_header(prev: Prev) -> Self {
13489        Self {
13490            prev: Some(prev),
13491            header_offset: None,
13492        }
13493    }
13494    fn write_header(prev: &mut Prev) {
13495        let mut header = PushBuiltinNfgenmsg::new();
13496        header.set_cmd(14u8);
13497        header.set_version(1u8);
13498        prev.as_rec_mut().extend(header.as_slice());
13499    }
13500    pub fn end_nested(mut self) -> Prev {
13501        let mut prev = self.prev.take().unwrap();
13502        if let Some(header_offset) = &self.header_offset {
13503            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13504        }
13505        prev
13506    }
13507    #[doc = "ID of the NAPI instance."]
13508    pub fn push_id(mut self, value: u32) -> Self {
13509        push_header(self.as_rec_mut(), 2u16, 4 as u16);
13510        self.as_rec_mut().extend(value.to_ne_bytes());
13511        self
13512    }
13513    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13514    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
13515        push_header(self.as_rec_mut(), 5u16, 4 as u16);
13516        self.as_rec_mut().extend(value.to_ne_bytes());
13517        self
13518    }
13519    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
13520    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
13521        push_header(self.as_rec_mut(), 6u16, 4 as u16);
13522        self.as_rec_mut().extend(value.to_ne_bytes());
13523        self
13524    }
13525    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13526    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
13527        push_header(self.as_rec_mut(), 7u16, 4 as u16);
13528        self.as_rec_mut().extend(value.to_ne_bytes());
13529        self
13530    }
13531    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
13532    pub fn push_threaded(mut self, value: u32) -> Self {
13533        push_header(self.as_rec_mut(), 8u16, 4 as u16);
13534        self.as_rec_mut().extend(value.to_ne_bytes());
13535        self
13536    }
13537}
13538impl<Prev: Rec> Drop for PushOpNapiSetDoRequest<Prev> {
13539    fn drop(&mut self) {
13540        if let Some(prev) = &mut self.prev {
13541            if let Some(header_offset) = &self.header_offset {
13542                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13543            }
13544        }
13545    }
13546}
13547#[doc = "Set configurable NAPI instance settings."]
13548#[derive(Clone)]
13549pub enum OpNapiSetDoRequest {
13550    #[doc = "ID of the NAPI instance."]
13551    Id(u32),
13552    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13553    DeferHardIrqs(u32),
13554    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
13555    GroFlushTimeout(u32),
13556    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13557    IrqSuspendTimeout(u32),
13558    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
13559    Threaded(u32),
13560}
13561impl<'a> IterableOpNapiSetDoRequest<'a> {
13562    #[doc = "ID of the NAPI instance."]
13563    pub fn get_id(&self) -> Result<u32, ErrorContext> {
13564        let mut iter = self.clone();
13565        iter.pos = 0;
13566        for attr in iter {
13567            if let OpNapiSetDoRequest::Id(val) = attr? {
13568                return Ok(val);
13569            }
13570        }
13571        Err(ErrorContext::new_missing(
13572            "OpNapiSetDoRequest",
13573            "Id",
13574            self.orig_loc,
13575            self.buf.as_ptr() as usize,
13576        ))
13577    }
13578    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13579    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
13580        let mut iter = self.clone();
13581        iter.pos = 0;
13582        for attr in iter {
13583            if let OpNapiSetDoRequest::DeferHardIrqs(val) = attr? {
13584                return Ok(val);
13585            }
13586        }
13587        Err(ErrorContext::new_missing(
13588            "OpNapiSetDoRequest",
13589            "DeferHardIrqs",
13590            self.orig_loc,
13591            self.buf.as_ptr() as usize,
13592        ))
13593    }
13594    #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
13595    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
13596        let mut iter = self.clone();
13597        iter.pos = 0;
13598        for attr in iter {
13599            if let OpNapiSetDoRequest::GroFlushTimeout(val) = attr? {
13600                return Ok(val);
13601            }
13602        }
13603        Err(ErrorContext::new_missing(
13604            "OpNapiSetDoRequest",
13605            "GroFlushTimeout",
13606            self.orig_loc,
13607            self.buf.as_ptr() as usize,
13608        ))
13609    }
13610    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13611    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
13612        let mut iter = self.clone();
13613        iter.pos = 0;
13614        for attr in iter {
13615            if let OpNapiSetDoRequest::IrqSuspendTimeout(val) = attr? {
13616                return Ok(val);
13617            }
13618        }
13619        Err(ErrorContext::new_missing(
13620            "OpNapiSetDoRequest",
13621            "IrqSuspendTimeout",
13622            self.orig_loc,
13623            self.buf.as_ptr() as usize,
13624        ))
13625    }
13626    #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
13627    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
13628        let mut iter = self.clone();
13629        iter.pos = 0;
13630        for attr in iter {
13631            if let OpNapiSetDoRequest::Threaded(val) = attr? {
13632                return Ok(val);
13633            }
13634        }
13635        Err(ErrorContext::new_missing(
13636            "OpNapiSetDoRequest",
13637            "Threaded",
13638            self.orig_loc,
13639            self.buf.as_ptr() as usize,
13640        ))
13641    }
13642}
13643impl OpNapiSetDoRequest {
13644    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoRequest<'a> {
13645        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13646        IterableOpNapiSetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13647    }
13648    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13649        Napi::attr_from_type(r#type)
13650    }
13651}
13652#[derive(Clone, Copy, Default)]
13653pub struct IterableOpNapiSetDoRequest<'a> {
13654    buf: &'a [u8],
13655    pos: usize,
13656    orig_loc: usize,
13657}
13658impl<'a> IterableOpNapiSetDoRequest<'a> {
13659    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13660        Self {
13661            buf,
13662            pos: 0,
13663            orig_loc,
13664        }
13665    }
13666    pub fn get_buf(&self) -> &'a [u8] {
13667        self.buf
13668    }
13669}
13670impl<'a> Iterator for IterableOpNapiSetDoRequest<'a> {
13671    type Item = Result<OpNapiSetDoRequest, ErrorContext>;
13672    fn next(&mut self) -> Option<Self::Item> {
13673        let pos = self.pos;
13674        let mut r#type;
13675        loop {
13676            r#type = None;
13677            if self.buf.len() == self.pos {
13678                return None;
13679            }
13680            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13681                break;
13682            };
13683            r#type = Some(header.r#type);
13684            let res = match header.r#type {
13685                2u16 => OpNapiSetDoRequest::Id({
13686                    let res = parse_u32(next);
13687                    let Some(val) = res else { break };
13688                    val
13689                }),
13690                5u16 => OpNapiSetDoRequest::DeferHardIrqs({
13691                    let res = parse_u32(next);
13692                    let Some(val) = res else { break };
13693                    val
13694                }),
13695                6u16 => OpNapiSetDoRequest::GroFlushTimeout({
13696                    let res = parse_u32(next);
13697                    let Some(val) = res else { break };
13698                    val
13699                }),
13700                7u16 => OpNapiSetDoRequest::IrqSuspendTimeout({
13701                    let res = parse_u32(next);
13702                    let Some(val) = res else { break };
13703                    val
13704                }),
13705                8u16 => OpNapiSetDoRequest::Threaded({
13706                    let res = parse_u32(next);
13707                    let Some(val) = res else { break };
13708                    val
13709                }),
13710                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13711                n => continue,
13712            };
13713            return Some(Ok(res));
13714        }
13715        Some(Err(ErrorContext::new(
13716            "OpNapiSetDoRequest",
13717            r#type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13718            self.orig_loc,
13719            self.buf.as_ptr().wrapping_add(pos) as usize,
13720        )))
13721    }
13722}
13723impl std::fmt::Debug for IterableOpNapiSetDoRequest<'_> {
13724    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13725        let mut fmt = f.debug_struct("OpNapiSetDoRequest");
13726        for attr in self.clone() {
13727            let attr = match attr {
13728                Ok(a) => a,
13729                Err(err) => {
13730                    fmt.finish()?;
13731                    f.write_str("Err(")?;
13732                    err.fmt(f)?;
13733                    return f.write_str(")");
13734                }
13735            };
13736            match attr {
13737                OpNapiSetDoRequest::Id(val) => fmt.field("Id", &val),
13738                OpNapiSetDoRequest::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
13739                OpNapiSetDoRequest::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
13740                OpNapiSetDoRequest::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
13741                OpNapiSetDoRequest::Threaded(val) => fmt.field(
13742                    "Threaded",
13743                    &FormatEnum(val.into(), NapiThreaded::from_value),
13744                ),
13745            };
13746        }
13747        fmt.finish()
13748    }
13749}
13750impl IterableOpNapiSetDoRequest<'_> {
13751    pub fn lookup_attr(
13752        &self,
13753        offset: usize,
13754        missing_type: Option<u16>,
13755    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13756        let mut stack = Vec::new();
13757        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13758        if cur == offset + PushBuiltinNfgenmsg::len() {
13759            stack.push(("OpNapiSetDoRequest", offset));
13760            return (
13761                stack,
13762                missing_type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13763            );
13764        }
13765        if cur > offset || cur + self.buf.len() < offset {
13766            return (stack, None);
13767        }
13768        let mut attrs = self.clone();
13769        let mut last_off = cur + attrs.pos;
13770        while let Some(attr) = attrs.next() {
13771            let Ok(attr) = attr else { break };
13772            match attr {
13773                OpNapiSetDoRequest::Id(val) => {
13774                    if last_off == offset {
13775                        stack.push(("Id", last_off));
13776                        break;
13777                    }
13778                }
13779                OpNapiSetDoRequest::DeferHardIrqs(val) => {
13780                    if last_off == offset {
13781                        stack.push(("DeferHardIrqs", last_off));
13782                        break;
13783                    }
13784                }
13785                OpNapiSetDoRequest::GroFlushTimeout(val) => {
13786                    if last_off == offset {
13787                        stack.push(("GroFlushTimeout", last_off));
13788                        break;
13789                    }
13790                }
13791                OpNapiSetDoRequest::IrqSuspendTimeout(val) => {
13792                    if last_off == offset {
13793                        stack.push(("IrqSuspendTimeout", last_off));
13794                        break;
13795                    }
13796                }
13797                OpNapiSetDoRequest::Threaded(val) => {
13798                    if last_off == offset {
13799                        stack.push(("Threaded", last_off));
13800                        break;
13801                    }
13802                }
13803                _ => {}
13804            };
13805            last_off = cur + attrs.pos;
13806        }
13807        if !stack.is_empty() {
13808            stack.push(("OpNapiSetDoRequest", cur));
13809        }
13810        (stack, None)
13811    }
13812}
13813#[doc = "Set configurable NAPI instance settings."]
13814pub struct PushOpNapiSetDoReply<Prev: Rec> {
13815    pub(crate) prev: Option<Prev>,
13816    pub(crate) header_offset: Option<usize>,
13817}
13818impl<Prev: Rec> Rec for PushOpNapiSetDoReply<Prev> {
13819    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13820        self.prev.as_mut().unwrap().as_rec_mut()
13821    }
13822    fn as_rec(&self) -> &Vec<u8> {
13823        self.prev.as_ref().unwrap().as_rec()
13824    }
13825}
13826impl<Prev: Rec> PushOpNapiSetDoReply<Prev> {
13827    pub fn new(mut prev: Prev) -> Self {
13828        Self::write_header(&mut prev);
13829        Self::new_without_header(prev)
13830    }
13831    fn new_without_header(prev: Prev) -> Self {
13832        Self {
13833            prev: Some(prev),
13834            header_offset: None,
13835        }
13836    }
13837    fn write_header(prev: &mut Prev) {
13838        let mut header = PushBuiltinNfgenmsg::new();
13839        header.set_cmd(14u8);
13840        header.set_version(1u8);
13841        prev.as_rec_mut().extend(header.as_slice());
13842    }
13843    pub fn end_nested(mut self) -> Prev {
13844        let mut prev = self.prev.take().unwrap();
13845        if let Some(header_offset) = &self.header_offset {
13846            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13847        }
13848        prev
13849    }
13850}
13851impl<Prev: Rec> Drop for PushOpNapiSetDoReply<Prev> {
13852    fn drop(&mut self) {
13853        if let Some(prev) = &mut self.prev {
13854            if let Some(header_offset) = &self.header_offset {
13855                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13856            }
13857        }
13858    }
13859}
13860#[doc = "Set configurable NAPI instance settings."]
13861#[derive(Clone)]
13862pub enum OpNapiSetDoReply {}
13863impl<'a> IterableOpNapiSetDoReply<'a> {}
13864impl OpNapiSetDoReply {
13865    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoReply<'a> {
13866        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13867        IterableOpNapiSetDoReply::with_loc(attrs, buf.as_ptr() as usize)
13868    }
13869    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13870        Napi::attr_from_type(r#type)
13871    }
13872}
13873#[derive(Clone, Copy, Default)]
13874pub struct IterableOpNapiSetDoReply<'a> {
13875    buf: &'a [u8],
13876    pos: usize,
13877    orig_loc: usize,
13878}
13879impl<'a> IterableOpNapiSetDoReply<'a> {
13880    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13881        Self {
13882            buf,
13883            pos: 0,
13884            orig_loc,
13885        }
13886    }
13887    pub fn get_buf(&self) -> &'a [u8] {
13888        self.buf
13889    }
13890}
13891impl<'a> Iterator for IterableOpNapiSetDoReply<'a> {
13892    type Item = Result<OpNapiSetDoReply, ErrorContext>;
13893    fn next(&mut self) -> Option<Self::Item> {
13894        let pos = self.pos;
13895        let mut r#type;
13896        loop {
13897            r#type = None;
13898            if self.buf.len() == self.pos {
13899                return None;
13900            }
13901            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13902                break;
13903            };
13904            r#type = Some(header.r#type);
13905            let res = match header.r#type {
13906                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13907                n => continue,
13908            };
13909            return Some(Ok(res));
13910        }
13911        Some(Err(ErrorContext::new(
13912            "OpNapiSetDoReply",
13913            r#type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13914            self.orig_loc,
13915            self.buf.as_ptr().wrapping_add(pos) as usize,
13916        )))
13917    }
13918}
13919impl std::fmt::Debug for IterableOpNapiSetDoReply<'_> {
13920    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13921        let mut fmt = f.debug_struct("OpNapiSetDoReply");
13922        for attr in self.clone() {
13923            let attr = match attr {
13924                Ok(a) => a,
13925                Err(err) => {
13926                    fmt.finish()?;
13927                    f.write_str("Err(")?;
13928                    err.fmt(f)?;
13929                    return f.write_str(")");
13930                }
13931            };
13932            match attr {};
13933        }
13934        fmt.finish()
13935    }
13936}
13937impl IterableOpNapiSetDoReply<'_> {
13938    pub fn lookup_attr(
13939        &self,
13940        offset: usize,
13941        missing_type: Option<u16>,
13942    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13943        let mut stack = Vec::new();
13944        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13945        if cur == offset + PushBuiltinNfgenmsg::len() {
13946            stack.push(("OpNapiSetDoReply", offset));
13947            return (
13948                stack,
13949                missing_type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13950            );
13951        }
13952        (stack, None)
13953    }
13954}
13955#[derive(Debug)]
13956pub struct RequestOpNapiSetDoRequest<'r> {
13957    request: Request<'r>,
13958}
13959impl<'r> RequestOpNapiSetDoRequest<'r> {
13960    pub fn new(mut request: Request<'r>) -> Self {
13961        PushOpNapiSetDoRequest::write_header(&mut request.buf_mut());
13962        Self { request: request }
13963    }
13964    pub fn encode(&mut self) -> PushOpNapiSetDoRequest<&mut Vec<u8>> {
13965        PushOpNapiSetDoRequest::new_without_header(self.request.buf_mut())
13966    }
13967    pub fn into_encoder(self) -> PushOpNapiSetDoRequest<RequestBuf<'r>> {
13968        PushOpNapiSetDoRequest::new_without_header(self.request.buf)
13969    }
13970    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpNapiSetDoRequest<'buf> {
13971        OpNapiSetDoRequest::new(buf)
13972    }
13973}
13974impl NetlinkRequest for RequestOpNapiSetDoRequest<'_> {
13975    fn protocol(&self) -> Protocol {
13976        Protocol::Generic("netdev".as_bytes())
13977    }
13978    fn flags(&self) -> u16 {
13979        self.request.flags
13980    }
13981    fn payload(&self) -> &[u8] {
13982        self.request.buf()
13983    }
13984    type ReplyType<'buf> = IterableOpNapiSetDoReply<'buf>;
13985    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13986        OpNapiSetDoReply::new(buf)
13987    }
13988    fn lookup(
13989        buf: &[u8],
13990        offset: usize,
13991        missing_type: Option<u16>,
13992    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13993        OpNapiSetDoRequest::new(buf).lookup_attr(offset, missing_type)
13994    }
13995}
13996#[doc = "Bind dmabuf to netdev for TX"]
13997pub struct PushOpBindTxDoRequest<Prev: Rec> {
13998    pub(crate) prev: Option<Prev>,
13999    pub(crate) header_offset: Option<usize>,
14000}
14001impl<Prev: Rec> Rec for PushOpBindTxDoRequest<Prev> {
14002    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
14003        self.prev.as_mut().unwrap().as_rec_mut()
14004    }
14005    fn as_rec(&self) -> &Vec<u8> {
14006        self.prev.as_ref().unwrap().as_rec()
14007    }
14008}
14009impl<Prev: Rec> PushOpBindTxDoRequest<Prev> {
14010    pub fn new(mut prev: Prev) -> Self {
14011        Self::write_header(&mut prev);
14012        Self::new_without_header(prev)
14013    }
14014    fn new_without_header(prev: Prev) -> Self {
14015        Self {
14016            prev: Some(prev),
14017            header_offset: None,
14018        }
14019    }
14020    fn write_header(prev: &mut Prev) {
14021        let mut header = PushBuiltinNfgenmsg::new();
14022        header.set_cmd(15u8);
14023        header.set_version(1u8);
14024        prev.as_rec_mut().extend(header.as_slice());
14025    }
14026    pub fn end_nested(mut self) -> Prev {
14027        let mut prev = self.prev.take().unwrap();
14028        if let Some(header_offset) = &self.header_offset {
14029            finalize_nested_header(prev.as_rec_mut(), *header_offset);
14030        }
14031        prev
14032    }
14033    #[doc = "netdev ifindex to bind the dmabuf to."]
14034    pub fn push_ifindex(mut self, value: u32) -> Self {
14035        push_header(self.as_rec_mut(), 1u16, 4 as u16);
14036        self.as_rec_mut().extend(value.to_ne_bytes());
14037        self
14038    }
14039    #[doc = "dmabuf file descriptor to bind."]
14040    pub fn push_fd(mut self, value: u32) -> Self {
14041        push_header(self.as_rec_mut(), 3u16, 4 as u16);
14042        self.as_rec_mut().extend(value.to_ne_bytes());
14043        self
14044    }
14045}
14046impl<Prev: Rec> Drop for PushOpBindTxDoRequest<Prev> {
14047    fn drop(&mut self) {
14048        if let Some(prev) = &mut self.prev {
14049            if let Some(header_offset) = &self.header_offset {
14050                finalize_nested_header(prev.as_rec_mut(), *header_offset);
14051            }
14052        }
14053    }
14054}
14055#[doc = "Bind dmabuf to netdev for TX"]
14056#[derive(Clone)]
14057pub enum OpBindTxDoRequest {
14058    #[doc = "netdev ifindex to bind the dmabuf to."]
14059    Ifindex(u32),
14060    #[doc = "dmabuf file descriptor to bind."]
14061    Fd(u32),
14062}
14063impl<'a> IterableOpBindTxDoRequest<'a> {
14064    #[doc = "netdev ifindex to bind the dmabuf to."]
14065    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
14066        let mut iter = self.clone();
14067        iter.pos = 0;
14068        for attr in iter {
14069            if let OpBindTxDoRequest::Ifindex(val) = attr? {
14070                return Ok(val);
14071            }
14072        }
14073        Err(ErrorContext::new_missing(
14074            "OpBindTxDoRequest",
14075            "Ifindex",
14076            self.orig_loc,
14077            self.buf.as_ptr() as usize,
14078        ))
14079    }
14080    #[doc = "dmabuf file descriptor to bind."]
14081    pub fn get_fd(&self) -> Result<u32, ErrorContext> {
14082        let mut iter = self.clone();
14083        iter.pos = 0;
14084        for attr in iter {
14085            if let OpBindTxDoRequest::Fd(val) = attr? {
14086                return Ok(val);
14087            }
14088        }
14089        Err(ErrorContext::new_missing(
14090            "OpBindTxDoRequest",
14091            "Fd",
14092            self.orig_loc,
14093            self.buf.as_ptr() as usize,
14094        ))
14095    }
14096}
14097impl OpBindTxDoRequest {
14098    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoRequest<'a> {
14099        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
14100        IterableOpBindTxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
14101    }
14102    fn attr_from_type(r#type: u16) -> Option<&'static str> {
14103        Dmabuf::attr_from_type(r#type)
14104    }
14105}
14106#[derive(Clone, Copy, Default)]
14107pub struct IterableOpBindTxDoRequest<'a> {
14108    buf: &'a [u8],
14109    pos: usize,
14110    orig_loc: usize,
14111}
14112impl<'a> IterableOpBindTxDoRequest<'a> {
14113    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
14114        Self {
14115            buf,
14116            pos: 0,
14117            orig_loc,
14118        }
14119    }
14120    pub fn get_buf(&self) -> &'a [u8] {
14121        self.buf
14122    }
14123}
14124impl<'a> Iterator for IterableOpBindTxDoRequest<'a> {
14125    type Item = Result<OpBindTxDoRequest, ErrorContext>;
14126    fn next(&mut self) -> Option<Self::Item> {
14127        let pos = self.pos;
14128        let mut r#type;
14129        loop {
14130            r#type = None;
14131            if self.buf.len() == self.pos {
14132                return None;
14133            }
14134            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
14135                break;
14136            };
14137            r#type = Some(header.r#type);
14138            let res = match header.r#type {
14139                1u16 => OpBindTxDoRequest::Ifindex({
14140                    let res = parse_u32(next);
14141                    let Some(val) = res else { break };
14142                    val
14143                }),
14144                3u16 => OpBindTxDoRequest::Fd({
14145                    let res = parse_u32(next);
14146                    let Some(val) = res else { break };
14147                    val
14148                }),
14149                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
14150                n => continue,
14151            };
14152            return Some(Ok(res));
14153        }
14154        Some(Err(ErrorContext::new(
14155            "OpBindTxDoRequest",
14156            r#type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14157            self.orig_loc,
14158            self.buf.as_ptr().wrapping_add(pos) as usize,
14159        )))
14160    }
14161}
14162impl std::fmt::Debug for IterableOpBindTxDoRequest<'_> {
14163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14164        let mut fmt = f.debug_struct("OpBindTxDoRequest");
14165        for attr in self.clone() {
14166            let attr = match attr {
14167                Ok(a) => a,
14168                Err(err) => {
14169                    fmt.finish()?;
14170                    f.write_str("Err(")?;
14171                    err.fmt(f)?;
14172                    return f.write_str(")");
14173                }
14174            };
14175            match attr {
14176                OpBindTxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
14177                OpBindTxDoRequest::Fd(val) => fmt.field("Fd", &val),
14178            };
14179        }
14180        fmt.finish()
14181    }
14182}
14183impl IterableOpBindTxDoRequest<'_> {
14184    pub fn lookup_attr(
14185        &self,
14186        offset: usize,
14187        missing_type: Option<u16>,
14188    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14189        let mut stack = Vec::new();
14190        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14191        if cur == offset + PushBuiltinNfgenmsg::len() {
14192            stack.push(("OpBindTxDoRequest", offset));
14193            return (
14194                stack,
14195                missing_type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14196            );
14197        }
14198        if cur > offset || cur + self.buf.len() < offset {
14199            return (stack, None);
14200        }
14201        let mut attrs = self.clone();
14202        let mut last_off = cur + attrs.pos;
14203        while let Some(attr) = attrs.next() {
14204            let Ok(attr) = attr else { break };
14205            match attr {
14206                OpBindTxDoRequest::Ifindex(val) => {
14207                    if last_off == offset {
14208                        stack.push(("Ifindex", last_off));
14209                        break;
14210                    }
14211                }
14212                OpBindTxDoRequest::Fd(val) => {
14213                    if last_off == offset {
14214                        stack.push(("Fd", last_off));
14215                        break;
14216                    }
14217                }
14218                _ => {}
14219            };
14220            last_off = cur + attrs.pos;
14221        }
14222        if !stack.is_empty() {
14223            stack.push(("OpBindTxDoRequest", cur));
14224        }
14225        (stack, None)
14226    }
14227}
14228#[doc = "Bind dmabuf to netdev for TX"]
14229pub struct PushOpBindTxDoReply<Prev: Rec> {
14230    pub(crate) prev: Option<Prev>,
14231    pub(crate) header_offset: Option<usize>,
14232}
14233impl<Prev: Rec> Rec for PushOpBindTxDoReply<Prev> {
14234    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
14235        self.prev.as_mut().unwrap().as_rec_mut()
14236    }
14237    fn as_rec(&self) -> &Vec<u8> {
14238        self.prev.as_ref().unwrap().as_rec()
14239    }
14240}
14241impl<Prev: Rec> PushOpBindTxDoReply<Prev> {
14242    pub fn new(mut prev: Prev) -> Self {
14243        Self::write_header(&mut prev);
14244        Self::new_without_header(prev)
14245    }
14246    fn new_without_header(prev: Prev) -> Self {
14247        Self {
14248            prev: Some(prev),
14249            header_offset: None,
14250        }
14251    }
14252    fn write_header(prev: &mut Prev) {
14253        let mut header = PushBuiltinNfgenmsg::new();
14254        header.set_cmd(15u8);
14255        header.set_version(1u8);
14256        prev.as_rec_mut().extend(header.as_slice());
14257    }
14258    pub fn end_nested(mut self) -> Prev {
14259        let mut prev = self.prev.take().unwrap();
14260        if let Some(header_offset) = &self.header_offset {
14261            finalize_nested_header(prev.as_rec_mut(), *header_offset);
14262        }
14263        prev
14264    }
14265    #[doc = "id of the dmabuf binding"]
14266    pub fn push_id(mut self, value: u32) -> Self {
14267        push_header(self.as_rec_mut(), 4u16, 4 as u16);
14268        self.as_rec_mut().extend(value.to_ne_bytes());
14269        self
14270    }
14271}
14272impl<Prev: Rec> Drop for PushOpBindTxDoReply<Prev> {
14273    fn drop(&mut self) {
14274        if let Some(prev) = &mut self.prev {
14275            if let Some(header_offset) = &self.header_offset {
14276                finalize_nested_header(prev.as_rec_mut(), *header_offset);
14277            }
14278        }
14279    }
14280}
14281#[doc = "Bind dmabuf to netdev for TX"]
14282#[derive(Clone)]
14283pub enum OpBindTxDoReply {
14284    #[doc = "id of the dmabuf binding"]
14285    Id(u32),
14286}
14287impl<'a> IterableOpBindTxDoReply<'a> {
14288    #[doc = "id of the dmabuf binding"]
14289    pub fn get_id(&self) -> Result<u32, ErrorContext> {
14290        let mut iter = self.clone();
14291        iter.pos = 0;
14292        for attr in iter {
14293            if let OpBindTxDoReply::Id(val) = attr? {
14294                return Ok(val);
14295            }
14296        }
14297        Err(ErrorContext::new_missing(
14298            "OpBindTxDoReply",
14299            "Id",
14300            self.orig_loc,
14301            self.buf.as_ptr() as usize,
14302        ))
14303    }
14304}
14305impl OpBindTxDoReply {
14306    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoReply<'a> {
14307        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
14308        IterableOpBindTxDoReply::with_loc(attrs, buf.as_ptr() as usize)
14309    }
14310    fn attr_from_type(r#type: u16) -> Option<&'static str> {
14311        Dmabuf::attr_from_type(r#type)
14312    }
14313}
14314#[derive(Clone, Copy, Default)]
14315pub struct IterableOpBindTxDoReply<'a> {
14316    buf: &'a [u8],
14317    pos: usize,
14318    orig_loc: usize,
14319}
14320impl<'a> IterableOpBindTxDoReply<'a> {
14321    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
14322        Self {
14323            buf,
14324            pos: 0,
14325            orig_loc,
14326        }
14327    }
14328    pub fn get_buf(&self) -> &'a [u8] {
14329        self.buf
14330    }
14331}
14332impl<'a> Iterator for IterableOpBindTxDoReply<'a> {
14333    type Item = Result<OpBindTxDoReply, ErrorContext>;
14334    fn next(&mut self) -> Option<Self::Item> {
14335        let pos = self.pos;
14336        let mut r#type;
14337        loop {
14338            r#type = None;
14339            if self.buf.len() == self.pos {
14340                return None;
14341            }
14342            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
14343                break;
14344            };
14345            r#type = Some(header.r#type);
14346            let res = match header.r#type {
14347                4u16 => OpBindTxDoReply::Id({
14348                    let res = parse_u32(next);
14349                    let Some(val) = res else { break };
14350                    val
14351                }),
14352                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
14353                n => continue,
14354            };
14355            return Some(Ok(res));
14356        }
14357        Some(Err(ErrorContext::new(
14358            "OpBindTxDoReply",
14359            r#type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14360            self.orig_loc,
14361            self.buf.as_ptr().wrapping_add(pos) as usize,
14362        )))
14363    }
14364}
14365impl std::fmt::Debug for IterableOpBindTxDoReply<'_> {
14366    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14367        let mut fmt = f.debug_struct("OpBindTxDoReply");
14368        for attr in self.clone() {
14369            let attr = match attr {
14370                Ok(a) => a,
14371                Err(err) => {
14372                    fmt.finish()?;
14373                    f.write_str("Err(")?;
14374                    err.fmt(f)?;
14375                    return f.write_str(")");
14376                }
14377            };
14378            match attr {
14379                OpBindTxDoReply::Id(val) => fmt.field("Id", &val),
14380            };
14381        }
14382        fmt.finish()
14383    }
14384}
14385impl IterableOpBindTxDoReply<'_> {
14386    pub fn lookup_attr(
14387        &self,
14388        offset: usize,
14389        missing_type: Option<u16>,
14390    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14391        let mut stack = Vec::new();
14392        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14393        if cur == offset + PushBuiltinNfgenmsg::len() {
14394            stack.push(("OpBindTxDoReply", offset));
14395            return (
14396                stack,
14397                missing_type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14398            );
14399        }
14400        if cur > offset || cur + self.buf.len() < offset {
14401            return (stack, None);
14402        }
14403        let mut attrs = self.clone();
14404        let mut last_off = cur + attrs.pos;
14405        while let Some(attr) = attrs.next() {
14406            let Ok(attr) = attr else { break };
14407            match attr {
14408                OpBindTxDoReply::Id(val) => {
14409                    if last_off == offset {
14410                        stack.push(("Id", last_off));
14411                        break;
14412                    }
14413                }
14414                _ => {}
14415            };
14416            last_off = cur + attrs.pos;
14417        }
14418        if !stack.is_empty() {
14419            stack.push(("OpBindTxDoReply", cur));
14420        }
14421        (stack, None)
14422    }
14423}
14424#[derive(Debug)]
14425pub struct RequestOpBindTxDoRequest<'r> {
14426    request: Request<'r>,
14427}
14428impl<'r> RequestOpBindTxDoRequest<'r> {
14429    pub fn new(mut request: Request<'r>) -> Self {
14430        PushOpBindTxDoRequest::write_header(&mut request.buf_mut());
14431        Self { request: request }
14432    }
14433    pub fn encode(&mut self) -> PushOpBindTxDoRequest<&mut Vec<u8>> {
14434        PushOpBindTxDoRequest::new_without_header(self.request.buf_mut())
14435    }
14436    pub fn into_encoder(self) -> PushOpBindTxDoRequest<RequestBuf<'r>> {
14437        PushOpBindTxDoRequest::new_without_header(self.request.buf)
14438    }
14439    pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpBindTxDoRequest<'buf> {
14440        OpBindTxDoRequest::new(buf)
14441    }
14442}
14443impl NetlinkRequest for RequestOpBindTxDoRequest<'_> {
14444    fn protocol(&self) -> Protocol {
14445        Protocol::Generic("netdev".as_bytes())
14446    }
14447    fn flags(&self) -> u16 {
14448        self.request.flags
14449    }
14450    fn payload(&self) -> &[u8] {
14451        self.request.buf()
14452    }
14453    type ReplyType<'buf> = IterableOpBindTxDoReply<'buf>;
14454    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
14455        OpBindTxDoReply::new(buf)
14456    }
14457    fn lookup(
14458        buf: &[u8],
14459        offset: usize,
14460        missing_type: Option<u16>,
14461    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14462        OpBindTxDoRequest::new(buf).lookup_attr(offset, missing_type)
14463    }
14464}
14465use crate::traits::LookupFn;
14466use crate::utils::RequestBuf;
14467#[derive(Debug)]
14468pub struct Request<'buf> {
14469    buf: RequestBuf<'buf>,
14470    flags: u16,
14471    writeback: Option<&'buf mut Option<RequestInfo>>,
14472}
14473#[allow(unused)]
14474#[derive(Debug, Clone)]
14475pub struct RequestInfo {
14476    protocol: Protocol,
14477    flags: u16,
14478    name: &'static str,
14479    lookup: LookupFn,
14480}
14481impl Request<'static> {
14482    pub fn new() -> Self {
14483        Self::new_from_buf(Vec::new())
14484    }
14485    pub fn new_from_buf(buf: Vec<u8>) -> Self {
14486        Self {
14487            flags: 0,
14488            buf: RequestBuf::Own(buf),
14489            writeback: None,
14490        }
14491    }
14492    pub fn into_buf(self) -> Vec<u8> {
14493        match self.buf {
14494            RequestBuf::Own(buf) => buf,
14495            _ => unreachable!(),
14496        }
14497    }
14498}
14499impl<'buf> Request<'buf> {
14500    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
14501        buf.clear();
14502        Self::new_extend(buf)
14503    }
14504    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
14505        Self {
14506            flags: 0,
14507            buf: RequestBuf::Ref(buf),
14508            writeback: None,
14509        }
14510    }
14511    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
14512        let Some(writeback) = &mut self.writeback else {
14513            return;
14514        };
14515        **writeback = Some(RequestInfo {
14516            protocol,
14517            flags: self.flags,
14518            name,
14519            lookup,
14520        })
14521    }
14522    pub fn buf(&self) -> &Vec<u8> {
14523        self.buf.buf()
14524    }
14525    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
14526        self.buf.buf_mut()
14527    }
14528    #[doc = "Set `NLM_F_CREATE` flag"]
14529    pub fn set_create(mut self) -> Self {
14530        self.flags |= consts::NLM_F_CREATE as u16;
14531        self
14532    }
14533    #[doc = "Set `NLM_F_EXCL` flag"]
14534    pub fn set_excl(mut self) -> Self {
14535        self.flags |= consts::NLM_F_EXCL as u16;
14536        self
14537    }
14538    #[doc = "Set `NLM_F_REPLACE` flag"]
14539    pub fn set_replace(mut self) -> Self {
14540        self.flags |= consts::NLM_F_REPLACE as u16;
14541        self
14542    }
14543    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
14544    pub fn set_change(self) -> Self {
14545        self.set_create().set_replace()
14546    }
14547    #[doc = "Set `NLM_F_APPEND` flag"]
14548    pub fn set_append(mut self) -> Self {
14549        self.flags |= consts::NLM_F_APPEND as u16;
14550        self
14551    }
14552    #[doc = "Set `NLM_F_DUMP` flag"]
14553    fn set_dump(mut self) -> Self {
14554        self.flags |= consts::NLM_F_DUMP as u16;
14555        self
14556    }
14557    pub fn op_dev_get_dump_request(self) -> RequestOpDevGetDumpRequest<'buf> {
14558        let mut res = RequestOpDevGetDumpRequest::new(self);
14559        res.request.do_writeback(
14560            res.protocol(),
14561            "op-dev-get-dump-request",
14562            RequestOpDevGetDumpRequest::lookup,
14563        );
14564        res
14565    }
14566    pub fn op_dev_get_do_request(self) -> RequestOpDevGetDoRequest<'buf> {
14567        let mut res = RequestOpDevGetDoRequest::new(self);
14568        res.request.do_writeback(
14569            res.protocol(),
14570            "op-dev-get-do-request",
14571            RequestOpDevGetDoRequest::lookup,
14572        );
14573        res
14574    }
14575    pub fn op_page_pool_get_dump_request(self) -> RequestOpPagePoolGetDumpRequest<'buf> {
14576        let mut res = RequestOpPagePoolGetDumpRequest::new(self);
14577        res.request.do_writeback(
14578            res.protocol(),
14579            "op-page-pool-get-dump-request",
14580            RequestOpPagePoolGetDumpRequest::lookup,
14581        );
14582        res
14583    }
14584    pub fn op_page_pool_get_do_request(self) -> RequestOpPagePoolGetDoRequest<'buf> {
14585        let mut res = RequestOpPagePoolGetDoRequest::new(self);
14586        res.request.do_writeback(
14587            res.protocol(),
14588            "op-page-pool-get-do-request",
14589            RequestOpPagePoolGetDoRequest::lookup,
14590        );
14591        res
14592    }
14593    pub fn op_page_pool_stats_get_dump_request(self) -> RequestOpPagePoolStatsGetDumpRequest<'buf> {
14594        let mut res = RequestOpPagePoolStatsGetDumpRequest::new(self);
14595        res.request.do_writeback(
14596            res.protocol(),
14597            "op-page-pool-stats-get-dump-request",
14598            RequestOpPagePoolStatsGetDumpRequest::lookup,
14599        );
14600        res
14601    }
14602    pub fn op_page_pool_stats_get_do_request(self) -> RequestOpPagePoolStatsGetDoRequest<'buf> {
14603        let mut res = RequestOpPagePoolStatsGetDoRequest::new(self);
14604        res.request.do_writeback(
14605            res.protocol(),
14606            "op-page-pool-stats-get-do-request",
14607            RequestOpPagePoolStatsGetDoRequest::lookup,
14608        );
14609        res
14610    }
14611    pub fn op_queue_get_dump_request(self) -> RequestOpQueueGetDumpRequest<'buf> {
14612        let mut res = RequestOpQueueGetDumpRequest::new(self);
14613        res.request.do_writeback(
14614            res.protocol(),
14615            "op-queue-get-dump-request",
14616            RequestOpQueueGetDumpRequest::lookup,
14617        );
14618        res
14619    }
14620    pub fn op_queue_get_do_request(self) -> RequestOpQueueGetDoRequest<'buf> {
14621        let mut res = RequestOpQueueGetDoRequest::new(self);
14622        res.request.do_writeback(
14623            res.protocol(),
14624            "op-queue-get-do-request",
14625            RequestOpQueueGetDoRequest::lookup,
14626        );
14627        res
14628    }
14629    pub fn op_napi_get_dump_request(self) -> RequestOpNapiGetDumpRequest<'buf> {
14630        let mut res = RequestOpNapiGetDumpRequest::new(self);
14631        res.request.do_writeback(
14632            res.protocol(),
14633            "op-napi-get-dump-request",
14634            RequestOpNapiGetDumpRequest::lookup,
14635        );
14636        res
14637    }
14638    pub fn op_napi_get_do_request(self) -> RequestOpNapiGetDoRequest<'buf> {
14639        let mut res = RequestOpNapiGetDoRequest::new(self);
14640        res.request.do_writeback(
14641            res.protocol(),
14642            "op-napi-get-do-request",
14643            RequestOpNapiGetDoRequest::lookup,
14644        );
14645        res
14646    }
14647    pub fn op_qstats_get_dump_request(self) -> RequestOpQstatsGetDumpRequest<'buf> {
14648        let mut res = RequestOpQstatsGetDumpRequest::new(self);
14649        res.request.do_writeback(
14650            res.protocol(),
14651            "op-qstats-get-dump-request",
14652            RequestOpQstatsGetDumpRequest::lookup,
14653        );
14654        res
14655    }
14656    pub fn op_bind_rx_do_request(self) -> RequestOpBindRxDoRequest<'buf> {
14657        let mut res = RequestOpBindRxDoRequest::new(self);
14658        res.request.do_writeback(
14659            res.protocol(),
14660            "op-bind-rx-do-request",
14661            RequestOpBindRxDoRequest::lookup,
14662        );
14663        res
14664    }
14665    pub fn op_napi_set_do_request(self) -> RequestOpNapiSetDoRequest<'buf> {
14666        let mut res = RequestOpNapiSetDoRequest::new(self);
14667        res.request.do_writeback(
14668            res.protocol(),
14669            "op-napi-set-do-request",
14670            RequestOpNapiSetDoRequest::lookup,
14671        );
14672        res
14673    }
14674    pub fn op_bind_tx_do_request(self) -> RequestOpBindTxDoRequest<'buf> {
14675        let mut res = RequestOpBindTxDoRequest::new(self);
14676        res.request.do_writeback(
14677            res.protocol(),
14678            "op-bind-tx-do-request",
14679            RequestOpBindTxDoRequest::lookup,
14680        );
14681        res
14682    }
14683}